@maplat/transform 0.4.1 → 0.5.1

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.
package/README.md CHANGED
@@ -1,171 +1,341 @@
1
- # Maplat Transform
2
-
3
- [![CI](https://github.com/code4history/MaplatTransform/actions/workflows/test.yml/badge.svg)](https://github.com/code4history/MaplatTransform/actions/workflows/test.yml)
4
-
5
- A JavaScript library that performs coordinate transformation between two plane coordinate systems using transformation definitions generated by Maplat.
6
- This is part of the [Maplat](https://github.com/code4history/Maplat/) project.
7
-
8
- 日本語のREADMEは[こちら](./README.ja.md)
9
-
10
- ## Key Features
11
-
12
- - **Import Transformation Definitions:** Import and build internal structures from transformation definitions generated by Maplat
13
- - **Bidirectional Coordinate Transformation:** Convert coordinates between two planes in both directions
14
- - **Topology Preservation:** Maintains homeomorphic properties during transformation
15
- - **Multiple Coordinate System Support:** Handles transformations between various coordinate systems including standard orthogonal coordinates, Y-axis inverted coordinates, and distorted coordinates like bird's-eye views
16
- - **State Management:** Save and restore transformation states
17
-
18
- ## Requirements
19
-
20
- - **Node.js:** >= 20
21
- - **pnpm:** >= 9 (for development)
22
-
23
- ## Installation
24
-
25
- ### pnpm (Recommended)
26
-
27
- ```sh
28
- pnpm add @maplat/transform
29
- ```
30
-
31
- ### npm
32
-
33
- ```sh
34
- npm install @maplat/transform
35
- ```
36
-
37
- ### Browser
38
-
39
- ```html
40
- <script src="https://unpkg.com/@maplat/transform/dist/maplat_transform.umd.js"></script>
41
- ```
42
-
43
- ## Basic Usage
44
-
45
- ```javascript
46
- import { Transform } from '@maplat/transform';
47
-
48
- // Import transformation definition
49
- const transform = new Transform();
50
- transform.setCompiled(compiledData); // Apply transformation definition generated by Maplat
51
-
52
- // Forward transformation (source → target coordinate system)
53
- const transformed = transform.transform([100, 100], false);
54
-
55
- // Backward transformation (target → source coordinate system)
56
- const restored = transform.transform(transformed, true);
57
- ```
58
-
59
- ### Error Handling
60
-
61
- The library may throw errors in the following cases:
62
-
63
- - Transformation errors in strict mode
64
- - Attempting backward transformation when not allowed
65
- - Invalid data structure during transformation
66
-
67
- If errors occur, the transformation definition data needs to be modified. Please use editor tools that incorporate [@maplat/tin](https://github.com/code4history/MaplatTin/) to modify transformation definitions.
68
-
69
- ## API Reference
70
-
71
- ### Transform Class
72
-
73
- The main class for coordinate transformation.
74
-
75
- #### Constructor
76
-
77
- ```javascript
78
- const transform = new Transform();
79
- ```
80
-
81
- #### Methods
82
-
83
- ##### `setCompiled(compiled: Compiled | CompiledLegacy): void`
84
-
85
- Import and apply a compiled transformation definition generated by Maplat.
86
-
87
- - **Parameters:**
88
- - `compiled`: Compiled transformation definition object
89
-
90
- ##### `transform(apoint: number[], backward?: boolean, ignoreBounds?: boolean): number[] | false`
91
-
92
- Perform coordinate transformation.
93
-
94
- - **Parameters:**
95
- - `apoint`: Coordinate to transform `[x, y]`
96
- - `backward`: Whether to perform backward transformation (default: `false`)
97
- - `ignoreBounds`: Whether to ignore boundary checks (default: `false`)
98
- - **Returns:** Transformed coordinate or `false` if out of bounds
99
- - **Throws:** Error if backward transformation is attempted when `strict_status == "strict_error"`
100
-
101
- #### Static Constants
102
-
103
- **Vertex Modes:**
104
- - `Transform.VERTEX_PLAIN`: Standard plane coordinate system
105
- - `Transform.VERTEX_BIRDEYE`: Bird's-eye view coordinate system
106
-
107
- **Strict Modes:**
108
- - `Transform.MODE_STRICT`: Strict transformation mode
109
- - `Transform.MODE_AUTO`: Automatic mode selection
110
- - `Transform.MODE_LOOSE`: Loose transformation mode
111
-
112
- **Strict Status:**
113
- - `Transform.STATUS_STRICT`: Strict status
114
- - `Transform.STATUS_ERROR`: Error status (backward transformation not allowed)
115
- - `Transform.STATUS_LOOSE`: Loose status
116
-
117
- **Y-axis Modes:**
118
- - `Transform.YAXIS_FOLLOW`: Follow Y-axis direction
119
- - `Transform.YAXIS_INVERT`: Invert Y-axis direction
120
-
121
- ### Exported Types
122
-
123
- - `PointSet`, `BiDirectionKey`, `WeightBufferBD`, `VertexMode`, `StrictMode`, `StrictStatus`, `YaxisMode`
124
- - `CentroidBD`, `TinsBD`, `KinksBD`, `VerticesParamsBD`, `IndexedTinsBD`
125
- - `Compiled`, `CompiledLegacy`
126
- - `Tins`, `Tri`, `PropertyTriKey`
127
- - `Edge`, `EdgeSet`, `EdgeSetLegacy`
128
-
129
- ### Exported Utility Functions
130
-
131
- - `transformArr`: Low-level coordinate transformation function
132
- - `rotateVerticesTriangle`: Rotate vertices of a triangle
133
- - `counterTri`: Counter triangle utility
134
- - `normalizeEdges`: Normalize edge definitions
135
-
136
- ### Format Version
137
-
138
- ```javascript
139
- import { format_version } from '@maplat/transform';
140
- console.log(format_version); // Current format version
141
- ```
142
-
143
- ## Documentation
144
-
145
- For detailed technical information about the transformation internals, see:
146
- - [Transform Internals](./docs/transform-internals.md) - Runtime notes on how Transform class reconstructs state and performs coordinate lookups
147
-
148
- ## Development
149
-
150
- ### Running Tests
151
-
152
- ```sh
153
- pnpm test
154
- ```
155
-
156
- ## Important Note
157
-
158
- This library specializes in executing coordinate transformations and does not include functionality for generating or editing transformation definitions. If you need to create or edit transformation definitions, please use the [@maplat/tin](https://github.com/code4history/MaplatTin/) package.
159
-
160
- ## License
161
-
162
- Maplat Limited License 1.1
163
-
164
- Copyright (c) 2025 Code for History
165
-
166
- ### Developers
167
-
168
- - Kohei Otsuka
169
- - Code for History
170
-
171
- We welcome your contributions! Feel free to submit [issues and pull requests](https://github.com/code4history/MaplatTransform/issues).
1
+ # Maplat Transform
2
+
3
+ [![CI](https://github.com/code4history/MaplatTransform/actions/workflows/test.yml/badge.svg)](https://github.com/code4history/MaplatTransform/actions/workflows/test.yml)
4
+
5
+ A JavaScript library that performs coordinate transformation between two plane coordinate systems using transformation definitions generated by Maplat.
6
+ This is part of the [Maplat](https://github.com/code4history/Maplat/) project.
7
+
8
+ 日本語のREADMEは[こちら](./README.ja.md)
9
+
10
+ ## Key Features
11
+
12
+ - **Import Transformation Definitions:** Import and build internal structures from transformation definitions generated by Maplat
13
+ - **V2/V3 Format Support:** Compatible with both legacy V2 compiled format (4 fixed boundary vertices) and the new V3 format (N boundary vertices for higher accuracy)
14
+ - **Bidirectional Coordinate Transformation:** Convert coordinates between two planes in both directions
15
+ - **Topology Preservation:** Maintains homeomorphic properties during transformation
16
+ - **Multiple Coordinate System Support:** Handles transformations between various coordinate systems including standard orthogonal coordinates, Y-axis inverted coordinates, and distorted coordinates like bird's-eye views
17
+ - **State Management:** Save and restore transformation states
18
+ - **Sub-map Selection (Processing 2):** For maps with multiple overlapping TIN regions (`sub_maps`), automatically determines which TIN to apply based on region boundaries, priority, and importance
19
+ - **Viewport Transformation (Processing 3):** Converts a display viewport (center, zoom, rotation) in pixel coordinate space to a viewport in the map coordinate space (EPSG:3857)
20
+ - **Cross-map Viewport Sync (Processing 4):** Converts a display viewport from one pixel map directly to the corresponding viewport of another pixel map, via the shared map coordinate space
21
+
22
+ ## Requirements
23
+
24
+ - **Node.js:** >= 20
25
+ - **pnpm:** >= 9 (for development)
26
+
27
+ ## Installation
28
+
29
+ ### pnpm (Recommended)
30
+
31
+ ```sh
32
+ pnpm add @maplat/transform
33
+ ```
34
+
35
+ ### npm
36
+
37
+ ```sh
38
+ npm install @maplat/transform
39
+ ```
40
+
41
+ ### Browser
42
+
43
+ ```html
44
+ <script src="https://unpkg.com/@maplat/transform/dist/maplat_transform.umd.js"></script>
45
+ ```
46
+
47
+ ## Basic Usage
48
+
49
+ ```javascript
50
+ import { Transform } from '@maplat/transform';
51
+
52
+ // Import transformation definition
53
+ const transform = new Transform();
54
+ transform.setCompiled(compiledData); // Apply transformation definition generated by Maplat
55
+
56
+ // Forward transformation (source → target coordinate system)
57
+ const transformed = transform.transform([100, 100], false);
58
+
59
+ // Backward transformation (target → source coordinate system)
60
+ const restored = transform.transform(transformed, true);
61
+ ```
62
+
63
+ ### Error Handling
64
+
65
+ The library may throw errors in the following cases:
66
+
67
+ - Transformation errors in strict mode
68
+ - Attempting backward transformation when not allowed
69
+ - Invalid data structure during transformation
70
+
71
+ If errors occur, the transformation definition data needs to be modified. Please use editor tools that incorporate [@maplat/tin](https://github.com/code4history/MaplatTin/) to modify transformation definitions.
72
+
73
+ ## MapTransform Usage
74
+
75
+ ### Processing 2 — Sub-map selection and coordinate transformation
76
+
77
+ When a single map image contains multiple overlapping TIN definitions (`sub_maps`), use `MapTransform` to automatically select the correct TIN and transform coordinates.
78
+
79
+ ```javascript
80
+ import { MapTransform } from '@maplat/transform';
81
+
82
+ const mt = new MapTransform();
83
+ mt.setMapData({
84
+ compiled: mainCompiledData, // Main TIN compiled data
85
+ sub_maps: [
86
+ { compiled: sub0Data, priority: 1, importance: 1 },
87
+ { compiled: sub1Data, priority: 2, importance: 2 },
88
+ ],
89
+ });
90
+
91
+ // Forward: pixel XY → EPSG:3857 (returns [layerIndex, mercCoord] or false)
92
+ const result = mt.xy2MercWithLayer([320, 240]);
93
+ if (result) {
94
+ const [layerIndex, merc] = result;
95
+ console.log('layer:', layerIndex, 'merc:', merc);
96
+ }
97
+
98
+ // Reverse: EPSG:3857 pixel XY (returns up to 2 layers, each [layerIndex, xyCoord] or undefined)
99
+ const results = mt.merc2XyWithLayer([15000000, 4000000]);
100
+ results.forEach((r, i) => {
101
+ if (r) console.log(`result ${i}: layer ${r[0]}, xy`, r[1]);
102
+ });
103
+ ```
104
+
105
+ ### Processing 3 Viewport transformation
106
+
107
+ Convert a pixel-map viewport (center position, zoom level, rotation angle) to and from a geographic viewport in EPSG:3857. The viewport is represented as five Mercator points (center + four cardinal offsets).
108
+
109
+ ```javascript
110
+ import { MapTransform } from '@maplat/transform';
111
+
112
+ const mt = new MapTransform();
113
+ mt.setMapData({ compiled: compiledData });
114
+
115
+ const canvasSize = [800, 600]; // [width, height] in pixels
116
+
117
+ // Pixel viewport → EPSG:3857 five points
118
+ const viewpoint = {
119
+ center: [15000000, 4000000], // EPSG:3857 center of the pixel-space viewport
120
+ zoom: 14,
121
+ rotation: 0,
122
+ };
123
+ const mercs = mt.viewpoint2Mercs(viewpoint, canvasSize);
124
+ // mercs: [[cx,cy], [north], [east], [south], [west]] (EPSG:3857)
125
+
126
+ // EPSG:3857 five points → pixel viewport
127
+ const vp = mt.mercs2Viewpoint(mercs, canvasSize);
128
+ console.log(vp.center, vp.zoom, vp.rotation);
129
+ ```
130
+
131
+ ### Processing 4 — Cross-map viewport synchronization
132
+
133
+ Convert the display viewport of one pixel map to the corresponding viewport of another pixel map, using the shared EPSG:3857 space as an intermediary.
134
+
135
+ ```javascript
136
+ import { MapTransform } from '@maplat/transform';
137
+
138
+ const mtA = new MapTransform();
139
+ mtA.setMapData({ compiled: compiledDataA });
140
+
141
+ const mtB = new MapTransform();
142
+ mtB.setMapData({ compiled: compiledDataB });
143
+
144
+ const canvasSize = [800, 600];
145
+
146
+ // Map A viewport (pixel space A)
147
+ const vpA = { center: [15000000, 4000000], zoom: 14, rotation: 0 };
148
+
149
+ // Pixel space A → EPSG:3857 five points (Processing 3 forward)
150
+ const mercs = mtA.viewpoint2Mercs(vpA, canvasSize);
151
+
152
+ // EPSG:3857 five points → Map B viewport (Processing 3 reverse)
153
+ const vpB = mtB.mercs2Viewpoint(mercs, canvasSize);
154
+ console.log('Map B viewport:', vpB);
155
+ ```
156
+
157
+ ## API Reference
158
+
159
+ ### Transform Class
160
+
161
+ The main class for coordinate transformation.
162
+
163
+ #### Constructor
164
+
165
+ ```javascript
166
+ const transform = new Transform();
167
+ ```
168
+
169
+ #### Methods
170
+
171
+ ##### `setCompiled(compiled: Compiled | CompiledLegacy): void`
172
+
173
+ Import and apply a compiled transformation definition generated by Maplat. Supports legacy format, V2 (4 boundary vertices), and V3 (N boundary vertices) automatically.
174
+
175
+ - **Parameters:**
176
+ - `compiled`: Compiled transformation definition object (V2, V3, or legacy format)
177
+
178
+ ##### `transform(apoint: number[], backward?: boolean, ignoreBounds?: boolean): number[] | false`
179
+
180
+ Perform coordinate transformation.
181
+
182
+ - **Parameters:**
183
+ - `apoint`: Coordinate to transform `[x, y]`
184
+ - `backward`: Whether to perform backward transformation (default: `false`)
185
+ - `ignoreBounds`: Whether to ignore boundary checks (default: `false`)
186
+ - **Returns:** Transformed coordinate or `false` if out of bounds
187
+ - **Throws:** Error if backward transformation is attempted when `strict_status == "strict_error"`
188
+
189
+ #### Static Constants
190
+
191
+ **Vertex Modes:**
192
+ - `Transform.VERTEX_PLAIN`: Standard plane coordinate system
193
+ - `Transform.VERTEX_BIRDEYE`: Bird's-eye view coordinate system
194
+
195
+ **Strict Modes:**
196
+ - `Transform.MODE_STRICT`: Strict transformation mode
197
+ - `Transform.MODE_AUTO`: Automatic mode selection
198
+ - `Transform.MODE_LOOSE`: Loose transformation mode
199
+
200
+ **Strict Status:**
201
+ - `Transform.STATUS_STRICT`: Strict status
202
+ - `Transform.STATUS_ERROR`: Error status (backward transformation not allowed)
203
+ - `Transform.STATUS_LOOSE`: Loose status
204
+
205
+ **Y-axis Modes:**
206
+ - `Transform.YAXIS_FOLLOW`: Follow Y-axis direction
207
+ - `Transform.YAXIS_INVERT`: Invert Y-axis direction
208
+
209
+ ### MapTransform Class
210
+
211
+ The class for sub-map selection, viewport transformation, and cross-map viewport synchronization (Processings 2–4).
212
+
213
+ #### Constructor
214
+
215
+ ```javascript
216
+ const mt = new MapTransform();
217
+ ```
218
+
219
+ #### Methods
220
+
221
+ ##### `setMapData(mapData: MapData): void`
222
+
223
+ Load a main TIN and optional sub-map TINs.
224
+
225
+ - **Parameters:**
226
+ - `mapData`: `{ compiled, maxZoom?, sub_maps? }` — main compiled TIN data, optional explicit maxZoom, and optional array of sub-map definitions
227
+
228
+ ##### `xy2Merc(xy: number[]): number[] | false`
229
+
230
+ Transform a pixel coordinate to EPSG:3857 using the main TIN.
231
+
232
+ - **Parameters:** `xy` — pixel coordinate `[x, y]`
233
+ - **Returns:** EPSG:3857 coordinate, or `false` if out of bounds
234
+
235
+ ##### `merc2Xy(merc: number[]): number[] | false`
236
+
237
+ Transform an EPSG:3857 coordinate to pixel coordinate using the main TIN (reverse).
238
+
239
+ - **Parameters:** `merc` — EPSG:3857 coordinate `[x, y]`
240
+ - **Returns:** Pixel coordinate, or `false` if out of bounds
241
+
242
+ ##### `xy2MercWithLayer(xy: number[]): [number, number[]] | false`
243
+
244
+ Transform a pixel coordinate to EPSG:3857, automatically selecting the appropriate TIN from sub-maps based on priority and region (Processing 2).
245
+
246
+ - **Parameters:** `xy` — pixel coordinate `[x, y]`
247
+ - **Returns:** `[layerIndex, mercCoord]` or `false` if out of bounds
248
+
249
+ ##### `merc2XyWithLayer(merc: number[]): ([number, number[]] | undefined)[]`
250
+
251
+ Transform an EPSG:3857 coordinate to pixel coordinate across all applicable TIN layers, returning up to 2 results ordered by importance (Processing 2).
252
+ > To return more than 2 layers, increase the limit in the `.slice(0, 2)` / `.filter(i < 2)` lines inside the implementation.
253
+
254
+ - **Parameters:** `merc` — EPSG:3857 coordinate `[x, y]`
255
+ - **Returns:** Array of up to 2 elements; each is `[layerIndex, xyCoord]` or `undefined`
256
+
257
+ ##### `viewpoint2Mercs(viewpoint: Viewpoint, size: [number, number]): number[][]`
258
+
259
+ Convert a pixel-space viewport to five EPSG:3857 points (Processing 3).
260
+
261
+ - **Parameters:**
262
+ - `viewpoint`: `{ center, zoom, rotation }` — viewport in pixel space (center as EPSG:3857 equivalent via `xy2SysCoord`)
263
+ - `size`: Canvas size `[width, height]`
264
+ - **Returns:** Array of 5 EPSG:3857 points `[center, north, east, south, west]`
265
+ - **Throws:** Error if the center point is outside the TIN bounds
266
+
267
+ ##### `mercs2Viewpoint(mercs: number[][], size: [number, number]): Viewpoint`
268
+
269
+ Convert five EPSG:3857 points back to a pixel-space viewport (Processing 3 reverse).
270
+
271
+ - **Parameters:**
272
+ - `mercs`: Array of 5 EPSG:3857 points (as returned by `viewpoint2Mercs`)
273
+ - `size`: Canvas size `[width, height]`
274
+ - **Returns:** `Viewpoint` — `{ center, zoom, rotation }` in pixel space
275
+ - **Throws:** Error if the center point cannot be reverse-transformed
276
+
277
+ #### Accessors
278
+
279
+ - `maxxy: number` — `2^maxZoom × 256`; the pixel-to-EPSG:3857 scale factor
280
+
281
+ ### Exported Types
282
+
283
+ - `PointSet`, `BiDirectionKey`, `WeightBufferBD`, `VertexMode`, `StrictMode`, `StrictStatus`, `YaxisMode`
284
+ - `CentroidBD`, `TinsBD`, `KinksBD`, `VerticesParamsBD`, `IndexedTinsBD`
285
+ - `Compiled`, `CompiledLegacy`
286
+ - `Tins`, `Tri`, `PropertyTriKey`
287
+ - `Edge`, `EdgeSet`, `EdgeSetLegacy`
288
+ - `Viewpoint` — `{ center: number[], zoom: number, rotation: number }`
289
+ - `MapData` — `{ compiled: Compiled, maxZoom?: number, sub_maps?: SubMapData[] }`
290
+ - `SubMapData` — `{ compiled: Compiled, priority: number, importance: number, bounds?: number[][] }`
291
+
292
+ ### Exported Utility Functions
293
+
294
+ - `transformArr`: Low-level coordinate transformation function
295
+ - `rotateVerticesTriangle`: Rotate vertices of a triangle
296
+ - `counterTri`: Counter triangle utility
297
+ - `normalizeEdges`: Normalize edge definitions
298
+
299
+ ### Format Version
300
+
301
+ ```javascript
302
+ import { format_version } from '@maplat/transform';
303
+ console.log(format_version); // Current format version
304
+ ```
305
+
306
+ The compiled data format has two modern versions:
307
+
308
+ - **V2:** Uses 4 fixed boundary vertices derived from the map bounding box
309
+ - **V3:** Uses N boundary vertices (≥4) for more precise boundary definition, improving transformation accuracy especially near map edges
310
+
311
+ Both formats are handled transparently by `setCompiled()`. V3 compiled data is generated by [@maplat/tin](https://github.com/code4history/MaplatTin/) version 3 or later.
312
+
313
+ ## Documentation
314
+
315
+ For detailed technical information about the transformation internals, see:
316
+ - [Transform Internals](./docs/transform-internals.md) - Runtime notes on how Transform class reconstructs state and performs coordinate lookups
317
+
318
+ ## Development
319
+
320
+ ### Running Tests
321
+
322
+ ```sh
323
+ pnpm test
324
+ ```
325
+
326
+ ## Important Note
327
+
328
+ This library specializes in executing coordinate transformations and does not include functionality for generating or editing transformation definitions. If you need to create or edit transformation definitions, please use the [@maplat/tin](https://github.com/code4history/MaplatTin/) package.
329
+
330
+ ## License
331
+
332
+ Maplat Limited License 1.1
333
+
334
+ Copyright (c) 2025 Code for History
335
+
336
+ ### Developers
337
+
338
+ - Kohei Otsuka
339
+ - Code for History
340
+
341
+ We welcome your contributions! Feel free to submit [issues and pull requests](https://github.com/code4history/MaplatTransform/issues).