@orbat-mapper/tactical-draw-adapter-maplibre 0.2.0-alpha.2 → 0.2.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +50 -27
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { project, unproject } from "@orbat-mapper/control-measures";
2
- import { BaseMapAdapter, PointerCallbackHub, TOUCH_HIT_TOLERANCE_PX, bindAbortable, nearestWorldCopyLng, pickHitTolerance, tryControlMeasureIdFromFeature } from "@orbat-mapper/tactical-draw";
2
+ import { BaseMapAdapter, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, PointerCallbackHub, TOUCH_HIT_TOLERANCE_PX, bindAbortable, nearestWorldCopyLng, pickHitTolerance, tryControlMeasureIdFromFeature } from "@orbat-mapper/tactical-draw";
3
3
  //#region src/ml-adapter.ts
4
4
  function emptyFC() {
5
5
  return {
@@ -59,39 +59,47 @@ function buildCirclePointFilter(style) {
59
59
  "Point"
60
60
  ];
61
61
  }
62
- function buildTextSizeExpression() {
63
- const size = [
62
+ /** Web Mercator world circumference in meters (2π × 6378137). */
63
+ const WEB_MERCATOR_CIRCUMFERENCE = 40075016.686;
64
+ /**
65
+ * Per-feature text size (ADR-0028): a ground-anchored label carries
66
+ * `textSizeMeters` and renders at `textSizeMeters / resolution`, clamped to
67
+ * the layer's `textSizeMinPixels`/`textSizeMaxPixels` band; a screen-anchored
68
+ * one carries `textSizePixels` and renders at that constant; neither renders
69
+ * the 14px engine default. Layout properties only take zoom as an
70
+ * `interpolate`/`step` input, so the ground conversion is evaluated at every
71
+ * integer zoom stop (resolution = world circumference / 512·2^zoom pixels,
72
+ * matching `getResolution`); the linear ramp between stops approximates the
73
+ * exponential exactly closely enough at 1-zoom granularity.
74
+ */
75
+ function buildTextSizeExpression(text) {
76
+ const minPx = text.textSizeMinPixels ?? DEFAULT_TEXT_SIZE_MIN_PIXELS;
77
+ const maxPx = text.textSizeMaxPixels ?? DEFAULT_TEXT_SIZE_MAX_PIXELS;
78
+ const screenOrDefault = [
64
79
  "coalesce",
65
80
  ["get", "textSizePixels"],
66
81
  14
67
82
  ];
68
- const referenceZoom = [
69
- "coalesce",
70
- ["get", "textSizeZoom"],
71
- 0
72
- ];
73
- const sizeAtZoom = (zoom) => [
74
- "min",
75
- 254,
76
- [
83
+ const sizeAtZoom = (zoom) => {
84
+ return [
77
85
  "case",
78
- ["has", "textSizeZoom"],
86
+ ["has", "textSizeMeters"],
79
87
  [
80
- "*",
81
- size,
88
+ "min",
89
+ maxPx,
82
90
  [
83
- "^",
84
- 2,
91
+ "max",
92
+ minPx,
85
93
  [
86
- "-",
87
- zoom,
88
- referenceZoom
94
+ "*",
95
+ ["get", "textSizeMeters"],
96
+ Math.pow(2, zoom + 9) / WEB_MERCATOR_CIRCUMFERENCE
89
97
  ]
90
98
  ]
91
99
  ],
92
- size
93
- ]
94
- ];
100
+ screenOrDefault
101
+ ];
102
+ };
95
103
  return [
96
104
  "interpolate",
97
105
  ["linear"],
@@ -136,6 +144,22 @@ function buildSymbolLayer(symbolId, sourceId, text) {
136
144
  ],
137
145
  "#000"
138
146
  ];
147
+ const textAnchor = text.labelProperty ? [
148
+ "case",
149
+ [
150
+ "==",
151
+ ["get", "textAnchor"],
152
+ "start"
153
+ ],
154
+ "left",
155
+ [
156
+ "==",
157
+ ["get", "textAnchor"],
158
+ "end"
159
+ ],
160
+ "right",
161
+ "center"
162
+ ] : "center";
139
163
  return {
140
164
  id: symbolId,
141
165
  type: "symbol",
@@ -143,8 +167,9 @@ function buildSymbolLayer(symbolId, sourceId, text) {
143
167
  layout: {
144
168
  "text-field": text.labelProperty ? ["get", text.labelProperty] : text.text ?? "",
145
169
  "text-font": ["Open Sans Regular"],
146
- "text-size": buildTextSizeExpression(),
170
+ "text-size": buildTextSizeExpression(text),
147
171
  "text-rotate": textRotate,
172
+ "text-anchor": textAnchor,
148
173
  "text-rotation-alignment": "map",
149
174
  "text-pitch-alignment": "map",
150
175
  "text-allow-overlap": true
@@ -508,9 +533,7 @@ var MapLibreAdapter = class extends BaseMapAdapter {
508
533
  else this.map.doubleClickZoom.disable();
509
534
  }
510
535
  getResolution() {
511
- const zoom = this.map.getZoom();
512
- const center = this.map.getCenter();
513
- return 40075016.686 * Math.cos(center.lat * Math.PI / 180) / Math.pow(2, zoom + 8);
536
+ return WEB_MERCATOR_CIRCUMFERENCE / Math.pow(2, this.map.getZoom() + 9);
514
537
  }
515
538
  getZoom() {
516
539
  return this.map.getZoom();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbat-mapper/tactical-draw-adapter-maplibre",
3
- "version": "0.2.0-alpha.2",
3
+ "version": "0.2.0-alpha.4",
4
4
  "description": "MapLibre GL JS engine adapter for @orbat-mapper/tactical-draw. Draw and edit tactical control measures (MIL-STD-2525 / APP-6) on a MapLibre map.",
5
5
  "license": "MIT",
6
6
  "author": "Orbat Mapper",
@@ -37,8 +37,8 @@
37
37
  "access": "public"
38
38
  },
39
39
  "dependencies": {
40
- "@orbat-mapper/control-measures": "^0.2.0-alpha.7",
41
- "@orbat-mapper/tactical-draw": "^0.2.0-alpha.6"
40
+ "@orbat-mapper/control-measures": "^0.2.0-alpha.11",
41
+ "@orbat-mapper/tactical-draw": "^0.2.0-alpha.14"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "maplibre-gl": ">=4.0.0 <6.0.0"