Skip to content

Commit 3f98fd7

Browse files
Merge pull request #143 from geostyler/142-fix-size-padding-characterInPolygon
fix(#142): size and padding character in polygon
2 parents b0f4d36 + 57f838f commit 3f98fd7

File tree

5 files changed

+2827
-41
lines changed

5 files changed

+2827
-41
lines changed

src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export const ESRI_SYMBOLS_FONT: string = "ESRI Default Marker";
22
export const POLYGON_FILL_RESIZE_FACTOR: number = 2 / 3;
33
export const OFFSET_FACTOR: number = 4 / 3;
4+
export const ESRI_SPECIAL_FONT: string[] = ["ttf://ESRI SDS 2.00", "ttf://ESRI SDS 1.95"];
5+
export const ESRI_SPECIAL_FONT_RESIZE_FACTOR: number = 1.8;
46

57
export enum MarkerPlacementPosition {
68
START = "startPoint",

src/esri/types/symbols/CIMSymbol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export type SymbolLayer = CIMObject & {
3333
separation: number;
3434
size: number;
3535
symbol: CIMSymbol;
36+
respectFrame: boolean;
3637
};
3738

3839
export type CIMSymbol = CIMObject & {

src/processSymbolLayer.ts

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { Effect, Options } from "./types.ts";
22
import { toWKT } from "./wktGeometries.ts";
33
import {
44
ESRI_SYMBOLS_FONT,
5+
ESRI_SPECIAL_FONT,
56
OFFSET_FACTOR,
67
POLYGON_FILL_RESIZE_FACTOR,
8+
ESRI_SPECIAL_FONT_RESIZE_FACTOR,
79
ptToPx,
810
} from "./constants.ts";
911
import {
@@ -76,15 +78,15 @@ const processSymbolLayerWithSubSymbol = (
7678
options: Options,
7779
maxX: number | null = null,
7880
maxY: number | null = null,
81+
respectFrame: boolean = true,
7982
): Symbolizer[] => {
8083
const symbolizers: Symbolizer[] = [];
8184
if (symbol.type === "CIMPolygonSymbol") {
8285
const markerPlacement = layer.markerPlacement || {};
8386
const polygonSymbolizer = formatPolygonSymbolizer(
8487
symbolizer as MarkSymbolizer,
8588
markerPlacement,
86-
maxX,
87-
maxY,
89+
respectFrame,
8890
);
8991
if (polygonSymbolizer) {
9092
symbolizers.push(polygonSymbolizer);
@@ -219,16 +221,14 @@ const processMarkerPlacementAlongLine = (
219221
const formatPolygonSymbolizer = (
220222
symbolizer: MarkSymbolizer,
221223
markerPlacement: CIMMarkerPlacement,
222-
maxX: number | null = null,
223-
maxY: number | null = null,
224+
respectFrame: boolean,
224225
): FillSymbolizer | LineSymbolizer | null => {
225226
const markerPlacementType = markerPlacement.type;
226227
if (markerPlacementType === "CIMMarkerPlacementInsidePolygon") {
227228
const padding = processMarkerPlacementInsidePolygon(
228229
symbolizer,
229230
markerPlacement,
230-
maxX,
231-
maxY,
231+
respectFrame,
232232
);
233233
return {
234234
kind: "Fill",
@@ -333,57 +333,43 @@ const processOrientedMarkerAtEndOfLine = (
333333
const processMarkerPlacementInsidePolygon = (
334334
symbolizer: MarkSymbolizer,
335335
markerPlacement: CIMMarkerPlacement,
336-
symMaxX: number | null = null,
337-
symMaxY: number | null = null,
336+
respectFrame: boolean = true
338337
): [
339338
Expression<number>,
340339
Expression<number>,
341340
Expression<number>,
342341
Expression<number>,
343342
] => {
343+
const isSpecialFont = ESRI_SPECIAL_FONT.some(font => symbolizer?.wellKnownName?.startsWith(font));
344344
// In case of markers in a polygon fill, it seems ArcGIS does some undocumented resizing of the marker.
345-
// We use an empirical factor to account for this, which works in most cases (but not all)
346-
const resizeFactor = symbolizer?.wellKnownName?.startsWith("wkt://POLYGON")
347-
? 1
348-
: POLYGON_FILL_RESIZE_FACTOR;
349-
350-
const radius = typeof symbolizer.radius === "number" ? symbolizer.radius : 0;
351-
352-
// Size is already in pixel.
353-
// Avoid null values and force them to 1 px
354-
const size = Math.round(radius * resizeFactor) || 1;
355-
symbolizer.radius = size;
356-
357-
// We use SLD graphic-margin as top, right, bottom, left to mimic the combination of
358-
// ArcGIS stepX, stepY, offsetX, offsetY
359-
let maxX = size / 2;
360-
let maxY = size / 2;
361-
362-
symMaxX = symMaxX ?? maxX;
363-
symMaxY = symMaxY ?? maxY;
364-
if (symMaxX && symMaxY) {
365-
maxX = Math.floor(symMaxX * resizeFactor) || 1;
366-
maxY = Math.floor(symMaxY * resizeFactor) || 1;
345+
// We use an empirical factor to account for this, which works in most cases. For special Fonts we need to
346+
// use another empirical factor when respectFrame is set to false.
347+
let resizeFactor: number;
348+
if (respectFrame) {
349+
resizeFactor = isSpecialFont ? 1 : POLYGON_FILL_RESIZE_FACTOR;
350+
} else {
351+
resizeFactor = isSpecialFont ? ESRI_SPECIAL_FONT_RESIZE_FACTOR : 1;
367352
}
368353

369354
let stepX = ptToPxProp(markerPlacement, "stepX", 0);
370355
let stepY = ptToPxProp(markerPlacement, "stepY", 0);
371356

372-
if (stepX < maxX) {
373-
stepX += maxX * 2;
374-
}
357+
const radius = typeof symbolizer.radius === "number" ? symbolizer.radius : 0;
358+
const size = Math.round(radius * 2 * resizeFactor) || 1;
359+
symbolizer.radius = size / 2;
375360

376-
if (stepY < maxY) {
377-
stepY += maxY * 2;
361+
if (stepX < size) {
362+
stepX = size;
378363
}
379364

380-
const offsetX = ptToPxProp(markerPlacement, "offsetX", 0);
381-
const offsetY = ptToPxProp(markerPlacement, "offsetY", 0);
365+
if (stepY < size) {
366+
stepY = size;
367+
}
382368

383-
const right = Math.round(stepX / 2 - maxX - offsetX);
384-
const left = Math.round(stepX / 2 - maxX + offsetX);
385-
const top = Math.round(stepY / 2 - maxY - offsetY);
386-
const bottom = Math.round(stepY / 2 - maxY + offsetY);
369+
const right = Math.round(stepX / 2 - size / 2);
370+
const left = Math.round(stepX / 2 - size / 2);
371+
const top = Math.round(stepY / 2 - size / 2);
372+
const bottom = Math.round(stepY / 2 - size / 2);
387373

388374
return [top, right, bottom, left];
389375
};
@@ -503,6 +489,7 @@ const processSymbolCharacterMarker = (
503489
let strokeColor = "#000000";
504490
let strokeWidth = 0;
505491
let strokeOpacity = 0;
492+
let respectFrame = layer.respectFrame;
506493
const symbolLayers = layer.symbol.symbolLayers;
507494
if (symbolLayers) {
508495
fillColor = extractFillColor(symbolLayers);
@@ -522,13 +509,17 @@ const processSymbolCharacterMarker = (
522509
color: fillColor,
523510
wellKnownName: name,
524511
radius: size / 2,
512+
respectFrame: respectFrame,
525513
} as Symbolizer;
526514

527515
const symbolizerWithSubSymbolizer = processSymbolLayerWithSubSymbol(
528516
symbol,
529517
layer,
530518
symbolCharacterMaker,
531519
options,
520+
undefined,
521+
undefined,
522+
respectFrame,
532523
);
533524
if (symbolizerWithSubSymbolizer.length) {
534525
return symbolizerWithSubSymbolizer;

0 commit comments

Comments
 (0)