pmtiles-swarm 0.68.0 → 0.68.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/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@
4
4
  ### ✨ Features and improvements
5
5
  - _...Add new stuff here..._
6
6
 
7
+ ### 🐞 Bug fixes
8
+ - _...Add new stuff here..._
9
+
10
+ ## 0.68.1
11
+ ### ✨ Features and improvements
12
+ - **A cutline may have holes in it, which is to say it may be a real boundary.** 0.68.0 refused
13
+ any shape with interior rings, on the reasoning that the even-odd fill would treat a hole as
14
+ solid. It does not — a ray to a point inside a hole crosses the outer ring and then the inner
15
+ one, which is two crossings, which is outside — so the refusal protected against nothing and
16
+ turned away almost every boundary worth clipping to. A country is islands and enclaves and
17
+ lakes; the German cutline this was written for is ninety-three rings.
18
+
19
+ Tested rather than reasoned about, because getting it wrong fills in exactly the ground somebody
20
+ cut out.
21
+
22
+ The documentation now also says how a shapefile becomes a cutline, since that is where every
23
+ real one starts: one `ogr2ogr -t_srs EPSG:4326`, and the filename is the name the recipe uses.
24
+ With a note to simplify — a boundary drawn for surveying carries far more detail than a tile can
25
+ show, and every point of it is a segment to index and test.
26
+
27
+
28
+
7
29
  ### 🐞 Bug fixes
8
30
  - _...Add new stuff here..._
9
31
 
@@ -857,8 +857,38 @@ coordinates inlined in one is neither. A rectangle is small enough to sit in the
857
857
  recipe itself, so `bounds` does.
858
858
 
859
859
  WGS84 on purpose. Web Mercator is arithmetic from there — no projection library,
860
- no dependency, no CRS handling beyond refusing what is not WGS84. Anything else
861
- converts once with the `ogr2ogr` that produced the shapefile in the first place.
860
+ no dependency, no CRS handling beyond refusing what is not WGS84.
861
+
862
+ ### Getting a shapefile in
863
+
864
+ A cutline usually starts life as a shapefile in a projected CRS, because that is
865
+ what `gdalwarp -cutline` wants. One `ogr2ogr` converts it, and it is the same
866
+ tool that produced the shapefile in the first place:
867
+
868
+ ```sh
869
+ ogr2ogr -t_srs EPSG:4326 \
870
+ data/cutlines/germany.geojson \
871
+ datasets/OpenDTM_DE/cutline/germany_cutline_25832.shp
872
+ ```
873
+
874
+ The name of the file is the name the recipe uses, so that one becomes
875
+ `"cutline": "germany"`. Nothing has to restart: cutlines are read when the node
876
+ starts and the console lists whatever is there.
877
+
878
+ **Simplify it.** A national boundary drawn for surveying carries far more detail
879
+ than a tile can show — Germany's is ninety-three rings and sixty-five thousand
880
+ points in its first record alone — and every one of them is a segment to index
881
+ and to test. What matters is being right to about a pixel at the deepest zoom
882
+ served, which at z14 is roughly five metres:
883
+
884
+ ```sh
885
+ ogr2ogr -t_srs EPSG:4326 -simplify 0.0001 out.geojson in.shp
886
+ ```
887
+
888
+ Holes and islands are kept, and want to be: a country is islands and enclaves
889
+ and lakes. Under the even-odd rule an interior ring needs no special handling
890
+ and gets none — a ray to a point inside one crosses the outer ring and then the
891
+ inner ring, which is two crossings, which is outside.
862
892
 
863
893
  Edges are treated as straight lines in Mercator after their endpoints are
864
894
  projected. That is what every rasteriser does, GDAL's included, and the error
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmtiles-swarm",
3
- "version": "0.68.0",
3
+ "version": "0.68.1",
4
4
  "description": "BitTorrent distribution for PMTiles map archives: create torrents, watch folders, publish and subscribe to RSS feeds, and seed through qBittorrent or an embedded client",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/cutline.js CHANGED
@@ -48,9 +48,13 @@ export function worldY(lat) {
48
48
  /**
49
49
  * Reads the rings out of GeoJSON, whatever shape it arrived in.
50
50
  *
51
- * Only the outer rings are kept. A hole is a real thing and this does not
52
- * pretend to handle one -- the even-odd rule below would treat it as solid --
53
- * so a cutline with holes is refused rather than silently filled in.
51
+ * Every ring, interior ones included. Under the even-odd rule a hole needs no
52
+ * special handling and gets none: a ray to a point inside one crosses the outer
53
+ * ring and then the inner ring, which is two crossings, which is outside. An
54
+ * earlier version of this refused shapes with holes on the assumption that they
55
+ * would be filled in. They are not, and refusing them would have turned away
56
+ * almost every real boundary -- a country is islands and enclaves and lakes,
57
+ * and Germany's is ninety-three rings.
54
58
  * @param {object} geojson - A Feature, FeatureCollection, or bare geometry.
55
59
  * @returns {number[][][]} - Rings of `[lon, lat]`.
56
60
  */
@@ -58,13 +62,9 @@ export function ringsOf(geojson) {
58
62
  const rings = [];
59
63
 
60
64
  const fromPolygon = (coordinates) => {
61
- if (coordinates.length > 1) {
62
- throw new Error(
63
- 'this cutline has interior rings, and clipping to a shape with holes ' +
64
- 'is not something this does',
65
- );
65
+ for (const ring of coordinates) {
66
+ if (ring?.length >= 4) rings.push(ring);
66
67
  }
67
- if (coordinates[0]?.length >= 4) rings.push(coordinates[0]);
68
68
  };
69
69
 
70
70
  const walk = (node) => {