Skip to content

Commit 3a269da

Browse files
Merge pull request #140 from geostyler/fix-139-lineSymbolizer-withMarkerPlacement
fix(#139): case MarkerPosition, added test
2 parents 360a075 + 4fc4ff8 commit 3a269da

File tree

3 files changed

+475
-56
lines changed

3 files changed

+475
-56
lines changed

src/processSymbolLayer.ts

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,43 @@ const processSymbolLayerWithSubSymbol = (
9393
}
9494
if (symbol.type === "CIMLineSymbol") {
9595
if (layer.type === "CIMCharacterMarker") {
96-
if (orientedMarkerAtStartOfLine(layer.markerPlacement)) {
97-
const startSymbolizer = processOrientedMarkerAtEndOfLine(
98-
layer,
99-
"start",
100-
options,
101-
);
102-
if (startSymbolizer) {
103-
symbolizers.push(startSymbolizer);
96+
const orientedMarkerPosition = getOrientedMarkerLinePosition(
97+
layer.markerPlacement,
98+
);
99+
if (orientedMarkerPosition) {
100+
const processOrientedMarkerAtEndOfLineFn = (
101+
position: "start" | "end",
102+
) => {
103+
const orientedMarkerSymbolizer = processOrientedMarkerAtEndOfLine(
104+
layer,
105+
position,
106+
options,
107+
);
108+
if (orientedMarkerSymbolizer) {
109+
symbolizers.push(orientedMarkerSymbolizer);
110+
}
111+
};
112+
if (
113+
orientedMarkerPosition === "start" ||
114+
orientedMarkerPosition === "both"
115+
) {
116+
processOrientedMarkerAtEndOfLineFn("start");
104117
}
105-
}
106-
if (orientedMarkerAtEndOfLine(layer.markerPlacement)) {
107-
const endSymbolizer = processOrientedMarkerAtEndOfLine(
108-
layer,
109-
"end",
110-
options,
111-
);
112-
if (endSymbolizer) {
113-
symbolizers.push(endSymbolizer);
118+
119+
if (
120+
orientedMarkerPosition === "end" ||
121+
orientedMarkerPosition === "both"
122+
) {
123+
processOrientedMarkerAtEndOfLineFn("end");
114124
}
125+
} else {
126+
const lineSymbolizer = formatLineSymbolizer(
127+
symbolizer as PointSymbolizer,
128+
layer as SymbolLayer,
129+
);
130+
symbolizers.push(lineSymbolizer);
115131
}
116-
const lineSymbolizer = formatLineSymbolizer(
117-
symbolizer as PointSymbolizer,
118-
layer as SymbolLayer,
119-
);
120-
symbolizers.push(lineSymbolizer);
132+
121133
return symbolizers;
122134
}
123135
// Not CIMCharacterMarker
@@ -254,6 +266,10 @@ const processOrientedMarkerAtEndOfLine = (
254266
// markerPositionFnc = MarkerPlacementPosition.END;
255267
// markerRotationFnc = MarkerPlacementAngle.END;
256268
rotation = layer?.rotation ?? 0;
269+
} else if (orientedMarker === "both") {
270+
// markerPositionFnc = MarkerPlacementPosition.BOTH;
271+
// markerRotationFnc = MarkerPlacementAngle.BOTH;
272+
rotation = layer?.rotation ?? 90;
257273
} else {
258274
return undefined;
259275
}
@@ -303,7 +319,7 @@ const processOrientedMarkerAtEndOfLine = (
303319
kind: "Mark",
304320
color: fillColor,
305321
wellKnownName: name,
306-
radius: ptToPxProp(layer, "size", 10),
322+
radius: ptToPxProp(layer, "size", 10) / 2,
307323
// @ts-ignore FIXME see issue #66
308324
geometry: [null, ["PropertyName", "shape"]],
309325
// geometry: [markerPositionFnc, ["PropertyName", "shape"]],
@@ -372,43 +388,30 @@ const processMarkerPlacementInsidePolygon = (
372388
return [top, right, bottom, left];
373389
};
374390

375-
const orientedMarkerAtStartOfLine = (
391+
const getOrientedMarkerLinePosition = (
376392
markerPlacement: CIMMarkerPlacement,
377-
): boolean => {
393+
): "start" | "end" | "both" | undefined => {
378394
if (markerPlacement?.angleToLine) {
379-
if (
380-
markerPlacement.type === "CIMMarkerPlacementAtRatioPositions" &&
381-
markerPlacement.positionArray[0] === 0 &&
382-
markerPlacement.flipFirst
383-
) {
384-
return true;
385-
} else if (markerPlacement.type === "CIMMarkerPlacementAtExtremities") {
386-
return (
387-
markerPlacement.extremityPlacement === "Both" ||
388-
markerPlacement.extremityPlacement === "JustBegin"
389-
);
390-
}
391-
}
392-
return false;
393-
};
394-
395-
const orientedMarkerAtEndOfLine = (
396-
markerPlacement: CIMMarkerPlacement,
397-
): boolean => {
398-
if (markerPlacement?.angleToLine) {
399-
if (
400-
markerPlacement.type === "CIMMarkerPlacementAtRatioPositions" &&
401-
markerPlacement.positionArray[0] === 1
402-
) {
403-
return true;
395+
if (markerPlacement.type === "CIMMarkerPlacementAtRatioPositions") {
396+
if (markerPlacement.positionArray[0] === 0 && markerPlacement.flipFirst) {
397+
return "start";
398+
}
399+
if (markerPlacement.positionArray[0] === 1) {
400+
return "end";
401+
}
404402
} else if (markerPlacement.type === "CIMMarkerPlacementAtExtremities") {
405-
return (
406-
markerPlacement.extremityPlacement === "Both" ||
407-
markerPlacement.extremityPlacement === "JustEnd"
408-
);
403+
if (markerPlacement.extremityPlacement === "Both") {
404+
return "both";
405+
}
406+
if (markerPlacement.extremityPlacement === "JustBegin") {
407+
return "start";
408+
}
409+
if (markerPlacement.extremityPlacement === "JustEnd") {
410+
return "end";
411+
}
409412
}
410413
}
411-
return false;
414+
return undefined;
412415
};
413416

414417
const processSymbolSolidStroke = (
@@ -672,7 +675,7 @@ const processSymbolHatchFill = (layer: SymbolLayer): Symbolizer[] => {
672675
// For the straight hatch markers, it looks that dividing the value by 2 gives best results.
673676
neededSize = neededSize / 2;
674677
// To keep the "original size" given by the separation value, we play with a negative margin.
675-
let negativeMargin = ((neededSize - separation)) * -1;
678+
let negativeMargin = (neededSize - separation) * -1;
676679
if (wellKnowName === getStraightHatchMarker()[0]) {
677680
fillSymbolizer.graphicFillPadding = [
678681
negativeMargin,

tests/renderer.polyline.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,45 @@ describe("Parse dashed and dotted polyline renderer", () => {
197197
]);
198198
});
199199
});
200+
201+
describe("Parse polyline renderer with markerPlacement at the end", () => {
202+
let geostylerStyle: ReadStyleResult;
203+
204+
beforeAll(async () => {
205+
geostylerStyle = await loadGeostylerStyle(
206+
"./tests/testdata/polyline/polyline_withMarkerPlacement.lyrx",
207+
);
208+
});
209+
210+
it("should parse a valid style object", () => {
211+
expect(geostylerStyle).toBeDefined();
212+
expect(geostylerStyle.output).toBeDefined();
213+
expect(geostylerStyle.output?.name).toBe("fc_polyline_withMarkerPlacement");
214+
});
215+
216+
it("should have a single rule", () => {
217+
const rules = geostylerStyle.output?.rules;
218+
expect(rules).toHaveLength(1);
219+
220+
});
221+
222+
it("should have two correct symbolizers", () => {
223+
const symbolizers = geostylerStyle.output?.rules?.[0].symbolizers;
224+
expect(symbolizers).toHaveLength(2);
225+
const symbolizerLine = geostylerStyle.output?.rules?.[0].symbolizers?.[0] as LineSymbolizer;
226+
expect(symbolizerLine).toBeDefined();
227+
expect(symbolizerLine?.kind).toBe("Line");
228+
expect(symbolizerLine?.color).toBe("#0070ff");
229+
expect(symbolizerLine?.opacity).toBe(1);
230+
expect(symbolizerLine?.width).toBe(0.5333333333333333);
231+
expect(symbolizerLine?.cap).toBe("butt");
232+
expect(symbolizerLine?.join).toBe("round");
233+
234+
const symbolizerMarker = geostylerStyle.output?.rules?.[0].symbolizers?.[1] as MarkSymbolizer;
235+
expect(symbolizerMarker).toBeDefined();
236+
expect(symbolizerMarker?.kind).toBe("Mark");
237+
expect(symbolizerMarker?.wellKnownName).toBe("ttf://ESRI Dimensioning#0x21");
238+
expect(symbolizerMarker?.fillOpacity).toBe(1);
239+
expect(symbolizerMarker?.radius).toBe(4);
240+
});
241+
});

0 commit comments

Comments
 (0)