@osmix/geojson 0.0.8 → 0.0.10

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.
@@ -1,778 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { fromGeoJSON } from "../src/osm-from-geojson";
3
- describe("@osmix/geojson: createOsmFromGeoJSON", () => {
4
- it("should convert Point features to Nodes", async () => {
5
- const geojson = {
6
- type: "FeatureCollection",
7
- features: [
8
- {
9
- type: "Feature",
10
- geometry: {
11
- type: "Point",
12
- coordinates: [-122.4194, 37.7749],
13
- },
14
- properties: {
15
- name: "San Francisco",
16
- population: 873965,
17
- },
18
- },
19
- {
20
- type: "Feature",
21
- geometry: {
22
- type: "Point",
23
- coordinates: [-122.4094, 37.7849],
24
- },
25
- properties: {
26
- name: "Another Point",
27
- },
28
- },
29
- ],
30
- };
31
- const osm = await fromGeoJSON(geojson);
32
- expect(osm.nodes.size).toBe(2);
33
- expect(osm.ways.size).toBe(0);
34
- const node1 = osm.nodes.getById(-1);
35
- expect(node1).toBeDefined();
36
- expect(node1?.lon).toBe(-122.4194);
37
- expect(node1?.lat).toBe(37.7749);
38
- expect(node1?.tags?.["name"]).toBe("San Francisco");
39
- // OSM tags are stored as strings, so numbers are converted
40
- expect(node1?.tags?.["population"]).toBe("873965");
41
- const node2 = osm.nodes.getById(-2);
42
- expect(node2).toBeDefined();
43
- expect(node2?.lon).toBe(-122.4094);
44
- expect(node2?.lat).toBe(37.7849);
45
- expect(node2?.tags?.["name"]).toBe("Another Point");
46
- });
47
- it("should convert LineString features to Ways with Nodes", async () => {
48
- const geojson = {
49
- type: "FeatureCollection",
50
- features: [
51
- {
52
- type: "Feature",
53
- geometry: {
54
- type: "LineString",
55
- coordinates: [
56
- [-122.4194, 37.7749],
57
- [-122.4094, 37.7849],
58
- [-122.3994, 37.7949],
59
- ],
60
- },
61
- properties: {
62
- highway: "primary",
63
- name: "Main Street",
64
- },
65
- },
66
- ],
67
- };
68
- const osm = await fromGeoJSON(geojson);
69
- expect(osm.nodes.size).toBe(3);
70
- expect(osm.ways.size).toBe(1);
71
- const way = osm.ways.getById(-1);
72
- expect(way).toBeDefined();
73
- expect(way?.refs).toHaveLength(3);
74
- expect(way?.tags?.["highway"]).toBe("primary");
75
- expect(way?.tags?.["name"]).toBe("Main Street");
76
- // Verify nodes were created
77
- const node1 = osm.nodes.getById(way.refs[0]);
78
- const node2 = osm.nodes.getById(way.refs[1]);
79
- const node3 = osm.nodes.getById(way.refs[2]);
80
- expect(node1?.lon).toBe(-122.4194);
81
- expect(node1?.lat).toBe(37.7749);
82
- expect(node2?.lon).toBe(-122.4094);
83
- expect(node2?.lat).toBe(37.7849);
84
- expect(node3?.lon).toBe(-122.3994);
85
- expect(node3?.lat).toBe(37.7949);
86
- });
87
- it("should use feature IDs when present", async () => {
88
- const geojson = {
89
- type: "FeatureCollection",
90
- features: [
91
- {
92
- type: "Feature",
93
- id: 100,
94
- geometry: {
95
- type: "Point",
96
- coordinates: [-122.4194, 37.7749],
97
- },
98
- properties: {
99
- name: "Point with ID",
100
- },
101
- },
102
- {
103
- type: "Feature",
104
- id: "200",
105
- geometry: {
106
- type: "LineString",
107
- coordinates: [
108
- [-122.4194, 37.7749],
109
- [-122.4094, 37.7849],
110
- ],
111
- },
112
- properties: {
113
- highway: "primary",
114
- },
115
- },
116
- ],
117
- };
118
- const osm = await fromGeoJSON(geojson);
119
- // Point should use ID 100
120
- const node = osm.nodes.getById(100);
121
- expect(node).toBeDefined();
122
- expect(node?.tags?.["name"]).toBe("Point with ID");
123
- // Way should use ID 200
124
- const way = osm.ways.getById(200);
125
- expect(way).toBeDefined();
126
- expect(way?.tags?.["highway"]).toBe("primary");
127
- });
128
- it("should generate sequential IDs when feature IDs are not present", async () => {
129
- const geojson = {
130
- type: "FeatureCollection",
131
- features: [
132
- {
133
- type: "Feature",
134
- geometry: {
135
- type: "Point",
136
- coordinates: [-122.4194, 37.7749],
137
- },
138
- properties: {},
139
- },
140
- {
141
- type: "Feature",
142
- geometry: {
143
- type: "Point",
144
- coordinates: [-122.4094, 37.7849],
145
- },
146
- properties: {},
147
- },
148
- {
149
- type: "Feature",
150
- geometry: {
151
- type: "LineString",
152
- coordinates: [
153
- [-122.3994, 37.7949],
154
- [-122.3894, 37.8049],
155
- ],
156
- },
157
- properties: {},
158
- },
159
- ],
160
- };
161
- const osm = await fromGeoJSON(geojson);
162
- // Nodes should have sequential IDs starting from 1
163
- expect(osm.nodes.getById(-1)).toBeDefined();
164
- expect(osm.nodes.getById(-2)).toBeDefined();
165
- expect(osm.nodes.getById(-3)).toBeDefined();
166
- expect(osm.nodes.getById(-4)).toBeDefined();
167
- // Way should have ID 1
168
- expect(osm.ways.getById(-1)).toBeDefined();
169
- });
170
- it("should convert all properties to OSM tags", async () => {
171
- const geojson = {
172
- type: "FeatureCollection",
173
- features: [
174
- {
175
- type: "Feature",
176
- geometry: {
177
- type: "Point",
178
- coordinates: [-122.4194, 37.7749],
179
- },
180
- properties: {
181
- name: "Test",
182
- population: 1000,
183
- boolean: true,
184
- nullValue: null,
185
- undefinedValue: undefined,
186
- },
187
- },
188
- ],
189
- };
190
- const osm = await fromGeoJSON(geojson);
191
- const node = osm.nodes.getById(-1);
192
- expect(node?.tags?.["name"]).toBe("Test");
193
- // OSM tags are stored as strings, so numbers are converted
194
- expect(node?.tags?.["population"]).toBe("1000");
195
- expect(node?.tags?.["boolean"]).toBe("true");
196
- expect(node?.tags?.["nullValue"]).toBeUndefined();
197
- expect(node?.tags?.["undefinedValue"]).toBeUndefined();
198
- });
199
- it("should reuse nodes when LineStrings share coordinates", async () => {
200
- const geojson = {
201
- type: "FeatureCollection",
202
- features: [
203
- {
204
- type: "Feature",
205
- geometry: {
206
- type: "LineString",
207
- coordinates: [
208
- [-122.4194, 37.7749],
209
- [-122.4094, 37.7849],
210
- ],
211
- },
212
- properties: {
213
- highway: "primary",
214
- },
215
- },
216
- {
217
- type: "Feature",
218
- geometry: {
219
- type: "LineString",
220
- coordinates: [
221
- [-122.4094, 37.7849], // Shared coordinate
222
- [-122.3994, 37.7949],
223
- ],
224
- },
225
- properties: {
226
- highway: "secondary",
227
- },
228
- },
229
- ],
230
- };
231
- const osm = await fromGeoJSON(geojson);
232
- // Should have 3 nodes (shared coordinate is reused)
233
- expect(osm.nodes.size).toBe(3);
234
- expect(osm.ways.size).toBe(2);
235
- const way1 = osm.ways.getById(-1);
236
- const way2 = osm.ways.getById(-2);
237
- // Each way should have its own nodes
238
- expect(way1?.refs).toHaveLength(2);
239
- expect(way2?.refs).toHaveLength(2);
240
- // Nodes at the same coordinate are reused
241
- expect(way1?.refs[1]).toBe(way2?.refs[0]);
242
- });
243
- it("should error on LineStrings with less than 2 coordinates", () => {
244
- const geojson = {
245
- type: "FeatureCollection",
246
- features: [
247
- {
248
- type: "Feature",
249
- geometry: {
250
- type: "LineString",
251
- coordinates: [[-122.4194, 37.7749]], // Only one coordinate
252
- },
253
- properties: {},
254
- },
255
- ],
256
- };
257
- expect(() => fromGeoJSON(geojson)).toThrow("Invalid GeoJSON coordinates in LineString.");
258
- });
259
- it("should error on LineStrings with invalid coordinates that result in less than 2 valid nodes", () => {
260
- const geojson = {
261
- type: "FeatureCollection",
262
- features: [
263
- {
264
- type: "Feature",
265
- geometry: {
266
- type: "LineString",
267
- coordinates: [
268
- [-122.4194, 37.7749], // Valid coordinate
269
- [undefined, undefined],
270
- ],
271
- },
272
- properties: {
273
- highway: "primary",
274
- },
275
- },
276
- {
277
- type: "Feature",
278
- geometry: {
279
- type: "LineString",
280
- coordinates: [
281
- [-122.4194, 37.7749],
282
- [-122.4094, 37.7849],
283
- ],
284
- },
285
- properties: {
286
- highway: "secondary",
287
- },
288
- },
289
- ],
290
- };
291
- expect(() => fromGeoJSON(geojson)).toThrow();
292
- });
293
- it("should handle mixed Point and LineString features", async () => {
294
- const geojson = {
295
- type: "FeatureCollection",
296
- features: [
297
- {
298
- type: "Feature",
299
- geometry: {
300
- type: "Point",
301
- coordinates: [-122.4194, 37.7749],
302
- },
303
- properties: {
304
- name: "Start Point",
305
- },
306
- },
307
- {
308
- type: "Feature",
309
- geometry: {
310
- type: "LineString",
311
- coordinates: [
312
- [-122.4194, 37.7749], // Same as point
313
- [-122.4094, 37.7849],
314
- ],
315
- },
316
- properties: {
317
- highway: "primary",
318
- },
319
- },
320
- {
321
- type: "Feature",
322
- geometry: {
323
- type: "Point",
324
- coordinates: [-122.3994, 37.7949],
325
- },
326
- properties: {
327
- name: "End Point",
328
- },
329
- },
330
- ],
331
- };
332
- const osm = await fromGeoJSON(geojson);
333
- // Should have 3 nodes (point node is reused by LineString)
334
- expect(osm.nodes.size).toBe(3);
335
- expect(osm.ways.size).toBe(1);
336
- const way = osm.ways.getById(-1);
337
- expect(way?.refs).toHaveLength(2);
338
- // First node of way should be the same as the point node
339
- const pointNode = osm.nodes.getById(-1);
340
- expect(way?.refs[0]).toBe(-1);
341
- expect(pointNode?.lon).toBe(-122.4194);
342
- expect(pointNode?.lat).toBe(37.7749);
343
- });
344
- it("should build indexes after conversion", async () => {
345
- const geojson = {
346
- type: "FeatureCollection",
347
- features: [
348
- {
349
- type: "Feature",
350
- geometry: {
351
- type: "Point",
352
- coordinates: [-122.4194, 37.7749],
353
- },
354
- properties: {},
355
- },
356
- ],
357
- };
358
- const osm = await fromGeoJSON(geojson);
359
- expect(osm.isReady()).toBe(true);
360
- expect(osm.nodes.isReady()).toBe(true);
361
- expect(osm.ways.isReady()).toBe(true);
362
- });
363
- it("should handle features without properties", async () => {
364
- const geojson = {
365
- type: "FeatureCollection",
366
- features: [
367
- {
368
- type: "Feature",
369
- geometry: {
370
- type: "Point",
371
- coordinates: [-122.4194, 37.7749],
372
- },
373
- properties: null,
374
- },
375
- ],
376
- };
377
- const osm = await fromGeoJSON(geojson);
378
- const node = osm.nodes.getById(-1);
379
- expect(node).toBeDefined();
380
- expect(node?.tags).toBeUndefined();
381
- });
382
- it("should convert Polygon features to Ways with area tags", async () => {
383
- const geojson = {
384
- type: "FeatureCollection",
385
- features: [
386
- {
387
- type: "Feature",
388
- geometry: {
389
- type: "Polygon",
390
- coordinates: [
391
- [
392
- [-122.4194, 37.7749],
393
- [-122.4094, 37.7749],
394
- [-122.4094, 37.7849],
395
- [-122.4194, 37.7849],
396
- [-122.4194, 37.7749], // Closed ring
397
- ],
398
- ],
399
- },
400
- properties: {
401
- building: "yes",
402
- name: "Test Building",
403
- },
404
- },
405
- ],
406
- };
407
- const osm = await fromGeoJSON(geojson);
408
- expect(osm.nodes.size).toBe(4); // 4 unique nodes (last is duplicate)
409
- expect(osm.ways.size).toBe(1);
410
- expect(osm.relations.size).toBe(0); // No relation for simple polygon
411
- const way = osm.ways.getById(-1);
412
- expect(way).toBeDefined();
413
- expect(way?.tags?.["building"]).toBe("yes");
414
- expect(way?.tags?.["name"]).toBe("Test Building");
415
- expect(way?.tags?.["area"]).toBe("yes");
416
- expect(way?.refs).toHaveLength(5); // 4 nodes + closing node
417
- expect(way?.refs[0]).toBe(way?.refs[4]); // Ring is closed
418
- });
419
- it("should convert Polygon with holes to relation with multiple Ways", async () => {
420
- const geojson = {
421
- type: "FeatureCollection",
422
- features: [
423
- {
424
- type: "Feature",
425
- geometry: {
426
- type: "Polygon",
427
- coordinates: [
428
- // Outer ring
429
- [
430
- [-122.4194, 37.7749],
431
- [-122.4094, 37.7749],
432
- [-122.4094, 37.7849],
433
- [-122.4194, 37.7849],
434
- [-122.4194, 37.7749],
435
- ],
436
- // Hole
437
- [
438
- [-122.4164, 37.7779],
439
- [-122.4144, 37.7779],
440
- [-122.4144, 37.7799],
441
- [-122.4164, 37.7799],
442
- [-122.4164, 37.7779],
443
- ],
444
- ],
445
- },
446
- properties: {
447
- building: "yes",
448
- },
449
- },
450
- ],
451
- };
452
- const osm = await fromGeoJSON(geojson);
453
- // Should have outer ring way + hole way + relation
454
- expect(osm.ways.size).toBe(2);
455
- expect(osm.relations.size).toBe(1);
456
- const outerWay = osm.ways.getById(-1);
457
- expect(outerWay).toBeDefined();
458
- expect(outerWay?.tags?.["area"]).toBe("yes");
459
- expect(outerWay?.tags?.["building"]).toBeUndefined(); // Tags go on relation
460
- const holeWay = osm.ways.getById(-2);
461
- expect(holeWay).toBeDefined();
462
- expect(holeWay?.tags?.["area"]).toBe("yes");
463
- expect(holeWay?.tags?.["building"]).toBeUndefined(); // Tags go on relation
464
- const relation = osm.relations.getById(-1);
465
- expect(relation).toBeDefined();
466
- expect(relation?.tags?.["type"]).toBe("multipolygon");
467
- expect(relation?.tags?.["building"]).toBe("yes");
468
- expect(relation?.members).toHaveLength(2);
469
- expect(relation?.members[0]?.type).toBe("way");
470
- expect(relation?.members[0]?.ref).toBe(-1);
471
- expect(relation?.members[0]?.role).toBe("outer");
472
- expect(relation?.members[1]?.type).toBe("way");
473
- expect(relation?.members[1]?.ref).toBe(-2);
474
- expect(relation?.members[1]?.role).toBe("inner");
475
- });
476
- it("should convert MultiPolygon features to relation with multiple Ways", async () => {
477
- const geojson = {
478
- type: "FeatureCollection",
479
- features: [
480
- {
481
- type: "Feature",
482
- geometry: {
483
- type: "MultiPolygon",
484
- coordinates: [
485
- // First polygon
486
- [
487
- [
488
- [-122.4194, 37.7749],
489
- [-122.4094, 37.7749],
490
- [-122.4094, 37.7849],
491
- [-122.4194, 37.7849],
492
- [-122.4194, 37.7749],
493
- ],
494
- ],
495
- // Second polygon
496
- [
497
- [
498
- [-122.3994, 37.7649],
499
- [-122.3894, 37.7649],
500
- [-122.3894, 37.7749],
501
- [-122.3994, 37.7749],
502
- [-122.3994, 37.7649],
503
- ],
504
- ],
505
- ],
506
- },
507
- properties: {
508
- landuse: "residential",
509
- },
510
- },
511
- ],
512
- };
513
- const osm = await fromGeoJSON(geojson);
514
- // Should have 2 ways + 1 relation
515
- expect(osm.ways.size).toBe(2);
516
- expect(osm.relations.size).toBe(1);
517
- const way1 = osm.ways.getById(-1);
518
- expect(way1).toBeDefined();
519
- expect(way1?.tags?.["landuse"]).toBeUndefined(); // Tags go on relation
520
- expect(way1?.tags?.["area"]).toBe("yes");
521
- const way2 = osm.ways.getById(-2);
522
- expect(way2).toBeDefined();
523
- expect(way2?.tags?.["landuse"]).toBeUndefined(); // Tags go on relation
524
- expect(way2?.tags?.["area"]).toBe("yes");
525
- const relation = osm.relations.getById(-1);
526
- expect(relation).toBeDefined();
527
- expect(relation?.tags?.["type"]).toBe("multipolygon");
528
- expect(relation?.tags?.["landuse"]).toBe("residential");
529
- expect(relation?.members).toHaveLength(2);
530
- expect(relation?.members[0]?.type).toBe("way");
531
- expect(relation?.members[0]?.ref).toBe(-1);
532
- expect(relation?.members[0]?.role).toBe("outer");
533
- expect(relation?.members[1]?.type).toBe("way");
534
- expect(relation?.members[1]?.ref).toBe(-2);
535
- expect(relation?.members[1]?.role).toBe("outer");
536
- });
537
- it("should convert MultiPolygon with holes to relation with multiple Ways", async () => {
538
- const geojson = {
539
- type: "FeatureCollection",
540
- features: [
541
- {
542
- type: "Feature",
543
- geometry: {
544
- type: "MultiPolygon",
545
- coordinates: [
546
- // First polygon with hole
547
- [
548
- // Outer ring
549
- [
550
- [-122.4194, 37.7749],
551
- [-122.4094, 37.7749],
552
- [-122.4094, 37.7849],
553
- [-122.4194, 37.7849],
554
- [-122.4194, 37.7749],
555
- ],
556
- // Hole
557
- [
558
- [-122.4164, 37.7779],
559
- [-122.4144, 37.7779],
560
- [-122.4144, 37.7799],
561
- [-122.4164, 37.7799],
562
- [-122.4164, 37.7779],
563
- ],
564
- ],
565
- // Second polygon (no holes)
566
- [
567
- [
568
- [-122.3994, 37.7649],
569
- [-122.3894, 37.7649],
570
- [-122.3894, 37.7749],
571
- [-122.3994, 37.7749],
572
- [-122.3994, 37.7649],
573
- ],
574
- ],
575
- ],
576
- },
577
- properties: {
578
- landuse: "residential",
579
- },
580
- },
581
- ],
582
- };
583
- const osm = await fromGeoJSON(geojson);
584
- // Should have 3 ways + 1 relation
585
- expect(osm.ways.size).toBe(3);
586
- expect(osm.relations.size).toBe(1);
587
- const outerWay = osm.ways.getById(-1);
588
- expect(outerWay).toBeDefined();
589
- expect(outerWay?.tags?.["area"]).toBe("yes");
590
- const holeWay = osm.ways.getById(-2);
591
- expect(holeWay).toBeDefined();
592
- expect(holeWay?.tags?.["area"]).toBe("yes");
593
- const secondPolyWay = osm.ways.getById(-3);
594
- expect(secondPolyWay).toBeDefined();
595
- expect(secondPolyWay?.tags?.["area"]).toBe("yes");
596
- const relation = osm.relations.getById(-1);
597
- expect(relation).toBeDefined();
598
- expect(relation?.tags?.["type"]).toBe("multipolygon");
599
- expect(relation?.tags?.["landuse"]).toBe("residential");
600
- expect(relation?.members).toHaveLength(3);
601
- expect(relation?.members[0]?.type).toBe("way");
602
- expect(relation?.members[0]?.ref).toBe(-1);
603
- expect(relation?.members[0]?.role).toBe("outer");
604
- expect(relation?.members[1]?.type).toBe("way");
605
- expect(relation?.members[1]?.ref).toBe(-2);
606
- expect(relation?.members[1]?.role).toBe("inner");
607
- expect(relation?.members[2]?.type).toBe("way");
608
- expect(relation?.members[2]?.ref).toBe(-3);
609
- expect(relation?.members[2]?.role).toBe("outer");
610
- });
611
- it("should error on Polygon with unclosed ring", () => {
612
- const geojson = {
613
- type: "FeatureCollection",
614
- features: [
615
- {
616
- type: "Feature",
617
- geometry: {
618
- type: "Polygon",
619
- coordinates: [
620
- [
621
- [-122.4194, 37.7749],
622
- [-122.4094, 37.7749],
623
- [-122.4094, 37.7849],
624
- [-122.4194, 37.7849],
625
- // Not closed - should throw error
626
- ],
627
- ],
628
- },
629
- properties: {
630
- building: "yes",
631
- },
632
- },
633
- ],
634
- };
635
- expect(() => fromGeoJSON(geojson)).toThrow("Outer ring of Polygon is not closed.");
636
- });
637
- it("should skip invalid Polygons with less than 3 coordinates", async () => {
638
- const geojson = {
639
- type: "FeatureCollection",
640
- features: [
641
- {
642
- type: "Feature",
643
- geometry: {
644
- type: "Polygon",
645
- coordinates: [
646
- [
647
- [-122.4194, 37.7749],
648
- [-122.4094, 37.7749],
649
- // Only 2 coordinates - invalid
650
- ],
651
- ],
652
- },
653
- properties: {},
654
- },
655
- {
656
- type: "Feature",
657
- geometry: {
658
- type: "Polygon",
659
- coordinates: [
660
- [
661
- [-122.4194, 37.7749],
662
- [-122.4094, 37.7749],
663
- [-122.4094, 37.7849],
664
- [-122.4194, 37.7849],
665
- [-122.4194, 37.7749],
666
- ],
667
- ],
668
- },
669
- properties: {
670
- building: "yes",
671
- },
672
- },
673
- ],
674
- };
675
- const osm = await fromGeoJSON(geojson);
676
- // Should only have one way (the valid one)
677
- expect(osm.ways.size).toBe(1);
678
- expect(osm.ways.getById(-1)?.tags?.["building"]).toBe("yes");
679
- });
680
- it("should normalize winding order using rewind", async () => {
681
- // Create a polygon with clockwise winding (should be normalized to counterclockwise)
682
- const geojson = {
683
- type: "FeatureCollection",
684
- features: [
685
- {
686
- type: "Feature",
687
- geometry: {
688
- type: "Polygon",
689
- coordinates: [
690
- // Clockwise ring (will be normalized by rewind)
691
- [
692
- [-122.4194, 37.7749],
693
- [-122.4194, 37.7849],
694
- [-122.4094, 37.7849],
695
- [-122.4094, 37.7749],
696
- [-122.4194, 37.7749],
697
- ],
698
- ],
699
- },
700
- properties: {
701
- building: "yes",
702
- },
703
- },
704
- ],
705
- };
706
- const osm = await fromGeoJSON(geojson);
707
- // Should still create the way successfully (rewind normalizes winding)
708
- expect(osm.ways.size).toBe(1);
709
- const way = osm.ways.getById(-1);
710
- expect(way).toBeDefined();
711
- expect(way?.tags?.["building"]).toBe("yes");
712
- expect(way?.tags?.["area"]).toBe("yes");
713
- });
714
- it("should error on unclosed hole ring", () => {
715
- const geojson = {
716
- type: "FeatureCollection",
717
- features: [
718
- {
719
- type: "Feature",
720
- geometry: {
721
- type: "Polygon",
722
- coordinates: [
723
- // Outer ring (closed)
724
- [
725
- [-122.4194, 37.7749],
726
- [-122.4094, 37.7749],
727
- [-122.4094, 37.7849],
728
- [-122.4194, 37.7849],
729
- [-122.4194, 37.7749],
730
- ],
731
- // Hole ring (not closed - should throw error)
732
- [
733
- [-122.4164, 37.7779],
734
- [-122.4144, 37.7779],
735
- [-122.4144, 37.7799],
736
- [-122.4164, 37.7799],
737
- // Missing closing coordinate
738
- ],
739
- ],
740
- },
741
- properties: {
742
- building: "yes",
743
- },
744
- },
745
- ],
746
- };
747
- expect(() => fromGeoJSON(geojson)).toThrow("Hole ring of Polygon is not closed.");
748
- });
749
- it("should error on unclosed MultiPolygon ring", () => {
750
- const geojson = {
751
- type: "FeatureCollection",
752
- features: [
753
- {
754
- type: "Feature",
755
- geometry: {
756
- type: "MultiPolygon",
757
- coordinates: [
758
- [
759
- [
760
- [-122.4194, 37.7749],
761
- [-122.4094, 37.7749],
762
- [-122.4094, 37.7849],
763
- [-122.4194, 37.7849],
764
- // Not closed - should throw error
765
- ],
766
- ],
767
- ],
768
- },
769
- properties: {
770
- landuse: "residential",
771
- },
772
- },
773
- ],
774
- };
775
- expect(() => fromGeoJSON(geojson)).toThrow("Outer ring of Polygon is not closed.");
776
- });
777
- });
778
- //# sourceMappingURL=osm-from-geojson.test.js.map