Compare commits

..

278 Commits

Author SHA1 Message Date
370252731a Print details of the feature when Wagyu throws an exception 2019-05-28 18:22:28 -07:00
b550c7b4a6 Merge pull request #760 from mapbox/preserve-shared-nodes
Add an option to keep intersection nodes from being simplified away
2019-05-16 10:38:56 -07:00
dcdfb94ba9 Bump version number for --no-simplification-of-shared-nodes 2019-05-16 10:13:43 -07:00
42ee195bc3 Add an option to keep intersection nodes from being simplified away 2019-05-13 17:39:07 -07:00
9dc92a452a Merge pull request #757 from mapbox/map-scale
Add map scale to table of zoom level equivalences
2019-05-09 16:48:20 -07:00
1b14034cb5 Add map scale to table of zoom level equivalences 2019-05-08 13:47:53 -07:00
363d21bfc1 Merge pull request #748 from mapbox/high-longitude
Be more consistent about when longitudes beyond 180 are allowed
2019-04-12 12:45:56 -07:00
4d3e30773f Be more consistent about when longitudes beyond 180 are allowed 2019-04-12 12:12:14 -07:00
b147ff22b1 Merge pull request #735 from mapbox/raw-tiles-zoom-enumerate
Fix -Z and -z for tile directories in tile-join and tippecanoe-decode
2019-04-08 17:03:06 -07:00
7be3710b40 Rebuild documentation 2019-04-08 16:33:11 -07:00
fcab1da952 Merge branch 'master' into raw-tiles-zoom-enumerate 2019-04-08 16:33:03 -07:00
a8a183df2d Update changelog and version 2019-04-08 16:32:39 -07:00
9d06af968a Merge pull request #730 from andrewharvey/patch-4
Update README.md to include ndjson-cli suggestion
2019-04-08 16:32:08 -07:00
ffab876002 Don't run shell filters if the current zoom is below the minzoom 2019-04-08 16:30:19 -07:00
99dc019d92 Fix tests after merge 2019-04-08 16:29:56 -07:00
e89bdecb6d Merge branch 'master' into raw-tiles-zoom-enumerate 2019-04-08 16:28:12 -07:00
18b6473cdb Merge pull request #744 from mapbox/track-flags
Record the command line options in the tileset metadata
2019-04-05 13:45:55 -07:00
382563a5b1 Sort wildcards in Makefile to provide test stability 2019-04-05 13:15:46 -07:00
26a07b2167 Forgot to update this test standard 2019-04-05 12:05:03 -07:00
f95b9bcc65 Use single-quote quoting instead of backslash quoting 2019-04-05 11:30:57 -07:00
4f7459c797 Record the command line options in the tileset metadata 2019-04-04 17:03:36 -07:00
e051c53051 Fix duplicated error message for unknown option 2019-03-19 10:16:14 -07:00
ac12932089 Return a successful error status for --help and --version 2019-03-19 10:13:44 -07:00
7419d64aab Suggest https instead of ssh for "git clone"
to avoid the need for authentication
2019-03-19 10:06:46 -07:00
25b9c51ac8 Fix -Z and -z for tile directories in tile-join and tippecanoe-decode 2019-03-18 18:01:32 -07:00
0704ec9882 Update README.md to include ndjson-cli suggestion
Most software in the ecosystem is unable to write arbitrary data to the tippecanoe object, so it might be helpful to show how users can make these GeoJSON extensions work. #685
2019-03-11 16:40:59 +11:00
945d80400b Merge pull request #725 from mapbox/geobuf-multilinestring
Fix reading of MultiLineStrings in Geobuf input
2019-03-01 16:22:00 -08:00
1bc475b789 Fix reading of MultiLineStrings in Geobuf input 2019-03-01 15:52:24 -08:00
907ddeb7ba Merge pull request #718 from mapbox/decode-mvt
Make tile-join and tippecanoe-decode more flexible about directories
2019-02-20 14:08:22 -08:00
90afdf8fb2 Merge branch 'master' into decode-mvt 2019-02-20 12:06:06 -08:00
8df0455230 Make tile-join and tippecanoe-decode more flexible about directories:
* Accept .mvt as well as .pbf in directories of tiles
* Allow tippecanoe-decode and tile-join of directories with no metadata
2019-02-20 12:04:10 -08:00
454f75ef91 Merge pull request #716 from mapbox/keep-id-attribute
Don't exclude the attribute that is specified to be the feature ID
2019-02-14 12:40:22 -08:00
435a788c3f Don't exclude the attribute that is specified to be the feature ID 2019-02-14 11:40:58 -08:00
9387fe6546 Current behavior if the ID attribute is also excluded 2019-02-14 10:48:22 -08:00
b1ae63ab86 Merge pull request #707 from mapbox/unused-filter
Remove now-unused filter argument during parsing
2019-02-14 10:43:11 -08:00
451175dd35 Merge pull request #715 from mapbox/multiple-include
Clarify use of multiple -x or -y options
2019-02-14 10:42:43 -08:00
8c2df5f7b4 Clarify use of multiple -x or -y options 2019-02-13 16:45:11 -08:00
87bdaa1a25 Merge pull request #711 from andrewharvey/patch-3
update broken links in README.md
2019-02-04 10:06:00 -08:00
185f7d752e update broken links in README.md 2019-02-03 21:31:16 +11:00
e805d113d0 Remove now-unused filter argument during parsing 2019-01-22 14:26:06 -08:00
610afc2332 Merge pull request #702 from mapbox/minzoom-0
Fix a bug that disallowed a per-feature minzoom of 0
2019-01-16 13:08:54 -08:00
6da2090960 Fix a bug that disallowed a per-feature minzoom of 0 2019-01-16 11:56:25 -08:00
454ae96242 Merge pull request #697 from wsw0108/typo
fix some typo
2019-01-02 10:16:06 -08:00
2eb7f5dfae read_json.cpp: fix semantic typo 2018-12-25 20:04:41 +08:00
b746688018 serial.cpp: fix shift-op typo 2018-12-25 20:03:57 +08:00
5421dbf8f9 Merge pull request #695 from mapbox/cookbook-replace-features
Add cookbook example for adding and removing features with tile-join
2018-12-20 15:31:34 -08:00
0505e0e7d5 Add cookbook example for adding and removing features with tile-join 2018-12-20 15:06:44 -08:00
255f795c91 Merge pull request #691 from mapbox/detail-limit
Limit detail to 30 and buffer 127 to prevent coordinate delta overflow
2018-12-18 17:31:51 -08:00
32b14b1269 Limit detail to 30 and buffer 127 to prevent coordinate delta overflow 2018-12-18 15:53:11 -08:00
b31b0b04b6 Merge pull request #684 from mapbox/metadata-exists
Better error message if the output tileset already exists
2018-12-13 15:07:31 -08:00
28f773a933 Better error message if the output tileset already exists 2018-12-13 11:20:06 -08:00
45fbdf43c5 Merge pull request #683 from mapbox/coalesce-points
Point features may now be coalesced into MultiPoint features with --coalesce
2018-12-12 16:58:30 -08:00
6376c283ba Add Hilbert Curve feature sequencing as an option 2018-12-12 10:51:00 -08:00
5f1c0e151f Add a table of zoom level precisions to the documentation 2018-12-11 17:52:51 -08:00
ca4aad0c64 Point features may now be coalesced into MultiPoint features with --coalesce 2018-12-11 17:09:13 -08:00
4b20948369 Merge pull request #681 from Plantain/master
Update coalesce-smallest-as-needed documentation
2018-12-04 12:49:23 -08:00
3eea8b0e4b Update coalesce-smallest-as-needed documentation 2018-12-04 22:19:50 +02:00
9c708aa3c4 Merge pull request #676 from mapbox/empty-coordinate
Make it an error, not a warning, to have missing coordinates for a point
2018-11-26 15:34:11 -08:00
cf28e6b88b Make it an error, not a warning, to have missing coordinates for a point 2018-11-26 14:50:45 -08:00
506526ddfa Merge pull request #657 from mapbox/drop-features-earlier
Drop LineStrings and Polygons early in tiling if they are smaller than a pixel
2018-11-26 10:57:30 -08:00
4fec7a162e Reduce coordinate precision so GeoJSON and geobuf have the same results 2018-11-26 10:22:05 -08:00
5229990523 Fix gridding of small squares; use less memory for small features 2018-11-21 15:34:43 -08:00
739445cb6c Merge pull request #665 from mapbox/coerce-id-leading-zero
Ignore leading zeroes when converting string attributes to feature IDs
2018-11-07 16:31:35 -08:00
f9c9ff3853 Ignore leading zeroes when converting string attributes to feature IDs 2018-11-07 15:46:44 -08:00
949468e6f5 Merge pull request #658 from mapbox/coerce-feature-ids
Add an option to convert stringified number feature IDs to numbers
2018-11-07 14:45:08 -08:00
a3150642d3 Merge pull request #663 from jingsam/ignore
chore: ignore geobuf tests files and node_modules
2018-11-07 10:36:04 -08:00
752f77d58e chore: ignore geobuf tests files and node_modules 2018-11-07 14:49:51 +08:00
cc7c0cc6c9 Don't test string ID conversion with geobuf, because it fails 2018-11-02 15:28:51 -07:00
bd2423a5ea Add an option to use a specified feature attribute as the feature ID 2018-11-02 15:21:52 -07:00
53de8a2014 Add an option to convert stringified number feature IDs to numbers 2018-11-01 17:07:33 -07:00
b8ffdda32e Merge pull request #656 from mapbox/tile-join-maxzoom
Warn in tile-join if tilesets being joined have different maxzooms
2018-10-31 16:09:11 -07:00
9c79cf7162 Warn in tile-join if tilesets being joined have different maxzooms 2018-10-31 14:25:25 -07:00
d3ae48534e Merge pull request #650 from mapbox/filter-crash
Fix null pointer crash/add bounding box option
2018-10-23 11:59:28 -07:00
1cf3b0accc Fix the feature bounding box after clipping 2018-10-23 10:55:07 -07:00
5dfbc4a281 Add --clip-bounding-box option to clip input geometry 2018-10-22 16:49:33 -07:00
0acdeef525 Fix null pointer crash when looking for feature extent in filter output 2018-10-22 13:26:53 -07:00
e18748e29b Merge pull request #647 from mapbox/attribute-compare
Bug fix: mismatched features could be coalesced if from a prefilter
2018-10-10 15:12:38 -07:00
1b75ca33b4 Bug fix: mismatched features could be coalesced if from a prefilter 2018-10-10 14:35:46 -07:00
b7fb576544 Merge pull request #645 from mapbox/empty-tileset-dir
Create the output tile directory even if there are no valid features
2018-09-24 13:52:31 -07:00
b2999fe9a8 Create the output tile directory even if there are no valid features 2018-09-24 11:16:13 -07:00
03199a77a5 Merge pull request #642 from mapbox/maxzoom-minzoom
Issue an error message in tile-join if minzoom is greater than maxzoom
2018-09-07 12:07:47 -07:00
7aebce7e0e Issue an error message in tile-join if minzoom is greater than maxzoom 2018-09-07 10:08:02 -07:00
9949d7ed1a Merge pull request #639 from mapbox/tile-stats-limits
Add options to change the tilestats limits
2018-08-31 17:50:42 -07:00
2530efd525 Used the tilestats sample values limit instead of the attributes limit 2018-08-31 16:52:38 -07:00
216c0cf428 Be consistent about pluralization in the tilestats options 2018-08-31 16:19:55 -07:00
bc84b41246 Add options to change the tilestats limits 2018-08-31 15:12:00 -07:00
5483720ee1 Merge pull request #635 from jingsam/ignore-check-files
chore: ignore generated check and mbtiles files in tests
2018-08-23 10:34:38 -07:00
5d6e6e07d6 chore: ignore generated check and mbtiles files in tests 2018-08-23 14:16:50 +08:00
15df8e8431 Merge pull request #633 from mapbox/tile-join-name-len
Keep tile-join from generating a tileset name longer than 255 chars
2018-08-21 10:01:58 -07:00
addbd0a854 Keep tile-join from generating a tileset name longer than 255 chars 2018-08-20 17:45:18 -07:00
de40169f16 Merge pull request #631 from mapbox/filename-warning
Fix missing filename in warning messages
2018-08-16 14:20:38 -07:00
0a3e4ad561 Fix missing filename in warning messages 2018-08-16 13:46:37 -07:00
1ef2005f04 Merge pull request #623 from mapbox/cookbook
Add a cookbook section to the README
2018-08-16 12:08:37 -07:00
f0517d090b Merge pull request #627 from mapbox/geojson-loop
Factor out the GeoJSON parsing loop from feature serialization
2018-08-08 15:14:14 -07:00
19c132e79c Be more cautious about use of a null feature for bare geometries 2018-08-08 14:17:08 -07:00
98cf4d94aa Don't accept features or geometries inside another object's properties 2018-08-08 13:42:49 -07:00
ba8966a4ae Use the same GeoJSON parsing loop in tippecanoe-json-tool 2018-08-08 13:11:25 -07:00
79363e397b Factor out the GeoJSON parsing loop from feature serialization 2018-08-08 13:11:10 -07:00
2e80377b24 Merge pull request #626 from mapbox/tile-join-remove-attrs
Add --exclude-all to tile-join
2018-08-07 11:12:57 -07:00
8d67e460d4 Add --exclude-all to tile-join 2018-08-07 10:27:38 -07:00
5c881c11ef Merge pull request #620 from mapbox/wagyu-initializer
Upgrade to Wagyu 0.4.3
2018-08-06 13:30:24 -07:00
baab0cef55 Increment version number 2018-08-06 12:25:22 -07:00
60629da37a Merge branch 'master' into wagyu-initializer 2018-08-06 10:15:20 -07:00
7221c7ba0d Merge pull request #624 from mapbox/trim-csv
Add "csv" to the list of suffixes to trim off of layer names
2018-08-02 10:05:19 -07:00
c9cc12e7ff Add "csv" to the list of suffixes to trim off of layer names 2018-08-01 17:49:54 -07:00
4958c47abc Merge pull request #607 from mapbox/catch-all-exceptions-in-decode
decode: catch all exceptions
2018-08-01 16:31:59 -07:00
18e8bea18d Add a point visualization example. Always make -z the first option. 2018-08-01 15:21:58 -07:00
510df9e28f Add a cookbook section to the README 2018-08-01 14:52:30 -07:00
bec1f41a4f Merge pull request #622 from mapbox/cluster-maxzoom
Take cluster distance into account when guessing a maxzoom
2018-08-01 13:54:47 -07:00
3fb833979e Take cluster distance into account when guessing a maxzoom 2018-08-01 13:14:14 -07:00
c4cd7faaaa Workaround to make it compile on g++-4.8.4 2018-08-01 10:21:32 -07:00
e9eca57393 Upgrade to Wagyu 0.4.3 2018-07-31 17:47:52 -07:00
796fa19729 Add missing initializer
Fixes https://github.com/mapbox/tippecanoe/issues/602
2018-07-31 16:54:42 -07:00
28ebec275a Merge pull request #616 from mapbox/antimeridian
Duplicate features within the buffer of the antimeridian on both sides
2018-07-30 15:06:11 -07:00
759bceb986 Duplicate features within the buffer of the antimeridian on both sides 2018-07-27 16:14:49 -07:00
faa952ec7d Merge pull request #615 from mapbox/generate-ids
Add an option to automatically assign ids to features
2018-07-26 16:17:08 -07:00
6f295f29fc Add an option to automatically assign ids to features 2018-07-26 15:08:47 -07:00
50b1eadf87 Merge pull request #612 from mapbox/negative-shift
Don't guess a higher maxzoom than is allowed for manual selection
2018-07-25 11:59:36 -07:00
856c055857 Don't guess a higher maxzoom than is allowed for manual selection
If maxzoom + detail > 32, some geometric operations are undefined
2018-07-25 11:18:40 -07:00
206c75f0ab Merge pull request #604 from mapbox/per-feature-zoom-check
Require that per-feature maxzoom and minzoom be small integers
2018-07-19 15:25:05 -07:00
87a1bb7851 Add an option to treat empty CSV columns as nulls, not empty strings 2018-07-19 14:33:33 -07:00
3cb09d0e2a Add the ability to specify the file format with -L{"format":"…"} 2018-07-17 14:57:56 -07:00
6683939483 catch all exceptions 2018-07-13 18:27:24 -07:00
07ab900393 Report decompression errors in tippecanoe-decode 2018-07-13 17:02:49 -07:00
d1a0e495ce Require that per-feature maxzoom and minzoom be small integers
Also fixes a place in the Makefile that accidentally still used
CFLAGS instead of CXXFLAGS
2018-07-12 11:24:30 -07:00
d64ac19f11 Merge pull request #591 from mapbox/attribute-filter
Add a filter extension to allow filtering individual attributes
2018-06-20 00:10:28 +02:00
c2bb35e6ff Bump version number 2018-06-19 14:15:27 -07:00
262fbf26f0 Fix missing null pointer check 2018-06-19 13:10:58 -07:00
9dac499ab4 Consistently refer to attributes, not properties
Except when referring to their representation in GeoJSON
2018-06-18 14:34:10 -07:00
8d6bd4e10f Add a filter extension to allow filtering individual attributes 2018-06-18 11:26:22 -07:00
54983c7536 Merge pull request #588 from mapbox/less-codecov
Don't complain about coverage of the diff itself
2018-06-08 23:58:43 +02:00
4d8a3c6bdc Don't complain about coverage of the diff itself 2018-06-08 14:24:18 -07:00
bc3d4c6a34 Merge pull request #587 from mapbox/tag-version
Include a generator field in tileset metadata with the Tippecanoe version
2018-06-08 19:10:12 +02:00
7f90ba5e1b Include version number in tile-join output too 2018-06-07 21:37:25 -07:00
4da6b932b3 Use "generator" instead of "creator". Silence another status message. 2018-06-07 15:17:58 -07:00
b0229530ac Turn off progress indicators during tests
(For the sake of Travis's 4MB log limit)

Also fix a few places that logged progress even when told not to.
2018-06-07 13:27:49 -07:00
11c6c869aa Include a creator field in tileset metadata with the Tippecanoe version
Also finally eradicates binary diffs from the tests
2018-06-07 11:20:12 -07:00
9f1913bc37 Merge pull request #585 from mapbox/nulls-from-filter
Be careful not to allow null attributes from prefilter/postfilter output to make it into tiles
2018-06-06 12:57:03 -07:00
760a0c9209 Add missing JSON type check; bump version number. 2018-06-06 11:54:23 -07:00
c9eed0d457 Be careful to remove null attributes from prefilter/postfilter output 2018-06-06 11:48:57 -07:00
2318673108 Be more systematic about nulls and undefined attribute values
It is an error to write a null attribute to a tile, but
null attributes found within existing tiles will be decoded
into JSON as null.
2018-06-06 11:48:01 -07:00
6e231f5911 Merge pull request #581 from mapbox/force-polygon-winding
Add --use-source-polygon-winding and --reverse-source-polygon-winding
2018-06-01 23:19:43 +02:00
c650329eb2 Use a complete feature in the winding test instead of a bare geometry 2018-06-01 13:33:58 -07:00
48486b5d7b Add --use-source-polygon-winding and --reverse-source-polygon-winding 2018-06-01 12:59:28 -07:00
38bca4a179 Merge pull request #574 from mapbox/layer-description
Add the option to specify layer file, name, and description as JSON
2018-05-25 01:49:06 +02:00
48f7f1dd38 Preserve layer and attribute descriptions across tile-join 2018-05-24 16:01:57 -07:00
bb8b01a702 Add option to specify description for attributes in tileset metadata 2018-05-24 14:18:22 -07:00
54532795f6 Trailing commas in CSVs are now treated as empty fields.
Empty fields are now treated as empty strings rather than nulls
in tippecanoe-json-tool, for consistency with tile-join.
2018-05-24 13:54:00 -07:00
32b3a15406 Add test for JSON specification of layer file, name, and description 2018-05-24 12:41:14 -07:00
53731709b2 Add the option to specify layer file, name, and description as JSON 2018-05-24 11:30:42 -07:00
7128ac44d5 Track layer description as part of the tilestats 2018-05-24 10:27:43 -07:00
b65a5d1bb8 Merge pull request #571 from mapbox/atomic-decode
Thread safety fix for decoding quadkeys to coordinates
2018-05-23 01:39:39 +02:00
02cb3a3fb8 Thread safety fix for decoding quadkeys to coordinates 2018-05-18 14:45:03 -07:00
5494b7da3d Merge pull request #570 from mapbox/nan-coordinates
Explicitly check for infinite and not-a-number input coordinates
2018-05-17 00:01:43 +02:00
dc3aa2ddfa Test CSV geometry with invalid coordinates 2018-05-16 14:29:28 -07:00
a4825f6af4 Explicitly check for infinite and not-a-number input coordinates 2018-05-15 12:55:17 -07:00
3f7ba2915a Merge pull request #569 from mapbox/tile-join-vasprintf
Add #define needed for Cygwin
2018-05-15 21:01:55 +02:00
445c33fb88 Add #define needed for Cygwin 2018-05-14 17:43:42 -07:00
6db02e8457 Merge pull request #568 from mapbox/gzip-input
Directly support gzipped GeoJSON files as input
2018-05-15 00:08:51 +02:00
73398a0484 Use the FILE-like abstraction that zlib already provides 2018-05-14 12:40:38 -07:00
0244f04b71 Detect if the compressed input runs out before the stream is complete 2018-05-14 11:35:29 -07:00
d0d953f4a2 Use a loop instead of spelling out .json and .json.gz separately 2018-05-14 10:46:45 -07:00
09565b4632 Fix arithmetic overflows 2018-05-11 17:29:29 -07:00
974bfb3543 Add missing initializer in can't-be-compressed case 2018-05-11 17:13:06 -07:00
450a8a741f Fix reference to uncompressed version of test file that I compressed 2018-05-11 16:49:09 -07:00
dbd69142b0 Test and documentation 2018-05-11 16:34:18 -07:00
14b618adc9 Make stream lookahead work; simplify the interface 2018-05-11 16:02:53 -07:00
9f7dc4b46d Use zlib to decompress gzipped input 2018-05-11 15:51:53 -07:00
72b8142388 JSON-reading glue to use the stream abstraction 2018-05-11 14:58:29 -07:00
33b0d5c15c Start an abstraction layer for input streams 2018-05-11 14:44:10 -07:00
8e8b74b0ce Merge pull request #567 from mapbox/checkdisk-race
Make file positions and lengths thread-safe
2018-05-07 16:31:25 -07:00
f070c7464b Add missing #include 2018-05-07 15:10:18 -07:00
59dd095607 Make file positions and lengths thread-safe 2018-05-07 14:42:49 -07:00
2cf0524037 Merge pull request #566 from mapbox/extend-zooms-with-feature-limit
Also take note of --force-feature-limit if extending zooms
2018-05-04 22:31:20 +02:00
8ba884530a Also take note of --force-feature-limit if extending zooms 2018-05-04 12:43:27 -07:00
43312fd83e Merge pull request #565 from mapbox/gnusource
Add #define to fix the build on Cygwin
2018-05-04 20:42:19 +02:00
b8cfab1eaf Add #define to fix the build on Cygwin 2018-05-04 10:37:27 -07:00
af69c85d23 Merge pull request #561 from mapbox/exit-status
Use an exit status of 100 if some but not all zoom levels succeeded
2018-04-20 10:44:13 +03:00
a383f5c725 Use an exit status of 100 if some but not all zoom levels succeeded 2018-04-18 20:48:13 +03:00
066934a666 Merge pull request #553 from mapbox/zoom-filter
Allow filtering features by zoom level in conditional expressions
2018-04-09 09:24:25 -07:00
cb4630452b Include another already-merged PR in changelog 2018-04-09 08:33:14 -07:00
7006272b75 Merge pull request #555 from andrewharvey/csv-null-geometry
Skip csv lines with no geometry as is done for geojson
2018-04-09 08:27:05 -07:00
767763c855 Merge pull request #556 from jingsam/ignore-tippecanoe-json-tool
Ignore tippecanoe-json-tool
2018-04-09 08:26:08 -07:00
cc6a97f112 Ignore tippecanoe-json-tool 2018-04-08 17:19:19 +08:00
0d6112cf20 include empty geometry test for csv 2018-04-07 08:05:45 +10:00
970af8109e skip csv lines with no geometry as is done for geojson 2018-04-06 10:56:51 +10:00
1b26becad9 Clear up some confusion about attribute count and external references
Now the count is always adjacent to whereever the key/value pair is
stored, and is not kept in the serial feature object other than as
the length of the vectors of keys and values.
2018-04-05 15:40:14 -07:00
d01d8177a0 Allow filtering features by zoom level in conditional expressions
This moves filtering from the serialization stage to the
tiling stage so that the zoom level can be known to the filter.

The side effect is to carry null attributes much further through
the pipeline than previously.
2018-04-05 14:15:19 -07:00
6b29966e4a Merge pull request #548 from mapbox/integrity-check
Check integrity of sqlite3 file before decoding or tile-joining
2018-03-29 13:03:25 -07:00
7f843c4d36 Check integrity of sqlite3 file before decoding or tile-joining 2018-03-29 12:02:59 -07:00
0304d164d8 Merge pull request #545 from mapbox/install-ubuntu
Instruction on installing on Ubuntu
2018-03-29 09:11:20 -07:00
d5b0da3ae0 Add link to Development section for compiler and prerequisite info 2018-03-28 12:25:48 -07:00
a45fec573d install on Ubuntu 2018-03-28 15:41:51 +05:30
3cea1257a5 Merge pull request #542 from mapbox/coverage
Trying to fix code coverage
2018-03-21 14:21:15 -07:00
8ff6e73b6d Add codecov badge 2018-03-21 11:48:37 -07:00
cc2cae144e Add yml file for code coverage 2018-03-19 16:27:56 -07:00
239a798bfe Try codecov for code coverage 2018-03-19 16:05:14 -07:00
db2c7dbe62 Update list of directories to exclude from code coverage 2018-03-19 15:54:04 -07:00
a1d002ccb1 Merge pull request #541 from mapbox/fix-decode-tile
Always include tile and layer in tippecanoe-decode, fixing corrupt JSON.
2018-03-19 11:18:03 -07:00
e21e4d3b88 Forgot the indentation change in this test 2018-03-16 17:06:54 -07:00
3d1ebdb82f Add missing #include 2018-03-16 16:26:19 -07:00
3c827b1d68 Use the standard JSON writer when writing metadata.json 2018-03-16 15:35:26 -07:00
ebb0334ef0 Use the standard JSON writer for tilestats
With a lot of weird special cases to keep the formatting
exactly like it accidentally was before
2018-03-16 15:19:23 -07:00
08fc2f281e JSON can be written to either a FILE or a string 2018-03-16 14:20:52 -07:00
1c4aa57ffd Change the JSON writing functions to object methods 2018-03-16 13:43:21 -07:00
623e0c90fe More regularization of JSON writing 2018-03-15 17:07:26 -07:00
ddf4a45b33 Use JSON writer functions for tile size stats 2018-03-15 15:19:52 -07:00
605ccbe077 Helper functions so I will stop writing JSON by hand 2018-03-15 14:42:53 -07:00
35aa291aac Restore accidentally deleted test 2018-03-15 12:35:59 -07:00
71df4d3e81 Always include tile and layer in tippecanoe-decode, fixing corrupt JSON. 2018-03-14 16:35:59 -07:00
e690a1b585 Merge pull request #540 from mapbox/progress-frequency
Add --progress-interval setting to reduce progress indicator frequency
2018-03-14 14:47:01 -07:00
fac0ebbf52 All the other places where I used volatile but really wanted atomic 2018-03-13 15:21:21 -07:00
f1eede1106 Track the last progress update with an atomic type, not volatile 2018-03-13 15:04:28 -07:00
834c05038c Add --progress-interval setting to reduce progress indicator frequency 2018-03-13 14:51:48 -07:00
ca91cec923 Merge pull request #537 from mapbox/adjust-cluster
Make clusters look better by averaging locations of clustered points
2018-03-02 11:15:07 -08:00
2b936af96a Fix indentation 2018-03-02 10:35:58 -08:00
18e345efb0 Make clusters look better by averaging locations of clustered points 2018-03-01 16:53:59 -08:00
61cbc3eca0 Merge pull request #536 from mapbox/accumulate-attribute
Accumulate specified attributes when features are dropped, clustered, or coalesced
2018-02-28 16:25:11 -08:00
10a1bc8580 Fix use of references into the wrong string pool after parallel input 2018-02-28 13:09:55 -08:00
a2dfaf85d0 Some basic tests for feature attribute accumulation 2018-02-27 17:49:48 -08:00
bfb6778e07 Add feature density tilestats during tiling instead of as a special case 2018-02-27 17:04:15 -08:00
d66d05213f Add the mean as an option for accumulating attributes 2018-02-27 16:12:29 -08:00
f87b71b739 Check the layer before letting a feature be coalsced/clustered/dropped 2018-02-27 15:45:09 -08:00
ebe10a27d7 Add documentation 2018-02-27 14:45:46 -08:00
c604a51039 Don't coalesce features whose non-string-pool attributes don't match
Fortunately most attributes are in the string pool, but ones that
have passed through the prefilter are not. (Nor are attributes that
are generated by clustering or by attribute accumulation.)
2018-02-27 13:38:37 -08:00
e939a85251 Make sure numeric command line arguments are actually numbers 2018-02-26 17:35:39 -08:00
45b1a1d9e0 Sum, product, concat, and comma operations work now 2018-02-26 16:47:15 -08:00
06ed9d14d8 Add an attribute for square root of cluster count 2018-02-26 12:53:43 -08:00
e4e39289a2 Fix the raw-tiles test and make it a little less fragile 2018-02-26 11:32:18 -08:00
a8a342f701 Send dot-dropping through the same pipeline.
The first feature in a tile can never be dropped, since there is
no previous feature to attach its properties to.

Remove the previous special case that reset the dropping counter
at the first feature within each tile proper (as opposed to the
first feature in each tile, including its buffer, which is now
the one that is guaranteed to be preserved).
2018-02-23 17:19:54 -08:00
7fe0c87806 Get attribute accmulation by concatenation working 2018-02-23 16:16:11 -08:00
27154c8f06 Cluster onto the previous feature instead of onto the next
This also allows doing the attribute and tilestats all at once
at the end of the tile instead of having to update a feature
to handle the last cluster.
2018-02-23 12:26:58 -08:00
30a277a43e Always keep the first feature so there is something to coalesce onto 2018-02-22 17:25:54 -08:00
79df57f2c3 Merge pull request #535 from mapbox/logo-image
Add logo image
2018-02-22 15:07:44 -08:00
3235955807 Add logo image 2018-02-22 14:58:51 -08:00
bc0edec753 Call a function that will eventually preserve the attributes 2018-02-20 17:24:15 -08:00
b73e710855 Add --accumulate-attribute flag and pass the result to tiling 2018-02-20 16:19:49 -08:00
03577cf967 Merge pull request #529 from mapbox/files-left-open
Close input files that were being left open after parallel reading
2018-02-12 15:53:32 -05:00
2d625d5807 Pass through any non-ASCII characters from file names into layer names
The Docker build doesn't include proper locale support
2018-02-07 13:15:36 -08:00
2b7d64736f Set locale before running tests in Docker 2018-02-06 17:58:24 -08:00
17942b3a89 Add an option to produce only a single tile 2018-02-06 17:25:58 -08:00
7ab94d43c6 Preserve non-ASCII characters when making layernames from filenames 2018-02-06 17:22:26 -08:00
8726366a4c Remember to close the input file after CSV parsing too 2018-02-06 16:23:44 -08:00
2e5b597ca1 Add --coalesce-fraction-as-needed and --coalesce-densest-as-needed 2018-02-06 14:39:05 -08:00
8fa5a5ff87 Report distances in both feet and meters 2018-02-06 12:15:24 -08:00
8e7b22cf1b Close input files that were being left open after parallel reading 2018-02-06 12:02:23 -08:00
e2a34929d1 Merge pull request #522 from carimatics/master
Fix Release file not found error when execute docker build command.
2018-01-31 07:13:57 -08:00
042fa77357 Fix Release file not found error when execute docker build command. 2018-01-30 23:49:34 +09:00
21b9b1993f Merge pull request #515 from mapbox/vector-bounds
Fix out-of-bounds error when no threads were needed for a zoom level
2018-01-19 10:27:20 -08:00
d49606babf Fix opportunities for integer overflow 2018-01-18 12:37:15 -08:00
e07a4dd51b Fix out-of-bounds error when no threads were needed for a zoom level 2018-01-18 12:12:35 -08:00
eb966ae398 Merge pull request #511 from mapbox/cluster
Add an option for clustering features
2017-12-21 09:55:20 -08:00
aaf08a6c55 Add an option to specify the clustering distance directly 2017-12-20 17:33:30 -08:00
fc32a0e897 Add a test for the case that was getting stuck in a loop 2017-12-19 12:46:13 -08:00
01884a3bf6 Make sure the feature gap always increases when trying to reduce density 2017-12-19 12:09:30 -08:00
6524b6510e Credit dangling clustered count at the end of a tile to the last feature 2017-12-18 12:55:22 -08:00
b03dabe098 Add an option for clustering features 2017-12-14 14:30:08 -08:00
5687ee041f Merge pull request #503 from mapbox/geocsv
Add input support for CSV file format
2017-12-14 10:11:07 -08:00
be79d13cbc Add missing #include 2017-12-13 14:52:46 -08:00
2e32004589 Don't coalesce features that have different IDs.
Remove the 700-point limit on coalesced features, since
polygon merging is no longer a performance problem.
2017-12-13 12:05:53 -08:00
82a2b5dfdc Add CSV test and documentation 2017-12-13 11:32:19 -08:00
ed0b69a3c8 Fix check for non-numeric CSV data. Use same column name code as mapnik 2017-12-07 11:28:39 -08:00
ec475b3beb Check for strings vs numbers in CSV attributes 2017-12-06 15:20:01 -08:00
afb5cece96 Verify that CSV input is encoded as UTF-8 2017-12-06 13:32:44 -08:00
f3e6afa4e9 Basic geographic CSV parsing 2017-12-05 17:18:19 -08:00
f2f76082df Merge pull request #501 from mapbox/refactor-dirtiles
Clean up duplicated code for reading tiles from a directory
2017-12-01 14:35:03 -08:00
e4743d9527 Test successful and failed attempts to write to existing tilesets 2017-11-30 15:56:35 -08:00
d7f44ab082 Factor out code for reading metadata.json 2017-11-30 15:49:38 -08:00
1acd771743 Factor out code for enumerating the tiles in a directory 2017-11-30 15:37:46 -08:00
ad86d06cce Merge pull request #500 from mapbox/allow-existing-test
Make --allow-existing work on dirs; trim .geojson from layer names
2017-11-30 11:15:38 -08:00
1b1be9f872 Also trim .geobuf from layer names 2017-11-29 16:44:55 -08:00
ba1c343204 Make --allow-existing work on dirs; trim .geojson from layer names 2017-11-29 16:24:48 -08:00
ca028dd1cc Merge pull request #495 from mapbox/bare-geom-crash
Add null pointer check when checking for bare geometry. Fix coalescing of wrong features.
2017-11-22 17:53:25 -08:00
8ac7c46788 Make the same null pointer fix in jsontool.cpp as in geojson.cpp 2017-11-22 13:06:39 -08:00
2234e37883 Quadkey-order index is a better secondary key for --reorder anyway 2017-11-22 12:49:40 -08:00
8230987405 Fix a bug that could cause the wrong features to be coalesced 2017-11-22 11:54:25 -08:00
9964784e77 Add null pointer check when testing for bare geometry in GeoJSON 2017-11-21 15:01:33 -08:00
ac67013930 Merge pull request #473 from mapbox/json-join
Working on tools for joining CSV data to GeoJSON
2017-11-21 10:50:01 -08:00
287 changed files with 135902 additions and 25566 deletions

11
.gitignore vendored
View File

@ -34,10 +34,19 @@ tippecanoe
tile-join
tippecanoe-decode
tippecanoe-enumerate
tippecanoe-json-tool
unit
# Tests
tests/**/*.mbtiles
tests/**/*.check
tests/**/*.geobuf
# Vim
*.swp
# Mac
# Mac
.DS_Store
# Nodejs
node_modules

View File

@ -43,7 +43,7 @@ matrix:
# debug+leak+address-sanitizer build
- os: linux
compiler: clang
env: CLANG_VERSION='3.8.0' BUILDTYPE=Debug ASAN_OPTIONS=detect_leaks=1 CC="clang-3.8" CXX="clang++-3.8" CXXFLAGS="-fsanitize=address" CFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" FEWER=true
env: CLANG_VERSION='3.8.0' BUILDTYPE=Debug ASAN_OPTIONS=detect_leaks=1 CC="clang-3.8" CXX="clang++-3.8" CXXFLAGS="-fsanitize=address,undefined" CFLAGS="-fsanitize=address,undefined" LDFLAGS="-fsanitize=address,undefined" FEWER=true
addons:
apt:
sources: ['ubuntu-toolchain-r-test' ]
@ -52,6 +52,13 @@ matrix:
- os: linux
compiler: clang
env: CLANG_VERSION='3.8.0' BUILDTYPE=Debug CC="clang-3.8" CXX="clang++-3.8" CXXFLAGS="--coverage" CFLAGS="--coverage" LDFLAGS="--coverage"
after_script:
- mason install llvm-cov 3.9.1
- mason link llvm-cov 3.9.1
- which llvm-cov
- curl -S -f https://codecov.io/bash -o codecov
- chmod +x codecov
- ./codecov -x "llvm-cov gcov" -Z
addons:
apt:
sources: ['ubuntu-toolchain-r-test' ]
@ -101,8 +108,3 @@ script:
BUILDTYPE=${BUILDTYPE} make fewer-tests; else
BUILDTYPE=${BUILDTYPE} make test geobuf-test;
fi
- if [ -n "${COVERAGE}" ]; then
/usr/bin/llvm-cov-3.5 -lp *.o;
pip install --user cpp-coveralls;
~/.local/bin/coveralls --no-gcov -i ./ --exclude clipper;
fi

View File

@ -1,3 +1,261 @@
## 1.34.3
* Add an option to keep intersection nodes from being simplified away
## 1.34.2
* Be more consistent about when longitudes beyond 180 are allowed.
Now if the entire feature is beyond 180, it will still appear.
## 1.34.1
* Don't run shell filters if the current zoom is below the minzoom
* Fix -Z and -z for tile directories in tile-join and tippecanoe-decode
* Return a successful error status for --help and --version
## 1.34.0
* Record the command line options in the tileset metadata
## 1.33.0
* MultiLineStrings were previously ignored in Geobuf input
## 1.32.12
* Accept .mvt as well as .pbf in directories of tiles
* Allow tippecanoe-decode and tile-join of directories with no metadata
## 1.32.11
* Don't let attribute exclusion apply to the attribute that has been specified
to become the feature ID
## 1.32.10
* Fix a bug that disallowed a per-feature minzoom of 0
## 1.32.9
* Limit tile detail to 30 and buffer size to 127 to prevent coordinate
delta overflow in vector tiles.
## 1.32.8
* Better error message if the output tileset already exists
## 1.32.7
* Point features may now be coalesced into MultiPoint features with --coalesce.
* Add --hilbert option to put features in Hilbert Curve sequence
## 1.32.6
* Make it an error, not a warning, to have missing coordinates for a point
## 1.32.5
* Use less memory on lines and polygons that are too small for the tile
* Fix coordinate rounding problem that was causing --grid-low-zooms grids
to be lost at low zooms if the original polygons were not aligned to
tile boundaries
## 1.32.4
* Ignore leading zeroes when converting string attributes to feature IDs
## 1.32.3
* Add an option to convert stringified number feature IDs to numbers
* Add an option to use a specified feature attribute as the feature ID
## 1.32.2
* Warn in tile-join if tilesets being joined have inconsistent maxzooms
## 1.32.1
* Fix null pointer crash when reading filter output that does not
tag features with their extent
* Add `--clip-bounding-box` option to clip input geometry
## 1.32.0
* Fix a bug that allowed coalescing of features with mismatched attributes
if they had been passed through a shell prefilter
## 1.31.7
* Create the output tile directory even if there are no valid features
## 1.31.6
* Issue an error message in tile-join if minzoom is greater than maxzoom
## 1.31.5
* Add options to change the tilestats limits
## 1.31.4
* Keep tile-join from generating a tileset name longer than 255 characters
## 1.31.3
* Fix the missing filename in JSON parsing warning messages
## 1.31.2
* Don't accept anything inside another JSON object's properties as a
feature or geometry of its own.
## 1.31.1
* Add --exclude-all to tile-join
## 1.31.0
* Upgrade Wagyu to version 0.4.3
## 1.30.6
* Take cluster distance into account when guessing a maxzoom
## 1.30.4
* Features within the z0 tile buffer of the antimeridian (not only
those that cross it) are duplicated on both sides.
## 1.30.3
* Add an option to automatically assign ids to features
## 1.30.2
* Don't guess a higher maxzoom than is allowed for manual selection
## 1.30.1
* Ensure that per-feature minzoom and maxzoom are integers
* Report compression errors in tippecanoe-decode
* Add the ability to specify the file format with -L{"format":"…"}
* Add an option to treat empty CSV columns as nulls, not empty strings
## 1.30.0
* Add a filter extension to allow filtering individual attributes
## 1.29.3
* Include a generator field in tileset metadata with the Tippecanoe version
## 1.29.2
* Be careful to remove null attributes from prefilter/postfilter output
## 1.29.1
* Add --use-source-polygon-winding and --reverse-source-polygon-winding
## 1.29.0
* Add the option to specify layer file, name, and description as JSON
* Add the option to specify the description for attributes in the
tileset metadata
* In CSV input, a trailing comma now counts as a trailing empty field
* In tippecanoe-json-tool, an empty CSV field is now an empty string,
not null (for consistency with tile-join)
## 1.28.1
* Explicitly check for infinite and not-a-number input coordinates
## 1.28.0
* Directly support gzipped GeoJSON as input files
## 1.27.16
* Fix thread safety issues related to the out-of-disk-space checker
## 1.27.15
* --extend-zooms-if-still-dropping now also extends zooms if features
are dropped by --force-feature-limit
## 1.27.14
* Use an exit status of 100 if some zoom levels were successfully
written but not all zoom levels could be tiled.
## 1.27.13
* Allow filtering features by zoom level in conditional expressions
* Lines in CSV input with empty geometry columns will be ignored
## 1.27.12
* Check integrity of sqlite3 file before decoding or tile-joining
## 1.27.11
* Always include tile and layer in tippecanoe-decode, fixing corrupt JSON.
* Clean up writing of JSON in general.
## 1.27.10
* Add --progress-interval setting to reduce progress indicator frequency
## 1.27.9
* Make clusters look better by averaging locations of clustered points
## 1.27.8
* Add --accumulate-attribute to keep attributes of dropped, coalesced,
or clustered features
* Make sure numeric command line arguments are actually numbers
* Don't coalesce features whose non-string-pool attributes don't match
## 1.27.7
* Add an option to produce only a single tile
* Retain non-ASCII characters in layernames generated from filenames
* Remember to close input files after reading them
* Add --coalesce-fraction-as-needed and --coalesce-densest-as-needed
* Report distances in both feet and meters
## 1.27.6
* Fix opportunities for integer overflow and out-of-bounds references
## 1.27.5
* Add --cluster-densest-as-needed to cluster features
* Add --maximum-tile-features to set the maximum number of features in a tile
## 1.27.4
* Support CSV point input
* Don't coalesce features that have different IDs but are otherwise identical
* Remove the 700-point limit on coalesced features, since polygon merging
is no longer a performance problem
## 1.27.3
* Clean up duplicated code for reading tiles from a directory
## 1.27.2
* Tippecanoe-decode can decode directories of tiles, not just mbtiles
* The --allow-existing option works on directories of tiles
* Trim .geojson, not just .json, when making layer names from filenames
## 1.27.1
* Fix a potential null pointer when parsing GeoJSON with bare geometries
* Fix a bug that could cause the wrong features to be coalesced when
input was parsed in parallel
## 1.27.0
* Add tippecanoe-json-tool for sorting and joining GeoJSON files

View File

@ -1,5 +1,5 @@
# Start from ubuntu
FROM ubuntu:17.04
FROM ubuntu:16.04
# Update repos and install dependencies
RUN apt-get update \

267
Makefile
View File

@ -47,19 +47,19 @@ C = $(wildcard *.c) $(wildcard *.cpp)
INCLUDES = -I/usr/local/include -I.
LIBS = -L/usr/local/lib
tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o plugin.o read_json.o write_json.o geobuf.o evaluator.o
tippecanoe: geojson.o jsonpull/jsonpull.o tile.o pool.o mbtiles.o geometry.o projection.o memfile.o mvt.o serial.o main.o text.o dirtiles.o plugin.o read_json.o write_json.o geobuf.o evaluator.o geocsv.o csv.o geojson-loop.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
tippecanoe-enumerate: enumerate.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lsqlite3
tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o
tippecanoe-decode: decode.o projection.o mvt.o write_json.o text.o jsonpull/jsonpull.o dirtiles.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3
tile-join: tile-join.o projection.o pool.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o
tile-join: tile-join.o projection.o pool.o mbtiles.o mvt.o memfile.o dirtiles.o jsonpull/jsonpull.o text.o evaluator.o csv.o write_json.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o
tippecanoe-json-tool: jsontool.o jsonpull/jsonpull.o csv.o text.o geojson-loop.o
$(CXX) $(PG) $(LIBS) $(FINAL_FLAGS) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) -lm -lz -lsqlite3 -lpthread
unit: unit.o text.o
@ -74,7 +74,7 @@ unit: unit.o text.o
$(CXX) -MMD $(PG) $(INCLUDES) $(FINAL_FLAGS) $(CXXFLAGS) -c -o $@ $<
clean:
rm -f ./tippecanoe ./tippecanoe-* ./tile-join ./unit *.o *.d */*.o */*.d
rm -f ./tippecanoe ./tippecanoe-* ./tile-join ./unit *.o *.d */*.o */*.d tests/**/*.mbtiles tests/**/*.check
indent:
clang-format -i -style="{BasedOnStyle: Google, IndentWidth: 8, UseTab: Always, AllowShortIfStatementsOnASingleLine: false, ColumnLimit: 0, ContinuationIndentWidth: 8, SpaceAfterCStyleCast: true, IndentCaseLabels: false, AllowShortBlocksOnASingleLine: false, AllowShortFunctionsOnASingleLine: false, SortIncludes: false}" $(C) $(H)
@ -82,18 +82,22 @@ indent:
TESTS = $(wildcard tests/*/out/*.json)
SPACE = $(NULL) $(NULL)
test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit json-tool-test
test: tippecanoe tippecanoe-decode $(addsuffix .check,$(TESTS)) raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit json-tool-test allow-existing-test csv-test layer-json-test
./unit
suffixes = json json.gz
# Work around Makefile and filename punctuation limits: _ for space, @ for :, % for /
%.json.check:
./tippecanoe -aD -f -o $@.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json.check,%,$(word 4,$(subst /, ,$@)))))) $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json) < /dev/null
./tippecanoe-decode $@.mbtiles > $@.out
./tippecanoe -q -a@ -f -o $@.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json.check,%,$(word 4,$(subst /, ,$@)))))) $(foreach suffix,$(suffixes),$(sort $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.$(suffix)))) < /dev/null
./tippecanoe-decode -x generator $@.mbtiles > $@.out
cmp $@.out $(patsubst %.check,%,$@)
rm $@.out $@.mbtiles
# Don't test overflow with geobuf, because it fails (https://github.com/mapbox/geobuf/issues/87)
geobuf-test: tippecanoe-json-tool $(addsuffix .checkbuf,$(filter-out tests/overflow/out/-z0.json,$(TESTS)))
# Don't test stringids with geobuf, because it fails
nogeobuf = tests/overflow/out/-z0.json $(wildcard tests/stringid/out/*.json)
geobuf-test: tippecanoe-json-tool $(addsuffix .checkbuf,$(filter-out $(nogeobuf),$(TESTS)))
# For quicker address sanitizer build, hope that regular JSON parsing is tested enough by parallel and join tests
fewer-tests: tippecanoe tippecanoe-decode geobuf-test raw-tiles-test parallel-test pbf-test join-test enumerate-test decode-test join-filter-test unit
@ -101,8 +105,9 @@ fewer-tests: tippecanoe tippecanoe-decode geobuf-test raw-tiles-test parallel-te
# XXX Use proper makefile rules instead of a for loop
%.json.checkbuf:
for i in $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json); do ./tippecanoe-json-tool -w $$i | ./node_modules/geobuf/bin/json2geobuf > $$i.geobuf; done
./tippecanoe -aD -f -o $@.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json.checkbuf,%,$(word 4,$(subst /, ,$@)))))) $(addsuffix .geobuf,$(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json)) < /dev/null
./tippecanoe-decode $@.mbtiles | sed 's/checkbuf/check/g' > $@.out
for i in $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json.gz); do gzip -dc $$i | ./tippecanoe-json-tool -w | ./node_modules/geobuf/bin/json2geobuf > $$i.geobuf; done
./tippecanoe -q -a@ -f -o $@.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json.checkbuf,%,$(word 4,$(subst /, ,$@)))))) $(foreach suffix,$(suffixes),$(addsuffix .geobuf,$(sort $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.$(suffix))))) < /dev/null
./tippecanoe-decode -x generator $@.mbtiles | sed 's/checkbuf/check/g' | sed 's/\.geobuf//g' > $@.out
cmp $@.out $(patsubst %.checkbuf,%,$@)
rm $@.out $@.mbtiles
@ -114,18 +119,18 @@ parallel-test:
perl -e 'for ($$i = 0; $$i < 20; $$i++) { $$lon = rand(360) - 180; $$lat = rand(180) - 90; $$v = rand(1); print "{ \"type\": \"Feature\", \"properties\": { }, \"tippecanoe\": { \"layer\": \"$$v\" }, \"geometry\": { \"type\": \"Point\", \"coordinates\": [ $$lon, $$lat ] } }\n"; }' > tests/parallel/in4.json
echo -n "" > tests/parallel/empty1.json
echo "" > tests/parallel/empty2.json
./tippecanoe -z5 -f -pi -l test -n test -o tests/parallel/linear-file.mbtiles tests/parallel/in[1234].json tests/parallel/empty[12].json
./tippecanoe -z5 -f -pi -l test -n test -P -o tests/parallel/parallel-file.mbtiles tests/parallel/in[1234].json tests/parallel/empty[12].json
cat tests/parallel/in[1234].json | ./tippecanoe -z5 -f -pi -l test -n test -o tests/parallel/linear-pipe.mbtiles
cat tests/parallel/in[1234].json | ./tippecanoe -z5 -f -pi -l test -n test -P -o tests/parallel/parallel-pipe.mbtiles
cat tests/parallel/in[1234].json | sed 's/^/@/' | tr '@' '\036' | ./tippecanoe -z5 -f -pi -l test -n test -o tests/parallel/implicit-pipe.mbtiles
./tippecanoe -z5 -f -pi -l test -n test -P -o tests/parallel/parallel-pipes.mbtiles <(cat tests/parallel/in1.json) <(cat tests/parallel/empty1.json) <(cat tests/parallel/empty2.json) <(cat tests/parallel/in2.json) /dev/null <(cat tests/parallel/in3.json) <(cat tests/parallel/in4.json)
./tippecanoe-decode tests/parallel/linear-file.mbtiles > tests/parallel/linear-file.json
./tippecanoe-decode tests/parallel/parallel-file.mbtiles > tests/parallel/parallel-file.json
./tippecanoe-decode tests/parallel/linear-pipe.mbtiles > tests/parallel/linear-pipe.json
./tippecanoe-decode tests/parallel/parallel-pipe.mbtiles > tests/parallel/parallel-pipe.json
./tippecanoe-decode tests/parallel/implicit-pipe.mbtiles > tests/parallel/implicit-pipe.json
./tippecanoe-decode tests/parallel/parallel-pipes.mbtiles > tests/parallel/parallel-pipes.json
./tippecanoe -q -z5 -f -pi -l test -n test -o tests/parallel/linear-file.mbtiles tests/parallel/in[1234].json tests/parallel/empty[12].json
./tippecanoe -q -z5 -f -pi -l test -n test -P -o tests/parallel/parallel-file.mbtiles tests/parallel/in[1234].json tests/parallel/empty[12].json
cat tests/parallel/in[1234].json | ./tippecanoe -q -z5 -f -pi -l test -n test -o tests/parallel/linear-pipe.mbtiles
cat tests/parallel/in[1234].json | ./tippecanoe -q -z5 -f -pi -l test -n test -P -o tests/parallel/parallel-pipe.mbtiles
cat tests/parallel/in[1234].json | sed 's/^/@/' | tr '@' '\036' | ./tippecanoe -q -z5 -f -pi -l test -n test -o tests/parallel/implicit-pipe.mbtiles
./tippecanoe -q -z5 -f -pi -l test -n test -P -o tests/parallel/parallel-pipes.mbtiles <(cat tests/parallel/in1.json) <(cat tests/parallel/empty1.json) <(cat tests/parallel/empty2.json) <(cat tests/parallel/in2.json) /dev/null <(cat tests/parallel/in3.json) <(cat tests/parallel/in4.json)
./tippecanoe-decode -x generator -x generator_options tests/parallel/linear-file.mbtiles > tests/parallel/linear-file.json
./tippecanoe-decode -x generator -x generator_options tests/parallel/parallel-file.mbtiles > tests/parallel/parallel-file.json
./tippecanoe-decode -x generator -x generator_options tests/parallel/linear-pipe.mbtiles > tests/parallel/linear-pipe.json
./tippecanoe-decode -x generator -x generator_options tests/parallel/parallel-pipe.mbtiles > tests/parallel/parallel-pipe.json
./tippecanoe-decode -x generator -x generator_options tests/parallel/implicit-pipe.mbtiles > tests/parallel/implicit-pipe.json
./tippecanoe-decode -x generator -x generator_options tests/parallel/parallel-pipes.mbtiles > tests/parallel/parallel-pipes.json
cmp tests/parallel/linear-file.json tests/parallel/parallel-file.json
cmp tests/parallel/linear-file.json tests/parallel/linear-pipe.json
cmp tests/parallel/linear-file.json tests/parallel/parallel-pipe.json
@ -133,111 +138,203 @@ parallel-test:
cmp tests/parallel/linear-file.json tests/parallel/parallel-pipes.json
rm tests/parallel/*.mbtiles tests/parallel/*.json
raw-tiles-test:
./tippecanoe -f -e tests/raw-tiles/raw-tiles tests/raw-tiles/hackspots.geojson -pC
diff -x '*.DS_Store' -rq tests/raw-tiles/raw-tiles tests/raw-tiles/compare
rm -rf tests/raw-tiles/raw-tiles
raw-tiles-test:
./tippecanoe -q -f -e tests/raw-tiles/raw-tiles -r1 -pC tests/raw-tiles/hackspots.geojson
./tippecanoe-decode -x generator tests/raw-tiles/raw-tiles > tests/raw-tiles/raw-tiles.json.check
cmp tests/raw-tiles/raw-tiles.json.check tests/raw-tiles/raw-tiles.json
# Test that -z and -Z work in tippecanoe-decode
./tippecanoe-decode -x generator -Z6 -z7 tests/raw-tiles/raw-tiles > tests/raw-tiles/raw-tiles-z67.json.check
cmp tests/raw-tiles/raw-tiles-z67.json.check tests/raw-tiles/raw-tiles-z67.json
# Test that -z and -Z work in tile-join
./tile-join -q -f -Z6 -z7 -e tests/raw-tiles/raw-tiles-z67 tests/raw-tiles/raw-tiles
./tippecanoe-decode -x generator tests/raw-tiles/raw-tiles-z67 > tests/raw-tiles/raw-tiles-z67-join.json.check
cmp tests/raw-tiles/raw-tiles-z67-join.json.check tests/raw-tiles/raw-tiles-z67-join.json
rm -rf tests/raw-tiles/raw-tiles tests/raw-tiles/raw-tiles-z67 tests/raw-tiles/raw-tiles.json.check raw-tiles-z67.json.check tests/raw-tiles/raw-tiles-z67-join.json.check
# Test that metadata.json is created even if all features are clipped away
./tippecanoe -q -f -e tests/raw-tiles/nothing tests/raw-tiles/nothing.geojson
./tippecanoe-decode -x generator tests/raw-tiles/nothing > tests/raw-tiles/nothing.json.check
cmp tests/raw-tiles/nothing.json.check tests/raw-tiles/nothing.json
rm -r tests/raw-tiles/nothing tests/raw-tiles/nothing.json.check
decode-test:
mkdir -p tests/muni/decode
./tippecanoe -z11 -Z11 -f -o tests/muni/decode/multi.mbtiles tests/muni/*.json
./tippecanoe-decode -l subway tests/muni/decode/multi.mbtiles > tests/muni/decode/multi.mbtiles.json.check
./tippecanoe-decode -c tests/muni/decode/multi.mbtiles > tests/muni/decode/multi.mbtiles.pipeline.json.check
./tippecanoe-decode --stats tests/muni/decode/multi.mbtiles > tests/muni/decode/multi.mbtiles.stats.json.check
./tippecanoe -q -z11 -Z11 -f -o tests/muni/decode/multi.mbtiles tests/muni/*.json
./tippecanoe-decode -x generator -l subway tests/muni/decode/multi.mbtiles > tests/muni/decode/multi.mbtiles.json.check
./tippecanoe-decode -x generator -c tests/muni/decode/multi.mbtiles > tests/muni/decode/multi.mbtiles.pipeline.json.check
./tippecanoe-decode -x generator tests/muni/decode/multi.mbtiles 11 327 791 > tests/muni/decode/multi.mbtiles.onetile.json.check
./tippecanoe-decode -x generator --stats tests/muni/decode/multi.mbtiles > tests/muni/decode/multi.mbtiles.stats.json.check
cmp tests/muni/decode/multi.mbtiles.json.check tests/muni/decode/multi.mbtiles.json
cmp tests/muni/decode/multi.mbtiles.pipeline.json.check tests/muni/decode/multi.mbtiles.pipeline.json
cmp tests/muni/decode/multi.mbtiles.onetile.json.check tests/muni/decode/multi.mbtiles.onetile.json
cmp tests/muni/decode/multi.mbtiles.stats.json.check tests/muni/decode/multi.mbtiles.stats.json
rm -f tests/muni/decode/multi.mbtiles.json.check tests/muni/decode/multi.mbtiles tests/muni/decode/multi.mbtiles.pipeline.json.check tests/muni/decode/multi.mbtiles.stats.json.check
rm -f tests/muni/decode/multi.mbtiles.json.check tests/muni/decode/multi.mbtiles tests/muni/decode/multi.mbtiles.pipeline.json.check tests/muni/decode/multi.mbtiles.stats.json.check tests/muni/decode/multi.mbtiles.onetile.json.check
pbf-test:
./tippecanoe-decode tests/pbf/11-328-791.vector.pbf 11 328 791 > tests/pbf/11-328-791.vector.pbf.out
./tippecanoe-decode -x generator tests/pbf/11-328-791.vector.pbf 11 328 791 > tests/pbf/11-328-791.vector.pbf.out
cmp tests/pbf/11-328-791.json tests/pbf/11-328-791.vector.pbf.out
rm tests/pbf/11-328-791.vector.pbf.out
./tippecanoe-decode -s EPSG:3857 tests/pbf/11-328-791.vector.pbf 11 328 791 > tests/pbf/11-328-791.3857.vector.pbf.out
./tippecanoe-decode -x generator -s EPSG:3857 tests/pbf/11-328-791.vector.pbf 11 328 791 > tests/pbf/11-328-791.3857.vector.pbf.out
cmp tests/pbf/11-328-791.3857.json tests/pbf/11-328-791.3857.vector.pbf.out
rm tests/pbf/11-328-791.3857.vector.pbf.out
enumerate-test:
./tippecanoe -z5 -f -o tests/ne_110m_admin_0_countries/out/enum.mbtiles tests/ne_110m_admin_0_countries/in.json
./tippecanoe -q -z5 -f -o tests/ne_110m_admin_0_countries/out/enum.mbtiles tests/ne_110m_admin_0_countries/in.json.gz
./tippecanoe-enumerate tests/ne_110m_admin_0_countries/out/enum.mbtiles > tests/ne_110m_admin_0_countries/out/enum.check
cmp tests/ne_110m_admin_0_countries/out/enum tests/ne_110m_admin_0_countries/out/enum.check
rm tests/ne_110m_admin_0_countries/out/enum.mbtiles tests/ne_110m_admin_0_countries/out/enum.check
join-test:
./tippecanoe -f -z12 -o tests/join-population/tabblock_06001420.mbtiles tests/join-population/tabblock_06001420.json
./tippecanoe -f -Z5 -z10 -o tests/join-population/macarthur.mbtiles -l macarthur tests/join-population/macarthur.json
./tile-join -f -Z6 -z9 -o tests/join-population/macarthur-6-9.mbtiles tests/join-population/macarthur.mbtiles
./tippecanoe-decode tests/join-population/macarthur-6-9.mbtiles > tests/join-population/macarthur-6-9.mbtiles.json.check
join-test: tile-join
./tippecanoe -q -f -z12 -o tests/join-population/tabblock_06001420.mbtiles -YALAND10:'Land area' -L'{"file": "tests/join-population/tabblock_06001420.json", "description": "population"}'
./tippecanoe -q -f -Z5 -z10 -o tests/join-population/macarthur.mbtiles -l macarthur tests/join-population/macarthur.json
./tile-join -q -f -Z6 -z9 -o tests/join-population/macarthur-6-9.mbtiles tests/join-population/macarthur.mbtiles
./tippecanoe-decode -x generator tests/join-population/macarthur-6-9.mbtiles > tests/join-population/macarthur-6-9.mbtiles.json.check
cmp tests/join-population/macarthur-6-9.mbtiles.json.check tests/join-population/macarthur-6-9.mbtiles.json
rm -f tests/join-population/macarthur-6-9.mbtiles.json.check tests/join-population/macarthur-6-9.mbtiles
./tippecanoe -f -d10 -D10 -Z9 -z11 -o tests/join-population/macarthur2.mbtiles -l macarthur tests/join-population/macarthur2.json
./tile-join -q -f -Z6 -z9 -X -o tests/join-population/macarthur-6-9-exclude.mbtiles tests/join-population/macarthur.mbtiles
./tippecanoe-decode -x generator tests/join-population/macarthur-6-9-exclude.mbtiles > tests/join-population/macarthur-6-9-exclude.mbtiles.json.check
cmp tests/join-population/macarthur-6-9-exclude.mbtiles.json.check tests/join-population/macarthur-6-9-exclude.mbtiles.json
rm -f tests/join-population/macarthur-6-9.mbtiles.json.check tests/join-population/macarthur-6-9.mbtiles tests/join-population/macarthur-6-9-exclude.mbtiles.json.check tests/join-population/macarthur-6-9-exclude.mbtiles
./tippecanoe -q -f -d10 -D10 -Z9 -z11 -o tests/join-population/macarthur2.mbtiles -l macarthur tests/join-population/macarthur2.json
./tile-join --quiet --force -o tests/join-population/joined.mbtiles -x GEOID10 -c tests/join-population/population.csv tests/join-population/tabblock_06001420.mbtiles
./tile-join --quiet --force -o tests/join-population/joined-null.mbtiles --empty-csv-columns-are-null -x GEOID10 -c tests/join-population/population.csv tests/join-population/tabblock_06001420.mbtiles
./tile-join --quiet --force --no-tile-stats -o tests/join-population/joined-no-tile-stats.mbtiles -x GEOID10 -c tests/join-population/population.csv tests/join-population/tabblock_06001420.mbtiles
./tile-join -f -i -o tests/join-population/joined-i.mbtiles -x GEOID10 -c tests/join-population/population.csv tests/join-population/tabblock_06001420.mbtiles
./tile-join -f -o tests/join-population/merged.mbtiles tests/join-population/tabblock_06001420.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tile-join -f -c tests/join-population/windows.csv -o tests/join-population/windows.mbtiles tests/join-population/macarthur.mbtiles
./tippecanoe-decode --maximum-zoom=11 --minimum-zoom=4 tests/join-population/joined.mbtiles > tests/join-population/joined.mbtiles.json.check
./tippecanoe-decode --maximum-zoom=11 --minimum-zoom=4 tests/join-population/joined-no-tile-stats.mbtiles > tests/join-population/joined-no-tile-stats.mbtiles.json.check
./tippecanoe-decode tests/join-population/joined-i.mbtiles > tests/join-population/joined-i.mbtiles.json.check
./tippecanoe-decode tests/join-population/merged.mbtiles > tests/join-population/merged.mbtiles.json.check
./tippecanoe-decode tests/join-population/windows.mbtiles > tests/join-population/windows.mbtiles.json.check
./tile-join -q -f -i -o tests/join-population/joined-i.mbtiles -x GEOID10 -c tests/join-population/population.csv tests/join-population/tabblock_06001420.mbtiles
./tile-join -q -f -o tests/join-population/merged.mbtiles tests/join-population/tabblock_06001420.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tile-join -q -f -c tests/join-population/windows.csv -o tests/join-population/windows.mbtiles tests/join-population/macarthur.mbtiles
./tippecanoe-decode -x generator --maximum-zoom=11 --minimum-zoom=4 tests/join-population/joined.mbtiles > tests/join-population/joined.mbtiles.json.check
./tippecanoe-decode -x generator --maximum-zoom=11 --minimum-zoom=4 tests/join-population/joined-null.mbtiles > tests/join-population/joined-null.mbtiles.json.check
./tippecanoe-decode -x generator --maximum-zoom=11 --minimum-zoom=4 tests/join-population/joined-no-tile-stats.mbtiles > tests/join-population/joined-no-tile-stats.mbtiles.json.check
./tippecanoe-decode -x generator tests/join-population/joined-i.mbtiles > tests/join-population/joined-i.mbtiles.json.check
./tippecanoe-decode -x generator tests/join-population/merged.mbtiles > tests/join-population/merged.mbtiles.json.check
./tippecanoe-decode -x generator tests/join-population/windows.mbtiles > tests/join-population/windows.mbtiles.json.check
cmp tests/join-population/joined.mbtiles.json.check tests/join-population/joined.mbtiles.json
cmp tests/join-population/joined-null.mbtiles.json.check tests/join-population/joined-null.mbtiles.json
cmp tests/join-population/joined-no-tile-stats.mbtiles.json.check tests/join-population/joined-no-tile-stats.mbtiles.json
cmp tests/join-population/joined-i.mbtiles.json.check tests/join-population/joined-i.mbtiles.json
cmp tests/join-population/merged.mbtiles.json.check tests/join-population/merged.mbtiles.json
cmp tests/join-population/windows.mbtiles.json.check tests/join-population/windows.mbtiles.json
./tile-join -f -l macarthur -n "macarthur name" -N "macarthur description" -A "macarthur attribution" -o tests/join-population/just-macarthur.mbtiles tests/join-population/merged.mbtiles
./tile-join -f -L macarthur -o tests/join-population/no-macarthur.mbtiles tests/join-population/merged.mbtiles
./tippecanoe-decode tests/join-population/just-macarthur.mbtiles > tests/join-population/just-macarthur.mbtiles.json.check
./tippecanoe-decode tests/join-population/no-macarthur.mbtiles > tests/join-population/no-macarthur.mbtiles.json.check
rm -f tests/join-population/joined-null.mbtiles tests/join-population/joined-null.mbtiles.json.check
./tile-join -q -f -l macarthur -n "macarthur name" -N "macarthur description" -A "macarthur's attribution" -o tests/join-population/just-macarthur.mbtiles tests/join-population/merged.mbtiles
./tile-join -q -f -L macarthur -o tests/join-population/no-macarthur.mbtiles tests/join-population/merged.mbtiles
./tippecanoe-decode -x generator tests/join-population/just-macarthur.mbtiles > tests/join-population/just-macarthur.mbtiles.json.check
./tippecanoe-decode -x generator tests/join-population/no-macarthur.mbtiles > tests/join-population/no-macarthur.mbtiles.json.check
cmp tests/join-population/just-macarthur.mbtiles.json.check tests/join-population/just-macarthur.mbtiles.json
cmp tests/join-population/no-macarthur.mbtiles.json.check tests/join-population/no-macarthur.mbtiles.json
./tile-join --no-tile-compression -f -e tests/join-population/raw-merged-folder tests/join-population/tabblock_06001420.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
diff -x '*.DS_Store' -rq tests/join-population/raw-merged-folder tests/join-population/raw-merged-folder-compare
./tippecanoe -z12 -f -e tests/join-population/tabblock_06001420-folder tests/join-population/tabblock_06001420.json
./tippecanoe -Z5 -z10 -f -e tests/join-population/macarthur-folder -l macarthur tests/join-population/macarthur.json
./tippecanoe -d10 -D10 -Z9 -z11 -f -e tests/join-population/macarthur2-folder -l macarthur tests/join-population/macarthur2.json
./tile-join -f -o tests/join-population/merged-folder.mbtiles tests/join-population/tabblock_06001420-folder tests/join-population/macarthur-folder tests/join-population/macarthur2-folder
./tippecanoe-decode tests/join-population/merged-folder.mbtiles > tests/join-population/merged-folder.mbtiles.json.check
cmp tests/join-population/no-macarthur.mbtiles.json.check tests/join-population/no-macarthur.mbtiles.json
./tile-join -q --no-tile-compression -f -e tests/join-population/raw-merged-folder tests/join-population/tabblock_06001420.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tippecanoe-decode -x generator tests/join-population/raw-merged-folder > tests/join-population/raw-merged-folder.json.check
cmp tests/join-population/raw-merged-folder.json.check tests/join-population/raw-merged-folder.json
rm -f tests/join-population/raw-merged-folder.json.check
./tippecanoe -q -z12 -f -e tests/join-population/tabblock_06001420-folder -YALAND10:'Land area' -L'{"file": "tests/join-population/tabblock_06001420.json", "description": "population"}'
./tippecanoe -q -Z5 -z10 -f -e tests/join-population/macarthur-folder -l macarthur tests/join-population/macarthur.json
./tippecanoe -q -d10 -D10 -Z9 -z11 -f -e tests/join-population/macarthur2-folder -l macarthur tests/join-population/macarthur2.json
./tile-join -q -f -o tests/join-population/merged-folder.mbtiles tests/join-population/tabblock_06001420-folder tests/join-population/macarthur-folder tests/join-population/macarthur2-folder
./tippecanoe-decode -x generator tests/join-population/merged-folder.mbtiles > tests/join-population/merged-folder.mbtiles.json.check
cmp tests/join-population/merged-folder.mbtiles.json.check tests/join-population/merged-folder.mbtiles.json
./tile-join -n "merged name" -N "merged description" -f -e tests/join-population/merged-mbtiles-to-folder tests/join-population/tabblock_06001420.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tile-join -n "merged name" -N "merged description" -f -e tests/join-population/merged-folders-to-folder tests/join-population/tabblock_06001420-folder tests/join-population/macarthur-folder tests/join-population/macarthur2-folder
diff -x '*.DS_Store' -rq tests/join-population/merged-mbtiles-to-folder tests/join-population/merged-folders-to-folder
./tile-join -f -c tests/join-population/windows.csv -o tests/join-population/windows-merged.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -c tests/join-population/windows.csv -f -e tests/join-population/windows-merged-folder tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -f -o tests/join-population/windows-merged2.mbtiles tests/join-population/windows-merged-folder
./tippecanoe-decode tests/join-population/windows-merged.mbtiles > tests/join-population/windows-merged.mbtiles.json.check
./tippecanoe-decode tests/join-population/windows-merged2.mbtiles > tests/join-population/windows-merged2.mbtiles.json.check
./tile-join -q -n "merged name" -N "merged description" -f -e tests/join-population/merged-mbtiles-to-folder tests/join-population/tabblock_06001420.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tile-join -q -n "merged name" -N "merged description" -f -e tests/join-population/merged-folders-to-folder tests/join-population/tabblock_06001420-folder tests/join-population/macarthur-folder tests/join-population/macarthur2-folder
./tippecanoe-decode -x generator -x generator_options tests/join-population/merged-mbtiles-to-folder > tests/join-population/merged-mbtiles-to-folder.json.check
./tippecanoe-decode -x generator -x generator_options tests/join-population/merged-folders-to-folder > tests/join-population/merged-folders-to-folder.json.check
cmp tests/join-population/merged-mbtiles-to-folder.json.check tests/join-population/merged-folders-to-folder.json.check
rm -f tests/join-population/merged-mbtiles-to-folder.json.check tests/join-population/merged-folders-to-folder.json.check
./tile-join -q -f -c tests/join-population/windows.csv -o tests/join-population/windows-merged.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -q -c tests/join-population/windows.csv -f -e tests/join-population/windows-merged-folder tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -q -f -o tests/join-population/windows-merged2.mbtiles tests/join-population/windows-merged-folder
./tippecanoe-decode -x generator -x generator_options tests/join-population/windows-merged.mbtiles > tests/join-population/windows-merged.mbtiles.json.check
./tippecanoe-decode -x generator -x generator_options tests/join-population/windows-merged2.mbtiles > tests/join-population/windows-merged2.mbtiles.json.check
cmp tests/join-population/windows-merged.mbtiles.json.check tests/join-population/windows-merged2.mbtiles.json.check
./tile-join -f -o tests/join-population/macarthur-and-macarthur2-merged.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -f -e tests/join-population/macarthur-and-macarthur2-folder tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -f -o tests/join-population/macarthur-and-macarthur2-merged2.mbtiles tests/join-population/macarthur-and-macarthur2-folder
./tippecanoe-decode tests/join-population/macarthur-and-macarthur2-merged.mbtiles > tests/join-population/macarthur-and-macarthur2-merged.mbtiles.json.check
./tippecanoe-decode tests/join-population/macarthur-and-macarthur2-merged2.mbtiles > tests/join-population/macarthur-and-macarthur2-merged2.mbtiles.json.check
./tile-join -q -f -o tests/join-population/macarthur-and-macarthur2-merged.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -q -f -e tests/join-population/macarthur-and-macarthur2-folder tests/join-population/macarthur.mbtiles tests/join-population/macarthur2-folder
./tile-join -q -f -o tests/join-population/macarthur-and-macarthur2-merged2.mbtiles tests/join-population/macarthur-and-macarthur2-folder
./tippecanoe-decode -x generator -x generator_options tests/join-population/macarthur-and-macarthur2-merged.mbtiles > tests/join-population/macarthur-and-macarthur2-merged.mbtiles.json.check
./tippecanoe-decode -x generator -x generator_options tests/join-population/macarthur-and-macarthur2-merged2.mbtiles > tests/join-population/macarthur-and-macarthur2-merged2.mbtiles.json.check
cmp tests/join-population/macarthur-and-macarthur2-merged.mbtiles.json.check tests/join-population/macarthur-and-macarthur2-merged2.mbtiles.json.check
rm tests/join-population/tabblock_06001420.mbtiles tests/join-population/joined.mbtiles tests/join-population/joined-i.mbtiles tests/join-population/joined.mbtiles.json.check tests/join-population/joined-i.mbtiles.json.check tests/join-population/macarthur.mbtiles tests/join-population/merged.mbtiles tests/join-population/merged.mbtiles.json.check tests/join-population/merged-folder.mbtiles tests/join-population/macarthur2.mbtiles tests/join-population/windows.mbtiles tests/join-population/windows-merged.mbtiles tests/join-population/windows-merged2.mbtiles tests/join-population/windows.mbtiles.json.check tests/join-population/just-macarthur.mbtiles tests/join-population/no-macarthur.mbtiles tests/join-population/just-macarthur.mbtiles.json.check tests/join-population/no-macarthur.mbtiles.json.check tests/join-population/merged-folder.mbtiles.json.check tests/join-population/windows-merged.mbtiles.json.check tests/join-population/windows-merged2.mbtiles.json.check tests/join-population/macarthur-and-macarthur2-merged.mbtiles tests/join-population/macarthur-and-macarthur2-merged2.mbtiles tests/join-population/macarthur-and-macarthur2-merged.mbtiles.json.check tests/join-population/macarthur-and-macarthur2-merged2.mbtiles.json.check
rm -rf tests/join-population/raw-merged-folder tests/join-population/tabblock_06001420-folder tests/join-population/macarthur-folder tests/join-population/macarthur2-folder tests/join-population/merged-mbtiles-to-folder tests/join-population/merged-folders-to-folder tests/join-population/windows-merged-folder tests/join-population/macarthur-and-macarthur2-folder
# Test renaming of layers
./tippecanoe -f -Z5 -z10 -o tests/join-population/macarthur.mbtiles -l macarthur1 tests/join-population/macarthur.json
./tippecanoe -f -Z5 -z10 -o tests/join-population/macarthur2.mbtiles -l macarthur2 tests/join-population/macarthur2.json
./tile-join -R macarthur1:one --rename-layer=macarthur2:two -f -o tests/join-population/renamed.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tippecanoe-decode tests/join-population/renamed.mbtiles > tests/join-population/renamed.mbtiles.json.check
./tippecanoe -q -f -Z5 -z10 -o tests/join-population/macarthur.mbtiles -l macarthur1 tests/join-population/macarthur.json
./tippecanoe -q -f -Z5 -z10 -o tests/join-population/macarthur2.mbtiles -l macarthur2 tests/join-population/macarthur2.json
./tile-join -q -R macarthur1:one --rename-layer=macarthur2:two -f -o tests/join-population/renamed.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
./tippecanoe-decode -x generator tests/join-population/renamed.mbtiles > tests/join-population/renamed.mbtiles.json.check
cmp tests/join-population/renamed.mbtiles.json.check tests/join-population/renamed.mbtiles.json
rm -f tests/join-population/renamed.mbtiles.json.check tests/join-population/renamed.mbtiles.json.check tests/join-population/macarthur.mbtiles tests/join-population/macarthur2.mbtiles
# Make sure the concatenated name isn't too long
./tippecanoe -q -f -z0 -n 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json
./tile-join -f -o tests/join-population/concat.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles
./tippecanoe-decode -x generator tests/join-population/concat.mbtiles > tests/join-population/concat.mbtiles.json.check
cmp tests/join-population/concat.mbtiles.json.check tests/join-population/concat.mbtiles.json
rm tests/join-population/concat.mbtiles.json.check tests/join-population/concat.mbtiles tests/join-population/macarthur.mbtiles
join-filter-test:
# Comes out different from the direct tippecanoe run because null attributes are lost
./tippecanoe -z0 -f -o tests/feature-filter/out/all.mbtiles tests/feature-filter/in.json
./tile-join -J tests/feature-filter/filter -f -o tests/feature-filter/out/filtered.mbtiles tests/feature-filter/out/all.mbtiles
./tippecanoe-decode tests/feature-filter/out/filtered.mbtiles > tests/feature-filter/out/filtered.json.check
./tippecanoe -q -z0 -f -o tests/feature-filter/out/all.mbtiles tests/feature-filter/in.json
./tile-join -q -J tests/feature-filter/filter -f -o tests/feature-filter/out/filtered.mbtiles tests/feature-filter/out/all.mbtiles
./tippecanoe-decode -x generator tests/feature-filter/out/filtered.mbtiles > tests/feature-filter/out/filtered.json.check
cmp tests/feature-filter/out/filtered.json.check tests/feature-filter/out/filtered.json.standard
rm -f tests/feature-filter/out/filtered.json.check tests/feature-filter/out/filtered.mbtiles tests/feature-filter/out/all.mbtiles
# Test zoom level filtering
./tippecanoe -q -r1 -z8 -f -o tests/feature-filter/out/places.mbtiles tests/ne_110m_populated_places/in.json
./tile-join -q -J tests/feature-filter/places-filter -f -o tests/feature-filter/out/places-filter.mbtiles tests/feature-filter/out/places.mbtiles
./tippecanoe-decode -x generator tests/feature-filter/out/places-filter.mbtiles > tests/feature-filter/out/places-filter.mbtiles.json.check
cmp tests/feature-filter/out/places-filter.mbtiles.json.check tests/feature-filter/out/places-filter.mbtiles.json.standard
rm -f tests/feature-filter/out/places.mbtiles tests/feature-filter/out/places-filter.mbtiles tests/feature-filter/out/places-filter.mbtiles.json.check
json-tool-test: tippecanoe-json-tool
./tippecanoe-json-tool -e GEOID10 tests/join-population/tabblock_06001420.json | sort > tests/join-population/tabblock_06001420.json.sort
./tippecanoe-json-tool -c tests/join-population/population.csv tests/join-population/tabblock_06001420.json.sort > tests/join-population/tabblock_06001420.json.sort.joined
./tippecanoe-json-tool --empty-csv-columns-are-null -c tests/join-population/population.csv tests/join-population/tabblock_06001420.json.sort > tests/join-population/tabblock_06001420-null.json.sort.joined
cmp tests/join-population/tabblock_06001420.json.sort.joined tests/join-population/tabblock_06001420.json.sort.joined.standard
cmp tests/join-population/tabblock_06001420-null.json.sort.joined tests/join-population/tabblock_06001420-null.json.sort.joined.standard
rm -f tests/join-population/tabblock_06001420.json.sort tests/join-population/tabblock_06001420.json.sort.joined
rm -f tests/join-population/tabblock_06001420-null.json.sort.joined
allow-existing-test:
# Make a tileset
./tippecanoe -q -Z0 -z0 -f -o tests/allow-existing/both.mbtiles tests/coalesce-tract/tl_2010_06001_tract10.json
# Writing to existing should fail
if ./tippecanoe -q -Z1 -z1 -o tests/allow-existing/both.mbtiles tests/coalesce-tract/tl_2010_06001_tract10.json; then exit 1; else exit 0; fi
# Replace existing
./tippecanoe -q -Z8 -z9 -f -o tests/allow-existing/both.mbtiles tests/coalesce-tract/tl_2010_06001_tract10.json
./tippecanoe -q -Z10 -z11 -F -o tests/allow-existing/both.mbtiles tests/coalesce-tract/tl_2010_06001_tract10.json
./tippecanoe-decode -x generator -x generator_options tests/allow-existing/both.mbtiles > tests/allow-existing/both.mbtiles.json.check
cmp tests/allow-existing/both.mbtiles.json.check tests/allow-existing/both.mbtiles.json
# Make a tileset
./tippecanoe -q -Z0 -z0 -f -e tests/allow-existing/both.dir tests/coalesce-tract/tl_2010_06001_tract10.json
# Writing to existing should fail
if ./tippecanoe -q -Z1 -z1 -e tests/allow-existing/both.dir tests/coalesce-tract/tl_2010_06001_tract10.json; then exit 1; else exit 0; fi
# Replace existing
./tippecanoe -q -Z8 -z9 -f -e tests/allow-existing/both.dir tests/coalesce-tract/tl_2010_06001_tract10.json
./tippecanoe -q -Z10 -z11 -F -e tests/allow-existing/both.dir tests/coalesce-tract/tl_2010_06001_tract10.json
./tippecanoe-decode -x generator -x generator_options tests/allow-existing/both.dir | sed 's/both\.dir/both.mbtiles/g' > tests/allow-existing/both.dir.json.check
cmp tests/allow-existing/both.dir.json.check tests/allow-existing/both.mbtiles.json
rm -r tests/allow-existing/both.dir.json.check tests/allow-existing/both.dir tests/allow-existing/both.mbtiles.json.check tests/allow-existing/both.mbtiles
csv-test:
# Reading from named CSV
./tippecanoe -q -zg -f -o tests/csv/out.mbtiles tests/csv/ne_110m_populated_places_simple.csv
./tippecanoe-decode -x generator -x generator_options tests/csv/out.mbtiles > tests/csv/out.mbtiles.json.check
cmp tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles.json
rm -f tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles
# Reading from named CSV, with nulls
./tippecanoe -q --empty-csv-columns-are-null -zg -f -o tests/csv/out-null.mbtiles tests/csv/ne_110m_populated_places_simple.csv
./tippecanoe-decode -x generator tests/csv/out-null.mbtiles > tests/csv/out-null.mbtiles.json.check
cmp tests/csv/out-null.mbtiles.json.check tests/csv/out-null.mbtiles.json
rm -f tests/csv/out-null.mbtiles.json.check tests/csv/out-null.mbtiles
# Same, but specifying csv with -L format
./tippecanoe -q -zg -f -o tests/csv/out.mbtiles -L'{"file":"", "format":"csv", "layer":"ne_110m_populated_places_simple"}' < tests/csv/ne_110m_populated_places_simple.csv
./tippecanoe-decode -x generator -x generator_options tests/csv/out.mbtiles > tests/csv/out.mbtiles.json.check
cmp tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles.json
rm -f tests/csv/out.mbtiles.json.check tests/csv/out.mbtiles
layer-json-test:
# GeoJSON with description and named layer
./tippecanoe -q -z0 -r1 -yNAME -f -o tests/layer-json/out.mbtiles -L'{"file":"tests/ne_110m_populated_places/in.json", "description":"World cities", "layer":"places"}'
./tippecanoe-decode -x generator -x generator_options tests/layer-json/out.mbtiles > tests/layer-json/out.mbtiles.json.check
cmp tests/layer-json/out.mbtiles.json.check tests/layer-json/out.mbtiles.json
rm -f tests/layer-json/out.mbtiles.json.check tests/layer-json/out.mbtiles
# Same, but reading from the standard input
./tippecanoe -q -z0 -r1 -yNAME -f -o tests/layer-json/out.mbtiles -L'{"file":"", "description":"World cities", "layer":"places"}' < tests/ne_110m_populated_places/in.json
./tippecanoe-decode -x generator -x generator_options tests/layer-json/out.mbtiles > tests/layer-json/out.mbtiles.json.check
cmp tests/layer-json/out.mbtiles.json.check tests/layer-json/out.mbtiles.json
rm -f tests/layer-json/out.mbtiles.json.check tests/layer-json/out.mbtiles
# Use this target to regenerate the standards that the tests are compared against
# after making a change that legitimately changes their output
@ -245,7 +342,7 @@ json-tool-test: tippecanoe-json-tool
prep-test: $(TESTS)
tests/%.json: Makefile tippecanoe tippecanoe-decode
./tippecanoe -f -o $@.check.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json,%,$(word 4,$(subst /, ,$@)))))) $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.json)
./tippecanoe-decode $@.check.mbtiles > $@
./tippecanoe -q -a@ -f -o $@.check.mbtiles $(subst @,:,$(subst %,/,$(subst _, ,$(patsubst %.json,%,$(word 4,$(subst /, ,$@)))))) $(foreach suffix,$(suffixes),$(sort $(wildcard $(subst $(SPACE),/,$(wordlist 1,2,$(subst /, ,$@)))/*.$(suffix))))
./tippecanoe-decode -x generator $@.check.mbtiles > $@
cmp $(patsubst %.check,%,$@) $@
rm $@.check.mbtiles

307
README.md
View File

@ -1,11 +1,13 @@
tippecanoe
==========
Builds [vector tilesets](https://www.mapbox.com/developers/vector-tiles/) from large (or small) collections of [GeoJSON](http://geojson.org/) or [Geobuf](https://github.com/mapbox/geobuf) features,
Builds [vector tilesets](https://www.mapbox.com/developers/vector-tiles/) from large (or small) collections of [GeoJSON](http://geojson.org/), [Geobuf](https://github.com/mapbox/geobuf), or [CSV](https://en.wikipedia.org/wiki/Comma-separated_values) features,
[like these](MADE_WITH.md).
![Mapbox Tippecanoe](https://user-images.githubusercontent.com/1951835/36568734-ede27ec0-17df-11e8-8c22-ffaaebb8daf4.JPG)
[![Build Status](https://travis-ci.org/mapbox/tippecanoe.svg)](https://travis-ci.org/mapbox/tippecanoe)
[![Coverage Status](https://coveralls.io/repos/mapbox/tippecanoe/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapbox/tippecanoe?branch=master)
[![Coverage Status](https://codecov.io/gh/mapbox/tippecanoe/branch/master/graph/badge.svg)](https://codecov.io/gh/mapbox/tippecanoe)
Intent
------
@ -33,15 +35,28 @@ Installation
The easiest way to install tippecanoe on OSX is with [Homebrew](http://brew.sh/):
```js
```sh
$ brew install tippecanoe
```
On Ubuntu it will usually be easiest to build from the source repository:
```sh
$ git clone https://github.com/mapbox/tippecanoe.git
$ cd tippecanoe
$ make -j
$ make install
```
See [Development](#development) below for how to upgrade your
C++ compiler or install prerequisite packages if you get
compiler errors.
Usage
-----
```sh
$ tippecanoe -o file.mbtiles [options] [file.json file.geobuf ...]
$ tippecanoe -o file.mbtiles [options] [file.json file.json.gz file.geobuf ...]
```
If no files are specified, it reads GeoJSON from the standard input.
@ -86,6 +101,170 @@ with a custom layer name and description, and leaving out the `LINEARID` and `RT
$ cat tiger/tl_2014_*_roads.json | tippecanoe -o tiger.mbtiles -l roads -n "All TIGER roads, one zoom" -z12 -Z12 -d14 -x LINEARID -x RTTYP
```
Cookbook
--------
### Linear features (world railroads), visible at all zoom levels
```
curl -L -O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_railroads.zip
unzip ne_10m_railroads.zip
ogr2ogr -f GeoJSON ne_10m_railroads.geojson ne_10m_railroads.shp
tippecanoe -zg -o ne_10m_railroads.mbtiles --drop-densest-as-needed --extend-zooms-if-still-dropping ne_10m_railroads.geojson
```
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `--drop-densest-as-needed`: If the tiles are too big at low zoom levels, drop the least-visible features to allow tiles to be created with those features that remain
* `--extend-zooms-if-still-dropping`: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
### Discontinuous polygon features (buildings of Rhode Island), visible at all zoom levels
```
curl -L -O https://usbuildingdata.blob.core.windows.net/usbuildings-v1-1/RhodeIsland.zip
unzip RhodeIsland.zip
tippecanoe -zg -o RhodeIsland.mbtiles --drop-densest-as-needed --extend-zooms-if-still-dropping RhodeIsland.geojson
```
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `--drop-densest-as-needed`: If the tiles are too big at low or medium zoom levels, drop the least-visible features to allow tiles to be created with those features that remain
* `--extend-zooms-if-still-dropping`: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
### Continuous polygon features (states and provinces), visible at all zoom levels
```
curl -L -O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip
unzip -o ne_10m_admin_1_states_provinces.zip
ogr2ogr -f GeoJSON ne_10m_admin_1_states_provinces.geojson ne_10m_admin_1_states_provinces.shp
tippecanoe -zg -o ne_10m_admin_1_states_provinces.mbtiles --coalesce-densest-as-needed --extend-zooms-if-still-dropping ne_10m_admin_1_states_provinces.geojson
```
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `--coalesce-densest-as-needed`: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
* `--extend-zooms-if-still-dropping`: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
### Large point dataset (GPS bus locations), for visualization at all zoom levels
```
curl -L -O ftp://avl-data.sfmta.com/avl_data/avl_raw/sfmtaAVLRawData01012013.csv
sed 's/PREDICTABLE.*/PREDICTABLE/' sfmtaAVLRawData01012013.csv > sfmta.csv
tippecanoe -zg -o sfmta.mbtiles --drop-densest-as-needed --extend-zooms-if-still-dropping sfmta.csv
```
(The `sed` line is to clean the corrupt CSV header, which contains the wrong number of fields.)
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `--drop-densest-as-needed`: If the tiles are too big at low or medium zoom levels, drop the least-visible features to allow tiles to be created with those features that remain
* `--extend-zooms-if-still-dropping`: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
### Clustered points (world cities), summing the clustered population, visible at all zoom levels
```
curl -L -O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip
unzip -o ne_10m_populated_places.zip
ogr2ogr -f GeoJSON ne_10m_populated_places.geojson ne_10m_populated_places.shp
tippecanoe -zg -o ne_10m_populated_places.mbtiles -r1 --cluster-distance=10 --accumulate-attribute=POP_MAX:sum ne_10m_populated_places.geojson
```
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `-r1`: Do not automatically drop a fraction of points at low zoom levels, since clustering will be used instead
* `--cluster-distance=10`: Cluster together features that are closer than about 10 pixels from each other
* `--accumulate-attribute=POP_MAX:sum`: Sum the `POP_MAX` (population) attribute in features that are clustered together. Other attributes will be arbitrarily taken from the first feature in the cluster.
### Show countries at low zoom levels but states at higher zoom levels
```
curl -L -O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_countries.zip
unzip ne_10m_admin_0_countries.zip
ogr2ogr -f GeoJSON ne_10m_admin_0_countries.geojson ne_10m_admin_0_countries.shp
curl -L -O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip
unzip -o ne_10m_admin_1_states_provinces.zip
ogr2ogr -f GeoJSON ne_10m_admin_1_states_provinces.geojson ne_10m_admin_1_states_provinces.shp
tippecanoe -z3 -o countries-z3.mbtiles --coalesce-densest-as-needed ne_10m_admin_0_countries.geojson
tippecanoe -zg -Z4 -o states-Z4.mbtiles --coalesce-densest-as-needed --extend-zooms-if-still-dropping ne_10m_admin_1_states_provinces.geojson
tile-join -o states-countries.mbtiles countries-z3.mbtiles states-Z4.mbtiles
```
Countries:
* `-z3`: Only generate zoom levels 0 through 3
* `--coalesce-densest-as-needed`: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
States and Provinces:
* `-Z4`: Only generate zoom levels 4 and beyond
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `--coalesce-densest-as-needed`: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
* `--extend-zooms-if-still-dropping`: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
### Represent multiple sources (Illinois and Indiana counties) as separate layers
```
curl -L -O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_17_county10.zip
unzip tl_2010_17_county10.zip
ogr2ogr -f GeoJSON tl_2010_17_county10.geojson tl_2010_17_county10.shp
curl -L -O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_18_county10.zip
unzip tl_2010_18_county10.zip
ogr2ogr -f GeoJSON tl_2010_18_county10.geojson tl_2010_18_county10.shp
tippecanoe -zg -o counties-separate.mbtiles --coalesce-densest-as-needed --extend-zooms-if-still-dropping tl_2010_17_county10.geojson tl_2010_18_county10.geojson
```
* `-zg`: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
* `--coalesce-densest-as-needed`: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
* `--extend-zooms-if-still-dropping`: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
### Merge multiple sources (Illinois and Indiana counties) into the same layer
```
curl -L -O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_17_county10.zip
unzip tl_2010_17_county10.zip
ogr2ogr -f GeoJSON tl_2010_17_county10.geojson tl_2010_17_county10.shp
curl -L -O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_18_county10.zip
unzip tl_2010_18_county10.zip
ogr2ogr -f GeoJSON tl_2010_18_county10.geojson tl_2010_18_county10.shp
tippecanoe -zg -o counties-merged.mbtiles -l counties --coalesce-densest-as-needed --extend-zooms-if-still-dropping tl_2010_17_county10.geojson tl_2010_18_county10.geojson
```
As above, but
* `-l counties`: Specify the layer name instead of letting it be derived from the source file names
### Selectively remove and replace features (Census tracts) to update a tileset
```
# Retrieve and tile California 2000 Census tracts
curl -L -O https://www2.census.gov/geo/tiger/TIGER2010/TRACT/2000/tl_2010_06_tract00.zip
unzip tl_2010_06_tract00.zip
ogr2ogr -f GeoJSON tl_2010_06_tract00.shp.json tl_2010_06_tract00.shp
tippecanoe -z11 -o tracts.mbtiles -l tracts tl_2010_06_tract00.shp.json
# Create a copy of the tileset, minus Alameda County (FIPS code 001)
tile-join -j '{"*":["none",["==","COUNTYFP00","001"]]}' -f -o tracts-filtered.mbtiles tracts.mbtiles
# Retrieve and tile Alameda County Census tracts for 2010
curl -L -O https://www2.census.gov/geo/tiger/TIGER2010/TRACT/2010/tl_2010_06001_tract10.zip
unzip tl_2010_06001_tract10.zip
ogr2ogr -f GeoJSON tl_2010_06001_tract10.shp.json tl_2010_06001_tract10.shp
tippecanoe -z11 -o tracts-added.mbtiles -l tracts tl_2010_06001_tract10.shp.json
# Merge the filtered tileset and the tileset of new tracts into a final tileset
tile-join -o tracts-final.mbtiles tracts-filtered.mbtiles tracts-added.mbtiles
```
The `-z11` option explicitly specifies the maxzoom, to make sure both the old and new tilesets have the same zoom range.
The `-j` option to `tile-join` specifies a filter, so that only the desired features will be copied to the new tileset.
This filter excludes (using `none`) any features whose FIPS code (`COUNTYFP00`) is the code for Alameda County (`001`).
Options
-------
@ -127,10 +306,19 @@ If your input is formatted as newline-delimited GeoJSON, use `-P` to make input
### Input files and layer names
* _name_`.json` or _name_`.geojson`: Read the named GeoJSON input file into a layer called _name_.
* _name_`.geobuf` or _name_`.geobuf`: Read the named Geobuf input file into a layer called _name_.
* _name_`.json.gz` or _name_`.geojson.gz`: Read the named gzipped GeoJSON input file into a layer called _name_.
* _name_`.geobuf`: Read the named Geobuf input file into a layer called _name_.
* _name_`.csv`: Read the named CSV input file into a layer called _name_.
* `-l` _name_ or `--layer=`_name_: Use the specified layer name instead of deriving a name from the input filename or output tileset. If there are multiple input files
specified, the files are all merged into the single named layer, even if they try to specify individual names with `-L`.
* `-L` _name_`:`_file.json_ or `--named-layer=`_name_`:`_file.json_: Specify layer names for individual files. If your shell supports it, you can use a subshell redirect like `-L` _name_`:<(cat dir/*.json)` to specify a layer name for the output of streamed input.
* `-L{`_layer-json_`}` or `--named-layer={`_layer-json_`}`: Specify an input file and layer options by a JSON object. The JSON object must contain a `"file"` key to specify the filename to read from. (If the `"file"` key is an empty string, it means to read from the standard input stream.) It may also contain a `"layer"` field to specify the name of the layer, and/or a `"description"` field to specify the layer's description in the tileset metadata, and/or a `"format"` field to specify `csv` or `geobuf` file format if it is not obvious from the `name`. Example:
```
tippecanoe -z5 -o world.mbtiles -L'{"file":"ne_10m_admin_0_countries.json", "layer":"countries", "description":"Natural Earth countries"}'
```
CSV input files currently support only Point geometries, from columns named `latitude`, `longitude`, `lat`, `lon`, `long`, `lng`, `x`, or `y`.
### Parallel processing of input
@ -159,6 +347,32 @@ Parallel processing will also be automatic if the input file is in Geobuf format
* `-ae` or `--extend-zooms-if-still-dropping`: Increase the maxzoom if features are still being dropped at that zoom level.
The detail and simplification options that ordinarily apply only to the maximum zoom level will apply both to the originally
specified maximum zoom and to any levels added beyond that.
* `-R` _zoom_`/`_x_`/`_y_ or `--one-tile=`_zoom_`/`_x_`/`_y_: Set the minzoom and maxzoom to _zoom_ and produce only
the single specified tile at that zoom level.
If you know the precision to which you want your data to be represented,
or the map scale of a corresponding printed map,
this table shows the approximate precision and scale corresponding to various
`-z` options if you use the default `-d` detail of 12:
zoom level | precision (ft) | precision (m) | map scale
---------- | -------------- | ------------- | ---------
`-z0` | 32000 ft | 10000 m | 1:320,000,000
`-z1` | 16000 ft | 5000 m | 1:160,000,000
`-z2` | 8000 ft | 2500 m | 1:80,000,000
`-z3` | 4000 ft | 1250 m | 1:40,000,000
`-z4` | 2000 ft | 600 m | 1:20,000,000
`-z5` | 1000 ft | 300 m | 1:10,000,000
`-z6` | 500 ft | 150 m | 1:5,000,000
`-z7` | 250 ft | 80 m | 1:2,500,000
`-z8` | 125 ft | 40 m | 1:1,250,000
`-z9` | 64 ft | 20 m | 1:640,000
`-z10` | 32 ft | 10 m | 1:320,000
`-z11` | 16 ft | 5 m | 1:160,000
`-z12` | 8 ft | 2 m | 1:80,000
`-z13` | 4 ft | 1 m | 1:40,000
`-z14` | 2 ft | 0.5 m | 1:20,000
`-z15` | 1 ft | 0.25 m | 1:10,000
### Tile resolution
@ -172,15 +386,29 @@ resolution is obtained than by using a smaller _maxzoom_ or _detail_.
### Filtering feature attributes
* `-x` _name_ or `--exclude=`_name_: Exclude the named properties from all features
* `-y` _name_ or `--include=`_name_: Include the named properties in all features, excluding all those not explicitly named
* `-X` or `--exclude-all`: Exclude all properties and encode only geometries
* `-x` _name_ or `--exclude=`_name_: Exclude the named attributes from all features. You can specify multiple `-x` options to exclude several attributes. (Don't comma-separate names within a single `-x`.)
* `-y` _name_ or `--include=`_name_: Include the named attributes in all features, excluding all those not explicitly named. You can specify multiple `-y` options to explicitly include several attributes. (Don't comma-separate names within a single `-y`.)
* `-X` or `--exclude-all`: Exclude all attributes and encode only geometries
### Modifying feature attributes
* `-T`_attribute_`:`_type_ or `--attribute-type=`_attribute_`:`_type_: Coerce the named feature _attribute_ to be of the specified _type_.
The _type_ may be `string`, `float`, `int`, or `bool`.
If the type is `bool`, then original attributes of `0` (or, if numeric, `0.0`, etc.), `false`, `null`, or the empty string become `false`, and otherwise become `true`.
If the type is `float` or `int` and the original attribute was non-numeric, it becomes `0`.
If the type is `int` and the original attribute was floating-point, it is rounded to the nearest integer.
* `-j` *filter* or `--feature-filter`=*filter*: Check features against a per-layer filter (as defined in the [Mapbox GL Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-filter)) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer `"*"` apply to all layers.
* `-Y`_attribute_`:`_description_ or `--attribute-description=`_attribute_`:`_description_: Set the `description` for the specified attribute in the tileset metadata to _description_ instead of the usual `String`, `Number`, or `Boolean`.
* `-E`_attribute_`:`_operation_ or `--accumulate-attribute=`_attribute_`:`_operation_: Preserve the named _attribute_ from features
that are dropped, coalesced-as-needed, or clustered. The _operation_ may be
`sum`, `product`, `mean`, `max`, `min`, `concat`, or `comma`
to specify how the named _attribute_ is accumulated onto the attribute of the same name in a feature that does survive.
* `-pe` or `--empty-csv-columns-are-null`: Treat empty CSV columns as nulls rather than as empty strings.
* `-aI` or `--convert-stringified-ids-to-numbers`: If a feature ID is the string representation of a number, convert it to a plain number to use as the feature ID.
* `--use-attribute-for-id=`*name*: Use the attribute with the specified *name* as if it were specified as the feature ID. (If this attribute is a stringified number, you must also use `-aI` to convert it to a number.)
### Filtering features by attributes
* `-j` *filter* or `--feature-filter`=*filter*: Check features against a per-layer filter (as defined in the [Mapbox GL Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter)) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer `"*"` apply to all layers. The special variable `$zoom` refers to the current zoom level.
* `-J` *filter-file* or `--feature-filter-file`=*filter-file*: Like `-j`, but read the filter from a file.
Example: to find the Natural Earth countries with low `scalerank` but high `LABELRANK`:
@ -189,6 +417,23 @@ Example: to find the Natural Earth countries with low `scalerank` but high `LABE
tippecanoe -z5 -o filtered.mbtiles -j '{ "ne_10m_admin_0_countries": [ "all", [ "<", "scalerank", 3 ], [ ">", "LABELRANK", 5 ] ] }' ne_10m_admin_0_countries.geojson
```
Example: to retain only major TIGER roads at low zoom levels:
```
tippecanoe -o roads.mbtiles -j '{ "*": [ "any", [ ">=", "$zoom", 11 ], [ "in", "MTFCC", "S1100", "S1200" ] ] }' tl_2015_06001_roads.json
```
Tippecanoe also accepts expressions of the form `[ "attribute-filter", name, expression ]`, to filter individual feature attributes
instead of entire features. For example, you can exclude the road names at low zoom levels by doing
```
tippecanoe -o roads.mbtiles -j '{ "*": [ "attribute-filter", "FULLNAME", [ ">=", "$zoom", 9 ] ] }' tl_2015_06001_roads.json
```
An `attribute-filter` expression itself is always considered to evaluate to `true` (in other words, to retain the feature instead
of dropping it). If you want to use multiple `attribute-filter` expressions, or to use other expressions to remove features from
the same layer, enclose them in an `all` expression so they will all be evaluated.
### Dropping a fixed fraction of features by zoom level
* `-r` _rate_ or `--drop-rate=`_rate_: Rate at which dots are dropped at zoom levels below basezoom (default 2.5).
@ -201,14 +446,18 @@ tippecanoe -z5 -o filtered.mbtiles -j '{ "ne_10m_admin_0_countries": [ "all", [
compensate for the larger marker, or `-Bf`*number* to allow at most *number* features in the densest tile.
* `-al` or `--drop-lines`: Let "dot" dropping at lower zooms apply to lines too
* `-ap` or `--drop-polygons`: Let "dot" dropping at lower zooms apply to polygons too
* `-K` _distance_ or `--cluster-distance=`_distance_: Cluster points (as with `--cluster-densest-as-needed`, but without the experimental discovery process) that are approximately within _distance_ of each other. The units are tile coordinates within a nominally 256-pixel tile, so the maximum value of 255 allows only one feature per tile. Values around 10 are probably appropriate for typical marker sizes. See `--cluster-densest-as-needed` below for behavior.
### Dropping a fraction of features to keep under tile size limits
* `-as` or `--drop-densest-as-needed`: If a tile is too large, try to reduce it to under 500K by increasing the minimum spacing between features. The discovered spacing applies to the entire zoom level.
* `-ad` or `--drop-fraction-as-needed`: Dynamically drop some fraction of features from each zoom level to keep large tiles under the 500K size limit. (This is like `-pd` but applies to the entire zoom level, not to each tile.)
* `-an` or `--drop-smallest-as-needed`: Dynamically drop the smallest features (physically smallest: the shortest lines or the smallest polygons) from each zoom level to keep large tiles under the 500K size limit. This option will not work for point features.
* `-aN` or `--coalesce-smallest-as-needed`: Dynamically combine the smallest features (physically smallest: the shortest lines or the smallest polygons) from each zoom level into other nearby features to keep large tiles under the 500K size limit. This option will not work for point features, and will probably not help very much with LineStrings. It is mostly intended for polygons, to maintain the full original area covered by polygons while still reducing the feature count somehow. The attributes of the small polygons are *not* preserved into the combined features, only their geometry.
* `-aN` or `--coalesce-smallest-as-needed`: Dynamically combine the smallest features (physically smallest: the shortest lines or the smallest polygons) from each zoom level into other nearby features to keep large tiles under the 500K size limit. This option will not work for point features, and will probably not help very much with LineStrings. It is mostly intended for polygons, to maintain the full original area covered by polygons while still reducing the feature count somehow. The attributes of the small polygons are *not* preserved into the combined features (except through `--accumulate-attribute`), only their geometry. Furthermore, the polygons to which nested polygons are coalesced may not necessarily be the immediately enclosing features.
* `-aD` or `--coalesce-densest-as-needed`: Dynamically combine the densest features from each zoom level into other nearby features to keep large tiles under the 500K size limit. (Again, mostly useful for polygons.)
* `-aS` or `--coalesce-fraction-as-needed`: Dynamically combine a fraction of features from each zoom level into other nearby features to keep large tiles under the 500K size limit. (Again, mostly useful for polygons.)
* `-pd` or `--force-feature-limit`: Dynamically drop some fraction of features from large tiles to keep them under the 500K size limit. It will probably look ugly at the tile boundaries. (This is like `-ad` but applies to each tile individually, not to the entire zoom level.) You probably don't want to use this.
* `-aC` or `--cluster-densest-as-needed`: If a tile is too large, try to reduce its size by increasing the minimum spacing between features, and leaving one placeholder feature from each group. The remaining feature will be given a `"cluster": true` attribute to indicate that it represents a cluster, a `"point_count"` attribute to indicate the number of features that were clustered into it, and a `"sqrt_point_count"` attribute to indicate the relative width of a feature to represent the cluster. If the features being clustered are points, the representative feature will be located at the average of the original points' locations; otherwise, one of the original features will be left as the representative.
### Dropping tightly overlapping features
@ -221,6 +470,7 @@ tippecanoe -z5 -o filtered.mbtiles -j '{ "ne_10m_admin_0_countries": [ "all", [
the line or polygon within one tile unit of its proper location. You can probably go up to about 10 without too much visible difference.
* `-ps` or `--no-line-simplification`: Don't simplify lines and polygons
* `-pS` or `--simplify-only-low-zooms`: Don't simplify lines and polygons at maxzoom (but do simplify at lower zooms)
* `-pn` or `--no-simplification-of-shared-nodes`: Don't simplify away nodes that appear in more than one feature or are used multiple times within the same feature, so that the intersection node will not be lost from intersecting roads. (This will not be effective if you also use `--coalesce` or `--detect-shared-borders`.)
* `-pt` or `--no-tiny-polygon-reduction`: Don't combine the area of very small polygons into small squares that represent their combined area.
### Attempts to improve shared polygon boundaries
@ -237,25 +487,34 @@ tippecanoe -z5 -o filtered.mbtiles -j '{ "ne_10m_admin_0_countries": [ "all", [
### Reordering features within each tile
* `-pi` or `--preserve-input-order`: Preserve the original input order of features as the drawing order instead of ordering geographically. (This is implemented as a restoration of the original order at the end, so that dot-dropping is still geographic, which means it also undoes `-ao`).
* `-ao` or `--reorder`: Reorder features to put ones with the same properties in sequence, to try to get them to coalesce. You probably don't want to use this.
* `-ac` or `--coalesce`: Coalesce adjacent line and polygon features that have the same properties. You probably don't want to use this.
* `-ac` or `--coalesce`: Coalesce consecutive features that have the same attributes. This can be useful if you have lots of small polygons with identical attributes and you would like to merge them together.
* `-ao` or `--reorder`: Reorder features to put ones with the same attributes in sequence (instead of ones that are approximately spatially adjacent), to try to get them to coalesce. You probably want to use this if you use `--coalesce`.
* `-ar` or `--reverse`: Try reversing the directions of lines to make them coalesce and compress better. You probably don't want to use this.
* `-ah` or `--hilbert`: Put features in Hilbert Curve order instead of the usual Z-Order. This improves the odds that spatially adjacent features will be sequentially adjacent, and should improve density calculations and spatial coalescing. It should be the default eventually.
### Adding calculated attributes
* `-ag` or `--calculate-feature-density`: Add a new attribute, `tippecanoe_feature_density`, to each feature, to record how densely features are spaced in that area of the tile. You can use this attribute in the style to produce a glowing effect where points are densely packed. It can range from 0 in the sparsest areas to 255 in the densest.
* `-ai` or `--generate-ids`: Add an `id` (a feature ID, not an attribute named `id`) to each feature that does not already have one. There is currently no guarantee that the `id` added will be stable between runs or that it will not conflict with manually-assigned feature IDs. Future versions of Tippecanoe may change the mechanism for allocating IDs.
### Trying to correct bad source geometry
* `-aw` or `--detect-longitude-wraparound`: Detect when adjacent points within a feature jump to the other side of the world, and try to fix the geometry.
* `-aw` or `--detect-longitude-wraparound`: Detect when consecutive points within a feature jump to the other side of the world, and try to fix the geometry.
* `-pw` or `--use-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings.
* `-pW` or `--reverse-source-polygon-winding`: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings.
* `--clip-bounding-box=`*minlon*`,`*minlat*`,`*maxlon*`,`*maxlat*: Clip all features to the specified bounding box.
### Setting or disabling tile size limits
* `-M` _bytes_ or `--maximum-tile-bytes=`_bytes_: Use the specified number of _bytes_ as the maximum compressed tile size instead of 500K.
* `-O` _features_ or `--maximum-tile-features=`_features_: Use the specified number of _features_ as the maximum in a tile instead of 200,000.
* `-pf` or `--no-feature-limit`: Don't limit tiles to 200,000 features
* `-pk` or `--no-tile-size-limit`: Don't limit tiles to 500K bytes
* `-pC` or `--no-tile-compression`: Don't compress the PBF vector tile data.
* `-pg` or `--no-tile-stats`: Don't generate the `tilestats` row in the tileset metadata. Uploads without [tilestats](https://github.com/mapbox/mapbox-geostats) will take longer to process.
* `--tile-stats-attributes-limit=`*count*: Include `tilestats` information about at most *count* attributes instead of the default 1000.
* `--tile-stats-sample-values-limit=`*count*: Calculate `tilestats` attribute statistics based on *count* values instead of the default 1000.
* `--tile-stats-values-limit=`*count*: Report *count* unique attribute values in `tilestats` instead of the default 100.
### Temporary storage
@ -266,6 +525,7 @@ tippecanoe -z5 -o filtered.mbtiles -j '{ "ne_10m_admin_0_countries": [ "all", [
* `-q` or `--quiet`: Work quietly instead of reporting progress or warning messages
* `-Q` or `--no-progress-indicator`: Don't report progress, but still give warnings
* `-U` _seconds_ or `--progress-interval=`_seconds_: Don't report progress more often than the specified number of _seconds_.
* `-v` or `--version`: Report Tippecanoe's version number
### Filters
@ -287,7 +547,7 @@ The postfilter receives the features at tile resolution, after simplification, c
The layer name is provided as part of the `tippecanoe` element of the feature and must be passed through
to keep the feature in its correct layer. In the case of the prefilter, the `tippecanoe` element may also
contain `index`, `sequence`, and `extent` elements, which must be passed through for internal operations like
contain `index`, `sequence`, `extent`, and `dropped`, elements, which must be passed through for internal operations like
`--drop-densest-as-needed`, `--drop-smallest-as-needed`, and `--preserve-input-order` to work.
#### Examples:
@ -359,6 +619,12 @@ the filename or name specified using `--layer`, like this:
}
```
If your source GeoJSON only has `minzoom`, `maxzoom` and/or `layer` within `properties` you can use [ndjson-cli](https://github.com/mbostock/ndjson-cli/blob/master/README.md) to move them into the required `tippecanoe` object by piping the GeoJSON like this:
```sh
ndjson-map 'd.tippecanoe = { minzoom: d.properties.minzoom, maxzoom: d.properties.maxzoom, layer: d.properties.layer }, delete d.properties.minzoom, delete d.properties.maxzoom, delete d.properties.layer, d'
```
Geometric simplifications
-------------------------
@ -387,7 +653,7 @@ all of them should have had together.
Features in the same tile that share the same type and attributes are coalesced
together into a single geometry if you use `--coalesce`. You are strongly encouraged to use -x to exclude
any unnecessary properties to reduce wasted file size.
any unnecessary attributes to reduce wasted file size.
If a tile is larger than 500K, it will try encoding that tile at progressively
lower resolutions before failing if it still doesn't fit.
@ -496,9 +762,11 @@ The options are:
### Filtering features and feature attributes
* `-x` *key* or `--exclude=`*key*: Remove attributes of type *key* from the output. You can use this to remove the field you are matching against if you no longer need it after joining, or to remove any other attributes you don't want.
* `-X` or `--exclude-all`: Remove all attributes from the output.
* `-i` or `--if-matched`: Only include features that matched the CSV.
* `-j` *filter* or `--feature-filter`=*filter*: Check features against a per-layer filter (as defined in the [Mapbox GL Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-filter)) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer `"*"` apply to all layers.
* `-j` *filter* or `--feature-filter`=*filter*: Check features against a per-layer filter (as defined in the [Mapbox GL Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter)) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer `"*"` apply to all layers.
* `-J` *filter-file* or `--feature-filter-file`=*filter-file*: Like `-j`, but read the filter from a file.
* `-pe` or `--empty-csv-columns-are-null`: Treat empty CSV columns as nulls rather than as empty strings.
### Setting or disabling tile size limits
@ -581,7 +849,7 @@ or on an individual tile:
tippecanoe-decode file.mbtiles zoom x y
tippecanoe-decode file.vector.pbf zoom x y
If you decode an entire file, you get a nested `FeatureCollection` identifying each
Unless you use `-c`, the output is a set of nested FeatureCollections identifying each
tile and layer separately. Note that the same features generally appear at all zooms,
so the output for the file will have many copies of the same features at different
resolutions.
@ -623,7 +891,8 @@ something better.
* `-e` *attribute* or `--extract=`*attribute*: Extract the named attribute as a prefix to each feature.
The formatting makes excessive use of `\u` quoting so that it follows JSON string rules but will still
be sorted correctly by tools that just do ASCII comparisons.
* `-c` *file.csv* or `--csv=`*file.csv*: Join properties from the named sorted CSV file, using its first column as the join key. Geometries will be passed through even if they do not match the CSV; CSV lines that do not match a geometry will be discarded.
* `-c` *file.csv* or `--csv=`*file.csv*: Join attributes from the named sorted CSV file, using its first column as the join key. Geometries will be passed through even if they do not match the CSV; CSV lines that do not match a geometry will be discarded.
* `-pe` or `--empty-csv-columns-are-null`: Treat empty CSV columns as nulls rather than as empty strings.
### Example
@ -652,7 +921,7 @@ Sort GeoJSON block geometry so it is ordered by block ID. If you don't do this,
$ tippecanoe-json-tool -e GEOID10 tl_2010_18157_tabblock10.json | LC_ALL=C sort > tl_2010_18157_tabblock10.sort.json
```
Join block geometries to employment properties:
Join block geometries to employment attributes:
```
$ tippecanoe-json-tool -c in_wac_S000_JT00_2015.csv tl_2010_18157_tabblock10.sort.json > blocks-wac.json

6
codecov.yml Normal file
View File

@ -0,0 +1,6 @@
ignore:
- "test"
coverage:
status:
patch: off

25
csv.cpp
View File

@ -1,4 +1,5 @@
#include "csv.hpp"
#include "text.hpp"
std::vector<std::string> csv_split(const char *s) {
std::vector<std::string> ret;
@ -26,6 +27,11 @@ std::vector<std::string> csv_split(const char *s) {
while (*s && isspace(*s)) {
s++;
}
if (*s == '\0' || *s == '\r' || *s == '\n') {
ret.push_back(std::string(""));
break;
}
}
}
@ -67,6 +73,12 @@ void readcsv(const char *fn, std::vector<std::string> &header, std::map<std::str
std::string s;
if ((s = csv_getline(f)).size() > 0) {
std::string err = check_utf8(s);
if (err != "") {
fprintf(stderr, "%s: %s\n", fn, err.c_str());
exit(EXIT_FAILURE);
}
header = csv_split(s.c_str());
for (size_t i = 0; i < header.size(); i++) {
@ -74,6 +86,12 @@ void readcsv(const char *fn, std::vector<std::string> &header, std::map<std::str
}
}
while ((s = csv_getline(f)).size() > 0) {
std::string err = check_utf8(s);
if (err != "") {
fprintf(stderr, "%s: %s\n", fn, err.c_str());
exit(EXIT_FAILURE);
}
std::vector<std::string> line = csv_split(s.c_str());
if (line.size() > 0) {
line[0] = csv_dequote(line[0]);
@ -144,7 +162,12 @@ bool is_number(std::string const &s) {
}
}
return true;
if (*cp == '\0') {
return true;
} else {
// Something non-numeric at the end
return false;
}
}
return false;

View File

@ -11,29 +11,47 @@
#include <zlib.h>
#include <math.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <protozero/pbf_reader.hpp>
#include <sys/stat.h>
#include "mvt.hpp"
#include "projection.hpp"
#include "geometry.hpp"
#include "write_json.hpp"
#include "jsonpull/jsonpull.h"
#include "dirtiles.hpp"
int minzoom = 0;
int maxzoom = 32;
bool force = false;
void do_stats(mvt_tile &tile, size_t size, bool compressed, int z, unsigned x, unsigned y) {
printf("{ \"zoom\": %d, \"x\": %u, \"y\": %u, \"bytes\": %zu, \"compressed\": %s", z, x, y, size, compressed ? "true" : "false");
void do_stats(mvt_tile &tile, size_t size, bool compressed, int z, unsigned x, unsigned y, json_writer &state) {
state.json_write_hash();
state.json_write_string("zoom");
state.json_write_signed(z);
state.json_write_string("x");
state.json_write_unsigned(x);
state.json_write_string("y");
state.json_write_unsigned(y);
state.json_write_string("bytes");
state.json_write_unsigned(size);
state.json_write_string("compressed");
state.json_write_bool(compressed);
state.json_write_string("layers");
state.json_write_hash();
printf(", \"layers\": { ");
for (size_t i = 0; i < tile.layers.size(); i++) {
if (i != 0) {
printf(", ");
}
fprintq(stdout, tile.layers[i].name.c_str());
state.json_write_string(tile.layers[i].name);
int points = 0, lines = 0, polygons = 0;
size_t points = 0, lines = 0, polygons = 0;
for (size_t j = 0; j < tile.layers[i].features.size(); j++) {
if (tile.layers[i].features[j].type == mvt_point) {
points++;
@ -44,13 +62,30 @@ void do_stats(mvt_tile &tile, size_t size, bool compressed, int z, unsigned x, u
}
}
printf(": { \"points\": %d, \"lines\": %d, \"polygons\": %d, \"extent\": %lld }", points, lines, polygons, tile.layers[i].extent);
state.json_write_hash();
state.json_write_string("points");
state.json_write_unsigned(points);
state.json_write_string("lines");
state.json_write_unsigned(lines);
state.json_write_string("polygons");
state.json_write_unsigned(polygons);
state.json_write_string("extent");
state.json_write_signed(tile.layers[i].extent);
state.json_end_hash();
}
printf(" } }\n");
state.json_end_hash();
state.json_end_hash();
state.json_write_newline();
}
void handle(std::string message, int z, unsigned x, unsigned y, int describe, std::set<std::string> const &to_decode, bool pipeline, bool stats) {
void handle(std::string message, int z, unsigned x, unsigned y, std::set<std::string> const &to_decode, bool pipeline, bool stats, json_writer &state) {
mvt_tile tile;
bool was_compressed;
@ -59,34 +94,63 @@ void handle(std::string message, int z, unsigned x, unsigned y, int describe, st
fprintf(stderr, "Couldn't parse tile %d/%u/%u\n", z, x, y);
exit(EXIT_FAILURE);
}
} catch (protozero::unknown_pbf_wire_type_exception e) {
} catch (std::exception const &e) {
fprintf(stderr, "PBF decoding error in tile %d/%u/%u\n", z, x, y);
exit(EXIT_FAILURE);
}
if (stats) {
do_stats(tile, message.size(), was_compressed, z, x, y);
do_stats(tile, message.size(), was_compressed, z, x, y, state);
return;
}
if (!pipeline) {
printf("{ \"type\": \"FeatureCollection\"");
state.json_write_hash();
state.json_write_string("type");
state.json_write_string("FeatureCollection");
if (true) {
state.json_write_string("properties");
state.json_write_hash();
state.json_write_string("zoom");
state.json_write_signed(z);
state.json_write_string("x");
state.json_write_signed(x);
state.json_write_string("y");
state.json_write_signed(y);
if (describe) {
printf(", \"properties\": { \"zoom\": %d, \"x\": %d, \"y\": %d", z, x, y);
if (!was_compressed) {
printf(", \"compressed\": false");
state.json_write_string("compressed");
state.json_write_bool(false);
}
printf(" }");
state.json_end_hash();
if (projection != projections) {
printf(", \"crs\": { \"type\": \"name\", \"properties\": { \"name\": ");
fprintq(stdout, projection->alias);
printf(" } }");
state.json_write_string("crs");
state.json_write_hash();
state.json_write_string("type");
state.json_write_string("name");
state.json_write_string("properties");
state.json_write_hash();
state.json_write_string("name");
state.json_write_string(projection->alias);
state.json_end_hash();
state.json_end_hash();
}
}
printf(", \"features\": [\n");
state.json_write_string("features");
state.json_write_array();
state.json_write_newline();
}
bool first_layer = true;
@ -103,18 +167,34 @@ void handle(std::string message, int z, unsigned x, unsigned y, int describe, st
}
if (!pipeline) {
if (describe) {
if (true) {
if (!first_layer) {
printf(",\n");
state.json_comma_newline();
}
printf("{ \"type\": \"FeatureCollection\"");
printf(", \"properties\": { \"layer\": ");
fprintq(stdout, layer.name.c_str());
printf(", \"version\": %d, \"extent\": %lld", layer.version, layer.extent);
printf(" }");
printf(", \"features\": [\n");
state.json_write_hash();
state.json_write_string("type");
state.json_write_string("FeatureCollection");
state.json_write_string("properties");
state.json_write_hash();
state.json_write_string("layer");
state.json_write_string(layer.name);
state.json_write_string("version");
state.json_write_signed(layer.version);
state.json_write_string("extent");
state.json_write_signed(layer.extent);
state.json_end_hash();
state.json_write_string("features");
state.json_write_array();
state.json_write_newline();
first_layer = false;
}
}
@ -125,24 +205,30 @@ void handle(std::string message, int z, unsigned x, unsigned y, int describe, st
exit(EXIT_FAILURE);
}
layer_to_geojson(stdout, layer, z, x, y, !pipeline, pipeline, pipeline, 0, 0, 0, !force);
layer_to_geojson(layer, z, x, y, !pipeline, pipeline, pipeline, false, 0, 0, 0, !force, state);
if (!pipeline) {
if (describe) {
printf("] }\n");
if (true) {
state.json_end_array();
state.json_end_hash();
state.json_write_newline();
}
}
}
if (!pipeline) {
printf("] }\n");
state.json_end_array();
state.json_end_hash();
state.json_write_newline();
}
}
void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> const &to_decode, bool pipeline, bool stats) {
sqlite3 *db;
void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> const &to_decode, bool pipeline, bool stats, std::set<std::string> const &exclude_meta) {
sqlite3 *db = NULL;
bool isdir = false;
int oz = z;
unsigned ox = x, oy = y;
json_writer state(stdout);
int fd = open(fname, O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
@ -154,7 +240,7 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
if (strcmp(map, "SQLite format 3") != 0) {
if (z >= 0) {
std::string s = std::string(map, st.st_size);
handle(s, z, x, y, 1, to_decode, pipeline, stats);
handle(s, z, x, y, to_decode, pipeline, stats, state);
munmap(map, st.st_size);
return;
} else {
@ -176,16 +262,38 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
perror(fname);
}
if (sqlite3_open(fname, &db) != SQLITE_OK) {
fprintf(stderr, "%s: %s\n", fname, sqlite3_errmsg(db));
exit(EXIT_FAILURE);
struct stat st;
std::vector<zxy> tiles;
if (stat(fname, &st) == 0 && (st.st_mode & S_IFDIR) != 0) {
isdir = true;
db = dirmeta2tmp(fname);
tiles = enumerate_dirtiles(fname, minzoom, maxzoom);
} else {
if (sqlite3_open(fname, &db) != SQLITE_OK) {
fprintf(stderr, "%s: %s\n", fname, sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
char *err = NULL;
if (sqlite3_exec(db, "PRAGMA integrity_check;", NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "%s: integrity_check: %s\n", fname, err);
exit(EXIT_FAILURE);
}
}
if (z < 0) {
int within = 0;
if (!pipeline && !stats) {
printf("{ \"type\": \"FeatureCollection\", \"properties\": {\n");
state.json_write_hash();
state.json_write_string("type");
state.json_write_string("FeatureCollection");
state.json_write_string("properties");
state.json_write_hash();
state.json_write_newline();
const char *sql2 = "SELECT name, value from metadata order by name;";
sqlite3_stmt *stmt2;
@ -195,84 +303,134 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
}
while (sqlite3_step(stmt2) == SQLITE_ROW) {
if (within) {
printf(",\n");
}
within = 1;
const unsigned char *name = sqlite3_column_text(stmt2, 0);
const unsigned char *value = sqlite3_column_text(stmt2, 1);
if (name == NULL || value == NULL) {
fprintf(stderr, "Corrupt mbtiles file: null metadata\n");
exit(EXIT_FAILURE);
}
if (exclude_meta.count((char *) name) == 0) {
if (within) {
state.json_comma_newline();
}
within = 1;
fprintq(stdout, (char *) name);
printf(": ");
fprintq(stdout, (char *) value);
if (name == NULL || value == NULL) {
fprintf(stderr, "Corrupt mbtiles file: null metadata\n");
exit(EXIT_FAILURE);
}
state.json_write_string((char *) name);
state.json_write_string((char *) value);
}
}
state.json_write_newline();
state.wantnl = false; // XXX
sqlite3_finalize(stmt2);
}
if (stats) {
printf("[\n");
state.json_write_array();
state.json_write_newline();
}
const char *sql = "SELECT tile_data, zoom_level, tile_column, tile_row from tiles where zoom_level between ? and ? order by zoom_level, tile_column, tile_row;";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
fprintf(stderr, "%s: select failed: %s\n", fname, sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
sqlite3_bind_int(stmt, 1, minzoom);
sqlite3_bind_int(stmt, 2, maxzoom);
if (!pipeline && !stats) {
printf("\n}, \"features\": [\n");
state.json_end_hash();
state.json_write_string("features");
state.json_write_array();
state.json_write_newline();
}
within = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) {
if (!pipeline && !stats) {
if (within) {
printf(",\n");
if (isdir) {
within = 0;
for (size_t i = 0; i < tiles.size(); i++) {
if (!pipeline && !stats) {
if (within) {
state.json_comma_newline();
}
within = 1;
}
within = 1;
}
if (stats) {
if (within) {
printf(",\n");
if (stats) {
if (within) {
state.json_comma_newline();
}
within = 1;
}
within = 1;
std::string fn = std::string(fname) + "/" + tiles[i].path();
FILE *f = fopen(fn.c_str(), "rb");
if (f == NULL) {
perror(fn.c_str());
exit(EXIT_FAILURE);
}
std::string s;
char buf[2000];
ssize_t n;
while ((n = fread(buf, 1, 2000, f)) > 0) {
s.append(std::string(buf, n));
}
fclose(f);
handle(s, tiles[i].z, tiles[i].x, tiles[i].y, to_decode, pipeline, stats, state);
}
int len = sqlite3_column_bytes(stmt, 0);
int tz = sqlite3_column_int(stmt, 1);
int tx = sqlite3_column_int(stmt, 2);
int ty = sqlite3_column_int(stmt, 3);
if (tz < 0 || tz >= 32) {
fprintf(stderr, "Impossible zoom level %d in mbtiles\n", tz);
} else {
const char *sql = "SELECT tile_data, zoom_level, tile_column, tile_row from tiles where zoom_level between ? and ? order by zoom_level, tile_column, tile_row;";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
fprintf(stderr, "%s: select failed: %s\n", fname, sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
ty = (1LL << tz) - 1 - ty;
const char *s = (const char *) sqlite3_column_blob(stmt, 0);
sqlite3_bind_int(stmt, 1, minzoom);
sqlite3_bind_int(stmt, 2, maxzoom);
handle(std::string(s, len), tz, tx, ty, 1, to_decode, pipeline, stats);
within = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) {
if (!pipeline && !stats) {
if (within) {
state.json_comma_newline();
}
within = 1;
}
if (stats) {
if (within) {
state.json_comma_newline();
}
within = 1;
}
int len = sqlite3_column_bytes(stmt, 0);
int tz = sqlite3_column_int(stmt, 1);
int tx = sqlite3_column_int(stmt, 2);
int ty = sqlite3_column_int(stmt, 3);
if (tz < 0 || tz >= 32) {
fprintf(stderr, "Impossible zoom level %d in mbtiles\n", tz);
exit(EXIT_FAILURE);
}
ty = (1LL << tz) - 1 - ty;
const char *s = (const char *) sqlite3_column_blob(stmt, 0);
handle(std::string(s, len), tz, tx, ty, to_decode, pipeline, stats, state);
}
sqlite3_finalize(stmt);
}
if (!pipeline && !stats) {
printf("] }\n");
state.json_end_array();
state.json_end_hash();
state.json_write_newline();
}
if (stats) {
printf("]\n");
state.json_end_array();
state.json_write_newline();
}
if (pipeline) {
state.json_write_newline();
}
sqlite3_finalize(stmt);
} else {
int handled = 0;
while (z >= 0 && !handled) {
@ -295,7 +453,7 @@ void decode(char *fname, int z, unsigned x, unsigned y, std::set<std::string> co
fprintf(stderr, "%s: Warning: using tile %d/%u/%u instead of %d/%u/%u\n", fname, z, x, y, oz, ox, oy);
}
handle(std::string(s, len), z, x, y, 0, to_decode, pipeline, stats);
handle(std::string(s, len), z, x, y, to_decode, pipeline, stats, state);
handled = 1;
}
@ -325,6 +483,7 @@ int main(int argc, char **argv) {
std::set<std::string> to_decode;
bool pipeline = false;
bool stats = false;
std::set<std::string> exclude_meta;
struct option long_options[] = {
{"projection", required_argument, 0, 's'},
@ -334,6 +493,7 @@ int main(int argc, char **argv) {
{"tag-layer-and-zoom", no_argument, 0, 'c'},
{"stats", no_argument, 0, 'S'},
{"force", no_argument, 0, 'f'},
{"exclude-metadata-row", required_argument, 0, 'x'},
{0, 0, 0, 0},
};
@ -381,15 +541,19 @@ int main(int argc, char **argv) {
force = true;
break;
case 'x':
exclude_meta.insert(optarg);
break;
default:
usage(argv);
}
}
if (argc == optind + 4) {
decode(argv[optind], atoi(argv[optind + 1]), atoi(argv[optind + 2]), atoi(argv[optind + 3]), to_decode, pipeline, stats);
decode(argv[optind], atoi(argv[optind + 1]), atoi(argv[optind + 2]), atoi(argv[optind + 3]), to_decode, pipeline, stats, exclude_meta);
} else if (argc == optind + 1) {
decode(argv[optind], -1, -1, -1, to_decode, pipeline, stats);
decode(argv[optind], -1, -1, -1, to_decode, pipeline, stats, exclude_meta);
} else {
usage(argv);
}

View File

@ -2,15 +2,19 @@
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <sys/stat.h>
#include <sqlite3.h>
#include "jsonpull/jsonpull.h"
#include "dirtiles.hpp"
std::string dir_read_tile(std::string pbfPath) {
std::ifstream pbfFile(pbfPath, std::ios::in | std::ios::binary);
std::string dir_read_tile(std::string base, struct zxy tile) {
std::ifstream pbfFile(base + "/" + tile.path(), std::ios::in | std::ios::binary);
std::ostringstream contents;
contents << pbfFile.rdbuf();
pbfFile.close();
@ -39,7 +43,7 @@ void dir_write_tile(const char *outdir, int z, int tx, int ty, std::string const
pbfFile.close();
}
bool numeric(const char *s) {
static bool numeric(const char *s) {
if (*s == '\0') {
return false;
}
@ -51,33 +55,63 @@ bool numeric(const char *s) {
return true;
}
bool pbfname(const char *s) {
static bool pbfname(const char *s) {
while (*s >= '0' && *s <= '9') {
s++;
}
return strcmp(s, ".pbf") == 0;
return strcmp(s, ".pbf") == 0 || strcmp(s, ".mvt") == 0;
}
void check_dir(const char *dir, bool rm) {
void check_dir(const char *dir, char **argv, bool force, bool forcetable) {
struct stat st;
mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
std::string meta = std::string(dir) + "/" + "metadata.json";
if (rm) {
if (force) {
unlink(meta.c_str()); // error OK since it may not exist;
} else {
if (stat(meta.c_str(), &st) == 0) {
fprintf(stderr, "%s: file exists\n", meta.c_str());
exit(EXIT_FAILURE);
fprintf(stderr, "%s: Tileset \"%s\" already exists. You can use --force if you want to delete the old tileset.\n", argv[0], dir);
fprintf(stderr, "%s: %s: file exists\n", argv[0], meta.c_str());
if (!forcetable) {
exit(EXIT_FAILURE);
}
}
}
DIR *d1 = opendir(dir);
if (forcetable) {
// Don't clear existing tiles
return;
}
std::vector<zxy> tiles = enumerate_dirtiles(dir, INT_MIN, INT_MAX);
for (size_t i = 0; i < tiles.size(); i++) {
std::string fn = std::string(dir) + "/" + tiles[i].path();
if (force) {
if (unlink(fn.c_str()) != 0) {
perror(fn.c_str());
exit(EXIT_FAILURE);
}
} else {
fprintf(stderr, "%s: file exists\n", fn.c_str());
exit(EXIT_FAILURE);
}
}
}
std::vector<zxy> enumerate_dirtiles(const char *fname, int minzoom, int maxzoom) {
std::vector<zxy> tiles;
DIR *d1 = opendir(fname);
if (d1 != NULL) {
struct dirent *dp;
while ((dp = readdir(d1)) != NULL) {
if (numeric(dp->d_name)) {
std::string z = std::string(dir) + "/" + dp->d_name;
if (numeric(dp->d_name) && atoi(dp->d_name) >= minzoom && atoi(dp->d_name) <= maxzoom) {
std::string z = std::string(fname) + "/" + dp->d_name;
int tz = atoi(dp->d_name);
DIR *d2 = opendir(z.c_str());
if (d2 == NULL) {
@ -89,6 +123,7 @@ void check_dir(const char *dir, bool rm) {
while ((dp2 = readdir(d2)) != NULL) {
if (numeric(dp2->d_name)) {
std::string x = z + "/" + dp2->d_name;
int tx = atoi(dp2->d_name);
DIR *d3 = opendir(x.c_str());
if (d3 == NULL) {
@ -99,17 +134,13 @@ void check_dir(const char *dir, bool rm) {
struct dirent *dp3;
while ((dp3 = readdir(d3)) != NULL) {
if (pbfname(dp3->d_name)) {
std::string y = x + "/" + dp3->d_name;
if (rm) {
if (unlink(y.c_str()) != 0) {
perror(y.c_str());
exit(EXIT_FAILURE);
}
} else {
fprintf(stderr, "%s: file exists\n", y.c_str());
exit(EXIT_FAILURE);
int ty = atoi(dp3->d_name);
zxy tile(tz, tx, ty);
if (strstr(dp3->d_name, ".mvt") != NULL) {
tile.extension = ".mvt";
}
tiles.push_back(tile);
}
}
@ -123,4 +154,58 @@ void check_dir(const char *dir, bool rm) {
closedir(d1);
}
std::sort(tiles.begin(), tiles.end());
return tiles;
}
sqlite3 *dirmeta2tmp(const char *fname) {
sqlite3 *db;
char *err = NULL;
if (sqlite3_open("", &db) != SQLITE_OK) {
fprintf(stderr, "Temporary db: %s\n", sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
if (sqlite3_exec(db, "CREATE TABLE metadata (name text, value text);", NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "Create metadata table: %s\n", err);
exit(EXIT_FAILURE);
}
std::string name = fname;
name += "/metadata.json";
FILE *f = fopen(name.c_str(), "r");
if (f == NULL) {
perror(name.c_str());
} else {
json_pull *jp = json_begin_file(f);
json_object *o = json_read_tree(jp);
if (o == NULL) {
fprintf(stderr, "%s: metadata parsing error: %s\n", name.c_str(), jp->error);
exit(EXIT_FAILURE);
}
if (o->type != JSON_HASH) {
fprintf(stderr, "%s: bad metadata format\n", name.c_str());
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < o->length; i++) {
if (o->keys[i]->type != JSON_STRING || o->values[i]->type != JSON_STRING) {
fprintf(stderr, "%s: non-string in metadata\n", name.c_str());
}
char *sql = sqlite3_mprintf("INSERT INTO metadata (name, value) VALUES (%Q, %Q);", o->keys[i]->string, o->values[i]->string);
if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "set %s in metadata: %s\n", o->keys[i]->string, err);
}
sqlite3_free(sql);
}
json_end(jp);
fclose(f);
}
return db;
}

View File

@ -1,12 +1,49 @@
#include <string>
#include <vector>
#include <sys/stat.h>
#ifndef DIRTILES_HPP
#define DIRTILES_HPP
std::string dir_read_tile(std::string pbfPath);
void dir_write_tile(const char *outdir, int z, int tx, int ty, std::string const &pbf);
void check_dir(const char *d, bool rm);
void check_dir(const char *d, char **argv, bool force, bool forcetable);
struct zxy {
long long z;
long long x;
long long y;
std::string extension = ".pbf";
zxy(int _z, int _x, int _y)
: z(_z), x(_x), y(_y) {
}
bool operator<(const zxy &other) const {
if (z < other.z) {
return true;
}
if (z == other.z) {
if (x < other.x) {
return true;
}
if (x == other.x) {
if (y > other.y) {
return true; // reversed for TMS
}
}
}
return false;
}
std::string path() {
return std::to_string(z) + "/" + std::to_string(x) + "/" + std::to_string(y) + extension;
}
};
std::vector<zxy> enumerate_dirtiles(const char *fname, int minzoom, int maxzoom);
sqlite3 *dirmeta2tmp(const char *fname);
std::string dir_read_tile(std::string pbfPath, struct zxy tile);
#endif

View File

@ -11,6 +11,12 @@ void enumerate(char *fname) {
exit(EXIT_FAILURE);
}
char *err = NULL;
if (sqlite3_exec(db, "PRAGMA integrity_check;", NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "%s: integrity_check: %s\n", fname, err);
exit(EXIT_FAILURE);
}
const char *sql = "SELECT zoom_level, tile_column, tile_row from tiles order by zoom_level, tile_column, tile_row;";
sqlite3_stmt *stmt;

View File

@ -69,7 +69,7 @@ int compare(mvt_value one, json_object *two, bool &fail) {
exit(EXIT_FAILURE);
}
bool eval(std::map<std::string, mvt_value> const &feature, json_object *f) {
bool eval(std::map<std::string, mvt_value> const &feature, json_object *f, std::set<std::string> &exclude_attributes) {
if (f == NULL || f->type != JSON_ARRAY) {
fprintf(stderr, "Filter is not an array: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
@ -191,7 +191,7 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f) {
}
for (size_t i = 1; i < f->length; i++) {
bool out = eval(feature, f->array[i]);
bool out = eval(feature, f->array[i], exclude_attributes);
if (strcmp(f->array[0]->string, "all") == 0) {
v = v && out;
@ -269,11 +269,30 @@ bool eval(std::map<std::string, mvt_value> const &feature, json_object *f) {
}
}
if (strcmp(f->array[0]->string, "attribute-filter") == 0) {
if (f->length != 3) {
fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
}
if (f->array[1]->type != JSON_STRING) {
fprintf(stderr, "\"attribute-filter\" key is not a string: %s\n", json_stringify(f));
exit(EXIT_FAILURE);
}
bool ok = eval(feature, f->array[2], exclude_attributes);
if (!ok) {
exclude_attributes.insert(f->array[1]->string);
}
return true;
}
fprintf(stderr, "Unknown filter %s\n", json_stringify(f));
exit(EXIT_FAILURE);
}
bool evaluate(std::map<std::string, mvt_value> const &feature, std::string const &layer, json_object *filter) {
bool evaluate(std::map<std::string, mvt_value> const &feature, std::string const &layer, json_object *filter, std::set<std::string> &exclude_attributes) {
if (filter == NULL || filter->type != JSON_HASH) {
fprintf(stderr, "Error: filter is not a hash: %s\n", json_stringify(filter));
exit(EXIT_FAILURE);
@ -284,12 +303,12 @@ bool evaluate(std::map<std::string, mvt_value> const &feature, std::string const
f = json_hash_get(filter, layer.c_str());
if (ok && f != NULL) {
ok = eval(feature, f);
ok = eval(feature, f, exclude_attributes);
}
f = json_hash_get(filter, "*");
if (ok && f != NULL) {
ok = eval(feature, f);
ok = eval(feature, f, exclude_attributes);
}
return ok;

View File

@ -3,10 +3,11 @@
#include <map>
#include <string>
#include <set>
#include "jsonpull/jsonpull.h"
#include "mvt.hpp"
bool evaluate(std::map<std::string, mvt_value> const &feature, std::string const &layer, json_object *filter);
bool evaluate(std::map<std::string, mvt_value> const &feature, std::string const &layer, json_object *filter, std::set<std::string> &exclude_attributes);
json_object *parse_filter(const char *s);
json_object *read_filter(const char *fname);

View File

@ -13,6 +13,7 @@
#include "protozero/pbf_writer.hpp"
#include "milo/dtoa_milo.h"
#include "jsonpull/jsonpull.h"
#include "text.hpp"
#define POINT 0
#define MULTIPOINT 1
@ -253,6 +254,8 @@ std::vector<drawvec_type> readGeometry(protozero::pbf_reader &pbf, size_t dim, d
dv.dv = readLine(coords, dim, e, false);
} else if (type == POLYGON) {
dv.dv = readMultiLine(coords, lengths, dim, e, true);
} else if (type == MULTILINESTRING) {
dv.dv = readMultiLine(coords, lengths, dim, e, false);
} else if (type == MULTIPOLYGON) {
dv.dv = readMultiPolygon(coords, lengths, dim, e);
} else {
@ -387,7 +390,6 @@ void readFeature(protozero::pbf_reader &pbf, size_t dim, double e, std::vector<s
sf.t = dv[i].type;
sf.full_keys = full_keys;
sf.full_values = full_values;
sf.m = sf.full_values.size();
auto tip = other.find("tippecanoe");
if (tip != other.end()) {
@ -398,13 +400,13 @@ void readFeature(protozero::pbf_reader &pbf, size_t dim, double e, std::vector<s
json_object *min = json_hash_get(o, "minzoom");
if (min != NULL && (min->type == JSON_STRING || min->type == JSON_NUMBER)) {
sf.has_tippecanoe_minzoom = true;
sf.tippecanoe_minzoom = atoi(min->string);
sf.tippecanoe_minzoom = integer_zoom(sst->fname, min->string);
}
json_object *max = json_hash_get(o, "maxzoom");
if (max != NULL && (max->type == JSON_STRING || max->type == JSON_NUMBER)) {
sf.has_tippecanoe_maxzoom = true;
sf.tippecanoe_maxzoom = atoi(max->string);
sf.tippecanoe_maxzoom = integer_zoom(sst->fname, max->string);
}
json_object *tlayer = json_hash_get(o, "layer");
@ -476,7 +478,9 @@ void runQueue() {
}
}
*((*(feature_queue[0].sst))[0].layer_seq) = *((*(feature_queue[0].sst))[CPUS - 1].layer_seq);
// Lack of atomicity is OK, since we are single-threaded again here
long long was = *((*(feature_queue[0].sst))[CPUS - 1].layer_seq);
*((*(feature_queue[0].sst))[0].layer_seq) = was;
feature_queue.clear();
}
@ -510,7 +514,6 @@ void outBareGeometry(drawvec const &dv, int type, struct serialization_state *ss
sf.seq = (*sst->layer_seq);
sf.geometry = dv;
sf.t = type;
sf.m = 0;
serialize_feature(sst, sf);
}

139
geocsv.cpp Normal file
View File

@ -0,0 +1,139 @@
#include <stdlib.h>
#include <algorithm>
#include "geocsv.hpp"
#include "mvt.hpp"
#include "serial.hpp"
#include "projection.hpp"
#include "main.hpp"
#include "text.hpp"
#include "csv.hpp"
#include "milo/dtoa_milo.h"
#include "options.hpp"
void parse_geocsv(std::vector<struct serialization_state> &sst, std::string fname, int layer, std::string layername) {
FILE *f;
if (fname.size() == 0) {
f = stdin;
} else {
f = fopen(fname.c_str(), "r");
if (f == NULL) {
perror(fname.c_str());
exit(EXIT_FAILURE);
}
}
std::string s;
std::vector<std::string> header;
ssize_t latcol = -1, loncol = -1;
if ((s = csv_getline(f)).size() > 0) {
std::string err = check_utf8(s);
if (err != "") {
fprintf(stderr, "%s: %s\n", fname.c_str(), err.c_str());
exit(EXIT_FAILURE);
}
header = csv_split(s.c_str());
for (size_t i = 0; i < header.size(); i++) {
header[i] = csv_dequote(header[i]);
std::string lower(header[i]);
std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
if (lower == "y" || lower == "lat" || (lower.find("latitude") != std::string::npos)) {
latcol = i;
}
if (lower == "x" || lower == "lon" || lower == "lng" || lower == "long" || (lower.find("longitude") != std::string::npos)) {
loncol = i;
}
}
}
if (latcol < 0 || loncol < 0) {
fprintf(stderr, "%s: Can't find \"lat\" and \"lon\" columns\n", fname.c_str());
exit(EXIT_FAILURE);
}
size_t seq = 0;
while ((s = csv_getline(f)).size() > 0) {
std::string err = check_utf8(s);
if (err != "") {
fprintf(stderr, "%s: %s\n", fname.c_str(), err.c_str());
exit(EXIT_FAILURE);
}
seq++;
std::vector<std::string> line = csv_split(s.c_str());
if (line.size() != header.size()) {
fprintf(stderr, "%s:%zu: Mismatched column count: %zu in line, %zu in header\n", fname.c_str(), seq + 1, line.size(), header.size());
exit(EXIT_FAILURE);
}
if (line[loncol].empty() || line[latcol].empty()) {
static int warned = 0;
if (!warned) {
fprintf(stderr, "%s:%zu: null geometry (additional not reported)\n", fname.c_str(), seq + 1);
warned = 1;
}
continue;
}
double lon = atof(line[loncol].c_str());
double lat = atof(line[latcol].c_str());
long long x, y;
projection->project(lon, lat, 32, &x, &y);
drawvec dv;
dv.push_back(draw(VT_MOVETO, x, y));
std::vector<std::string> full_keys;
std::vector<serial_val> full_values;
for (size_t i = 0; i < line.size(); i++) {
if (i != (size_t) latcol && i != (size_t) loncol) {
line[i] = csv_dequote(line[i]);
serial_val sv;
if (is_number(line[i])) {
sv.type = mvt_double;
} else if (line[i].size() == 0 && prevent[P_EMPTY_CSV_COLUMNS]) {
sv.type = mvt_null;
line[i] = "null";
} else {
sv.type = mvt_string;
}
sv.s = line[i];
full_keys.push_back(header[i]);
full_values.push_back(sv);
}
}
serial_feature sf;
sf.layer = layer;
sf.layername = layername;
sf.segment = sst[0].segment;
sf.has_id = false;
sf.id = 0;
sf.has_tippecanoe_minzoom = false;
sf.has_tippecanoe_maxzoom = false;
sf.feature_minzoom = false;
sf.seq = *(sst[0].layer_seq);
sf.geometry = dv;
sf.t = 1; // POINT
sf.full_keys = full_keys;
sf.full_values = full_values;
serialize_feature(&sst[0], sf);
}
if (fname.size() != 0) {
if (fclose(f) != 0) {
perror("fclose");
exit(EXIT_FAILURE);
}
}
}

13
geocsv.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef GEOCSV_HPP
#define GEOCSV_HPP
#include <stdio.h>
#include <set>
#include <map>
#include <string>
#include "mbtiles.hpp"
#include "serial.hpp"
void parse_geocsv(std::vector<struct serialization_state> &sst, std::string fname, int layer, std::string layername);
#endif

184
geojson-loop.cpp Normal file
View File

@ -0,0 +1,184 @@
#ifdef MTRACE
#include <mcheck.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include "geojson-loop.hpp"
#include "jsonpull/jsonpull.h"
// XXX duplicated
#define GEOM_TYPES 6
static const char *geometry_names[GEOM_TYPES] = {
"Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon",
};
// XXX duplicated
static void json_context(json_object *j) {
char *s = json_stringify(j);
if (strlen(s) >= 500) {
sprintf(s + 497, "...");
}
fprintf(stderr, "In JSON object %s\n", s);
free(s); // stringify
}
void parse_json(json_feature_action *jfa, json_pull *jp) {
long long found_hashes = 0;
long long found_features = 0;
long long found_geometries = 0;
while (1) {
json_object *j = json_read(jp);
if (j == NULL) {
if (jp->error != NULL) {
fprintf(stderr, "%s:%d: %s\n", jfa->fname.c_str(), jp->line, jp->error);
if (jp->root != NULL) {
json_context(jp->root);
}
}
json_free(jp->root);
break;
}
if (j->type == JSON_HASH) {
found_hashes++;
if (found_hashes == 50 && found_features == 0 && found_geometries == 0) {
fprintf(stderr, "%s:%d: Warning: not finding any GeoJSON features or geometries in input yet after 50 objects.\n", jfa->fname.c_str(), jp->line);
}
}
json_object *type = json_hash_get(j, "type");
if (type == NULL || type->type != JSON_STRING) {
continue;
}
if (found_features == 0) {
int i;
int is_geometry = 0;
for (i = 0; i < GEOM_TYPES; i++) {
if (strcmp(type->string, geometry_names[i]) == 0) {
is_geometry = 1;
break;
}
}
if (is_geometry) {
if (j->parent != NULL) {
if (j->parent->type == JSON_ARRAY && j->parent->parent != NULL) {
if (j->parent->parent->type == JSON_HASH) {
json_object *geometries = json_hash_get(j->parent->parent, "geometries");
if (geometries != NULL) {
// Parent of Parent must be a GeometryCollection
is_geometry = 0;
}
}
} else if (j->parent->type == JSON_HASH) {
json_object *geometry = json_hash_get(j->parent, "geometry");
if (geometry != NULL) {
// Parent must be a Feature
is_geometry = 0;
}
}
}
}
if (is_geometry) {
json_object *jo = j;
while (jo != NULL) {
if (jo->parent != NULL && jo->parent->type == JSON_HASH) {
if (json_hash_get(jo->parent, "properties") == jo) {
// Ancestor is the value corresponding to a properties key
is_geometry = 0;
break;
}
}
jo = jo->parent;
}
}
if (is_geometry) {
if (found_features != 0 && found_geometries == 0) {
fprintf(stderr, "%s:%d: Warning: found a mixture of features and bare geometries\n", jfa->fname.c_str(), jp->line);
}
found_geometries++;
jfa->add_feature(j, false, NULL, NULL, NULL, j);
json_free(j);
continue;
}
}
if (strcmp(type->string, "Feature") != 0) {
if (strcmp(type->string, "FeatureCollection") == 0) {
jfa->check_crs(j);
json_free(j);
}
continue;
}
if (found_features == 0 && found_geometries != 0) {
fprintf(stderr, "%s:%d: Warning: found a mixture of features and bare geometries\n", jfa->fname.c_str(), jp->line);
}
found_features++;
json_object *geometry = json_hash_get(j, "geometry");
if (geometry == NULL) {
fprintf(stderr, "%s:%d: feature with no geometry\n", jfa->fname.c_str(), jp->line);
json_context(j);
json_free(j);
continue;
}
json_object *properties = json_hash_get(j, "properties");
if (properties == NULL || (properties->type != JSON_HASH && properties->type != JSON_NULL)) {
fprintf(stderr, "%s:%d: feature without properties hash\n", jfa->fname.c_str(), jp->line);
json_context(j);
json_free(j);
continue;
}
bool is_feature = true;
{
json_object *jo = j;
while (jo != NULL) {
if (jo->parent != NULL && jo->parent->type == JSON_HASH) {
if (json_hash_get(jo->parent, "properties") == jo) {
// Ancestor is the value corresponding to a properties key
is_feature = false;
break;
}
}
jo = jo->parent;
}
}
if (!is_feature) {
continue;
}
json_object *tippecanoe = json_hash_get(j, "tippecanoe");
json_object *id = json_hash_get(j, "id");
json_object *geometries = json_hash_get(geometry, "geometries");
if (geometries != NULL && geometries->type == JSON_ARRAY) {
jfa->add_feature(geometries, true, properties, id, tippecanoe, j);
} else {
jfa->add_feature(geometry, false, properties, id, tippecanoe, j);
}
json_free(j);
/* XXX check for any non-features in the outer object */
}
}

11
geojson-loop.hpp Normal file
View File

@ -0,0 +1,11 @@
#include <string>
#include "jsonpull/jsonpull.h"
struct json_feature_action {
std::string fname;
virtual int add_feature(json_object *geometry, bool geometrycollection, json_object *properties, json_object *id, json_object *tippecanoe, json_object *feature) = 0;
virtual void check_crs(json_object *j) = 0;
};
void parse_json(json_feature_action *action, json_pull *jp);

View File

@ -37,6 +37,7 @@
#include "text.hpp"
#include "read_json.hpp"
#include "mvt.hpp"
#include "geojson-loop.hpp"
int serialize_geojson_feature(struct serialization_state *sst, json_object *geometry, json_object *properties, json_object *id, int layer, json_object *tippecanoe, json_object *feature, std::string layername) {
json_object *geometry_type = json_hash_get(geometry, "type");
@ -82,19 +83,13 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom
if (tippecanoe != NULL) {
json_object *min = json_hash_get(tippecanoe, "minzoom");
if (min != NULL && min->type == JSON_NUMBER) {
tippecanoe_minzoom = min->number;
}
if (min != NULL && min->type == JSON_STRING) {
tippecanoe_minzoom = atoi(min->string);
if (min != NULL && (min->type == JSON_STRING || min->type == JSON_NUMBER)) {
tippecanoe_minzoom = integer_zoom(sst->fname, min->string);
}
json_object *max = json_hash_get(tippecanoe, "maxzoom");
if (max != NULL && max->type == JSON_NUMBER) {
tippecanoe_maxzoom = max->number;
}
if (max != NULL && max->type == JSON_STRING) {
tippecanoe_maxzoom = atoi(max->string);
if (max != NULL && (max->type == JSON_STRING || max->type == JSON_NUMBER)) {
tippecanoe_maxzoom = integer_zoom(sst->fname, max->string);
}
json_object *ln = json_hash_get(tippecanoe, "layer");
@ -118,6 +113,13 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom
fprintf(stderr, "Warning: Can't represent non-integer feature ID %s\n", id->string);
warned_frac = true;
}
} else if (std::to_string(id_value) != id->string) {
static bool warned = false;
if (!warned) {
fprintf(stderr, "Warning: Can't represent too-large feature ID %s\n", id->string);
warned = true;
}
} else {
has_id = true;
}
@ -130,13 +132,41 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom
}
}
} else {
static bool warned_nan = false;
bool converted = false;
if (!warned_nan) {
char *s = json_stringify(id);
fprintf(stderr, "Warning: Can't represent non-numeric feature ID %s\n", s);
free(s); // stringify
warned_nan = true;
if (additional[A_CONVERT_NUMERIC_IDS] && id->type == JSON_STRING) {
char *err = NULL;
id_value = strtoull(id->string, &err, 10);
if (err != NULL && *err != '\0') {
static bool warned_frac = false;
if (!warned_frac) {
fprintf(stderr, "Warning: Can't represent non-integer feature ID %s\n", id->string);
warned_frac = true;
}
} else if (std::to_string(id_value) != id->string) {
static bool warned = false;
if (!warned) {
fprintf(stderr, "Warning: Can't represent too-large feature ID %s\n", id->string);
warned = true;
}
} else {
has_id = true;
converted = true;
}
}
if (!converted) {
static bool warned_nan = false;
if (!warned_nan) {
char *s = json_stringify(id);
fprintf(stderr, "Warning: Can't represent non-numeric feature ID %s\n", s);
free(s); // stringify
warned_nan = true;
}
}
}
}
@ -193,7 +223,6 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom
sf.has_tippecanoe_maxzoom = (tippecanoe_maxzoom != -1);
sf.tippecanoe_maxzoom = tippecanoe_maxzoom;
sf.geometry = dv;
sf.m = m;
sf.feature_minzoom = 0; // Will be filled in during index merging
sf.seq = *(sst->layer_seq);
@ -222,7 +251,7 @@ void check_crs(json_object *j, const char *reading) {
json_object *properties = json_hash_get(crs, "properties");
if (properties != NULL) {
json_object *name = json_hash_get(properties, "name");
if (name->type == JSON_STRING) {
if (name != NULL && name->type == JSON_STRING) {
if (strcmp(name->string, projection->alias) != 0) {
if (!quiet) {
fprintf(stderr, "%s: Warning: GeoJSON specified projection \"%s\", not the expected \"%s\".\n", reading, name->string, projection->alias);
@ -234,127 +263,36 @@ void check_crs(json_object *j, const char *reading) {
}
}
void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std::string layername) {
long long found_hashes = 0;
long long found_features = 0;
long long found_geometries = 0;
struct json_serialize_action : json_feature_action {
serialization_state *sst;
int layer;
std::string layername;
while (1) {
json_object *j = json_read(jp);
if (j == NULL) {
if (jp->error != NULL) {
fprintf(stderr, "%s:%d: %s\n", sst->fname, jp->line, jp->error);
if (jp->root != NULL) {
json_context(jp->root);
}
}
json_free(jp->root);
break;
}
if (j->type == JSON_HASH) {
found_hashes++;
if (found_hashes == 50 && found_features == 0 && found_geometries == 0) {
fprintf(stderr, "%s:%d: Warning: not finding any GeoJSON features or geometries in input yet after 50 objects.\n", sst->fname, jp->line);
}
}
json_object *type = json_hash_get(j, "type");
if (type == NULL || type->type != JSON_STRING) {
continue;
}
if (found_features == 0) {
int i;
int is_geometry = 0;
for (i = 0; i < GEOM_TYPES; i++) {
if (strcmp(type->string, geometry_names[i]) == 0) {
is_geometry = 1;
break;
}
}
if (is_geometry) {
if (j->parent != NULL) {
if (j->parent->type == JSON_ARRAY) {
if (j->parent->parent->type == JSON_HASH) {
json_object *geometries = json_hash_get(j->parent->parent, "geometries");
if (geometries != NULL) {
// Parent of Parent must be a GeometryCollection
is_geometry = 0;
}
}
} else if (j->parent->type == JSON_HASH) {
json_object *geometry = json_hash_get(j->parent, "geometry");
if (geometry != NULL) {
// Parent must be a Feature
is_geometry = 0;
}
}
}
}
if (is_geometry) {
if (found_features != 0 && found_geometries == 0) {
fprintf(stderr, "%s:%d: Warning: found a mixture of features and bare geometries\n", sst->fname, jp->line);
}
found_geometries++;
serialize_geojson_feature(sst, j, NULL, NULL, layer, NULL, j, layername);
json_free(j);
continue;
}
}
if (strcmp(type->string, "Feature") != 0) {
if (strcmp(type->string, "FeatureCollection") == 0) {
check_crs(j, sst->fname);
json_free(j);
}
continue;
}
if (found_features == 0 && found_geometries != 0) {
fprintf(stderr, "%s:%d: Warning: found a mixture of features and bare geometries\n", sst->fname, jp->line);
}
found_features++;
json_object *geometry = json_hash_get(j, "geometry");
if (geometry == NULL) {
fprintf(stderr, "%s:%d: feature with no geometry\n", sst->fname, jp->line);
json_context(j);
json_free(j);
continue;
}
json_object *properties = json_hash_get(j, "properties");
if (properties == NULL || (properties->type != JSON_HASH && properties->type != JSON_NULL)) {
fprintf(stderr, "%s:%d: feature without properties hash\n", sst->fname, jp->line);
json_context(j);
json_free(j);
continue;
}
json_object *tippecanoe = json_hash_get(j, "tippecanoe");
json_object *id = json_hash_get(j, "id");
json_object *geometries = json_hash_get(geometry, "geometries");
if (geometries != NULL) {
size_t g;
for (g = 0; g < geometries->length; g++) {
serialize_geojson_feature(sst, geometries->array[g], properties, id, layer, tippecanoe, j, layername);
int add_feature(json_object *geometry, bool geometrycollection, json_object *properties, json_object *id, json_object *tippecanoe, json_object *feature) {
if (geometrycollection) {
int ret = 1;
for (size_t g = 0; g < geometry->length; g++) {
ret &= serialize_geojson_feature(sst, geometry->array[g], properties, id, layer, tippecanoe, feature, layername);
}
return ret;
} else {
serialize_geojson_feature(sst, geometry, properties, id, layer, tippecanoe, j, layername);
return serialize_geojson_feature(sst, geometry, properties, id, layer, tippecanoe, feature, layername);
}
json_free(j);
/* XXX check for any non-features in the outer object */
}
void check_crs(json_object *j) {
::check_crs(j, fname.c_str());
}
};
void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std::string layername) {
json_serialize_action jsa;
jsa.fname = sst->fname;
jsa.sst = sst;
jsa.layer = layer;
jsa.layername = layername;
parse_json(&jsa, jp);
}
void *run_parse_json(void *v) {

View File

@ -19,11 +19,12 @@
#include "projection.hpp"
#include "serial.hpp"
#include "main.hpp"
#include "options.hpp"
static int pnpoly(drawvec &vert, size_t start, size_t nvert, long long testx, long long testy);
static int clip(double *x0, double *y0, double *x1, double *y1, double xmin, double ymin, double xmax, double ymax);
drawvec decode_geometry(FILE *meta, long long *geompos, int z, unsigned tx, unsigned ty, long long *bbox, unsigned initial_x, unsigned initial_y) {
drawvec decode_geometry(FILE *meta, std::atomic<long long> *geompos, int z, unsigned tx, unsigned ty, long long *bbox, unsigned initial_x, unsigned initial_y) {
drawvec out;
bbox[0] = LLONG_MAX;
@ -267,8 +268,11 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip) {
}
mapbox::geometry::multi_polygon<long long> result;
#if 0
try {
#endif
wagyu.execute(mapbox::geometry::wagyu::clip_type_union, result, mapbox::geometry::wagyu::fill_type_positive, mapbox::geometry::wagyu::fill_type_positive);
#if 0
} catch (std::runtime_error e) {
FILE *f = fopen("/tmp/wagyu.log", "w");
fprintf(f, "%s\n", e.what());
@ -317,6 +321,7 @@ drawvec clean_or_clip_poly(drawvec &geom, int z, int buffer, bool clip) {
fprintf(stderr, "Internal error: Polygon cleaning failed. Log in /tmp/wagyu.log\n");
exit(EXIT_FAILURE);
}
#endif
drawvec ret;
decode_clipped(result, ret);
@ -594,16 +599,20 @@ drawvec reduce_tiny_poly(drawvec &geom, int z, int detail, bool *reduced, double
}
drawvec clip_point(drawvec &geom, int z, long long buffer) {
drawvec out;
long long min = 0;
long long area = 1LL << (32 - z);
min -= buffer * area / 256;
area += buffer * area / 256;
return clip_point(geom, min, min, area, area);
}
drawvec clip_point(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
drawvec out;
for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].x >= min && geom[i].y >= min && geom[i].x <= area && geom[i].y <= area) {
if (geom[i].x >= minx && geom[i].y >= miny && geom[i].x <= maxx && geom[i].y <= maxy) {
out.push_back(geom[i]);
}
}
@ -645,13 +654,17 @@ bool point_within_tile(long long x, long long y, int z) {
}
drawvec clip_lines(drawvec &geom, int z, long long buffer) {
drawvec out;
long long min = 0;
long long area = 1LL << (32 - z);
min -= buffer * area / 256;
area += buffer * area / 256;
return clip_lines(geom, min, min, area, area);
}
drawvec clip_lines(drawvec &geom, long long minx, long long miny, long long maxx, long long maxy) {
drawvec out;
for (size_t i = 0; i < geom.size(); i++) {
if (i > 0 && (geom[i - 1].op == VT_MOVETO || geom[i - 1].op == VT_LINETO) && geom[i].op == VT_LINETO) {
double x1 = geom[i - 1].x;
@ -660,7 +673,7 @@ drawvec clip_lines(drawvec &geom, int z, long long buffer) {
double x2 = geom[i - 0].x;
double y2 = geom[i - 0].y;
int c = clip(&x1, &y1, &x2, &y2, min, min, area, area);
int c = clip(&x1, &y1, &x2, &y2, minx, miny, maxx, maxy);
if (c > 1) { // clipped
out.push_back(draw(VT_MOVETO, x1, y1));
@ -793,7 +806,7 @@ drawvec impose_tile_boundaries(drawvec &geom, long long extent) {
return out;
}
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain) {
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain, drawvec const &shared_nodes) {
int res = 1 << (32 - detail - z);
long long area = 1LL << (32 - z);
@ -805,6 +818,13 @@ drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds,
} else {
geom[i].necessary = 1;
}
if (prevent[P_SIMPLIFY_SHARED_NODES]) {
auto pt = std::lower_bound(shared_nodes.begin(), shared_nodes.end(), geom[i]);
if (pt != shared_nodes.end() && *pt == geom[i]) {
geom[i].necessary = true;
}
}
}
if (mark_tile_bounds) {
@ -865,8 +885,8 @@ drawvec reorder_lines(drawvec &geom) {
// instead of down and to the right
// so that it will coalesce better
unsigned long long l1 = encode(geom[0].x, geom[0].y);
unsigned long long l2 = encode(geom[geom.size() - 1].x, geom[geom.size() - 1].y);
unsigned long long l1 = encode_index(geom[0].x, geom[0].y);
unsigned long long l2 = encode_index(geom[geom.size() - 1].x, geom[geom.size() - 1].y);
if (l1 > l2) {
drawvec out;
@ -912,8 +932,21 @@ drawvec fix_polygon(drawvec &geom) {
// Reverse ring if winding order doesn't match
// inner/outer expectation
double area = get_area(ring, 0, ring.size());
if ((area > 0) != outer) {
bool reverse_ring = false;
if (prevent[P_USE_SOURCE_POLYGON_WINDING]) {
// GeoJSON winding is reversed from vector winding
reverse_ring = true;
} else if (prevent[P_REVERSE_SOURCE_POLYGON_WINDING]) {
// GeoJSON winding is reversed from vector winding
reverse_ring = false;
} else {
double area = get_area(ring, 0, ring.size());
if ((area > 0) != outer) {
reverse_ring = true;
}
}
if (reverse_ring) {
drawvec tmp;
for (int a = ring.size() - 1; a >= 0; a--) {
tmp.push_back(ring[a]);
@ -1113,14 +1146,14 @@ drawvec stairstep(drawvec &geom, int z, int detail) {
double scale = 1 << (32 - detail - z);
for (size_t i = 0; i < geom.size(); i++) {
geom[i].x = std::round(geom[i].x / scale);
geom[i].y = std::round(geom[i].y / scale);
geom[i].x = std::floor(geom[i].x / scale);
geom[i].y = std::floor(geom[i].y / scale);
}
for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) {
out.push_back(geom[i]);
} else {
} else if (out.size() > 0) {
long long x0 = out[out.size() - 1].x;
long long y0 = out[out.size() - 1].y;
long long x1 = geom[i].x;
@ -1180,6 +1213,9 @@ drawvec stairstep(drawvec &geom, int z, int detail) {
}
// out.push_back(draw(VT_LINETO, xx, yy));
} else {
fprintf(stderr, "Can't happen: stairstepping lineto with no moveto\n");
exit(EXIT_FAILURE);
}
}

View File

@ -2,6 +2,7 @@
#define GEOMETRY_HPP
#include <vector>
#include <atomic>
#include <sqlite3.h>
#define VT_POINT 1
@ -55,7 +56,7 @@ struct draw {
typedef std::vector<draw> drawvec;
drawvec decode_geometry(FILE *meta, long long *geompos, int z, unsigned tx, unsigned ty, long long *bbox, unsigned initial_x, unsigned initial_y);
drawvec decode_geometry(FILE *meta, std::atomic<long long> *geompos, int z, unsigned tx, unsigned ty, long long *bbox, unsigned initial_x, unsigned initial_y);
void to_tile_scale(drawvec &geom, int z, int detail);
drawvec remove_noop(drawvec geom, int type, int shift);
drawvec clip_point(drawvec &geom, int z, long long buffer);
@ -67,7 +68,7 @@ drawvec clip_lines(drawvec &geom, int z, long long buffer);
drawvec stairstep(drawvec &geom, int z, int detail);
bool point_within_tile(long long x, long long y, int z);
int quick_check(long long *bbox, int z, long long buffer);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain);
drawvec simplify_lines(drawvec &geom, int z, int detail, bool mark_tile_bounds, double simplification, size_t retain, drawvec const &shared_nodes);
drawvec reorder_lines(drawvec &geom);
drawvec fix_polygon(drawvec &geom);
std::vector<drawvec> chop_polygon(std::vector<drawvec> &geoms);
@ -75,4 +76,8 @@ void check_polygon(drawvec &geom);
double get_area(drawvec &geom, size_t i, size_t j);
double get_mp_area(drawvec &geom);
drawvec simple_clip_poly(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
drawvec clip_lines(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
drawvec clip_point(drawvec &geom, long long x1, long long y1, long long x2, long long y2);
#endif

View File

@ -9,6 +9,8 @@
#include <vector>
#include "jsonpull/jsonpull.h"
#include "csv.hpp"
#include "text.hpp"
#include "geojson-loop.hpp"
int fail = EXIT_SUCCESS;
bool wrap = false;
@ -17,6 +19,7 @@ const char *extract = NULL;
FILE *csvfile = NULL;
std::vector<std::string> header;
std::vector<std::string> fields;
int pe = false;
std::string buffered;
int buffered_type = -1;
@ -208,6 +211,12 @@ void join_csv(json_object *j) {
exit(EXIT_FAILURE);
}
std::string err = check_utf8(s);
if (err != "") {
fprintf(stderr, "%s\n", err.c_str());
exit(EXIT_FAILURE);
}
header = csv_split(s.c_str());
for (size_t i = 0; i < header.size(); i++) {
@ -264,6 +273,12 @@ void join_csv(json_object *j) {
break;
}
std::string err = check_utf8(s);
if (err != "") {
fprintf(stderr, "%s\n", err.c_str());
exit(EXIT_FAILURE);
}
fields = csv_split(s.c_str());
for (size_t i = 0; i < fields.size(); i++) {
@ -305,7 +320,11 @@ void join_csv(json_object *j) {
} else if (is_number(v)) {
attr_type = JSON_NUMBER;
}
} else if (pe) {
attr_type = JSON_NULL;
}
if (attr_type != JSON_NULL) {
// This knows more about the structure of JSON objects than it ought to
json_object *ko = (json_object *) malloc(sizeof(json_object));
@ -344,70 +363,35 @@ void join_csv(json_object *j) {
}
}
struct json_join_action : json_feature_action {
int add_feature(json_object *geometry, bool, json_object *, json_object *, json_object *, json_object *feature) {
if (feature != geometry) { // a real feature, not a bare geometry
if (csvfile != NULL) {
join_csv(feature);
}
char *s = json_stringify(feature);
out(s, 1, json_hash_get(feature, "properties"));
free(s);
} else {
char *s = json_stringify(geometry);
out(s, 2, NULL);
free(s);
}
return 1;
}
void check_crs(json_object *) {
}
};
void process(FILE *fp, const char *fname) {
json_pull *jp = json_begin_file(fp);
while (1) {
json_object *j = json_read(jp);
if (j == NULL) {
if (jp->error != NULL) {
fprintf(stderr, "%s:%d: %s\n", fname, jp->line, jp->error);
}
json_free(jp->root);
break;
}
json_object *type = json_hash_get(j, "type");
if (type == NULL || type->type != JSON_STRING) {
continue;
}
if (strcmp(type->string, "Feature") == 0) {
if (csvfile != NULL) {
join_csv(j);
}
char *s = json_stringify(j);
out(s, 1, json_hash_get(j, "properties"));
free(s);
json_free(j);
} else if (strcmp(type->string, "Point") == 0 ||
strcmp(type->string, "MultiPoint") == 0 ||
strcmp(type->string, "LineString") == 0 ||
strcmp(type->string, "MultiLineString") == 0 ||
strcmp(type->string, "MultiPolygon") == 0) {
int is_geometry = 1;
if (j->parent != NULL) {
if (j->parent->type == JSON_ARRAY) {
if (j->parent->parent->type == JSON_HASH) {
json_object *geometries = json_hash_get(j->parent->parent, "geometries");
if (geometries != NULL) {
// Parent of Parent must be a GeometryCollection
is_geometry = 0;
}
}
} else if (j->parent->type == JSON_HASH) {
json_object *geometry = json_hash_get(j->parent, "geometry");
if (geometry != NULL) {
// Parent must be a Feature
is_geometry = 0;
}
}
}
if (is_geometry) {
char *s = json_stringify(j);
out(s, 2, NULL);
free(s);
json_free(j);
}
} else if (strcmp(type->string, "FeatureCollection") == 0) {
json_free(j);
}
}
json_join_action jja;
jja.fname = fname;
parse_json(&jja, jp);
json_end(jp);
}
@ -418,6 +402,8 @@ int main(int argc, char **argv) {
{"wrap", no_argument, 0, 'w'},
{"extract", required_argument, 0, 'e'},
{"csv", required_argument, 0, 'c'},
{"empty-csv-columns-are-null", no_argument, &pe, 1},
{"prevent", required_argument, 0, 'p'},
{0, 0, 0, 0},
};
@ -438,6 +424,9 @@ int main(int argc, char **argv) {
while ((i = getopt_long(argc, argv, getopt_str.c_str(), long_options, NULL)) != -1) {
switch (i) {
case 0:
break;
case 'w':
wrap = true;
break;
@ -450,6 +439,15 @@ int main(int argc, char **argv) {
csv = optarg;
break;
case 'p':
if (strcmp(optarg, "e") == 0) {
pe = true;
} else {
fprintf(stderr, "%s: Unknown option for -p%s\n", argv[0], optarg);
exit(EXIT_FAILURE);
}
break;
default:
fprintf(stderr, "Unexpected option -%c\n", i);
exit(EXIT_FAILURE);

808
main.cpp

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@
#define MAIN_HPP
#include <stddef.h>
#include <atomic>
#include <string>
struct index {
long long start = 0;
@ -17,19 +19,39 @@ struct index {
}
};
struct clipbbox {
double lon1;
double lat1;
double lon2;
double lat2;
long long minx;
long long miny;
long long maxx;
long long maxy;
};
extern std::vector<clipbbox> clipbboxes;
void checkdisk(std::vector<struct reader> *r);
extern int geometry_scale;
extern int quiet;
extern int quiet_progress;
extern double progress_interval;
extern std::atomic<double> last_progress;
extern size_t CPUS;
extern size_t TEMP_FILES;
extern size_t max_tile_size;
extern size_t max_tile_features;
extern int cluster_distance;
extern std::string attribute_for_id;
int mkstemp_cloexec(char *name);
FILE *fopen_oflag(const char *name, const char *mode, int oflag);
bool progress_time();
#define MAX_ZOOM 24

View File

@ -1,10 +1,12 @@
.TH tippecanoe
.PP
Builds vector tilesets \[la]https://www.mapbox.com/developers/vector-tiles/\[ra] from large (or small) collections of GeoJSON \[la]http://geojson.org/\[ra] or Geobuf \[la]https://github.com/mapbox/geobuf\[ra] features,
Builds vector tilesets \[la]https://www.mapbox.com/developers/vector-tiles/\[ra] from large (or small) collections of GeoJSON \[la]http://geojson.org/\[ra], Geobuf \[la]https://github.com/mapbox/geobuf\[ra], or CSV \[la]https://en.wikipedia.org/wiki/Comma-separated_values\[ra] features,
like these \[la]MADE_WITH.md\[ra]\&.
.PP
[Mapbox Tippecanoe](\[la]https://user-images.githubusercontent.com/1951835/36568734-ede27ec0-17df-11e8-8c22-ffaaebb8daf4.JPG\[ra])
.PP
[Build Status](https://travis\-ci.org/mapbox/tippecanoe.svg) \[la]https://travis-ci.org/mapbox/tippecanoe\[ra]
[Coverage Status](https://coveralls.io/repos/mapbox/tippecanoe/badge.svg?branch=master&service=github) \[la]https://coveralls.io/github/mapbox/tippecanoe?branch=master\[ra]
[Coverage Status](https://codecov.io/gh/mapbox/tippecanoe/branch/master/graph/badge.svg) \[la]https://codecov.io/gh/mapbox/tippecanoe\[ra]
.SH Intent
.PP
The goal of Tippecanoe is to enable making a scale\-independent view of your data,
@ -33,11 +35,26 @@ The easiest way to install tippecanoe on OSX is with Homebrew \[la]http://brew.s
$ brew install tippecanoe
.fi
.RE
.PP
On Ubuntu it will usually be easiest to build from the source repository:
.PP
.RS
.nf
$ git clone https://github.com/mapbox/tippecanoe.git
$ cd tippecanoe
$ make \-j
$ make install
.fi
.RE
.PP
See Development \[la]#development\[ra] below for how to upgrade your
C++ compiler or install prerequisite packages if you get
compiler errors.
.SH Usage
.PP
.RS
.nf
$ tippecanoe \-o file.mbtiles [options] [file.json file.geobuf ...]
$ tippecanoe \-o file.mbtiles [options] [file.json file.json.gz file.geobuf ...]
.fi
.RE
.PP
@ -84,6 +101,212 @@ with a custom layer name and description, and leaving out the \fB\fCLINEARID\fR
$ cat tiger/tl_2014_*_roads.json | tippecanoe \-o tiger.mbtiles \-l roads \-n "All TIGER roads, one zoom" \-z12 \-Z12 \-d14 \-x LINEARID \-x RTTYP
.fi
.RE
.SH Cookbook
.SS Linear features (world railroads), visible at all zoom levels
.PP
.RS
.nf
curl \-L \-O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_railroads.zip
unzip ne_10m_railroads.zip
ogr2ogr \-f GeoJSON ne_10m_railroads.geojson ne_10m_railroads.shp
tippecanoe \-zg \-o ne_10m_railroads.mbtiles \-\-drop\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping ne_10m_railroads.geojson
.fi
.RE
.RS
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-\-drop\-densest\-as\-needed\fR: If the tiles are too big at low zoom levels, drop the least\-visible features to allow tiles to be created with those features that remain
.IP \(bu 2
\fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
.RE
.SS Discontinuous polygon features (buildings of Rhode Island), visible at all zoom levels
.PP
.RS
.nf
curl \-L \-O https://usbuildingdata.blob.core.windows.net/usbuildings\-v1\-1/RhodeIsland.zip
unzip RhodeIsland.zip
tippecanoe \-zg \-o RhodeIsland.mbtiles \-\-drop\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping RhodeIsland.geojson
.fi
.RE
.RS
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-\-drop\-densest\-as\-needed\fR: If the tiles are too big at low or medium zoom levels, drop the least\-visible features to allow tiles to be created with those features that remain
.IP \(bu 2
\fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
.RE
.SS Continuous polygon features (states and provinces), visible at all zoom levels
.PP
.RS
.nf
curl \-L \-O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip
unzip \-o ne_10m_admin_1_states_provinces.zip
ogr2ogr \-f GeoJSON ne_10m_admin_1_states_provinces.geojson ne_10m_admin_1_states_provinces.shp
tippecanoe \-zg \-o ne_10m_admin_1_states_provinces.mbtiles \-\-coalesce\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping ne_10m_admin_1_states_provinces.geojson
.fi
.RE
.RS
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-\-coalesce\-densest\-as\-needed\fR: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
.IP \(bu 2
\fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
.RE
.SS Large point dataset (GPS bus locations), for visualization at all zoom levels
.PP
.RS
.nf
curl \-L \-O ftp://avl\-data.sfmta.com/avl_data/avl_raw/sfmtaAVLRawData01012013.csv
sed 's/PREDICTABLE.*/PREDICTABLE/' sfmtaAVLRawData01012013.csv > sfmta.csv
tippecanoe \-zg \-o sfmta.mbtiles \-\-drop\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping sfmta.csv
.fi
.RE
.PP
(The \fB\fCsed\fR line is to clean the corrupt CSV header, which contains the wrong number of fields.)
.RS
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-\-drop\-densest\-as\-needed\fR: If the tiles are too big at low or medium zoom levels, drop the least\-visible features to allow tiles to be created with those features that remain
.IP \(bu 2
\fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
.RE
.SS Clustered points (world cities), summing the clustered population, visible at all zoom levels
.PP
.RS
.nf
curl \-L \-O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip
unzip \-o ne_10m_populated_places.zip
ogr2ogr \-f GeoJSON ne_10m_populated_places.geojson ne_10m_populated_places.shp
tippecanoe \-zg \-o ne_10m_populated_places.mbtiles \-r1 \-\-cluster\-distance=10 \-\-accumulate\-attribute=POP_MAX:sum ne_10m_populated_places.geojson
.fi
.RE
.RS
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-r1\fR: Do not automatically drop a fraction of points at low zoom levels, since clustering will be used instead
.IP \(bu 2
\fB\fC\-\-cluster\-distance=10\fR: Cluster together features that are closer than about 10 pixels from each other
.IP \(bu 2
\fB\fC\-\-accumulate\-attribute=POP_MAX:sum\fR: Sum the \fB\fCPOP_MAX\fR (population) attribute in features that are clustered together. Other attributes will be arbitrarily taken from the first feature in the cluster.
.RE
.SS Show countries at low zoom levels but states at higher zoom levels
.PP
.RS
.nf
curl \-L \-O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_countries.zip
unzip ne_10m_admin_0_countries.zip
ogr2ogr \-f GeoJSON ne_10m_admin_0_countries.geojson ne_10m_admin_0_countries.shp
curl \-L \-O https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip
unzip \-o ne_10m_admin_1_states_provinces.zip
ogr2ogr \-f GeoJSON ne_10m_admin_1_states_provinces.geojson ne_10m_admin_1_states_provinces.shp
tippecanoe \-z3 \-o countries\-z3.mbtiles \-\-coalesce\-densest\-as\-needed ne_10m_admin_0_countries.geojson
tippecanoe \-zg \-Z4 \-o states\-Z4.mbtiles \-\-coalesce\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping ne_10m_admin_1_states_provinces.geojson
tile\-join \-o states\-countries.mbtiles countries\-z3.mbtiles states\-Z4.mbtiles
.fi
.RE
.PP
Countries:
.RS
.IP \(bu 2
\fB\fC\-z3\fR: Only generate zoom levels 0 through 3
.IP \(bu 2
\fB\fC\-\-coalesce\-densest\-as\-needed\fR: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
.RE
.PP
States and Provinces:
.RS
.IP \(bu 2
\fB\fC\-Z4\fR: Only generate zoom levels 4 and beyond
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-\-coalesce\-densest\-as\-needed\fR: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
.IP \(bu 2
\fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
.RE
.SS Represent multiple sources (Illinois and Indiana counties) as separate layers
.PP
.RS
.nf
curl \-L \-O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_17_county10.zip
unzip tl_2010_17_county10.zip
ogr2ogr \-f GeoJSON tl_2010_17_county10.geojson tl_2010_17_county10.shp
curl \-L \-O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_18_county10.zip
unzip tl_2010_18_county10.zip
ogr2ogr \-f GeoJSON tl_2010_18_county10.geojson tl_2010_18_county10.shp
tippecanoe \-zg \-o counties\-separate.mbtiles \-\-coalesce\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping tl_2010_17_county10.geojson tl_2010_18_county10.geojson
.fi
.RE
.RS
.IP \(bu 2
\fB\fC\-zg\fR: Automatically choose a maxzoom that should be sufficient to clearly distinguish the features and the detail within each feature
.IP \(bu 2
\fB\fC\-\-coalesce\-densest\-as\-needed\fR: If the tiles are too big at low or medium zoom levels, merge as many features together as are necessary to allow tiles to be created with those features that are still distinguished
.IP \(bu 2
\fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: If even the tiles at high zoom levels are too big, keep adding zoom levels until one is reached that can represent all the features
.RE
.SS Merge multiple sources (Illinois and Indiana counties) into the same layer
.PP
.RS
.nf
curl \-L \-O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_17_county10.zip
unzip tl_2010_17_county10.zip
ogr2ogr \-f GeoJSON tl_2010_17_county10.geojson tl_2010_17_county10.shp
curl \-L \-O https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/2010/tl_2010_18_county10.zip
unzip tl_2010_18_county10.zip
ogr2ogr \-f GeoJSON tl_2010_18_county10.geojson tl_2010_18_county10.shp
tippecanoe \-zg \-o counties\-merged.mbtiles \-l counties \-\-coalesce\-densest\-as\-needed \-\-extend\-zooms\-if\-still\-dropping tl_2010_17_county10.geojson tl_2010_18_county10.geojson
.fi
.RE
.PP
As above, but
.RS
.IP \(bu 2
\fB\fC\-l counties\fR: Specify the layer name instead of letting it be derived from the source file names
.RE
.SS Selectively remove and replace features (Census tracts) to update a tileset
.PP
.RS
.nf
# Retrieve and tile California 2000 Census tracts
curl \-L \-O https://www2.census.gov/geo/tiger/TIGER2010/TRACT/2000/tl_2010_06_tract00.zip
unzip tl_2010_06_tract00.zip
ogr2ogr \-f GeoJSON tl_2010_06_tract00.shp.json tl_2010_06_tract00.shp
tippecanoe \-z11 \-o tracts.mbtiles \-l tracts tl_2010_06_tract00.shp.json
# Create a copy of the tileset, minus Alameda County (FIPS code 001)
tile\-join \-j '{"*":["none",["==","COUNTYFP00","001"]]}' \-f \-o tracts\-filtered.mbtiles tracts.mbtiles
# Retrieve and tile Alameda County Census tracts for 2010
curl \-L \-O https://www2.census.gov/geo/tiger/TIGER2010/TRACT/2010/tl_2010_06001_tract10.zip
unzip tl_2010_06001_tract10.zip
ogr2ogr \-f GeoJSON tl_2010_06001_tract10.shp.json tl_2010_06001_tract10.shp
tippecanoe \-z11 \-o tracts\-added.mbtiles \-l tracts tl_2010_06001_tract10.shp.json
# Merge the filtered tileset and the tileset of new tracts into a final tileset
tile\-join \-o tracts\-final.mbtiles tracts\-filtered.mbtiles tracts\-added.mbtiles
.fi
.RE
.PP
The \fB\fC\-z11\fR option explicitly specifies the maxzoom, to make sure both the old and new tilesets have the same zoom range.
.PP
The \fB\fC\-j\fR option to \fB\fCtile\-join\fR specifies a filter, so that only the desired features will be copied to the new tileset.
This filter excludes (using \fB\fCnone\fR) any features whose FIPS code (\fB\fCCOUNTYFP00\fR) is the code for Alameda County (\fB\fC001\fR).
.SH Options
.PP
There are a lot of options. A lot of the time you won't want to use any of them
@ -132,13 +355,27 @@ or if metadata fields can't be set. You probably don't want to use this.
.IP \(bu 2
\fIname\fP\fB\fC\&.json\fR or \fIname\fP\fB\fC\&.geojson\fR: Read the named GeoJSON input file into a layer called \fIname\fP\&.
.IP \(bu 2
\fIname\fP\fB\fC\&.geobuf\fR or \fIname\fP\fB\fC\&.geobuf\fR: Read the named Geobuf input file into a layer called \fIname\fP\&.
\fIname\fP\fB\fC\&.json.gz\fR or \fIname\fP\fB\fC\&.geojson.gz\fR: Read the named gzipped GeoJSON input file into a layer called \fIname\fP\&.
.IP \(bu 2
\fIname\fP\fB\fC\&.geobuf\fR: Read the named Geobuf input file into a layer called \fIname\fP\&.
.IP \(bu 2
\fIname\fP\fB\fC\&.csv\fR: Read the named CSV input file into a layer called \fIname\fP\&.
.IP \(bu 2
\fB\fC\-l\fR \fIname\fP or \fB\fC\-\-layer=\fR\fIname\fP: Use the specified layer name instead of deriving a name from the input filename or output tileset. If there are multiple input files
specified, the files are all merged into the single named layer, even if they try to specify individual names with \fB\fC\-L\fR\&.
.IP \(bu 2
\fB\fC\-L\fR \fIname\fP\fB\fC:\fR\fIfile.json\fP or \fB\fC\-\-named\-layer=\fR\fIname\fP\fB\fC:\fR\fIfile.json\fP: Specify layer names for individual files. If your shell supports it, you can use a subshell redirect like \fB\fC\-L\fR \fIname\fP\fB\fC:<(cat dir/*.json)\fR to specify a layer name for the output of streamed input.
.IP \(bu 2
\fB\fC\-L{\fR\fIlayer\-json\fP\fB\fC}\fR or \fB\fC\-\-named\-layer={\fR\fIlayer\-json\fP\fB\fC}\fR: Specify an input file and layer options by a JSON object. The JSON object must contain a \fB\fC"file"\fR key to specify the filename to read from. (If the \fB\fC"file"\fR key is an empty string, it means to read from the standard input stream.) It may also contain a \fB\fC"layer"\fR field to specify the name of the layer, and/or a \fB\fC"description"\fR field to specify the layer's description in the tileset metadata, and/or a \fB\fC"format"\fR field to specify \fB\fCcsv\fR or \fB\fCgeobuf\fR file format if it is not obvious from the \fB\fCname\fR\&. Example:
.RE
.PP
.RS
.nf
tippecanoe \-z5 \-o world.mbtiles \-L'{"file":"ne_10m_admin_0_countries.json", "layer":"countries", "description":"Natural Earth countries"}'
.fi
.RE
.PP
CSV input files currently support only Point geometries, from columns named \fB\fClatitude\fR, \fB\fClongitude\fR, \fB\fClat\fR, \fB\fClon\fR, \fB\fClong\fR, \fB\fClng\fR, \fB\fCx\fR, or \fB\fCy\fR\&.
.SS Parallel processing of input
.RS
.IP \(bu 2
@ -172,7 +409,52 @@ Parallel processing will also be automatic if the input file is in Geobuf format
\fB\fC\-ae\fR or \fB\fC\-\-extend\-zooms\-if\-still\-dropping\fR: Increase the maxzoom if features are still being dropped at that zoom level.
The detail and simplification options that ordinarily apply only to the maximum zoom level will apply both to the originally
specified maximum zoom and to any levels added beyond that.
.IP \(bu 2
\fB\fC\-R\fR \fIzoom\fP\fB\fC/\fR\fIx\fP\fB\fC/\fR\fIy\fP or \fB\fC\-\-one\-tile=\fR\fIzoom\fP\fB\fC/\fR\fIx\fP\fB\fC/\fR\fIy\fP: Set the minzoom and maxzoom to \fIzoom\fP and produce only
the single specified tile at that zoom level.
.RE
.PP
If you know the precision to which you want your data to be represented,
this table shows the approximate precision corresponding to various
\fB\fC\-z\fR options if you use the default \fB\fC\-d\fR detail of 12:
.TS
allbox;
cb cb cb
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
l l l
.
zoom level precision (ft) precision (m)
\fB\fC\-z0\fR 32000 ft 10000 m
\fB\fC\-z1\fR 16000 ft 5000 m
\fB\fC\-z2\fR 8000 ft 2500 m
\fB\fC\-z3\fR 4000 ft 1250 m
\fB\fC\-z4\fR 2000 ft 600 m
\fB\fC\-z5\fR 1000 ft 300 m
\fB\fC\-z6\fR 500 ft 150 m
\fB\fC\-z7\fR 250 ft 80 m
\fB\fC\-z8\fR 125 ft 40 m
\fB\fC\-z9\fR 64 ft 20 m
\fB\fC\-z10\fR 32 ft 10 m
\fB\fC\-z11\fR 16 ft 5 m
\fB\fC\-z12\fR 8 ft 2 m
\fB\fC\-z13\fR 4 ft 1 m
\fB\fC\-z14\fR 2 ft 0.5 m
\fB\fC\-z15\fR 1 ft 0.25 m
.TE
.SS Tile resolution
.RS
.IP \(bu 2
@ -189,11 +471,14 @@ resolution is obtained than by using a smaller \fImaxzoom\fP or \fIdetail\fP\&.
.SS Filtering feature attributes
.RS
.IP \(bu 2
\fB\fC\-x\fR \fIname\fP or \fB\fC\-\-exclude=\fR\fIname\fP: Exclude the named properties from all features
\fB\fC\-x\fR \fIname\fP or \fB\fC\-\-exclude=\fR\fIname\fP: Exclude the named attributes from all features. You can specify multiple \fB\fC\-x\fR options to exclude several attributes. (Don't comma\-separate names within a single \fB\fC\-x\fR\&.)
.IP \(bu 2
\fB\fC\-y\fR \fIname\fP or \fB\fC\-\-include=\fR\fIname\fP: Include the named properties in all features, excluding all those not explicitly named
\fB\fC\-y\fR \fIname\fP or \fB\fC\-\-include=\fR\fIname\fP: Include the named attributes in all features, excluding all those not explicitly named. You can specify multiple \fB\fC\-y\fR options to explicitly include several attributes. (Don't comma\-separate names within a single \fB\fC\-y\fR\&.)
.IP \(bu 2
\fB\fC\-X\fR or \fB\fC\-\-exclude\-all\fR: Exclude all properties and encode only geometries
\fB\fC\-X\fR or \fB\fC\-\-exclude\-all\fR: Exclude all attributes and encode only geometries
.RE
.SS Modifying feature attributes
.RS
.IP \(bu 2
\fB\fC\-T\fR\fIattribute\fP\fB\fC:\fR\fItype\fP or \fB\fC\-\-attribute\-type=\fR\fIattribute\fP\fB\fC:\fR\fItype\fP: Coerce the named feature \fIattribute\fP to be of the specified \fItype\fP\&.
The \fItype\fP may be \fB\fCstring\fR, \fB\fCfloat\fR, \fB\fCint\fR, or \fB\fCbool\fR\&.
@ -201,7 +486,23 @@ If the type is \fB\fCbool\fR, then original attributes of \fB\fC0\fR (or, if num
If the type is \fB\fCfloat\fR or \fB\fCint\fR and the original attribute was non\-numeric, it becomes \fB\fC0\fR\&.
If the type is \fB\fCint\fR and the original attribute was floating\-point, it is rounded to the nearest integer.
.IP \(bu 2
\fB\fC\-j\fR \fIfilter\fP or \fB\fC\-\-feature\-filter\fR=\fIfilter\fP: Check features against a per\-layer filter (as defined in the Mapbox GL Style Specification \[la]https://www.mapbox.com/mapbox-gl-js/style-spec/#types-filter\[ra]) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer \fB\fC"*"\fR apply to all layers.
\fB\fC\-Y\fR\fIattribute\fP\fB\fC:\fR\fIdescription\fP or \fB\fC\-\-attribute\-description=\fR\fIattribute\fP\fB\fC:\fR\fIdescription\fP: Set the \fB\fCdescription\fR for the specified attribute in the tileset metadata to \fIdescription\fP instead of the usual \fB\fCString\fR, \fB\fCNumber\fR, or \fB\fCBoolean\fR\&.
.IP \(bu 2
\fB\fC\-E\fR\fIattribute\fP\fB\fC:\fR\fIoperation\fP or \fB\fC\-\-accumulate\-attribute=\fR\fIattribute\fP\fB\fC:\fR\fIoperation\fP: Preserve the named \fIattribute\fP from features
that are dropped, coalesced\-as\-needed, or clustered. The \fIoperation\fP may be
\fB\fCsum\fR, \fB\fCproduct\fR, \fB\fCmean\fR, \fB\fCmax\fR, \fB\fCmin\fR, \fB\fCconcat\fR, or \fB\fCcomma\fR
to specify how the named \fIattribute\fP is accumulated onto the attribute of the same name in a feature that does survive.
.IP \(bu 2
\fB\fC\-pe\fR or \fB\fC\-\-empty\-csv\-columns\-are\-null\fR: Treat empty CSV columns as nulls rather than as empty strings.
.IP \(bu 2
\fB\fC\-aI\fR or \fB\fC\-\-convert\-stringified\-ids\-to\-numbers\fR: If a feature ID is the string representation of a number, convert it to a plain number to use as the feature ID.
.IP \(bu 2
\fB\fC\-\-use\-attribute\-for\-id=\fR\fIname\fP: Use the attribute with the specified \fIname\fP as if it were specified as the feature ID. (If this attribute is a stringified number, you must also use \fB\fC\-aI\fR to convert it to a number.)
.RE
.SS Filtering features by attributes
.RS
.IP \(bu 2
\fB\fC\-j\fR \fIfilter\fP or \fB\fC\-\-feature\-filter\fR=\fIfilter\fP: Check features against a per\-layer filter (as defined in the Mapbox GL Style Specification \[la]https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter\[ra]) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer \fB\fC"*"\fR apply to all layers. The special variable \fB\fC$zoom\fR refers to the current zoom level.
.IP \(bu 2
\fB\fC\-J\fR \fIfilter\-file\fP or \fB\fC\-\-feature\-filter\-file\fR=\fIfilter\-file\fP: Like \fB\fC\-j\fR, but read the filter from a file.
.RE
@ -213,6 +514,27 @@ Example: to find the Natural Earth countries with low \fB\fCscalerank\fR but hig
tippecanoe \-z5 \-o filtered.mbtiles \-j '{ "ne_10m_admin_0_countries": [ "all", [ "<", "scalerank", 3 ], [ ">", "LABELRANK", 5 ] ] }' ne_10m_admin_0_countries.geojson
.fi
.RE
.PP
Example: to retain only major TIGER roads at low zoom levels:
.PP
.RS
.nf
tippecanoe \-o roads.mbtiles \-j '{ "*": [ "any", [ ">=", "$zoom", 11 ], [ "in", "MTFCC", "S1100", "S1200" ] ] }' tl_2015_06001_roads.json
.fi
.RE
.PP
Tippecanoe also accepts expressions of the form \fB\fC[ "attribute\-filter", name, expression ]\fR, to filter individual feature attributes
instead of entire features. For example, you can exclude the road names at low zoom levels by doing
.PP
.RS
.nf
tippecanoe \-o roads.mbtiles \-j '{ "*": [ "attribute\-filter", "FULLNAME", [ ">=", "$zoom", 9 ] ] }' tl_2015_06001_roads.json
.fi
.RE
.PP
An \fB\fCattribute\-filter\fR expression itself is always considered to evaluate to \fB\fCtrue\fR (in other words, to retain the feature instead
of dropping it). If you want to use multiple \fB\fCattribute\-filter\fR expressions, or to use other expressions to remove features from
the same layer, enclose them in an \fB\fCall\fR expression so they will all be evaluated.
.SS Dropping a fixed fraction of features by zoom level
.RS
.IP \(bu 2
@ -229,6 +551,8 @@ compensate for the larger marker, or \fB\fC\-Bf\fR\fInumber\fP to allow at most
\fB\fC\-al\fR or \fB\fC\-\-drop\-lines\fR: Let "dot" dropping at lower zooms apply to lines too
.IP \(bu 2
\fB\fC\-ap\fR or \fB\fC\-\-drop\-polygons\fR: Let "dot" dropping at lower zooms apply to polygons too
.IP \(bu 2
\fB\fC\-K\fR \fIdistance\fP or \fB\fC\-\-cluster\-distance=\fR\fIdistance\fP: Cluster points (as with \fB\fC\-\-cluster\-densest\-as\-needed\fR, but without the experimental discovery process) that are approximately within \fIdistance\fP of each other. The units are tile coordinates within a nominally 256\-pixel tile, so the maximum value of 255 allows only one feature per tile. Values around 10 are probably appropriate for typical marker sizes. See \fB\fC\-\-cluster\-densest\-as\-needed\fR below for behavior.
.RE
.SS Dropping a fraction of features to keep under tile size limits
.RS
@ -239,9 +563,15 @@ compensate for the larger marker, or \fB\fC\-Bf\fR\fInumber\fP to allow at most
.IP \(bu 2
\fB\fC\-an\fR or \fB\fC\-\-drop\-smallest\-as\-needed\fR: Dynamically drop the smallest features (physically smallest: the shortest lines or the smallest polygons) from each zoom level to keep large tiles under the 500K size limit. This option will not work for point features.
.IP \(bu 2
\fB\fC\-aN\fR or \fB\fC\-\-coalesce\-smallest\-as\-needed\fR: Dynamically combine the smallest features (physically smallest: the shortest lines or the smallest polygons) from each zoom level into other nearby features to keep large tiles under the 500K size limit. This option will not work for point features, and will probably not help very much with LineStrings. It is mostly intended for polygons, to maintain the full original area covered by polygons while still reducing the feature count somehow. The attributes of the small polygons are \fInot\fP preserved into the combined features, only their geometry.
\fB\fC\-aN\fR or \fB\fC\-\-coalesce\-smallest\-as\-needed\fR: Dynamically combine the smallest features (physically smallest: the shortest lines or the smallest polygons) from each zoom level into other nearby features to keep large tiles under the 500K size limit. This option will not work for point features, and will probably not help very much with LineStrings. It is mostly intended for polygons, to maintain the full original area covered by polygons while still reducing the feature count somehow. The attributes of the small polygons are \fInot\fP preserved into the combined features (except through \fB\fC\-\-accumulate\-attribute\fR), only their geometry. Furthermore, the polygons to which nested polygons are coalesced may not necessarily be the immediately enclosing features.
.IP \(bu 2
\fB\fC\-aD\fR or \fB\fC\-\-coalesce\-densest\-as\-needed\fR: Dynamically combine the densest features from each zoom level into other nearby features to keep large tiles under the 500K size limit. (Again, mostly useful for polygons.)
.IP \(bu 2
\fB\fC\-aS\fR or \fB\fC\-\-coalesce\-fraction\-as\-needed\fR: Dynamically combine a fraction of features from each zoom level into other nearby features to keep large tiles under the 500K size limit. (Again, mostly useful for polygons.)
.IP \(bu 2
\fB\fC\-pd\fR or \fB\fC\-\-force\-feature\-limit\fR: Dynamically drop some fraction of features from large tiles to keep them under the 500K size limit. It will probably look ugly at the tile boundaries. (This is like \fB\fC\-ad\fR but applies to each tile individually, not to the entire zoom level.) You probably don't want to use this.
.IP \(bu 2
\fB\fC\-aC\fR or \fB\fC\-\-cluster\-densest\-as\-needed\fR: If a tile is too large, try to reduce its size by increasing the minimum spacing between features, and leaving one placeholder feature from each group. The remaining feature will be given a \fB\fC"cluster": true\fR attribute to indicate that it represents a cluster, a \fB\fC"point_count"\fR attribute to indicate the number of features that were clustered into it, and a \fB\fC"sqrt_point_count"\fR attribute to indicate the relative width of a feature to represent the cluster. If the features being clustered are points, the representative feature will be located at the average of the original points' locations; otherwise, one of the original features will be left as the representative.
.RE
.SS Dropping tightly overlapping features
.RS
@ -283,27 +613,39 @@ the line or polygon within one tile unit of its proper location. You can probabl
.IP \(bu 2
\fB\fC\-pi\fR or \fB\fC\-\-preserve\-input\-order\fR: Preserve the original input order of features as the drawing order instead of ordering geographically. (This is implemented as a restoration of the original order at the end, so that dot\-dropping is still geographic, which means it also undoes \fB\fC\-ao\fR).
.IP \(bu 2
\fB\fC\-ao\fR or \fB\fC\-\-reorder\fR: Reorder features to put ones with the same properties in sequence, to try to get them to coalesce. You probably don't want to use this.
\fB\fC\-ac\fR or \fB\fC\-\-coalesce\fR: Coalesce consecutive features that have the same attributes. This can be useful if you have lots of small polygons with identical attributes and you would like to merge them together.
.IP \(bu 2
\fB\fC\-ac\fR or \fB\fC\-\-coalesce\fR: Coalesce adjacent line and polygon features that have the same properties. You probably don't want to use this.
\fB\fC\-ao\fR or \fB\fC\-\-reorder\fR: Reorder features to put ones with the same attributes in sequence (instead of ones that are approximately spatially adjacent), to try to get them to coalesce. You probably want to use this if you use \fB\fC\-\-coalesce\fR\&.
.IP \(bu 2
\fB\fC\-ar\fR or \fB\fC\-\-reverse\fR: Try reversing the directions of lines to make them coalesce and compress better. You probably don't want to use this.
.IP \(bu 2
\fB\fC\-ah\fR or \fB\fC\-\-hilbert\fR: Put features in Hilbert Curve order instead of the usual Z\-Order. This improves the odds that spatially adjacent features will be sequentially adjacent, and should improve density calculations and spatial coalescing. It should be the default eventually.
.RE
.SS Adding calculated attributes
.RS
.IP \(bu 2
\fB\fC\-ag\fR or \fB\fC\-\-calculate\-feature\-density\fR: Add a new attribute, \fB\fCtippecanoe_feature_density\fR, to each feature, to record how densely features are spaced in that area of the tile. You can use this attribute in the style to produce a glowing effect where points are densely packed. It can range from 0 in the sparsest areas to 255 in the densest.
.IP \(bu 2
\fB\fC\-ai\fR or \fB\fC\-\-generate\-ids\fR: Add an \fB\fCid\fR (a feature ID, not an attribute named \fB\fCid\fR) to each feature that does not already have one. There is currently no guarantee that the \fB\fCid\fR added will be stable between runs or that it will not conflict with manually\-assigned feature IDs. Future versions of Tippecanoe may change the mechanism for allocating IDs.
.RE
.SS Trying to correct bad source geometry
.RS
.IP \(bu 2
\fB\fC\-aw\fR or \fB\fC\-\-detect\-longitude\-wraparound\fR: Detect when adjacent points within a feature jump to the other side of the world, and try to fix the geometry.
\fB\fC\-aw\fR or \fB\fC\-\-detect\-longitude\-wraparound\fR: Detect when consecutive points within a feature jump to the other side of the world, and try to fix the geometry.
.IP \(bu 2
\fB\fC\-pw\fR or \fB\fC\-\-use\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the original polygon winding in the source data to distinguish inner (clockwise) and outer (counterclockwise) polygon rings.
.IP \(bu 2
\fB\fC\-pW\fR or \fB\fC\-\-reverse\-source\-polygon\-winding\fR: Instead of respecting GeoJSON polygon ring order, use the opposite of the original polygon winding in the source data to distinguish inner (counterclockwise) and outer (clockwise) polygon rings.
.IP \(bu 2
\fB\fC\-\-clip\-bounding\-box=\fR\fIminlon\fP\fB\fC,\fR\fIminlat\fP\fB\fC,\fR\fImaxlon\fP\fB\fC,\fR\fImaxlat\fP: Clip all features to the specified bounding box.
.RE
.SS Setting or disabling tile size limits
.RS
.IP \(bu 2
\fB\fC\-M\fR \fIbytes\fP or \fB\fC\-\-maximum\-tile\-bytes=\fR\fIbytes\fP: Use the specified number of \fIbytes\fP as the maximum compressed tile size instead of 500K.
.IP \(bu 2
\fB\fC\-O\fR \fIfeatures\fP or \fB\fC\-\-maximum\-tile\-features=\fR\fIfeatures\fP: Use the specified number of \fIfeatures\fP as the maximum in a tile instead of 200,000.
.IP \(bu 2
\fB\fC\-pf\fR or \fB\fC\-\-no\-feature\-limit\fR: Don't limit tiles to 200,000 features
.IP \(bu 2
\fB\fC\-pk\fR or \fB\fC\-\-no\-tile\-size\-limit\fR: Don't limit tiles to 500K bytes
@ -311,6 +653,12 @@ the line or polygon within one tile unit of its proper location. You can probabl
\fB\fC\-pC\fR or \fB\fC\-\-no\-tile\-compression\fR: Don't compress the PBF vector tile data.
.IP \(bu 2
\fB\fC\-pg\fR or \fB\fC\-\-no\-tile\-stats\fR: Don't generate the \fB\fCtilestats\fR row in the tileset metadata. Uploads without tilestats \[la]https://github.com/mapbox/mapbox-geostats\[ra] will take longer to process.
.IP \(bu 2
\fB\fC\-\-tile\-stats\-attributes\-limit=\fR\fIcount\fP: Include \fB\fCtilestats\fR information about at most \fIcount\fP attributes instead of the default 1000.
.IP \(bu 2
\fB\fC\-\-tile\-stats\-sample\-values\-limit=\fR\fIcount\fP: Calculate \fB\fCtilestats\fR attribute statistics based on \fIcount\fP values instead of the default 1000.
.IP \(bu 2
\fB\fC\-\-tile\-stats\-values\-limit=\fR\fIcount\fP: Report \fIcount\fP unique attribute values in \fB\fCtilestats\fR instead of the default 100.
.RE
.SS Temporary storage
.RS
@ -325,6 +673,8 @@ If you don't specify, it will use \fB\fC/tmp\fR\&.
.IP \(bu 2
\fB\fC\-Q\fR or \fB\fC\-\-no\-progress\-indicator\fR: Don't report progress, but still give warnings
.IP \(bu 2
\fB\fC\-U\fR \fIseconds\fP or \fB\fC\-\-progress\-interval=\fR\fIseconds\fP: Don't report progress more often than the specified number of \fIseconds\fP\&.
.IP \(bu 2
\fB\fC\-v\fR or \fB\fC\-\-version\fR: Report Tippecanoe's version number
.RE
.SS Filters
@ -349,7 +699,7 @@ The postfilter receives the features at tile resolution, after simplification, c
.PP
The layer name is provided as part of the \fB\fCtippecanoe\fR element of the feature and must be passed through
to keep the feature in its correct layer. In the case of the prefilter, the \fB\fCtippecanoe\fR element may also
contain \fB\fCindex\fR, \fB\fCsequence\fR, and \fB\fCextent\fR elements, which must be passed through for internal operations like
contain \fB\fCindex\fR, \fB\fCsequence\fR, \fB\fCextent\fR, and \fB\fCdropped\fR, elements, which must be passed through for internal operations like
\fB\fC\-\-drop\-densest\-as\-needed\fR, \fB\fC\-\-drop\-smallest\-as\-needed\fR, and \fB\fC\-\-preserve\-input\-order\fR to work.
.SS Examples:
.RS
@ -431,6 +781,14 @@ the filename or name specified using \fB\fC\-\-layer\fR, like this:
}
.fi
.RE
.PP
If your source GeoJSON only has \fB\fCminzoom\fR, \fB\fCmaxzoom\fR and/or \fB\fClayer\fR within \fB\fCproperties\fR you can use ndjson\-cli \[la]https://github.com/mbostock/ndjson-cli/blob/master/README.md\[ra] to move them into the required \fB\fCtippecanoe\fR object by piping the GeoJSON like this:
.PP
.RS
.nf
ndjson\-map 'd.tippecanoe = { minzoom: d.properties.minzoom, maxzoom: d.properties.maxzoom, layer: d.properties.layer }, delete d.properties.minzoom, delete d.properties.maxzoom, delete d.properties.layer, d'
.fi
.RE
.SH Geometric simplifications
.PP
At every zoom level, line and polygon features are subjected to Douglas\-Peucker
@ -458,7 +816,7 @@ all of them should have had together.
.PP
Features in the same tile that share the same type and attributes are coalesced
together into a single geometry if you use \fB\fC\-\-coalesce\fR\&. You are strongly encouraged to use \-x to exclude
any unnecessary properties to reduce wasted file size.
any unnecessary attributes to reduce wasted file size.
.PP
If a tile is larger than 500K, it will try encoding that tile at progressively
lower resolutions before failing if it still doesn't fit.
@ -586,11 +944,15 @@ The options are:
.IP \(bu 2
\fB\fC\-x\fR \fIkey\fP or \fB\fC\-\-exclude=\fR\fIkey\fP: Remove attributes of type \fIkey\fP from the output. You can use this to remove the field you are matching against if you no longer need it after joining, or to remove any other attributes you don't want.
.IP \(bu 2
\fB\fC\-X\fR or \fB\fC\-\-exclude\-all\fR: Remove all attributes from the output.
.IP \(bu 2
\fB\fC\-i\fR or \fB\fC\-\-if\-matched\fR: Only include features that matched the CSV.
.IP \(bu 2
\fB\fC\-j\fR \fIfilter\fP or \fB\fC\-\-feature\-filter\fR=\fIfilter\fP: Check features against a per\-layer filter (as defined in the Mapbox GL Style Specification \[la]https://www.mapbox.com/mapbox-gl-js/style-spec/#types-filter\[ra]) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer \fB\fC"*"\fR apply to all layers.
\fB\fC\-j\fR \fIfilter\fP or \fB\fC\-\-feature\-filter\fR=\fIfilter\fP: Check features against a per\-layer filter (as defined in the Mapbox GL Style Specification \[la]https://docs.mapbox.com/mapbox-gl-js/style-spec/#other-filter\[ra]) and only include those that match. Any features in layers that have no filter specified will be passed through. Filters for the layer \fB\fC"*"\fR apply to all layers.
.IP \(bu 2
\fB\fC\-J\fR \fIfilter\-file\fP or \fB\fC\-\-feature\-filter\-file\fR=\fIfilter\-file\fP: Like \fB\fC\-j\fR, but read the filter from a file.
.IP \(bu 2
\fB\fC\-pe\fR or \fB\fC\-\-empty\-csv\-columns\-are\-null\fR: Treat empty CSV columns as nulls rather than as empty strings.
.RE
.SS Setting or disabling tile size limits
.RS
@ -691,7 +1053,7 @@ tippecanoe\-decode file.vector.pbf zoom x y
.fi
.RE
.PP
If you decode an entire file, you get a nested \fB\fCFeatureCollection\fR identifying each
Unless you use \fB\fC\-c\fR, the output is a set of nested FeatureCollections identifying each
tile and layer separately. Note that the same features generally appear at all zooms,
so the output for the file will have many copies of the same features at different
resolutions.
@ -744,7 +1106,9 @@ something better.
The formatting makes excessive use of \fB\fC\\u\fR quoting so that it follows JSON string rules but will still
be sorted correctly by tools that just do ASCII comparisons.
.IP \(bu 2
\fB\fC\-c\fR \fIfile.csv\fP or \fB\fC\-\-csv=\fR\fIfile.csv\fP: Join properties from the named sorted CSV file, using its first column as the join key. Geometries will be passed through even if they do not match the CSV; CSV lines that do not match a geometry will be discarded.
\fB\fC\-c\fR \fIfile.csv\fP or \fB\fC\-\-csv=\fR\fIfile.csv\fP: Join attributes from the named sorted CSV file, using its first column as the join key. Geometries will be passed through even if they do not match the CSV; CSV lines that do not match a geometry will be discarded.
.IP \(bu 2
\fB\fC\-pe\fR or \fB\fC\-\-empty\-csv\-columns\-are\-null\fR: Treat empty CSV columns as nulls rather than as empty strings.
.RE
.SS Example
.PP
@ -779,7 +1143,7 @@ $ tippecanoe\-json\-tool \-e GEOID10 tl_2010_18157_tabblock10.json | LC_ALL=C so
.fi
.RE
.PP
Join block geometries to employment properties:
Join block geometries to employment attributes:
.PP
.RS
.nf

View File

@ -19,7 +19,7 @@ namespace geometry {
namespace wagyu {
template <typename T>
using active_bound_list = std::list<bound_ptr<T>>;
using active_bound_list = std::vector<bound_ptr<T>>;
template <typename T>
using active_bound_list_itr = typename active_bound_list<T>::iterator;
@ -83,37 +83,37 @@ bool is_even_odd_alt_fill_type(bound<T> const& bound,
}
template <typename T>
inline bool bound2_inserts_before_bound1(bound<T> const& bound1, bound<T> const& bound2) {
if (values_are_equal(bound2.current_x, bound1.current_x)) {
if (bound2.current_edge->top.y > bound1.current_edge->top.y) {
return bound2.current_edge->top.x <
get_current_x(*(bound1.current_edge), bound2.current_edge->top.y);
struct bound_insert_location {
bound<T> const& bound2;
bound_insert_location(bound<T> const& b) : bound2(b) {
}
bool operator()(bound_ptr<T> const& b) {
auto const& bound1 = *b;
if (values_are_equal(bound2.current_x, bound1.current_x)) {
if (bound2.current_edge->top.y > bound1.current_edge->top.y) {
return static_cast<double>(bound2.current_edge->top.x) <
get_current_x(*(bound1.current_edge), bound2.current_edge->top.y);
} else {
return static_cast<double>(bound1.current_edge->top.x) >
get_current_x(*(bound2.current_edge), bound1.current_edge->top.y);
}
} else {
return bound1.current_edge->top.x >
get_current_x(*(bound2.current_edge), bound1.current_edge->top.y);
return bound2.current_x < bound1.current_x;
}
} else {
return bound2.current_x < bound1.current_x;
}
}
};
template <typename T>
active_bound_list_itr<T> insert_bound_into_ABL(bound<T>& bnd, active_bound_list<T>& active_bounds) {
auto itr = active_bounds.begin();
while (itr != active_bounds.end() && !bound2_inserts_before_bound1(*(*itr), bnd)) {
++itr;
}
return active_bounds.insert(itr, &bnd);
}
active_bound_list_itr<T>
insert_bound_into_ABL(bound<T>& left, bound<T>& right, active_bound_list<T>& active_bounds) {
template <typename T>
active_bound_list_itr<T> insert_bound_into_ABL(bound<T>& bnd,
active_bound_list_itr<T> itr,
active_bound_list<T>& active_bounds) {
while (itr != active_bounds.end() && !bound2_inserts_before_bound1(*(*itr), bnd)) {
++itr;
}
return active_bounds.insert(itr, &bnd);
auto itr =
std::find_if(active_bounds.begin(), active_bounds.end(), bound_insert_location<T>(left));
itr = active_bounds.insert(itr, &right);
return active_bounds.insert(itr, &left);
}
template <typename T>
@ -147,39 +147,23 @@ inline bool next_edge_is_horizontal(active_bound_list_itr<T>& bnd) {
}
template <typename T>
inline void swap_positions_in_ABL(active_bound_list_itr<T>& bnd1,
active_bound_list_itr<T>& bnd2,
active_bound_list<T>& active_bounds) {
if (std::next(bnd2) == bnd1) {
active_bounds.splice(bnd2, active_bounds, bnd1);
} else {
active_bounds.splice(bnd1, active_bounds, bnd2);
}
}
template <typename T>
void next_edge_in_bound(active_bound_list_itr<T>& bnd, scanbeam_list<T>& scanbeam) {
++((*bnd)->current_edge);
if ((*bnd)->current_edge != (*bnd)->edges.end()) {
++((*bnd)->next_edge);
(*bnd)->current_x = static_cast<double>((*bnd)->current_edge->bot.x);
if (!current_edge_is_horizontal<T>(bnd)) {
scanbeam.push((*bnd)->current_edge->top.y);
void next_edge_in_bound(bound<T>& bnd, scanbeam_list<T>& scanbeam) {
auto& current_edge = bnd.current_edge;
++current_edge;
if (current_edge != bnd.edges.end()) {
++(bnd.next_edge);
bnd.current_x = static_cast<double>(current_edge->bot.x);
if (!is_horizontal<T>(*current_edge)) {
scanbeam.push_back(current_edge->top.y);
}
}
}
template <typename T>
active_bound_list_itr<T> get_maxima_pair(active_bound_list_itr<T> bnd,
active_bound_list_itr<T> get_maxima_pair(active_bound_list_itr<T> const& bnd,
active_bound_list<T>& active_bounds) {
auto bnd_itr = active_bounds.begin();
while (bnd_itr != active_bounds.end()) {
if (*bnd_itr == (*bnd)->maximum_bound) {
break;
}
++bnd_itr;
}
return bnd_itr;
bound_ptr<T> maximum = (*bnd)->maximum_bound;
return std::find(active_bounds.begin(), active_bounds.end(), maximum);
}
template <typename T>
@ -247,9 +231,7 @@ void set_winding_count(active_bound_list_itr<T>& bnd_itr,
if (is_even_odd_alt_fill_type(*(*bnd_itr), subject_fill_type, clip_fill_type)) {
// EvenOdd filling ...
while (bnd_itr_forward != bnd_itr) {
if ((*bnd_itr_forward)->winding_delta != 0) {
(*bnd_itr)->winding_count2 = ((*bnd_itr)->winding_count2 == 0 ? 1 : 0);
}
(*bnd_itr)->winding_count2 = ((*bnd_itr)->winding_count2 == 0 ? 1 : 0);
++bnd_itr_forward;
}
} else {
@ -362,21 +344,21 @@ void insert_lm_left_and_right_bound(bound<T>& left_bound,
fill_type clip_fill_type) {
// Both left and right bound
auto lb_abl_itr = insert_bound_into_ABL(left_bound, active_bounds);
auto rb_abl_itr = active_bounds.insert(std::next(lb_abl_itr), &right_bound);
auto lb_abl_itr = insert_bound_into_ABL(left_bound, right_bound, active_bounds);
auto rb_abl_itr = std::next(lb_abl_itr);
set_winding_count(lb_abl_itr, active_bounds, subject_fill_type, clip_fill_type);
(*rb_abl_itr)->winding_count = (*lb_abl_itr)->winding_count;
(*rb_abl_itr)->winding_count2 = (*lb_abl_itr)->winding_count2;
if (is_contributing(left_bound, cliptype, subject_fill_type, clip_fill_type)) {
add_local_minimum_point(lb_abl_itr, rb_abl_itr, active_bounds,
add_local_minimum_point(*(*lb_abl_itr), *(*rb_abl_itr), active_bounds,
(*lb_abl_itr)->current_edge->bot, rings);
}
// Add top of edges to scanbeam
scanbeam.push((*lb_abl_itr)->current_edge->top.y);
scanbeam.push_back((*lb_abl_itr)->current_edge->top.y);
if (!current_edge_is_horizontal<T>(rb_abl_itr)) {
scanbeam.push((*rb_abl_itr)->current_edge->top.y);
scanbeam.push_back((*rb_abl_itr)->current_edge->top.y);
}
}

View File

@ -36,6 +36,7 @@ struct bound {
bound() noexcept
: edges(),
current_edge(edges.end()),
next_edge(edges.end()),
last_point({ 0, 0 }),
ring(nullptr),
maximum_bound(nullptr),
@ -51,6 +52,7 @@ struct bound {
bound(bound<T>&& b) noexcept
: edges(std::move(b.edges)),
current_edge(std::move(b.current_edge)),
next_edge(std::move(b.next_edge)),
last_point(std::move(b.last_point)),
ring(std::move(b.ring)),
maximum_bound(std::move(b.maximum_bound)),
@ -62,6 +64,10 @@ struct bound {
poly_type(std::move(b.poly_type)),
side(std::move(b.side)) {
}
bound(bound<T>const& b) = delete;
bound<T>& operator=(bound<T> const&) = delete;
};
#ifdef DEBUG

View File

@ -0,0 +1,28 @@
#pragma once
namespace mapbox {
namespace geometry {
namespace wagyu {
template <typename It, class Compare, class MethodOnSwap>
void bubble_sort(It begin, It end, Compare c, MethodOnSwap m) {
if (begin == end) {
return;
}
bool modified = false;
auto last = end - 1;
do {
modified = false;
for (auto itr = begin; itr != last; ++itr) {
auto next = std::next(itr);
if (!c(*itr, *next)) {
m(*itr, *next);
std::iter_swap(itr, next);
modified = true;
}
}
} while (modified);
}
}
}
}

View File

@ -25,8 +25,8 @@ bool point_2_is_between_point_1_and_point_3(mapbox::geometry::point<T> const& pt
}
}
template <typename T>
bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge_list<T>& edges) {
template <typename T1, typename T2>
bool build_edge_list(mapbox::geometry::linear_ring<T2> const& path_geometry, edge_list<T1>& edges) {
if (path_geometry.size() < 3) {
return false;
@ -37,8 +37,8 @@ bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge
auto itr_rev = path_geometry.rbegin();
auto itr = path_geometry.begin();
mapbox::geometry::point<T> pt1 = *itr_rev;
mapbox::geometry::point<T> pt2 = *itr;
mapbox::geometry::point<T2> pt1 = *itr_rev;
mapbox::geometry::point<T2> pt2 = *itr;
// Find next non repeated point going backwards from
// end for pt1
@ -50,10 +50,10 @@ bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge
pt1 = *itr_rev;
}
++itr;
mapbox::geometry::point<T> pt3 = *itr;
mapbox::geometry::point<T2> pt3 = *itr;
auto itr_last = itr_rev.base();
mapbox::geometry::point<T> front_pt;
mapbox::geometry::point<T> back_pt;
mapbox::geometry::point<T2> front_pt;
mapbox::geometry::point<T2> back_pt;
while (true) {
if (pt3 == pt2) {
// Duplicate point advance itr, but do not
@ -84,10 +84,15 @@ bool build_edge_list(mapbox::geometry::linear_ring<T> const& path_geometry, edge
edges.pop_back(); // remove previous edge (pt1)
}
if (!edges.empty()) {
if (back_pt == edges.back().top) {
pt1 = edges.back().bot;
auto const& back_top = edges.back().top;
if (static_cast<T1>(back_pt.x) == back_top.x &&
static_cast<T1>(back_pt.y) == back_top.y) {
auto const& back_bot = edges.back().bot;
pt1 = mapbox::geometry::point<T2>(static_cast<T2>(back_bot.x),
static_cast<T2>(back_bot.y));
} else {
pt1 = edges.back().top;
pt1 = mapbox::geometry::point<T2>(static_cast<T2>(back_top.x),
static_cast<T2>(back_top.y));
}
back_pt = pt1;
} else {

View File

@ -9,26 +9,13 @@ namespace mapbox {
namespace geometry {
namespace wagyu {
template <typename T>
bool add_line_string(mapbox::geometry::line_string<T> const& path_geometry,
local_minimum_list<T>& minima_list) {
bool is_flat = true;
edge_list<T> new_edges;
new_edges.reserve(path_geometry.size());
if (!build_edge_list(path_geometry, new_edges, is_flat) || new_edges.empty()) {
return false;
}
add_line_to_local_minima_list(new_edges, minima_list, polygon_type_subject);
return true;
}
template <typename T>
bool add_linear_ring(mapbox::geometry::linear_ring<T> const& path_geometry,
local_minimum_list<T>& minima_list,
template <typename T1, typename T2>
bool add_linear_ring(mapbox::geometry::linear_ring<T2> const& path_geometry,
local_minimum_list<T1>& minima_list,
polygon_type p_type) {
edge_list<T> new_edges;
edge_list<T1> new_edges;
new_edges.reserve(path_geometry.size());
if (!build_edge_list(path_geometry, new_edges) || new_edges.empty()) {
if (!build_edge_list<T1, T2>(path_geometry, new_edges) || new_edges.empty()) {
return false;
}
add_ring_to_local_minima_list(new_edges, minima_list, p_type);

View File

@ -3,24 +3,28 @@
#include <mapbox/geometry/wagyu/ring.hpp>
#include <mapbox/geometry/wagyu/ring_util.hpp>
#include <mapbox/geometry/multi_polygon.hpp>
namespace mapbox {
namespace geometry {
namespace wagyu {
template <typename T>
void push_ring_to_polygon(mapbox::geometry::polygon<T>& poly, ring_ptr<T>& r, bool reverse_output) {
mapbox::geometry::linear_ring<T> lr;
lr.reserve(r->size + 1);
template <typename T1, typename T2>
void push_ring_to_polygon(mapbox::geometry::polygon<T2>& poly,
ring_ptr<T1> r,
bool reverse_output) {
mapbox::geometry::linear_ring<T2> lr;
lr.reserve(r->size() + 1);
auto firstPt = r->points;
auto ptIt = r->points;
if (reverse_output) {
do {
lr.emplace_back(ptIt->x, ptIt->y);
lr.emplace_back(static_cast<T2>(ptIt->x), static_cast<T2>(ptIt->y));
ptIt = ptIt->next;
} while (ptIt != firstPt);
} else {
do {
lr.emplace_back(ptIt->x, ptIt->y);
lr.emplace_back(static_cast<T2>(ptIt->x), static_cast<T2>(ptIt->y));
ptIt = ptIt->prev;
} while (ptIt != firstPt);
}
@ -28,28 +32,28 @@ void push_ring_to_polygon(mapbox::geometry::polygon<T>& poly, ring_ptr<T>& r, bo
poly.push_back(lr);
}
template <typename T>
void build_result_polygons(std::vector<mapbox::geometry::polygon<T>>& solution,
ring_list<T>& rings,
template <typename T1, typename T2>
void build_result_polygons(mapbox::geometry::multi_polygon<T2>& solution,
ring_vector<T1>const& rings,
bool reverse_output) {
for (auto& r : rings) {
assert(r->points);
std::size_t cnt = point_count(r->points);
if (cnt < 3) {
for (auto r : rings) {
if (r == nullptr) {
continue;
}
assert(r->points);
solution.emplace_back();
push_ring_to_polygon(solution.back(), r, reverse_output);
for (auto& c : r->children) {
assert(c->points);
cnt = point_count(c->points);
if (cnt < 3) {
for (auto c : r->children) {
if (c == nullptr) {
continue;
}
assert(c->points);
push_ring_to_polygon(solution.back(), c, reverse_output);
}
for (auto& c : r->children) {
for (auto c : r->children) {
if (c == nullptr) {
continue;
}
if (!c->children.empty()) {
build_result_polygons(solution, c->children, reverse_output);
}
@ -57,9 +61,9 @@ void build_result_polygons(std::vector<mapbox::geometry::polygon<T>>& solution,
}
}
template <typename T>
void build_result(std::vector<mapbox::geometry::polygon<T>>& solution,
ring_manager<T>& rings,
template <typename T1, typename T2>
void build_result(mapbox::geometry::multi_polygon<T2>& solution,
ring_manager<T1>const& rings,
bool reverse_output) {
build_result_polygons(solution, rings.children, reverse_output);
}

View File

@ -38,13 +38,16 @@ struct edge {
return *this;
}
edge(mapbox::geometry::point<T> const& current,
mapbox::geometry::point<T> const& next_pt) noexcept
: bot(current), top(current), dx(0.0) {
template <typename T2>
edge(mapbox::geometry::point<T2> const& current,
mapbox::geometry::point<T2> const& next_pt) noexcept
: bot(static_cast<T>(current.x), static_cast<T>(current.y)),
top(static_cast<T>(current.x), static_cast<T>(current.y)),
dx(0.0) {
if (current.y >= next_pt.y) {
top = next_pt;
top = mapbox::geometry::point<T>(static_cast<T>(next_pt.x), static_cast<T>(next_pt.y));
} else {
bot = next_pt;
bot = mapbox::geometry::point<T>(static_cast<T>(next_pt.x), static_cast<T>(next_pt.y));
}
double dy = static_cast<double>(top.y - bot.y);
if (value_is_zero(dy)) {

View File

@ -17,8 +17,8 @@ namespace wagyu {
template <typename T>
struct intersect_node {
active_bound_list_itr<T> bound1;
active_bound_list_itr<T> bound2;
bound_ptr<T> bound1;
bound_ptr<T> bound2;
mapbox::geometry::point<double> pt;
intersect_node(intersect_node<T>&& n)
@ -32,8 +32,8 @@ struct intersect_node {
return *this;
}
intersect_node(active_bound_list_itr<T> const& bound1_,
active_bound_list_itr<T> const& bound2_,
intersect_node(bound_ptr<T> const& bound1_,
bound_ptr<T> const& bound2_,
mapbox::geometry::point<double> const& pt_)
: bound1(bound1_), bound2(bound2_), pt(pt_) {
}
@ -49,9 +49,9 @@ inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, t
const intersect_node<T>& e) {
out << " point x: " << e.pt.x << " y: " << e.pt.y << std::endl;
out << " bound 1: " << std::endl;
out << *(*e.bound1) << std::endl;
out << *e.bound1 << std::endl;
out << " bound 2: " << std::endl;
out << *(*e.bound2) << std::endl;
out << *e.bound2 << std::endl;
return out;
}

View File

@ -2,11 +2,14 @@
#include <mapbox/geometry/wagyu/active_bound_list.hpp>
#include <mapbox/geometry/wagyu/bound.hpp>
#include <mapbox/geometry/wagyu/bubble_sort.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/intersect.hpp>
#include <mapbox/geometry/wagyu/ring_util.hpp>
#include <mapbox/geometry/wagyu/util.hpp>
#include <algorithm>
namespace mapbox {
namespace geometry {
namespace wagyu {
@ -17,8 +20,8 @@ struct intersect_list_sorter {
if (!values_are_equal(node2.pt.y, node1.pt.y)) {
return node2.pt.y < node1.pt.y;
} else {
return ((*node2.bound1)->winding_count2 + (*node2.bound2)->winding_count2) >
((*node1.bound1)->winding_count2 + (*node1.bound2)->winding_count2);
return (node2.bound1->winding_count2 + node2.bound2->winding_count2) >
(node1.bound1->winding_count2 + node1.bound2->winding_count2);
}
}
};
@ -60,9 +63,8 @@ bool get_edge_intersection(edge<T1> const& e1,
s2_x = p3_x - p2_x;
s2_y = p3_y - p2_y;
T2 s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
T2 s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
T2 t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0.0 && s <= 1.0 && t >= 0.0 && t <= 1.0) {
pt.x = p0_x + (t * s1_x);
@ -75,89 +77,89 @@ bool get_edge_intersection(edge<T1> const& e1,
}
template <typename T>
void build_intersect_list(active_bound_list<T>& active_bounds, intersect_list<T>& intersects) {
// bubblesort ...
bool isModified = false;
do {
isModified = false;
auto bnd = active_bounds.begin();
auto bnd_next = std::next(bnd);
while (bnd_next != active_bounds.end()) {
if ((*bnd)->current_x > (*bnd_next)->current_x &&
!slopes_equal(*((*bnd)->current_edge), *((*bnd_next)->current_edge))) {
mapbox::geometry::point<double> pt;
if (!get_edge_intersection<T, double>(*((*bnd)->current_edge),
*((*bnd_next)->current_edge), pt)) {
// LCOV_EXCL_START
throw std::runtime_error(
"Trying to find intersection of lines that do not intersect");
// LCOV_EXCL_END
}
intersects.emplace_back(bnd, bnd_next, pt);
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
bnd_next = std::next(bnd);
isModified = true;
} else {
bnd = bnd_next;
++bnd_next;
}
struct intersection_compare {
bool operator()(bound_ptr<T> const& b1, bound_ptr<T> const& b2) {
return !(b1->current_x > b2->current_x &&
!slopes_equal(*(b1->current_edge), *(b2->current_edge)));
}
};
template <typename T>
struct on_intersection_swap {
intersect_list<T>& intersects;
on_intersection_swap(intersect_list<T>& i) : intersects(i) {
}
void operator()(bound_ptr<T> const& b1, bound_ptr<T> const& b2) {
mapbox::geometry::point<double> pt;
if (!get_edge_intersection<T, double>(*(b1->current_edge), *(b2->current_edge), pt)) {
// LCOV_EXCL_START
throw std::runtime_error("Trying to find intersection of lines that do not intersect");
// LCOV_EXCL_END
}
} while (isModified);
intersects.emplace_back(b1, b2, pt);
}
};
template <typename T>
void build_intersect_list(active_bound_list<T>& active_bounds, intersect_list<T>& intersects) {
bubble_sort(active_bounds.begin(), active_bounds.end(), intersection_compare<T>(),
on_intersection_swap<T>(intersects));
}
template <typename T>
void intersect_bounds(active_bound_list_itr<T>& b1,
active_bound_list_itr<T>& b2,
void intersect_bounds(bound<T>& b1,
bound<T>& b2,
mapbox::geometry::point<T> const& pt,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type,
ring_manager<T>& rings,
active_bound_list<T>& active_bounds) {
bool b1Contributing = ((*b1)->ring != nullptr);
bool b2Contributing = ((*b2)->ring != nullptr);
bool b1Contributing = (b1.ring != nullptr);
bool b2Contributing = (b2.ring != nullptr);
// update winding counts...
// assumes that b1 will be to the Right of b2 ABOVE the intersection
if ((*b1)->poly_type == (*b2)->poly_type) {
if (is_even_odd_fill_type(*(*b1), subject_fill_type, clip_fill_type)) {
std::int32_t oldE1winding_count = (*b1)->winding_count;
(*b1)->winding_count = (*b2)->winding_count;
(*b2)->winding_count = oldE1winding_count;
if (b1.poly_type == b2.poly_type) {
if (is_even_odd_fill_type(b1, subject_fill_type, clip_fill_type)) {
std::swap(b1.winding_count, b2.winding_count);
} else {
if ((*b1)->winding_count + (*b2)->winding_delta == 0) {
(*b1)->winding_count = -(*b1)->winding_count;
if (b1.winding_count + b2.winding_delta == 0) {
b1.winding_count = -b1.winding_count;
} else {
(*b1)->winding_count += (*b2)->winding_delta;
b1.winding_count += b2.winding_delta;
}
if ((*b2)->winding_count - (*b1)->winding_delta == 0) {
(*b2)->winding_count = -(*b2)->winding_count;
if (b2.winding_count - b1.winding_delta == 0) {
b2.winding_count = -b2.winding_count;
} else {
(*b2)->winding_count -= (*b1)->winding_delta;
b2.winding_count -= b1.winding_delta;
}
}
} else {
if (!is_even_odd_fill_type(*(*b2), subject_fill_type, clip_fill_type)) {
(*b1)->winding_count2 += (*b2)->winding_delta;
if (!is_even_odd_fill_type(b2, subject_fill_type, clip_fill_type)) {
b1.winding_count2 += b2.winding_delta;
} else {
(*b1)->winding_count2 = ((*b1)->winding_count2 == 0) ? 1 : 0;
b1.winding_count2 = (b1.winding_count2 == 0) ? 1 : 0;
}
if (!is_even_odd_fill_type(*(*b1), subject_fill_type, clip_fill_type)) {
(*b2)->winding_count2 -= (*b1)->winding_delta;
if (!is_even_odd_fill_type(b1, subject_fill_type, clip_fill_type)) {
b2.winding_count2 -= b1.winding_delta;
} else {
(*b2)->winding_count2 = ((*b2)->winding_count2 == 0) ? 1 : 0;
b2.winding_count2 = (b2.winding_count2 == 0) ? 1 : 0;
}
}
fill_type b1FillType, b2FillType, b1FillType2, b2FillType2;
if ((*b1)->poly_type == polygon_type_subject) {
if (b1.poly_type == polygon_type_subject) {
b1FillType = subject_fill_type;
b1FillType2 = clip_fill_type;
} else {
b1FillType = clip_fill_type;
b1FillType2 = subject_fill_type;
}
if ((*b2)->poly_type == polygon_type_subject) {
if (b2.poly_type == polygon_type_subject) {
b2FillType = subject_fill_type;
b2FillType2 = clip_fill_type;
} else {
@ -168,51 +170,51 @@ void intersect_bounds(active_bound_list_itr<T>& b1,
std::int32_t b1Wc, b2Wc;
switch (b1FillType) {
case fill_type_positive:
b1Wc = (*b1)->winding_count;
b1Wc = b1.winding_count;
break;
case fill_type_negative:
b1Wc = -(*b1)->winding_count;
b1Wc = -b1.winding_count;
break;
case fill_type_even_odd:
case fill_type_non_zero:
default:
b1Wc = std::abs(static_cast<int>((*b1)->winding_count));
b1Wc = std::abs(static_cast<int>(b1.winding_count));
}
switch (b2FillType) {
case fill_type_positive:
b2Wc = (*b2)->winding_count;
b2Wc = b2.winding_count;
break;
case fill_type_negative:
b2Wc = -(*b2)->winding_count;
b2Wc = -b2.winding_count;
break;
case fill_type_even_odd:
case fill_type_non_zero:
default:
b2Wc = std::abs(static_cast<int>((*b2)->winding_count));
b2Wc = std::abs(static_cast<int>(b2.winding_count));
}
if (b1Contributing && b2Contributing) {
if ((b1Wc != 0 && b1Wc != 1) || (b2Wc != 0 && b2Wc != 1) ||
((*b1)->poly_type != (*b2)->poly_type && cliptype != clip_type_x_or)) {
(b1.poly_type != b2.poly_type && cliptype != clip_type_x_or)) {
add_local_maximum_point(b1, b2, pt, rings, active_bounds);
} else {
add_point(b1, active_bounds, pt, rings);
add_point(b2, active_bounds, pt, rings);
swap_sides(*(*b1), *(*b2));
swap_rings(*(*b1), *(*b2));
swap_sides(b1, b2);
swap_rings(b1, b2);
}
} else if (b1Contributing) {
if (b2Wc == 0 || b2Wc == 1) {
add_point(b1, active_bounds, pt, rings);
(*b2)->last_point = pt;
swap_sides(*(*b1), *(*b2));
swap_rings(*(*b1), *(*b2));
b2.last_point = pt;
swap_sides(b1, b2);
swap_rings(b1, b2);
}
} else if (b2Contributing) {
if (b1Wc == 0 || b1Wc == 1) {
(*b1)->last_point = pt;
b1.last_point = pt;
add_point(b2, active_bounds, pt, rings);
swap_sides(*(*b1), *(*b2));
swap_rings(*(*b1), *(*b2));
swap_sides(b1, b2);
swap_rings(b1, b2);
}
} else if ((b1Wc == 0 || b1Wc == 1) && (b2Wc == 0 || b2Wc == 1)) {
// neither bound is currently contributing ...
@ -220,30 +222,30 @@ void intersect_bounds(active_bound_list_itr<T>& b1,
std::int32_t b1Wc2, b2Wc2;
switch (b1FillType2) {
case fill_type_positive:
b1Wc2 = (*b1)->winding_count2;
b1Wc2 = b1.winding_count2;
break;
case fill_type_negative:
b1Wc2 = -(*b1)->winding_count2;
b1Wc2 = -b1.winding_count2;
break;
case fill_type_even_odd:
case fill_type_non_zero:
default:
b1Wc2 = std::abs(static_cast<int>((*b1)->winding_count2));
b1Wc2 = std::abs(static_cast<int>(b1.winding_count2));
}
switch (b2FillType2) {
case fill_type_positive:
b2Wc2 = (*b2)->winding_count2;
b2Wc2 = b2.winding_count2;
break;
case fill_type_negative:
b2Wc2 = -(*b2)->winding_count2;
b2Wc2 = -b2.winding_count2;
break;
case fill_type_even_odd:
case fill_type_non_zero:
default:
b2Wc2 = std::abs(static_cast<int>((*b2)->winding_count2));
b2Wc2 = std::abs(static_cast<int>(b2.winding_count2));
}
if ((*b1)->poly_type != (*b2)->poly_type) {
if (b1.poly_type != b2.poly_type) {
add_local_minimum_point(b1, b2, active_bounds, pt, rings);
} else if (b1Wc == 1 && b2Wc == 1) {
switch (cliptype) {
@ -259,8 +261,8 @@ void intersect_bounds(active_bound_list_itr<T>& b1,
}
break;
case clip_type_difference:
if ((((*b1)->poly_type == polygon_type_clip) && (b1Wc2 > 0) && (b2Wc2 > 0)) ||
(((*b1)->poly_type == polygon_type_subject) && (b1Wc2 <= 0) && (b2Wc2 <= 0))) {
if (((b1.poly_type == polygon_type_clip) && (b1Wc2 > 0) && (b2Wc2 > 0)) ||
((b1.poly_type == polygon_type_subject) && (b1Wc2 <= 0) && (b2Wc2 <= 0))) {
add_local_minimum_point(b1, b2, active_bounds, pt, rings);
}
break;
@ -268,16 +270,29 @@ void intersect_bounds(active_bound_list_itr<T>& b1,
add_local_minimum_point(b1, b2, active_bounds, pt, rings);
}
} else {
swap_sides(*(*b1), *(*b2));
swap_sides(b1, b2);
}
}
}
template <typename T>
bool bounds_adjacent(intersect_node<T> const& inode) {
return (std::next(inode.bound1) == inode.bound2) || (std::next(inode.bound2) == inode.bound1);
bool bounds_adjacent(intersect_node<T> const& inode, bound_ptr<T> next) {
return (next == inode.bound2) || (next == inode.bound1);
}
template <typename T>
struct find_first_bound {
bound_ptr<T> b1;
bound_ptr<T> b2;
find_first_bound(intersect_node<T> const& inode) : b1(inode.bound1), b2(inode.bound2) {
}
bool operator()(bound_ptr<T> const& b) {
return b == b1 || b == b2;
}
};
template <typename T>
void process_intersect_list(intersect_list<T>& intersects,
clip_type cliptype,
@ -286,9 +301,20 @@ void process_intersect_list(intersect_list<T>& intersects,
ring_manager<T>& rings,
active_bound_list<T>& active_bounds) {
for (auto node_itr = intersects.begin(); node_itr != intersects.end(); ++node_itr) {
if (!bounds_adjacent(*node_itr)) {
auto b1 = std::find_if(active_bounds.begin(), active_bounds.end(),
find_first_bound<T>(*node_itr));
auto b2 = std::next(b1);
if (!bounds_adjacent(*node_itr, *b2)) {
auto next_itr = std::next(node_itr);
while (next_itr != intersects.end() && !bounds_adjacent(*next_itr)) {
while (next_itr != intersects.end()) {
auto n1 = std::find_if(active_bounds.begin(), active_bounds.end(),
find_first_bound<T>(*next_itr));
auto n2 = std::next(n1);
if (bounds_adjacent(*next_itr, *n2)) {
b1 = n1;
b2 = n2;
break;
}
++next_itr;
}
if (next_itr == intersects.end()) {
@ -297,9 +323,9 @@ void process_intersect_list(intersect_list<T>& intersects,
std::iter_swap(node_itr, next_itr);
}
mapbox::geometry::point<T> pt = round_point<T>(node_itr->pt);
intersect_bounds(node_itr->bound1, node_itr->bound2, pt, cliptype, subject_fill_type,
intersect_bounds(*(node_itr->bound1), *(node_itr->bound2), pt, cliptype, subject_fill_type,
clip_fill_type, rings, active_bounds);
swap_positions_in_ABL(node_itr->bound1, node_itr->bound2, active_bounds);
std::iter_swap(b1, b2);
}
}
@ -331,7 +357,8 @@ void process_intersections(T top_y,
}
// Restore order of active bounds list
active_bounds.sort(
std::stable_sort(
active_bounds.begin(), active_bounds.end(),
[](bound_ptr<T> const& b1, bound_ptr<T> const& b2) { return b1->pos < b2->pos; });
// Sort the intersection list

View File

@ -3,6 +3,8 @@
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <algorithm>
#ifdef DEBUG
#include <stdexcept>
#endif
@ -102,7 +104,7 @@ bound<T> create_bound_towards_minimum(edge_list<T>& edges) {
if (next_edge == edges.end()) {
std::swap(edges, bnd.edges);
} else {
bnd.edges.reserve(std::distance(edges.begin(), next_edge));
bnd.edges.reserve(static_cast<std::size_t>(std::distance(edges.begin(), next_edge)));
std::move(edges.begin(), next_edge, std::back_inserter(bnd.edges));
edges.erase(edges.begin(), next_edge);
}
@ -147,7 +149,7 @@ bound<T> create_bound_towards_maximum(edge_list<T>& edges) {
if (next_edge == edges.end()) {
std::swap(bnd.edges, edges);
} else {
bnd.edges.reserve(std::distance(edges.begin(), next_edge));
bnd.edges.reserve(static_cast<std::size_t>(std::distance(edges.begin(), next_edge)));
std::move(edges.begin(), next_edge, std::back_inserter(bnd.edges));
edges.erase(edges.begin(), next_edge);
}
@ -234,12 +236,12 @@ void add_ring_to_local_minima_list(edge_list<T>& edges,
lm_minimum_has_horizontal = true;
++to_min_first_non_horizontal;
}
#ifdef DEBUG
if (to_max_first_non_horizontal == to_maximum.edges.end() ||
to_min_first_non_horizontal == to_minimum.edges.end()) {
throw std::runtime_error("should not have a horizontal only bound for a ring");
}
#endif
if (lm_minimum_has_horizontal) {
if (to_max_first_non_horizontal->bot.x > to_min_first_non_horizontal->bot.x) {
minimum_is_left = true;

View File

@ -37,18 +37,12 @@ struct point {
point_ptr<T> next;
point_ptr<T> prev;
point(point<T>&& p)
: ring(std::move(p.ring)),
x(std::move(p.x)),
y(std::move(p.y)),
next(std::move(p.next)),
prev(std::move(p.prev)) {
}
point() : ring(nullptr), x(0), y(0), prev(this), next(this) {
}
point(T x_, T y_) : ring(nullptr), x(x_), y(y_), next(this), prev(this) {
}
point(ring_ptr<T> ring_, mapbox::geometry::point<T> const& pt)
: ring(ring_), x(pt.x), y(pt.y), next(this), prev(this) {
}
@ -60,6 +54,12 @@ struct point {
}
};
template <typename T>
using point_vector = std::vector<point_ptr<T>>;
template <typename T>
using point_vector_itr = typename point_vector<T>::iterator;
template <typename T>
bool operator==(point<T> const& lhs, point<T> const& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y;

View File

@ -23,6 +23,7 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
fill_type subject_fill_type,
fill_type clip_fill_type) {
auto horizontal_itr_behind = horz_bound;
bool shifted = false;
bool is_maxima_edge = is_maxima(horz_bound, scanline_y);
auto bound_max_pair = active_bounds.end();
if (is_maxima_edge) {
@ -39,11 +40,15 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
auto bnd = std::next(horz_bound);
while (bnd != active_bounds.end()) {
if (*bnd == nullptr) {
++bnd;
continue;
}
// this code block inserts extra coords into horizontal edges (in output
// polygons) wherever hot pixels touch these horizontal edges. This helps
//'simplifying' polygons (ie if the Simplify property is set).
while (hp_itr != rings.hot_pixels.end() && hp_itr->y == scanline_y &&
hp_itr->x < std::llround((*bnd)->current_x) &&
hp_itr->x < wround<T>((*bnd)->current_x) &&
hp_itr->x < (*horz_bound)->current_edge->top.x) {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
@ -57,7 +62,7 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
// Also break if we've got to the end of an intermediate horizontal edge ...
// nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
if (std::llround((*bnd)->current_x) == (*horz_bound)->current_edge->top.x &&
if (wround<T>((*bnd)->current_x) == (*horz_bound)->current_edge->top.x &&
(*horz_bound)->next_edge != (*horz_bound)->edges.end() &&
(*horz_bound)->current_edge->dx < (*horz_bound)->next_edge->dx) {
break;
@ -65,99 +70,95 @@ active_bound_list_itr<T> process_horizontal_left_to_right(T scanline_y,
// note: may be done multiple times
if ((*horz_bound)->ring) {
add_point_to_ring(
*(*horz_bound),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y), rings);
add_point_to_ring(*(*horz_bound),
mapbox::geometry::point<T>(wround<T>((*bnd)->current_x), scanline_y),
rings);
}
// OK, so far we're still in range of the horizontal Edge but make sure
// we're at the last of consec. horizontals when matching with eMaxPair
if (is_maxima_edge && bnd == bound_max_pair) {
if ((*horz_bound)->ring) {
add_local_maximum_point(horz_bound, bound_max_pair,
add_local_maximum_point(*(*horz_bound), *(*bound_max_pair),
(*horz_bound)->current_edge->top, rings, active_bounds);
}
active_bounds.erase(bound_max_pair);
auto after_horz = active_bounds.erase(horz_bound);
if (horizontal_itr_behind != horz_bound) {
return horizontal_itr_behind;
} else {
return after_horz;
*bound_max_pair = nullptr;
*horz_bound = nullptr;
if (!shifted) {
++horizontal_itr_behind;
}
return horizontal_itr_behind;
}
intersect_bounds(horz_bound, bnd,
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y),
intersect_bounds(*(*horz_bound), *(*bnd),
mapbox::geometry::point<T>(wround<T>((*bnd)->current_x), scanline_y),
cliptype, subject_fill_type, clip_fill_type, rings, active_bounds);
auto next_bnd = std::next(bnd);
swap_positions_in_ABL(horz_bound, bnd, active_bounds);
if (current_edge_is_horizontal<T>(bnd) && horizontal_itr_behind == horz_bound) {
horizontal_itr_behind = bnd;
}
bnd = next_bnd;
std::iter_swap(horz_bound, bnd);
horz_bound = bnd;
++bnd;
shifted = true;
} // end while (bnd != active_bounds.end())
if ((*horz_bound)->ring) {
while (hp_itr != rings.hot_pixels.end() && hp_itr->y == scanline_y &&
hp_itr->x < std::llround((*horz_bound)->current_edge->top.x)) {
hp_itr->x < (*horz_bound)->current_edge->top.x) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
++hp_itr;
}
}
if ((*horz_bound)->next_edge != (*horz_bound)->edges.end()) {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
next_edge_in_bound(horz_bound, scanbeam);
} else {
next_edge_in_bound(horz_bound, scanbeam);
}
if (horizontal_itr_behind != horz_bound) {
return horizontal_itr_behind;
} else {
return std::next(horz_bound);
}
} else {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
}
auto after_horz = active_bounds.erase(horz_bound);
if (horizontal_itr_behind != horz_bound) {
return horizontal_itr_behind;
} else {
return after_horz;
}
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
}
if ((*horz_bound)->next_edge != (*horz_bound)->edges.end()) {
next_edge_in_bound(*(*horz_bound), scanbeam);
} else {
*horz_bound = nullptr;
}
if (!shifted) {
++horizontal_itr_behind;
}
return horizontal_itr_behind;
}
template <typename T>
active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
active_bound_list_itr<T>& horz_bound,
active_bound_list_itr<T>& horz_bound_fwd,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings,
scanbeam_list<T>& scanbeam,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type) {
bool is_maxima_edge = is_maxima(horz_bound, scanline_y);
auto bound_max_pair = active_bounds.end();
auto next_bnd_itr = std::next(horz_bound_fwd);
bool is_maxima_edge = is_maxima(horz_bound_fwd, scanline_y);
auto bound_max_pair = active_bounds.rend();
if (is_maxima_edge) {
bound_max_pair = get_maxima_pair<T>(horz_bound, active_bounds);
bound_max_pair =
active_bound_list_rev_itr<T>(get_maxima_pair<T>(horz_bound_fwd, active_bounds));
--bound_max_pair;
}
auto hp_itr_fwd = rings.current_hp_itr;
while (hp_itr_fwd != rings.hot_pixels.end() &&
(hp_itr_fwd->y < scanline_y ||
(hp_itr_fwd->y == scanline_y && hp_itr_fwd->x < (*horz_bound)->current_edge->top.x))) {
while (
hp_itr_fwd != rings.hot_pixels.end() &&
(hp_itr_fwd->y < scanline_y ||
(hp_itr_fwd->y == scanline_y && hp_itr_fwd->x < (*horz_bound_fwd)->current_edge->top.x))) {
++hp_itr_fwd;
}
auto hp_itr = hot_pixel_rev_itr<T>(hp_itr_fwd);
auto bnd = active_bound_list_rev_itr<T>(horz_bound);
auto bnd = active_bound_list_rev_itr<T>(horz_bound_fwd);
auto horz_bound = std::prev(bnd);
while (bnd != active_bounds.rend()) {
if (*bnd == nullptr) {
++bnd;
continue;
}
// this code block inserts extra coords into horizontal edges (in output
// polygons) wherever hot pixels touch these horizontal edges.
while (hp_itr != rings.hot_pixels.rend() && hp_itr->y == scanline_y &&
hp_itr->x > std::llround((*bnd)->current_x) &&
hp_itr->x > wround<T>((*bnd)->current_x) &&
hp_itr->x > (*horz_bound)->current_edge->top.x) {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), *hp_itr, rings);
@ -171,7 +172,7 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
// Also break if we've got to the end of an intermediate horizontal edge ...
// nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal.
if (std::llround((*bnd)->current_x) == (*horz_bound)->current_edge->top.x &&
if (wround<T>((*bnd)->current_x) == (*horz_bound)->current_edge->top.x &&
(*horz_bound)->next_edge != (*horz_bound)->edges.end() &&
(*horz_bound)->current_edge->dx < (*horz_bound)->next_edge->dx) {
break;
@ -179,32 +180,29 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
// note: may be done multiple times
if ((*horz_bound)->ring) {
add_point_to_ring(
*(*horz_bound),
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y), rings);
add_point_to_ring(*(*horz_bound),
mapbox::geometry::point<T>(wround<T>((*bnd)->current_x), scanline_y),
rings);
}
auto bnd_forward = --(bnd.base());
// OK, so far we're still in range of the horizontal Edge but make sure
// we're at the last of consec. horizontals when matching with eMaxPair
if (is_maxima_edge && bnd_forward == bound_max_pair) {
if (is_maxima_edge && bnd == bound_max_pair) {
if ((*horz_bound)->ring) {
add_local_maximum_point(horz_bound, bound_max_pair,
add_local_maximum_point(*(*horz_bound), *(*bound_max_pair),
(*horz_bound)->current_edge->top, rings, active_bounds);
}
active_bounds.erase(bound_max_pair);
return active_bounds.erase(horz_bound);
*bound_max_pair = nullptr;
*horz_bound = nullptr;
return next_bnd_itr;
}
intersect_bounds(bnd_forward, horz_bound,
mapbox::geometry::point<T>(std::llround((*bnd)->current_x), scanline_y),
intersect_bounds(*(*bnd), *(*horz_bound),
mapbox::geometry::point<T>(wround<T>((*bnd)->current_x), scanline_y),
cliptype, subject_fill_type, clip_fill_type, rings, active_bounds);
swap_positions_in_ABL(horz_bound, bnd_forward, active_bounds);
// Why are we not incrementing the bnd iterator here:
// It is because reverse iterators point to a `base()` iterator that is a forward
// iterator that is one ahead of the reverse bound. This will always be the horizontal
// bound,
// so what the reverse bound points to will have changed.
std::iter_swap(horz_bound, bnd);
horz_bound = bnd;
++bnd;
} // end while (bnd != active_bounds.rend())
if ((*horz_bound)->ring) {
@ -214,21 +212,16 @@ active_bound_list_itr<T> process_horizontal_right_to_left(T scanline_y,
++hp_itr;
}
}
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
}
if ((*horz_bound)->next_edge != (*horz_bound)->edges.end()) {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
next_edge_in_bound(horz_bound, scanbeam);
} else {
next_edge_in_bound(horz_bound, scanbeam);
}
return std::next(horz_bound);
next_edge_in_bound(*(*horz_bound), scanbeam);
} else {
if ((*horz_bound)->ring) {
add_point_to_ring(*(*horz_bound), (*horz_bound)->current_edge->top, rings);
}
return active_bounds.erase(horz_bound);
*horz_bound = nullptr;
}
return next_bnd_itr;
}
template <typename T>
@ -260,13 +253,15 @@ void process_horizontals(T scanline_y,
fill_type subject_fill_type,
fill_type clip_fill_type) {
for (auto bnd_itr = active_bounds.begin(); bnd_itr != active_bounds.end();) {
if (current_edge_is_horizontal<T>(bnd_itr)) {
if (*bnd_itr != nullptr && current_edge_is_horizontal<T>(bnd_itr)) {
bnd_itr = process_horizontal(scanline_y, bnd_itr, active_bounds, rings, scanbeam,
cliptype, subject_fill_type, clip_fill_type);
} else {
++bnd_itr;
}
}
active_bounds.erase(std::remove(active_bounds.begin(), active_bounds.end(), nullptr),
active_bounds.end());
}
}
}

View File

@ -22,39 +22,36 @@ active_bound_list_itr<T> do_maxima(active_bound_list_itr<T>& bnd,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type,
ring_manager<T>& rings,
ring_manager<T>& manager,
active_bound_list<T>& active_bounds) {
if (bndMaxPair == active_bounds.end()) {
if ((*bnd)->ring) {
add_point_to_ring(*(*bnd), (*bnd)->current_edge->top, rings);
}
return active_bounds.erase(bnd);
}
auto bnd_next = std::next(bnd);
auto return_bnd = bnd_next;
auto return_bnd = bnd;
bool skipped = false;
while (bnd_next != active_bounds.end() && bnd_next != bndMaxPair) {
if (*bnd_next == nullptr) {
++bnd_next;
continue;
}
skipped = true;
intersect_bounds(bnd, bnd_next, (*bnd)->current_edge->top, cliptype, subject_fill_type,
clip_fill_type, rings, active_bounds);
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
bnd_next = std::next(bnd);
intersect_bounds(*(*bnd), *(*bnd_next), (*bnd)->current_edge->top, cliptype,
subject_fill_type, clip_fill_type, manager, active_bounds);
std::iter_swap(bnd, bnd_next);
bnd = bnd_next;
++bnd_next;
}
if (!(*bnd)->ring && !(*bndMaxPair)->ring) {
active_bounds.erase(bndMaxPair);
} else if ((*bnd)->ring && (*bndMaxPair)->ring) {
add_local_maximum_point(bnd, bndMaxPair, (*bnd)->current_edge->top, rings, active_bounds);
active_bounds.erase(bndMaxPair);
} else {
if ((*bnd)->ring && (*bndMaxPair)->ring) {
add_local_maximum_point(*(*bnd), *(*bndMaxPair), (*bnd)->current_edge->top, manager,
active_bounds);
} else if ((*bnd)->ring || (*bndMaxPair)->ring) {
throw std::runtime_error("DoMaxima error");
}
auto prev_itr = active_bounds.erase(bnd);
if (skipped) {
return return_bnd;
} else {
return prev_itr;
*bndMaxPair = nullptr;
*bnd = nullptr;
if (!skipped) {
++return_bnd;
}
return return_bnd;
}
template <typename T>
@ -63,12 +60,16 @@ void process_edges_at_top_of_scanbeam(T top_y,
scanbeam_list<T>& scanbeam,
local_minimum_ptr_list<T> const& minima_sorted,
local_minimum_ptr_list_itr<T>& current_lm,
ring_manager<T>& rings,
ring_manager<T>& manager,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type) {
for (auto bnd = active_bounds.begin(); bnd != active_bounds.end();) {
if (*bnd == nullptr) {
++bnd;
continue;
}
// 1. Process maxima, treating them as if they are "bent" horizontal edges,
// but exclude maxima with horizontal edges.
@ -81,7 +82,7 @@ void process_edges_at_top_of_scanbeam(T top_y,
is_maxima(bnd_max_pair, top_y));
if (is_maxima_edge) {
bnd = do_maxima(bnd, bnd_max_pair, cliptype, subject_fill_type, clip_fill_type,
rings, active_bounds);
manager, active_bounds);
continue;
}
}
@ -89,23 +90,25 @@ void process_edges_at_top_of_scanbeam(T top_y,
// 2. Promote horizontal edges.
if (is_intermediate(bnd, top_y) && next_edge_is_horizontal<T>(bnd)) {
if ((*bnd)->ring) {
insert_hot_pixels_in_path(*(*bnd), (*bnd)->current_edge->top, rings, false);
insert_hot_pixels_in_path(*(*bnd), (*bnd)->current_edge->top, manager, false);
}
next_edge_in_bound(bnd, scanbeam);
next_edge_in_bound(*(*bnd), scanbeam);
if ((*bnd)->ring) {
add_point_to_ring(*(*bnd), (*bnd)->current_edge->bot, rings);
add_point_to_ring(*(*bnd), (*bnd)->current_edge->bot, manager);
}
} else {
(*bnd)->current_x = get_current_x(*((*bnd)->current_edge), top_y);
}
++bnd;
}
active_bounds.erase(std::remove(active_bounds.begin(), active_bounds.end(), nullptr),
active_bounds.end());
insert_horizontal_local_minima_into_ABL(top_y, minima_sorted, current_lm, active_bounds, rings,
scanbeam, cliptype, subject_fill_type, clip_fill_type);
insert_horizontal_local_minima_into_ABL(top_y, minima_sorted, current_lm, active_bounds,
manager, scanbeam, cliptype, subject_fill_type,
clip_fill_type);
process_horizontals(top_y, active_bounds, rings, scanbeam, cliptype, subject_fill_type,
process_horizontals(top_y, active_bounds, manager, scanbeam, cliptype, subject_fill_type,
clip_fill_type);
// 4. Promote intermediate vertices
@ -113,10 +116,9 @@ void process_edges_at_top_of_scanbeam(T top_y,
for (auto bnd = active_bounds.begin(); bnd != active_bounds.end(); ++bnd) {
if (is_intermediate(bnd, top_y)) {
if ((*bnd)->ring) {
add_point_to_ring(*(*bnd), (*bnd)->current_edge->top, rings);
insert_hot_pixels_in_path(*(*bnd), (*bnd)->current_edge->top, rings, false);
add_point_to_ring(*(*bnd), (*bnd)->current_edge->top, manager);
}
next_edge_in_bound(bnd, scanbeam);
next_edge_in_bound(*(*bnd), scanbeam);
}
}
}

View File

@ -18,23 +18,23 @@ mapbox::geometry::point<T> intersect(mapbox::geometry::point<T> a,
switch (edge) {
case 0:
return mapbox::geometry::point<T>(
static_cast<T>(a.x + static_cast<double>(b.x - a.x) * (box.min.y - a.y) / (b.y - a.y)),
mapbox::geometry::wagyu::wround<T>(static_cast<double>(a.x) + static_cast<double>(b.x - a.x) * static_cast<double>(box.min.y - a.y) / static_cast<double>(b.y - a.y)),
box.min.y);
case 1:
return mapbox::geometry::point<T>(
box.max.x,
static_cast<T>(a.y + static_cast<double>(b.y - a.y) * (box.max.x - a.x) / (b.x - a.x)));
mapbox::geometry::wagyu::wround<T>(static_cast<double>(a.y) + static_cast<double>(b.y - a.y) * static_cast<double>(box.max.x - a.x) / static_cast<double>(b.x - a.x)));
case 2:
return mapbox::geometry::point<T>(
static_cast<T>(a.x + static_cast<double>(b.x - a.x) * (box.max.y - a.y) / (b.y - a.y)),
mapbox::geometry::wagyu::wround<T>(static_cast<double>(a.x) + static_cast<double>(b.x - a.x) * static_cast<double>(box.max.y - a.y) / static_cast<double>(b.y - a.y)),
box.max.y);
default: // case 3
return mapbox::geometry::point<T>(
box.min.x,
static_cast<T>(a.y + static_cast<double>(b.y - a.y) * (box.min.x - a.x) / (b.x - a.x)));
mapbox::geometry::wagyu::wround<T>(static_cast<double>(a.y) + static_cast<double>(b.y - a.y) * static_cast<double>(box.min.x - a.x) / static_cast<double>(b.x - a.x)));
}
}
@ -57,7 +57,7 @@ bool inside(mapbox::geometry::point<T> p, size_t edge, mapbox::geometry::box<T>
template <typename T>
mapbox::geometry::linear_ring<T> quick_lr_clip(mapbox::geometry::linear_ring<T> const& ring,
mapbox::geometry::box<T> const& b) {
mapbox::geometry::box<T> const& b) {
mapbox::geometry::linear_ring<T> out = ring;
for (size_t edge = 0; edge < 4; edge++) {

View File

@ -5,6 +5,7 @@
#include <deque>
#include <list>
#include <map>
#include <mapbox/geometry/box.hpp>
#include <mapbox/geometry/wagyu/point.hpp>
#include <set>
#include <sstream>
@ -29,35 +30,117 @@ namespace mapbox {
namespace geometry {
namespace wagyu {
template <typename T>
double area_from_point(point_ptr<T> op, std::size_t& size, mapbox::geometry::box<T>& bbox) {
point_ptr<T> startOp = op;
size = 0;
double a = 0.0;
T min_x = op->x;
T max_x = op->x;
T min_y = op->y;
T max_y = op->y;
do {
++size;
if (op->x > max_x) {
max_x = op->x;
} else if (op->x < min_x) {
min_x = op->x;
}
if (op->y > max_y) {
max_y = op->y;
} else if (op->y < min_y) {
min_y = op->y;
}
a += static_cast<double>(op->prev->x + op->x) * static_cast<double>(op->prev->y - op->y);
op = op->next;
} while (op != startOp);
bbox.min.x = min_x;
bbox.max.x = max_x;
bbox.min.y = min_y;
bbox.max.y = max_y;
return a * 0.5;
}
// NOTE: ring and ring_ptr are forward declared in wagyu/point.hpp
template <typename T>
using ring_vector = std::vector<ring_ptr<T>>;
template <typename T>
using ring_list = std::list<ring_ptr<T>>;
template <typename T>
struct ring {
std::size_t ring_index; // To support unset 0 is undefined and indexes offset by 1
std::size_t size;
double area;
std::size_t size_; // number of points in the ring
double area_; // area of the ring
mapbox::geometry::box<T> bbox; // bounding box of the ring
ring_ptr<T> parent;
ring_list<T> children;
ring_vector<T> children;
point_ptr<T> points;
point_ptr<T> bottom_point;
bool is_hole_;
bool corrected;
ring(ring const&) = delete;
ring& operator=(ring const&) = delete;
ring()
: ring_index(0),
size(0),
area(std::numeric_limits<double>::quiet_NaN()),
size_(0),
area_(std::numeric_limits<double>::quiet_NaN()),
bbox({ 0, 0 }, { 0, 0 }),
parent(nullptr),
children(),
points(nullptr),
bottom_point(nullptr) {
bottom_point(nullptr),
is_hole_(false),
corrected(false) {
}
void reset_stats() {
area_ = std::numeric_limits<double>::quiet_NaN();
is_hole_ = false;
bbox.min.x = 0;
bbox.min.y = 0;
bbox.max.x = 0;
bbox.max.y = 0;
size_ = 0;
}
void recalculate_stats() {
if (points != nullptr) {
area_ = area_from_point(points, size_, bbox);
is_hole_ = !(area_ > 0.0);
}
}
void set_stats(double a, std::size_t s, mapbox::geometry::box<T> const& b) {
bbox = b;
area_ = a;
size_ = s;
is_hole_ = !(area_ > 0.0);
}
double area() {
if (std::isnan(area_)) {
recalculate_stats();
}
return area_;
}
bool is_hole() {
if (std::isnan(area_)) {
recalculate_stats();
}
return is_hole_;
}
std::size_t size() {
if (std::isnan(area_)) {
recalculate_stats();
}
return size_;
}
};
@ -73,8 +156,8 @@ using hot_pixel_rev_itr = typename hot_pixel_vector<T>::reverse_iterator;
template <typename T>
struct ring_manager {
ring_list<T> children;
std::vector<point_ptr<T>> all_points;
ring_vector<T> children;
point_vector<T> all_points;
hot_pixel_vector<T> hot_pixels;
hot_pixel_itr<T> current_hp_itr;
std::deque<point<T>> points;
@ -104,10 +187,10 @@ void preallocate_point_memory(ring_manager<T>& rings, std::size_t size) {
}
template <typename T>
ring_ptr<T> create_new_ring(ring_manager<T>& rings) {
rings.rings.emplace_back();
ring_ptr<T> result = &rings.rings.back();
result->ring_index = rings.index++;
ring_ptr<T> create_new_ring(ring_manager<T>& manager) {
manager.rings.emplace_back();
ring_ptr<T> result = &manager.rings.back();
result->ring_index = manager.index++;
return result;
}
@ -144,81 +227,190 @@ point_ptr<T> create_new_point(ring_ptr<T> r,
}
template <typename T>
void ring1_child_of_ring2(ring_ptr<T> ring1, ring_ptr<T> ring2, ring_manager<T>& manager) {
assert(ring1 != ring2);
if (ring1->parent == ring2) {
return;
void set_to_children(ring_ptr<T> r, ring_vector<T>& children) {
for (auto& c : children) {
if (c == nullptr) {
c = r;
return;
}
}
if (ring1->parent == nullptr) {
manager.children.remove(ring1);
} else {
ring1->parent->children.remove(ring1);
}
if (ring2 == nullptr) {
ring1->parent = nullptr;
manager.children.push_back(ring1);
} else {
ring1->parent = ring2;
ring2->children.push_back(ring1);
children.push_back(r);
}
template <typename T>
void remove_from_children(ring_ptr<T> r, ring_vector<T>& children) {
for (auto& c : children) {
if (c == r) {
c = nullptr;
return;
}
}
}
template <typename T>
void ring1_sibling_of_ring2(ring_ptr<T> ring1, ring_ptr<T> ring2, ring_manager<T>& manager) {
assert(ring1 != ring2);
if (ring1->parent == ring2->parent) {
void assign_as_child(ring_ptr<T> new_ring, ring_ptr<T> parent, ring_manager<T>& manager) {
// Assigning as a child assumes that this is
// a brand new ring. Therefore it does
// not have any existing relationships
if ((parent == nullptr && new_ring->is_hole()) ||
(parent != nullptr && new_ring->is_hole() == parent->is_hole())) {
throw std::runtime_error(
"Trying to assign a child that is the same orientation as the parent");
}
auto& children = parent == nullptr ? manager.children : parent->children;
set_to_children(new_ring, children);
new_ring->parent = parent;
}
template <typename T>
void reassign_as_child(ring_ptr<T> ring, ring_ptr<T> parent, ring_manager<T>& manager) {
// Reassigning a ring assumes it already
// has an existing parent
if ((parent == nullptr && ring->is_hole()) ||
(parent != nullptr && ring->is_hole() == parent->is_hole())) {
throw std::runtime_error(
"Trying to re-assign a child that is the same orientation as the parent");
}
// Remove the old child relationship
auto& old_children = ring->parent == nullptr ? manager.children : ring->parent->children;
remove_from_children(ring, old_children);
// Add new child relationship
auto& children = parent == nullptr ? manager.children : parent->children;
set_to_children(ring, children);
ring->parent = parent;
}
template <typename T>
void assign_as_sibling(ring_ptr<T> new_ring, ring_ptr<T> sibling, ring_manager<T>& manager) {
// Assigning as a sibling assumes that this is
// a brand new ring. Therefore it does
// not have any existing relationships
if (new_ring->is_hole() != sibling->is_hole()) {
throw std::runtime_error(
"Trying to assign to be a sibling that is not the same orientation as the sibling");
}
auto& children = sibling->parent == nullptr ? manager.children : sibling->parent->children;
set_to_children(new_ring, children);
new_ring->parent = sibling->parent;
}
template <typename T>
void reassign_as_sibling(ring_ptr<T> ring, ring_ptr<T> sibling, ring_manager<T>& manager) {
if (ring->parent == sibling->parent) {
return;
}
if (ring1->parent == nullptr) {
manager.children.remove(ring1);
} else {
ring1->parent->children.remove(ring1);
// Assigning as a sibling assumes that this is
// a brand new ring. Therefore it does
// not have any existing relationships
if (ring->is_hole() != sibling->is_hole()) {
throw std::runtime_error(
"Trying to assign to be a sibling that is not the same orientation as the sibling");
}
if (ring2->parent == nullptr) {
manager.children.push_back(ring1);
} else {
ring2->parent->children.push_back(ring1);
}
ring1->parent = ring2->parent;
// Remove the old child relationship
auto& old_children = ring->parent == nullptr ? manager.children : ring->parent->children;
remove_from_children(ring, old_children);
// Add new relationship
auto& children = sibling->parent == nullptr ? manager.children : sibling->parent->children;
set_to_children(ring, children);
ring->parent = sibling->parent;
}
template <typename T>
void ring1_replaces_ring2(ring_ptr<T> ring1, ring_ptr<T> ring2, ring_manager<T>& manager) {
assert(ring1 != ring2);
if (ring2->parent == nullptr) {
manager.children.remove(ring2);
} else {
ring2->parent->children.remove(ring2);
}
auto& ring1_children = ring1 == nullptr ? manager.children : ring1->children;
for (auto& c : ring2->children) {
if (c == nullptr) {
continue;
}
c->parent = ring1;
set_to_children(c, ring1_children);
c = nullptr;
}
if (ring1 == nullptr) {
manager.children.splice(manager.children.end(), ring2->children);
} else {
ring1->children.splice(ring1->children.end(), ring2->children);
}
ring2->parent = nullptr;
// Remove the old child relationship
auto& old_children = ring2->parent == nullptr ? manager.children : ring2->parent->children;
remove_from_children(ring2, old_children);
ring2->points = nullptr;
ring2->reset_stats();
}
template <typename T>
void remove_ring(ring_ptr<T> r, ring_manager<T>& manager) {
if (r->parent == nullptr) {
manager.children.remove(r);
for (auto& c : r->children) {
c->parent = nullptr;
void remove_points(point_ptr<T> pt) {
if (pt != nullptr) {
pt->prev->next = nullptr;
while (pt != nullptr) {
point_ptr<T> tmp = pt;
pt = pt->next;
tmp->next = nullptr;
tmp->prev = nullptr;
tmp->ring = nullptr;
}
manager.children.splice(manager.children.end(), r->children);
} else {
r->parent->children.remove(r);
for (auto& c : r->children) {
c->parent = r->parent;
}
r->parent->children.splice(r->parent->children.end(), r->children);
r->parent = nullptr;
}
}
template <typename T>
void remove_ring_and_points(ring_ptr<T> r,
ring_manager<T>& manager,
bool remove_children = true,
bool remove_from_parent = true) {
// Removes a ring and any children that might be
// under that ring.
for (auto& c : r->children) {
if (c == nullptr) {
continue;
}
if (remove_children) {
remove_ring_and_points(c, manager, true, false);
}
c = nullptr;
}
if (remove_from_parent) {
// Remove the old child relationship
auto& old_children = r->parent == nullptr ? manager.children : r->parent->children;
remove_from_children(r, old_children);
}
point_ptr<T> pt = r->points;
if (pt != nullptr) {
pt->prev->next = nullptr;
while (pt != nullptr) {
point_ptr<T> tmp = pt;
pt = pt->next;
tmp->next = nullptr;
tmp->prev = nullptr;
tmp->ring = nullptr;
}
}
r->points = nullptr;
r->reset_stats();
}
template <typename T>
void remove_ring(ring_ptr<T> r,
ring_manager<T>& manager,
bool remove_children = true,
bool remove_from_parent = true) {
// Removes a ring and any children that might be
// under that ring.
for (auto& c : r->children) {
if (c == nullptr) {
continue;
}
if (remove_children) {
remove_ring(c, manager, true, false);
}
c = nullptr;
}
if (remove_from_parent) {
// Remove the old child relationship
auto& old_children = r->parent == nullptr ? manager.children : r->parent->children;
remove_from_children(r, old_children);
}
r->points = nullptr;
r->reset_stats();
}
template <typename T>
inline std::size_t ring_depth(ring_ptr<T> r) {
std::size_t depth = 0;
@ -234,6 +426,10 @@ inline std::size_t ring_depth(ring_ptr<T> r) {
template <typename T>
inline bool ring_is_hole(ring_ptr<T> r) {
// This is different then the "normal" way of determing if
// a ring is a hole or not because it uses the depth of the
// the ring to determine if it is a hole or not. This is only done
// intially when rings are output from Vatti.
return ring_depth(r) & 1;
}
@ -263,17 +459,6 @@ void init(const_point_ptr<T>& node) {
set_prev(node, node);
}
template <typename T>
std::size_t point_count(const const_point_ptr<T>& orig_node) {
std::size_t size = 0;
point_ptr<T> n = orig_node;
do {
n = get_next(n);
++size;
} while (n != orig_node);
return size;
}
template <typename T>
void link_before(point_ptr<T>& node, point_ptr<T>& new_node) {
point_ptr<T> prev_node = get_prev(node);
@ -325,33 +510,11 @@ void reverse_ring(point_ptr<T> pp) {
} while (pp1 != pp);
}
template <typename T>
double area_from_point(point_ptr<T> op, std::size_t& size) {
point_ptr<T> startOp = op;
size = 1;
double a = 0.0;
do {
++size;
a += static_cast<double>(op->prev->x + op->x) * static_cast<double>(op->prev->y - op->y);
op = op->next;
} while (op != startOp);
return a * 0.5;
}
template <typename T>
double area(ring_ptr<T> r) {
assert(r != nullptr);
if (std::isnan(r->area)) {
r->area = area_from_point(r->points, r->size);
}
return r->area;
}
#ifdef DEBUG
template <class charT, class traits, typename T>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
const ring<T>& r) {
ring<T>& r) {
out << " ring_index: " << r.ring_index << std::endl;
if (!r.parent) {
// out << " parent_ring ptr: nullptr" << std::endl;
@ -368,7 +531,7 @@ inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, t
}
auto pt_itr = r.points;
if (pt_itr) {
out << " area: " << r.area << std::endl;
out << " area: " << r.area() << std::endl;
out << " points:" << std::endl;
out << " [[[" << pt_itr->x << "," << pt_itr->y << "],";
pt_itr = pt_itr->next;
@ -384,6 +547,22 @@ inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, t
return out;
}
template <typename T>
std::string debug_ring_addresses(ring_ptr<T> r) {
std::ostringstream out;
out << "Ring: " << r->ring_index << std::endl;
if (r->points == nullptr) {
out << " Ring has no points" << std::endl;
return out.str();
}
auto pt_itr = r->points;
do {
out << " [" << pt_itr->x << "," << pt_itr->y << "] - " << pt_itr << std::endl;
pt_itr = pt_itr->next;
} while (pt_itr != r->points);
return out.str();
}
template <typename T>
std::string output_as_polygon(ring_ptr<T> r) {
std::ostringstream out;
@ -399,6 +578,9 @@ std::string output_as_polygon(ring_ptr<T> r) {
}
out << "[" << pt_itr->x << "," << pt_itr->y << "]]";
for (auto const& c : r->children) {
if (c == nullptr) {
continue;
}
pt_itr = c->points;
if (pt_itr) {
out << ",[[" << pt_itr->x << "," << pt_itr->y << "],";
@ -420,22 +602,10 @@ std::string output_as_polygon(ring_ptr<T> r) {
template <class charT, class traits, typename T>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
const ring_list<T>& rings) {
out << "START RING LIST" << std::endl;
for (auto& r : rings) {
out << " ring: " << r->ring_index << " - " << r << std::endl;
out << *r;
}
out << "END RING LIST" << std::endl;
return out;
}
template <class charT, class traits, typename T>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
const ring_vector<T>& rings) {
ring_vector<T>& rings) {
out << "START RING VECTOR" << std::endl;
for (auto& r : rings) {
if (!r->points) {
if (r == nullptr || !r->points) {
continue;
}
out << " ring: " << r->ring_index << " - " << r << std::endl;
@ -447,7 +617,7 @@ inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, t
template <class charT, class traits, typename T>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
const std::deque<ring<T>>& rings) {
std::deque<ring<T>>& rings) {
out << "START RING VECTOR" << std::endl;
for (auto& r : rings) {
if (!r.points) {
@ -462,7 +632,7 @@ inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, t
template <class charT, class traits, typename T>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& out,
const hot_pixel_vector<T>& hp_vec) {
hot_pixel_vector<T>& hp_vec) {
out << "Hot Pixels: " << std::endl;
for (auto& hp : hp_vec) {
out << hp << std::endl;

View File

@ -15,7 +15,7 @@
// free(strs);
#endif
#include <queue>
#include <algorithm>
#include <mapbox/geometry/wagyu/active_bound_list.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
@ -28,55 +28,33 @@ namespace geometry {
namespace wagyu {
template <typename T>
void set_hole_state(active_bound_list_itr<T>& bnd,
active_bound_list<T>& active_bounds,
void set_hole_state(bound<T>& bnd,
active_bound_list<T> const& active_bounds,
ring_manager<T>& rings) {
auto bnd2 = active_bound_list_rev_itr<T>(bnd);
auto bnd_itr = std::find(active_bounds.rbegin(), active_bounds.rend(), &bnd);
++bnd_itr;
bound_ptr<T> bndTmp = nullptr;
// Find first non line ring to the left of current bound.
while (bnd2 != active_bounds.rend()) {
if ((*bnd2)->ring && (*bnd2)->winding_delta != 0) {
while (bnd_itr != active_bounds.rend()) {
if (*bnd_itr == nullptr) {
++bnd_itr;
continue;
}
if ((*bnd_itr)->ring) {
if (!bndTmp) {
bndTmp = (*bnd2);
} else if (bndTmp->ring == (*bnd2)->ring) {
bndTmp = (*bnd_itr);
} else if (bndTmp->ring == (*bnd_itr)->ring) {
bndTmp = nullptr;
}
}
++bnd2;
++bnd_itr;
}
if (!bndTmp) {
(*bnd)->ring->parent = nullptr;
rings.children.push_back((*bnd)->ring);
bnd.ring->parent = nullptr;
rings.children.push_back(bnd.ring);
} else {
(*bnd)->ring->parent = bndTmp->ring;
bndTmp->ring->children.push_back((*bnd)->ring);
}
}
template <typename T>
void set_hole_state(active_bound_list_rev_itr<T>& bnd,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings) {
auto bnd2 = std::next(bnd);
bound_ptr<T> bndTmp = nullptr;
// Find first non line ring to the left of current bound.
while (bnd2 != active_bounds.rend()) {
if ((*bnd2)->ring && (*bnd2)->winding_delta != 0) {
if (!bndTmp) {
bndTmp = (*bnd2);
} else if (bndTmp->ring == (*bnd2)->ring) {
bndTmp = nullptr;
}
}
++bnd2;
}
if (!bndTmp) {
(*bnd)->ring->parent = nullptr;
rings.children.push_back((*bnd)->ring);
} else {
(*bnd)->ring->parent = bndTmp->ring;
bndTmp->ring->children.push_back((*bnd)->ring);
bnd.ring->parent = bndTmp->ring;
bndTmp->ring->children.push_back(bnd.ring);
}
}
@ -328,29 +306,16 @@ void add_to_hot_pixels(mapbox::geometry::point<T> const& pt, ring_manager<T>& ri
}
template <typename T>
void add_first_point(active_bound_list_itr<T>& bnd,
void add_first_point(bound<T>& bnd,
active_bound_list<T>& active_bounds,
mapbox::geometry::point<T> const& pt,
ring_manager<T>& rings) {
ring_ptr<T> r = create_new_ring(rings);
(*bnd)->ring = r;
bnd.ring = r;
r->points = create_new_point(r, pt, rings);
set_hole_state(bnd, active_bounds, rings);
(*bnd)->last_point = pt;
}
template <typename T>
void add_first_point(active_bound_list_rev_itr<T>& bnd,
active_bound_list<T>& active_bounds,
mapbox::geometry::point<T> const& pt,
ring_manager<T>& rings) {
ring_ptr<T> r = create_new_ring(rings);
// no ring currently set!
(*bnd)->ring = r;
r->points = create_new_point(r, pt, rings);
set_hole_state(bnd, active_bounds, rings);
(*bnd)->last_point = pt;
bnd.last_point = pt;
}
template <typename T>
@ -377,64 +342,35 @@ void add_point_to_ring(bound<T>& bnd,
}
template <typename T>
void add_point(active_bound_list_itr<T>& bnd,
void add_point(bound<T>& bnd,
active_bound_list<T>& active_bounds,
mapbox::geometry::point<T> const& pt,
ring_manager<T>& rings) {
if (!(*bnd)->ring) {
if (bnd.ring == nullptr) {
add_first_point(bnd, active_bounds, pt, rings);
} else {
add_point_to_ring(*(*bnd), pt, rings);
add_point_to_ring(bnd, pt, rings);
}
}
template <typename T>
void add_point(active_bound_list_rev_itr<T>& bnd,
active_bound_list<T>& active_bounds,
mapbox::geometry::point<T> const& pt,
ring_manager<T>& rings) {
if (!(*bnd)->ring) {
add_first_point(bnd, active_bounds, pt, rings);
} else {
add_point_to_ring(*(*bnd), pt, rings);
}
}
template <typename T>
void add_local_minimum_point(active_bound_list_itr<T> b1,
active_bound_list_itr<T> b2,
void add_local_minimum_point(bound<T>& b1,
bound<T>& b2,
active_bound_list<T>& active_bounds,
mapbox::geometry::point<T> const& pt,
ring_manager<T>& rings) {
active_bound_list_itr<T> b;
active_bound_list_rev_itr<T> prev_bound;
active_bound_list_rev_itr<T> prev_b1(b1);
active_bound_list_rev_itr<T> prev_b2(b2);
if (is_horizontal(*((*b2)->current_edge)) ||
((*b1)->current_edge->dx > (*b2)->current_edge->dx)) {
if (is_horizontal(*b2.current_edge) || (b1.current_edge->dx > b2.current_edge->dx)) {
add_point(b1, active_bounds, pt, rings);
(*b2)->last_point = pt;
(*b2)->ring = (*b1)->ring;
(*b1)->side = edge_left;
(*b2)->side = edge_right;
b = b1;
if (prev_b1 != active_bounds.rend() && std::prev(b) == b2) {
prev_bound = prev_b2;
} else {
prev_bound = prev_b1;
}
b2.last_point = pt;
b2.ring = b1.ring;
b1.side = edge_left;
b2.side = edge_right;
} else {
add_point(b2, active_bounds, pt, rings);
(*b1)->last_point = pt;
(*b1)->ring = (*b2)->ring;
(*b1)->side = edge_right;
(*b2)->side = edge_left;
b = b2;
if (prev_b2 != active_bounds.rend() && std::prev(b) == b1) {
prev_bound = prev_b1;
} else {
prev_bound = prev_b2;
}
b1.last_point = pt;
b1.ring = b2.ring;
b1.side = edge_right;
b2.side = edge_left;
}
}
@ -443,7 +379,7 @@ inline double get_dx(point<T> const& pt1, point<T> const& pt2) {
if (pt1.y == pt2.y) {
return std::numeric_limits<double>::infinity();
} else {
return static_cast<double>(pt2.x - pt2.x) / static_cast<double>(pt2.y - pt1.y);
return static_cast<double>(pt2.x - pt1.x) / static_cast<double>(pt2.y - pt1.y);
}
}
@ -476,7 +412,8 @@ bool first_is_bottom_point(const_point_ptr<T> btmPt1, const_point_ptr<T> btmPt2)
if (values_are_equal(std::max(dx1p, dx1n), std::max(dx2p, dx2n)) &&
values_are_equal(std::min(dx1p, dx1n), std::min(dx2p, dx2n))) {
std::size_t s = 0;
return area_from_point(btmPt1, s) > 0.0; // if otherwise identical use orientation
mapbox::geometry::box<T> bbox({ 0, 0 }, { 0, 0 });
return area_from_point(btmPt1, s, bbox) > 0.0; // if otherwise identical use orientation
} else {
return (greater_than_or_equal(dx1p, dx2p) && greater_than_or_equal(dx1p, dx2n)) ||
(greater_than_or_equal(dx1n, dx2p) && greater_than_or_equal(dx1n, dx2n));
@ -569,13 +506,13 @@ void update_points_ring(ring_ptr<T> ring) {
}
template <typename T>
void append_ring(active_bound_list_itr<T>& b1,
active_bound_list_itr<T>& b2,
void append_ring(bound<T>& b1,
bound<T>& b2,
active_bound_list<T>& active_bounds,
ring_manager<T>& manager) {
// get the start and ends of both output polygons ...
ring_ptr<T> outRec1 = (*b1)->ring;
ring_ptr<T> outRec2 = (*b2)->ring;
ring_ptr<T> outRec1 = b1.ring;
ring_ptr<T> outRec2 = b2.ring;
ring_ptr<T> keep_ring;
bound_ptr<T> keep_bound;
@ -583,24 +520,24 @@ void append_ring(active_bound_list_itr<T>& b1,
bound_ptr<T> remove_bound;
if (ring1_child_below_ring2(outRec1, outRec2)) {
keep_ring = outRec2;
keep_bound = *b2;
keep_bound = &b2;
remove_ring = outRec1;
remove_bound = *b1;
remove_bound = &b1;
} else if (ring1_child_below_ring2(outRec2, outRec1)) {
keep_ring = outRec1;
keep_bound = *b1;
keep_bound = &b1;
remove_ring = outRec2;
remove_bound = *b2;
remove_bound = &b2;
} else if (outRec1 == get_lower_most_ring(outRec1, outRec2)) {
keep_ring = outRec1;
keep_bound = *b1;
keep_bound = &b1;
remove_ring = outRec2;
remove_bound = *b2;
remove_bound = &b2;
} else {
keep_ring = outRec2;
keep_bound = *b2;
keep_bound = &b2;
remove_ring = outRec1;
remove_bound = *b1;
remove_bound = &b1;
}
// get the start and ends of both output polygons and
@ -665,6 +602,9 @@ void append_ring(active_bound_list_itr<T>& b1,
remove_bound->ring = nullptr;
for (auto& b : active_bounds) {
if (b == nullptr) {
continue;
}
if (b->ring == remove_ring) {
b->ring = keep_ring;
b->side = keep_bound->side;
@ -674,18 +614,18 @@ void append_ring(active_bound_list_itr<T>& b1,
}
template <typename T>
void add_local_maximum_point(active_bound_list_itr<T>& b1,
active_bound_list_itr<T>& b2,
void add_local_maximum_point(bound<T>& b1,
bound<T>& b2,
mapbox::geometry::point<T> const& pt,
ring_manager<T>& rings,
active_bound_list<T>& active_bounds) {
insert_hot_pixels_in_path(*(*b2), pt, rings, false);
insert_hot_pixels_in_path(b2, pt, rings, false);
add_point(b1, active_bounds, pt, rings);
if ((*b1)->ring == (*b2)->ring) {
(*b1)->ring = nullptr;
(*b2)->ring = nullptr;
if (b1.ring == b2.ring) {
b1.ring = nullptr;
b2.ring = nullptr;
// I am not certain that order is important here?
} else if ((*b1)->ring->ring_index < (*b2)->ring->ring_index) {
} else if (b1.ring->ring_index < b2.ring->ring_index) {
append_ring(b1, b2, active_bounds, rings);
} else {
append_ring(b2, b1, active_bounds, rings);
@ -797,7 +737,7 @@ point_in_polygon_result point_in_polygon(mapbox::geometry::point<double> const&
if (value_is_zero(d)) {
return point_on_polygon;
}
if ((d > 0.0) == (op_next_y > op->y)) {
if ((d > 0.0) == (op_next_y > op_y)) {
// Switch between point outside polygon and point inside
// polygon
if (result == point_outside_polygon) {
@ -814,7 +754,7 @@ point_in_polygon_result point_in_polygon(mapbox::geometry::point<double> const&
if (value_is_zero(d)) {
return point_on_polygon;
}
if ((d > 0.0) == (op_next_y > op->y)) {
if ((d > 0.0) == (op_next_y > op_y)) {
// Switch between point outside polygon and point inside
// polygon
if (result == point_outside_polygon) {
@ -831,47 +771,68 @@ point_in_polygon_result point_in_polygon(mapbox::geometry::point<double> const&
return result;
}
template <typename T>
bool is_convex(point_ptr<T> edge) {
point_ptr<T> prev = edge->prev;
point_ptr<T> next = edge->next;
T v1x = edge->x - prev->x;
T v1y = edge->y - prev->y;
T v2x = next->x - edge->x;
T v2y = next->y - edge->y;
T cross = v1x * v2y - v2x * v1y;
if (cross < 0 && edge->ring->area() > 0) {
return true;
} else if (cross > 0 && edge->ring->area() < 0) {
return true;
} else {
return false;
}
}
template <typename T>
mapbox::geometry::point<double> centroid_of_points(point_ptr<T> edge) {
point_ptr<T> prev = edge->prev;
point_ptr<T> next = edge->next;
return { static_cast<double>(prev->x + edge->x + next->x) / 3.0, static_cast<double>(prev->y + edge->y + next->y) / 3.0 };
}
template <typename T>
point_in_polygon_result inside_or_outside_special(point_ptr<T> first_pt, point_ptr<T> other_poly) {
if (value_is_zero(area(first_pt->ring))) {
return point_inside_polygon;
}
if (value_is_zero(area(other_poly->ring))) {
return point_outside_polygon;
}
point_ptr<T> pt = first_pt;
// We are going to loop through all the points
// of the original triangle. The goal is to find a convex edge
// that with its next and previous forms a triangle with its centroid
// that is within the first ring. Then we will check the other polygon
// to see if it is within this polygon.
point_ptr<T> itr = first_pt;
do {
if (*pt == *(pt->prev) || *pt == *(pt->next) || *(pt->next) == *(pt->prev) ||
slopes_equal(*(pt->prev), *pt, *(pt->next))) {
pt = pt->next;
continue;
}
double dx = ((pt->prev->x - pt->x) / 3.0) + ((pt->next->x - pt->x) / 3.0);
double dy = ((pt->prev->y - pt->y) / 3.0) + ((pt->next->y - pt->y) / 3.0);
mapbox::geometry::point<double> offset_pt(pt->x + dx, pt->y + dy);
point_in_polygon_result res = point_in_polygon(offset_pt, pt);
if (res != point_inside_polygon) {
offset_pt.x = pt->x - dx;
offset_pt.y = pt->y - dy;
res = point_in_polygon(offset_pt, pt);
if (res != point_inside_polygon) {
pt = pt->next;
continue;
if (is_convex(itr)) {
auto pt = centroid_of_points(itr);
if (point_inside_polygon == point_in_polygon(pt, first_pt)) {
return point_in_polygon(pt, other_poly);
}
}
res = point_in_polygon(offset_pt, other_poly);
if (res == point_on_polygon) {
pt = pt->next;
continue;
}
return res;
} while (pt != first_pt);
return point_inside_polygon;
itr = itr->next;
} while (itr != first_pt);
throw std::runtime_error("Could not find a point within the polygon to test");
}
template <typename T>
bool box2_contains_box1(mapbox::geometry::box<T> const& box1,
mapbox::geometry::box<T> const& box2) {
return (box2.max.x >= box1.max.x && box2.max.y >= box1.max.y && box2.min.x <= box1.min.x &&
box2.min.y <= box1.min.y);
}
template <typename T>
bool poly2_contains_poly1(ring_ptr<T> ring1, ring_ptr<T> ring2) {
if (!box2_contains_box1(ring1->bbox, ring2->bbox)) {
return false;
}
if (std::fabs(ring2->area()) < std::fabs(ring1->area())) {
return false;
}
point_ptr<T> outpt1 = ring1->points->next;
point_ptr<T> outpt2 = ring2->points->next;
point_ptr<T> op = outpt1;
@ -886,21 +847,6 @@ bool poly2_contains_poly1(ring_ptr<T> ring1, ring_ptr<T> ring2) {
point_in_polygon_result res = inside_or_outside_special(outpt1, outpt2);
return res == point_inside_polygon;
}
template <typename T>
void dispose_out_points(point_ptr<T>& pp) {
if (pp == nullptr) {
return;
}
pp->prev->next = nullptr;
while (pp) {
point_ptr<T> tmpPp = pp;
pp = pp->next;
tmpPp->next = tmpPp;
tmpPp->prev = tmpPp;
tmpPp->ring = nullptr;
}
}
}
}
}

View File

@ -1,27 +1,26 @@
#pragma once
#include <queue>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/local_minimum.hpp>
#include <algorithm>
namespace mapbox {
namespace geometry {
namespace wagyu {
template <typename T>
using scanbeam_list = std::priority_queue<T>;
using scanbeam_list = std::vector<T>;
template <typename T>
bool pop_from_scanbeam(T& Y, scanbeam_list<T>& scanbeam) {
if (scanbeam.empty()) {
return false;
}
Y = scanbeam.top();
scanbeam.pop();
while (!scanbeam.empty() && Y == scanbeam.top()) {
scanbeam.pop();
} // Pop duplicates.
std::sort(scanbeam.begin(), scanbeam.end());
scanbeam.erase(std::unique(scanbeam.begin(), scanbeam.end()), scanbeam.end());
Y = scanbeam.back();
scanbeam.pop_back();
return true;
}
@ -29,7 +28,7 @@ template <typename T>
void setup_scanbeam(local_minimum_list<T>& minima_list, scanbeam_list<T>& scanbeam) {
for (auto lm = minima_list.begin(); lm != minima_list.end(); ++lm) {
scanbeam.push(lm->y);
scanbeam.push_back(lm->y);
}
}
}

View File

@ -2,6 +2,7 @@
#include <mapbox/geometry/wagyu/active_bound_list.hpp>
#include <mapbox/geometry/wagyu/bound.hpp>
#include <mapbox/geometry/wagyu/bubble_sort.hpp>
#include <mapbox/geometry/wagyu/config.hpp>
#include <mapbox/geometry/wagyu/edge.hpp>
#include <mapbox/geometry/wagyu/intersect.hpp>
@ -14,94 +15,114 @@ namespace mapbox {
namespace geometry {
namespace wagyu {
template <typename T>
struct hp_intersection_swap {
ring_manager<T>& manager;
hp_intersection_swap(ring_manager<T>& m) : manager(m) {
}
void operator()(bound_ptr<T> const& b1, bound_ptr<T> const& b2) {
mapbox::geometry::point<double> pt;
if (!get_edge_intersection<T, double>(*(b1->current_edge), *(b2->current_edge), pt)) {
// LCOV_EXCL_START
throw std::runtime_error("Trying to find intersection of lines that do not intersect");
// LCOV_EXCL_END
}
add_to_hot_pixels(round_point<T>(pt), manager);
}
};
template <typename T>
void process_hot_pixel_intersections(T top_y,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings) {
ring_manager<T>& manager) {
if (active_bounds.empty()) {
return;
}
update_current_x(active_bounds, top_y);
// bubblesort ...
bool isModified;
do {
isModified = false;
auto bnd = active_bounds.begin();
auto bnd_next = std::next(bnd);
while (bnd_next != active_bounds.end()) {
if ((*bnd)->current_x > (*bnd_next)->current_x &&
!slopes_equal(*(*bnd)->current_edge, *(*bnd_next)->current_edge)) {
mapbox::geometry::point<double> pt;
if (!get_edge_intersection<T, double>(*((*bnd)->current_edge),
*((*bnd_next)->current_edge), pt)) {
// LCOV_EXCL_START
throw std::runtime_error("Edges do not intersect!");
// LCOV_EXCL_END
bubble_sort(active_bounds.begin(), active_bounds.end(), intersection_compare<T>(),
hp_intersection_swap<T>(manager));
}
template <typename T>
bool horizontals_at_top_scanbeam(T top_y,
active_bound_list_itr<T>& bnd_curr,
active_bound_list<T>& active_bounds,
ring_manager<T>& manager) {
bool shifted = false;
auto& current_edge = (*bnd_curr)->current_edge;
(*bnd_curr)->current_x = static_cast<double>(current_edge->top.x);
if (current_edge->bot.x < current_edge->top.x) {
// left to right
auto bnd_next = std::next(bnd_curr);
while (bnd_next != active_bounds.end() &&
(*bnd_next == nullptr || (*bnd_next)->current_x < (*bnd_curr)->current_x)) {
if (*bnd_next != nullptr && (*bnd_next)->current_edge->top.y != top_y &&
(*bnd_next)->current_edge->bot.y != top_y) {
mapbox::geometry::point<T> pt(wround<T>((*bnd_next)->current_x), top_y);
add_to_hot_pixels(pt, manager);
}
std::iter_swap(bnd_curr, bnd_next);
++bnd_curr;
++bnd_next;
shifted = true;
}
} else {
// right to left
if (bnd_curr != active_bounds.begin()) {
auto bnd_prev = std::prev(bnd_curr);
while (bnd_curr != active_bounds.begin() &&
(*bnd_prev == nullptr || (*bnd_prev)->current_x > (*bnd_curr)->current_x)) {
if (*bnd_prev != nullptr && (*bnd_prev)->current_edge->top.y != top_y &&
(*bnd_prev)->current_edge->bot.y != top_y) {
mapbox::geometry::point<T> pt(wround<T>((*bnd_prev)->current_x), top_y);
add_to_hot_pixels(pt, manager);
}
std::iter_swap(bnd_curr, bnd_prev);
--bnd_curr;
if (bnd_curr != active_bounds.begin()) {
--bnd_prev;
}
add_to_hot_pixels(round_point<T>(pt), rings);
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
bnd_next = std::next(bnd);
isModified = true;
} else {
bnd = bnd_next;
++bnd_next;
}
}
} while (isModified);
}
return shifted;
}
template <typename T>
void process_hot_pixel_edges_at_top_of_scanbeam(T top_y,
scanbeam_list<T>& scanbeam,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings) {
ring_manager<T>& manager) {
for (auto bnd = active_bounds.begin(); bnd != active_bounds.end();) {
auto bnd_2 = std::next(bnd);
while ((*bnd)->current_edge != (*bnd)->edges.end() &&
(*bnd)->current_edge->top.y == top_y) {
add_to_hot_pixels((*bnd)->current_edge->top, rings);
if (current_edge_is_horizontal<T>(bnd)) {
(*bnd)->current_x = static_cast<double>((*bnd)->current_edge->top.x);
if ((*bnd)->current_edge->bot.x < (*bnd)->current_edge->top.x) {
// left to right
auto bnd_next = std::next(bnd);
while (bnd_next != active_bounds.end() &&
(*bnd_next)->current_x < (*bnd)->current_x) {
if (std::llround((*bnd_next)->current_edge->top.y) != top_y &&
std::llround((*bnd_next)->current_edge->bot.y) != top_y) {
mapbox::geometry::point<T> pt(std::llround((*bnd_next)->current_x),
top_y);
add_to_hot_pixels(pt, rings);
}
swap_positions_in_ABL(bnd, bnd_next, active_bounds);
bnd_next = std::next(bnd);
}
} else {
// right to left
if (bnd != active_bounds.begin()) {
auto bnd_prev = std::prev(bnd);
while (bnd != active_bounds.begin() &&
(*bnd_prev)->current_x > (*bnd)->current_x) {
if (std::llround((*bnd_prev)->current_edge->top.y) != top_y &&
std::llround((*bnd_prev)->current_edge->bot.y) != top_y) {
mapbox::geometry::point<T> pt(std::llround((*bnd_prev)->current_x),
top_y);
add_to_hot_pixels(pt, rings);
}
swap_positions_in_ABL(bnd, bnd_prev, active_bounds);
bnd_prev = std::prev(bnd);
}
}
if (*bnd == nullptr) {
++bnd;
continue;
}
bound<T>& current_bound = *(*bnd);
auto bnd_curr = bnd;
bool shifted = false;
auto& current_edge = current_bound.current_edge;
while (current_edge != current_bound.edges.end() && current_edge->top.y == top_y) {
add_to_hot_pixels(current_edge->top, manager);
if (is_horizontal(*current_edge)) {
if (horizontals_at_top_scanbeam(top_y, bnd_curr, active_bounds, manager)) {
shifted = true;
}
}
next_edge_in_bound(bnd, scanbeam);
next_edge_in_bound(current_bound, scanbeam);
}
if ((*bnd)->current_edge == (*bnd)->edges.end()) {
active_bounds.erase(bnd);
if (current_edge == current_bound.edges.end()) {
*bnd_curr = nullptr;
}
if (!shifted) {
++bnd;
}
bnd = bnd_2;
}
active_bounds.erase(std::remove(active_bounds.begin(), active_bounds.end(), nullptr),
active_bounds.end());
}
template <typename T>
@ -109,30 +130,32 @@ void insert_local_minima_into_ABL_hot_pixel(T top_y,
local_minimum_ptr_list<T>& minima_sorted,
local_minimum_ptr_list_itr<T>& lm,
active_bound_list<T>& active_bounds,
ring_manager<T>& rings,
ring_manager<T>& manager,
scanbeam_list<T>& scanbeam) {
while (lm != minima_sorted.end() && (*lm)->y == top_y) {
add_to_hot_pixels((*lm)->left_bound.edges.front().bot, rings);
add_to_hot_pixels((*lm)->left_bound.edges.front().bot, manager);
auto& left_bound = (*lm)->left_bound;
left_bound.current_edge = left_bound.edges.begin();
left_bound.current_x = static_cast<double>(left_bound.current_edge->bot.x);
auto lb_abl_itr = insert_bound_into_ABL(left_bound, active_bounds);
if (!current_edge_is_horizontal<T>(lb_abl_itr)) {
scanbeam.push((*lb_abl_itr)->current_edge->top.y);
}
auto& right_bound = (*lm)->right_bound;
left_bound.current_edge = left_bound.edges.begin();
left_bound.next_edge = std::next(left_bound.current_edge);
left_bound.current_x = static_cast<double>(left_bound.current_edge->bot.x);
right_bound.current_edge = right_bound.edges.begin();
right_bound.next_edge = std::next(right_bound.current_edge);
right_bound.current_x = static_cast<double>(right_bound.current_edge->bot.x);
auto rb_abl_itr = insert_bound_into_ABL(right_bound, lb_abl_itr, active_bounds);
auto lb_abl_itr = insert_bound_into_ABL(left_bound, right_bound, active_bounds);
if (!current_edge_is_horizontal<T>(lb_abl_itr)) {
scanbeam.push_back((*lb_abl_itr)->current_edge->top.y);
}
auto rb_abl_itr = std::next(lb_abl_itr);
if (!current_edge_is_horizontal<T>(rb_abl_itr)) {
scanbeam.push((*rb_abl_itr)->current_edge->top.y);
scanbeam.push_back((*rb_abl_itr)->current_edge->top.y);
}
++lm;
}
}
template <typename T>
void build_hot_pixels(local_minimum_list<T>& minima_list, ring_manager<T>& rings) {
void build_hot_pixels(local_minimum_list<T>& minima_list, ring_manager<T>& manager) {
active_bound_list<T> active_bounds;
scanbeam_list<T> scanbeam;
T scanline_y = std::numeric_limits<T>::max();
@ -153,19 +176,19 @@ void build_hot_pixels(local_minimum_list<T>& minima_list, ring_manager<T>& rings
reserve += lm.left_bound.edges.size() + 2;
reserve += lm.right_bound.edges.size() + 2;
}
rings.hot_pixels.reserve(reserve);
manager.hot_pixels.reserve(reserve);
while (pop_from_scanbeam(scanline_y, scanbeam) || current_lm != minima_sorted.end()) {
process_hot_pixel_intersections(scanline_y, active_bounds, rings);
process_hot_pixel_intersections(scanline_y, active_bounds, manager);
insert_local_minima_into_ABL_hot_pixel(scanline_y, minima_sorted, current_lm, active_bounds,
rings, scanbeam);
manager, scanbeam);
process_hot_pixel_edges_at_top_of_scanbeam(scanline_y, scanbeam, active_bounds, rings);
process_hot_pixel_edges_at_top_of_scanbeam(scanline_y, scanbeam, active_bounds, manager);
}
preallocate_point_memory(rings, rings.hot_pixels.size());
sort_hot_pixels(rings);
preallocate_point_memory(manager, manager.hot_pixels.size());
sort_hot_pixels(manager);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -31,17 +31,13 @@ double area(mapbox::geometry::linear_ring<T> const& poly) {
}
inline bool value_is_zero(double val) {
return std::fabs(val) < std::numeric_limits<double>::epsilon();
return std::fabs(val) < (5.0 * std::numeric_limits<double>::epsilon());
}
inline bool values_are_equal(double x, double y) {
return value_is_zero(x - y);
}
inline bool values_near_equal(double x, double y) {
return std::fabs(x - y) < (5.0 * std::numeric_limits<double>::epsilon());
}
inline bool greater_than_or_equal(double x, double y) {
return x > y || values_are_equal(x, y);
}
@ -74,6 +70,16 @@ bool slopes_equal(mapbox::geometry::point<T> const& pt1,
mapbox::geometry::point<T> const& pt4) {
return (pt1.y - pt2.y) * (pt3.x - pt4.x) == (pt1.x - pt2.x) * (pt3.y - pt4.y);
}
template <typename T>
inline T wround(double value) {
return static_cast<T>(::llround(value));
}
template <>
inline std::int64_t wround<std::int64_t>(double value) {
return ::llround(value);
}
}
}
}

View File

@ -19,16 +19,11 @@ namespace geometry {
namespace wagyu {
template <typename T>
bool execute_vatti(local_minimum_list<T>& minima_list,
ring_manager<T>& rings,
void execute_vatti(local_minimum_list<T>& minima_list,
ring_manager<T>& manager,
clip_type cliptype,
fill_type subject_fill_type,
fill_type clip_fill_type) {
if (minima_list.empty()) {
return false;
}
active_bound_list<T> active_bounds;
scanbeam_list<T> scanbeam;
T scanline_y = std::numeric_limits<T>::max();
@ -43,31 +38,28 @@ bool execute_vatti(local_minimum_list<T>& minima_list,
// std::clog << output_all_edges(minima_sorted) << std::endl;
setup_scanbeam(minima_list, scanbeam);
rings.current_hp_itr = rings.hot_pixels.begin();
manager.current_hp_itr = manager.hot_pixels.begin();
while (pop_from_scanbeam(scanline_y, scanbeam) || current_lm != minima_sorted.end()) {
process_intersections(scanline_y, active_bounds, cliptype, subject_fill_type,
clip_fill_type, rings);
clip_fill_type, manager);
update_current_hp_itr(scanline_y, rings);
update_current_hp_itr(scanline_y, manager);
// First we process bounds that has already been added to the active bound list --
// if the active bound list is empty local minima that are at this scanline_y and
// have a horizontal edge at the local minima will be processed
process_edges_at_top_of_scanbeam(scanline_y, active_bounds, scanbeam, minima_sorted,
current_lm, rings, cliptype, subject_fill_type,
current_lm, manager, cliptype, subject_fill_type,
clip_fill_type);
// Next we will add local minima bounds to the active bounds list that are on the local
// minima queue at
// this current scanline_y
insert_local_minima_into_ABL(scanline_y, minima_sorted, current_lm, active_bounds, rings,
insert_local_minima_into_ABL(scanline_y, minima_sorted, current_lm, active_bounds, manager,
scanbeam, cliptype, subject_fill_type, clip_fill_type);
}
// std::clog << rings.rings << std::endl;
// std::clog << output_as_polygon(rings.all_rings[0]);
return true;
}
}
}

View File

@ -16,10 +16,11 @@
#include <mapbox/geometry/wagyu/vatti.hpp>
#define WAGYU_MAJOR_VERSION 0
#define WAGYU_MINOR_VERSION 3
#define WAGYU_PATCH_VERSION 0
#define WAGYU_MINOR_VERSION 4
#define WAGYU_PATCH_VERSION 3
#define WAGYU_VERSION (WAGYU_MAJOR_VERSION * 100000) + (WAGYU_MINOR_VERSION * 100) + (WAGYU_PATCH_VERSION)
#define WAGYU_VERSION \
(WAGYU_MAJOR_VERSION * 100000) + (WAGYU_MINOR_VERSION * 100) + (WAGYU_PATCH_VERSION)
namespace mapbox {
namespace geometry {
@ -28,9 +29,7 @@ namespace wagyu {
template <typename T>
class wagyu {
private:
using value_type = T;
local_minimum_list<value_type> minima_list;
local_minimum_list<T> minima_list;
bool reverse_output;
wagyu(wagyu const&) = delete;
@ -44,12 +43,14 @@ public:
clear();
}
bool add_ring(mapbox::geometry::linear_ring<value_type> const& pg,
template <typename T2>
bool add_ring(mapbox::geometry::linear_ring<T2> const& pg,
polygon_type p_type = polygon_type_subject) {
return add_linear_ring(pg, minima_list, p_type);
}
bool add_polygon(mapbox::geometry::polygon<value_type> const& ppg,
template <typename T2>
bool add_polygon(mapbox::geometry::polygon<T2> const& ppg,
polygon_type p_type = polygon_type_subject) {
bool result = false;
for (auto const& r : ppg) {
@ -68,11 +69,11 @@ public:
minima_list.clear();
}
mapbox::geometry::box<value_type> get_bounds() {
mapbox::geometry::point<value_type> min = { 0, 0 };
mapbox::geometry::point<value_type> max = { 0, 0 };
mapbox::geometry::box<T> get_bounds() {
mapbox::geometry::point<T> min = { 0, 0 };
mapbox::geometry::point<T> max = { 0, 0 };
if (minima_list.empty()) {
return mapbox::geometry::box<value_type>(min, max);
return mapbox::geometry::box<T>(min, max);
}
bool first_set = false;
for (auto const& lm : minima_list) {
@ -109,25 +110,28 @@ public:
}
}
}
return mapbox::geometry::box<value_type>(min, max);
return mapbox::geometry::box<T>(min, max);
}
template <typename T2>
bool execute(clip_type cliptype,
mapbox::geometry::multi_polygon<value_type>& solution,
mapbox::geometry::multi_polygon<T2>& solution,
fill_type subject_fill_type,
fill_type clip_fill_type) {
ring_manager<T> rings;
build_hot_pixels(minima_list, rings);
if (!execute_vatti(minima_list, rings, cliptype, subject_fill_type, clip_fill_type)) {
if (minima_list.empty()) {
return false;
}
do_simple_polygons(rings);
ring_manager<T> manager;
build_result(solution, rings, reverse_output);
build_hot_pixels(minima_list, manager);
execute_vatti(minima_list, manager, cliptype, subject_fill_type, clip_fill_type);
correct_topology(manager);
build_result(solution, manager, reverse_output);
return true;
}

View File

@ -11,10 +11,17 @@
#include <string>
#include <set>
#include <map>
#include <sys/stat.h>
#include "mvt.hpp"
#include "mbtiles.hpp"
#include "text.hpp"
#include "milo/dtoa_milo.h"
#include "write_json.hpp"
#include "version.hpp"
size_t max_tilestats_attributes = 1000;
size_t max_tilestats_sample_values = 1000;
size_t max_tilestats_values = 100;
sqlite3 *mbtiles_open(char *dbname, char **argv, int forcetable) {
sqlite3 *outdb;
@ -38,7 +45,8 @@ sqlite3 *mbtiles_open(char *dbname, char **argv, int forcetable) {
exit(EXIT_FAILURE);
}
if (sqlite3_exec(outdb, "CREATE TABLE metadata (name text, value text);", NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "%s: create metadata table: %s\n", argv[0], err);
fprintf(stderr, "%s: Tileset \"%s\" already exists. You can use --force if you want to delete the old tileset.\n", argv[0], dbname);
fprintf(stderr, "%s: %s\n", argv[0], err);
if (!forcetable) {
exit(EXIT_FAILURE);
}
@ -86,38 +94,6 @@ void mbtiles_write_tile(sqlite3 *outdb, int z, int tx, int ty, const char *data,
}
}
static void quote(std::string &buf, std::string const &s) {
for (size_t i = 0; i < s.size(); i++) {
unsigned char ch = s[i];
if (ch == '\\' || ch == '\"') {
buf.push_back('\\');
buf.push_back(ch);
} else if (ch < ' ') {
char tmp[7];
sprintf(tmp, "\\u%04x", ch);
buf.append(std::string(tmp));
} else {
buf.push_back(ch);
}
}
}
void aprintf(std::string *buf, const char *format, ...) {
va_list ap;
char *tmp;
va_start(ap, format);
if (vasprintf(&tmp, format, ap) < 0) {
fprintf(stderr, "memory allocation failure\n");
exit(EXIT_FAILURE);
}
va_end(ap);
buf->append(tmp, strlen(tmp));
free(tmp);
}
bool type_and_string::operator<(const type_and_string &o) const {
if (string < o.string) {
return true;
@ -138,36 +114,36 @@ bool type_and_string::operator!=(const type_and_string &o) const {
return false;
}
std::string tilestats(std::map<std::string, layermap_entry> const &layermap1, size_t elements) {
void tilestats(std::map<std::string, layermap_entry> const &layermap1, size_t elements, json_writer &state) {
// Consolidate layers/attributes whose names are truncated
std::vector<std::map<std::string, layermap_entry>> lmv;
lmv.push_back(layermap1);
std::map<std::string, layermap_entry> layermap = merge_layermaps(lmv, true);
std::string out = "{\n";
state.json_write_hash();
out.append("\t\"layerCount\": ");
out.append(std::to_string(layermap.size()));
out.append(",\n");
state.nospace = true;
state.json_write_string("layerCount");
state.json_write_unsigned(layermap.size());
out.append("\t\"layers\": [\n");
state.nospace = true;
state.json_write_string("layers");
state.json_write_array();
bool first = true;
for (auto layer : layermap) {
if (!first) {
out.append(",\n");
}
first = false;
out.append("\t\t{\n");
state.nospace = true;
state.json_write_hash();
out.append("\t\t\t\"layer\": \"");
quote(out, layer.first.c_str());
out.append("\",\n");
state.nospace = true;
state.json_write_string("layer");
state.json_write_string(layer.first);
out.append("\t\t\t\"count\": ");
out.append(std::to_string(layer.second.points + layer.second.lines + layer.second.polygons));
out.append(",\n");
state.nospace = true;
state.json_write_string("count");
state.json_write_unsigned(layer.second.points + layer.second.lines + layer.second.polygons);
std::string geomtype = "Polygon";
if (layer.second.points >= layer.second.lines && layer.second.points >= layer.second.polygons) {
@ -176,45 +152,46 @@ std::string tilestats(std::map<std::string, layermap_entry> const &layermap1, si
geomtype = "LineString";
}
out.append("\t\t\t\"geometry\": \"");
quote(out, geomtype.c_str());
out.append("\",\n");
state.nospace = true;
state.json_write_string("geometry");
state.json_write_string(geomtype);
size_t attrib_count = layer.second.file_keys.size();
if (attrib_count > 1000) {
attrib_count = 1000;
if (attrib_count > max_tilestats_attributes) {
attrib_count = max_tilestats_attributes;
}
out.append("\t\t\t\"attributeCount\": ");
out.append(std::to_string(attrib_count));
out.append(",\n");
state.nospace = true;
state.json_write_string("attributeCount");
state.json_write_unsigned(attrib_count);
out.append("\t\t\t\"attributes\": [\n");
state.nospace = true;
state.json_write_string("attributes");
state.nospace = true;
state.json_write_array();
size_t attrs = 0;
for (auto attribute : layer.second.file_keys) {
if (attrs == elements) {
break;
}
if (attrs != 0) {
out.append(",\n");
}
attrs++;
out.append("\t\t\t\t{\n");
state.nospace = true;
state.json_write_hash();
out.append("\t\t\t\t\t\"attribute\": \"");
quote(out, attribute.first.c_str());
out.append("\",\n");
state.nospace = true;
state.json_write_string("attribute");
state.json_write_string(attribute.first);
size_t val_count = attribute.second.sample_values.size();
if (val_count > 1000) {
val_count = 1000;
if (val_count > max_tilestats_sample_values) {
val_count = max_tilestats_sample_values;
}
out.append("\t\t\t\t\t\"count\": ");
out.append(std::to_string(val_count));
out.append(",\n");
state.nospace = true;
state.json_write_string("count");
state.json_write_unsigned(val_count);
int type = 0;
for (auto s : attribute.second.sample_values) {
@ -233,11 +210,13 @@ std::string tilestats(std::map<std::string, layermap_entry> const &layermap1, si
type_str = "mixed";
}
out.append("\t\t\t\t\t\"type\": \"");
quote(out, type_str.c_str());
out.append("\",\n");
state.nospace = true;
state.json_write_string("type");
state.json_write_string(type_str);
out.append("\t\t\t\t\t\"values\": [\n");
state.nospace = true;
state.json_write_string("values");
state.json_write_array();
size_t vals = 0;
for (auto value : attribute.second.sample_values) {
@ -245,68 +224,53 @@ std::string tilestats(std::map<std::string, layermap_entry> const &layermap1, si
break;
}
state.nospace = true;
if (value.type == mvt_double || value.type == mvt_bool) {
if (vals != 0) {
out.append(",\n");
}
vals++;
out.append("\t\t\t\t\t\t");
out.append(value.string);
state.json_write_stringified(value.string);
} else {
std::string trunc = truncate16(value.string, 256);
if (trunc.size() == value.string.size()) {
if (vals != 0) {
out.append(",\n");
}
vals++;
out.append("\t\t\t\t\t\t\"");
quote(out, value.string.c_str());
out.append("\"");
state.json_write_string(value.string);
}
}
}
out.append("\n");
out.append("\t\t\t\t\t]");
state.nospace = true;
state.json_end_array();
if ((type & (1 << mvt_double)) != 0) {
out.append(",\n");
state.nospace = true;
state.json_write_string("min");
state.json_write_number(attribute.second.min);
out.append("\t\t\t\t\t\"min\": ");
out.append(milo::dtoa_milo(attribute.second.min));
out.append(",\n");
out.append("\t\t\t\t\t\"max\": ");
out.append(milo::dtoa_milo(attribute.second.max));
state.nospace = true;
state.json_write_string("max");
state.json_write_number(attribute.second.max);
}
out.append("\n");
out.append("\t\t\t\t}");
state.nospace = true;
state.json_end_hash();
}
out.append("\n\t\t\t]\n");
out.append("\t\t}");
state.nospace = true;
state.json_end_array();
state.nospace = true;
state.json_end_hash();
}
out.append("\n");
out.append("\t]\n");
out.append("}");
std::string out2;
for (size_t i = 0; i < out.size(); i++) {
if (out[i] != '\t' && out[i] != '\n') {
out2.push_back(out[i]);
}
}
return out2;
state.nospace = true;
state.json_end_array();
state.nospace = true;
state.json_end_hash();
}
void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fname, int minzoom, int maxzoom, double minlat, double minlon, double maxlat, double maxlon, double midlat, double midlon, int forcetable, const char *attribution, std::map<std::string, layermap_entry> const &layermap, bool vector, const char *description, bool do_tilestats) {
void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fname, int minzoom, int maxzoom, double minlat, double minlon, double maxlat, double maxlon, double midlat, double midlon, int forcetable, const char *attribution, std::map<std::string, layermap_entry> const &layermap, bool vector, const char *description, bool do_tilestats, std::map<std::string, std::string> const &attribute_descriptions, std::string const &program, std::string const &commandline) {
char *sql, *err;
sqlite3 *db = outdb;
@ -413,13 +377,37 @@ void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fnam
}
sqlite3_free(sql);
std::string version = program + " " + VERSION;
sql = sqlite3_mprintf("INSERT INTO metadata (name, value) VALUES ('generator', %Q);", version.c_str());
if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "set version: %s\n", err);
if (!forcetable) {
exit(EXIT_FAILURE);
}
}
sqlite3_free(sql);
sql = sqlite3_mprintf("INSERT INTO metadata (name, value) VALUES ('generator_options', %Q);", commandline.c_str());
if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
fprintf(stderr, "set commandline: %s\n", err);
if (!forcetable) {
exit(EXIT_FAILURE);
}
}
sqlite3_free(sql);
if (vector) {
size_t elements = 100;
size_t elements = max_tilestats_values;
std::string buf;
{
buf = "{";
aprintf(&buf, "\"vector_layers\": [ ");
json_writer state(&buf);
state.json_write_hash();
state.nospace = true;
state.json_write_string("vector_layers");
state.json_write_array();
std::vector<std::string> lnames;
for (auto ai = layermap.begin(); ai != layermap.end(); ++ai) {
@ -427,52 +415,69 @@ void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fnam
}
for (size_t i = 0; i < lnames.size(); i++) {
if (i != 0) {
aprintf(&buf, ", ");
}
auto fk = layermap.find(lnames[i]);
aprintf(&buf, "{ \"id\": \"");
quote(buf, lnames[i]);
aprintf(&buf, "\", \"description\": \"\", \"minzoom\": %d, \"maxzoom\": %d, \"fields\": {", fk->second.minzoom, fk->second.maxzoom);
state.json_write_hash();
state.json_write_string("id");
state.json_write_string(lnames[i]);
state.json_write_string("description");
state.json_write_string(fk->second.description);
state.json_write_string("minzoom");
state.json_write_signed(fk->second.minzoom);
state.json_write_string("maxzoom");
state.json_write_signed(fk->second.maxzoom);
state.json_write_string("fields");
state.json_write_hash();
state.nospace = true;
bool first = true;
for (auto j = fk->second.file_keys.begin(); j != fk->second.file_keys.end(); ++j) {
if (first) {
first = false;
} else {
aprintf(&buf, ", ");
}
aprintf(&buf, "\"");
quote(buf, j->first.c_str());
state.json_write_string(j->first);
int type = 0;
for (auto s : j->second.sample_values) {
type |= (1 << s.type);
}
auto f = attribute_descriptions.find(j->first);
if (f == attribute_descriptions.end()) {
int type = 0;
for (auto s : j->second.sample_values) {
type |= (1 << s.type);
}
if (type == (1 << mvt_double)) {
aprintf(&buf, "\": \"Number\"");
} else if (type == (1 << mvt_bool)) {
aprintf(&buf, "\": \"Boolean\"");
} else if (type == (1 << mvt_string)) {
aprintf(&buf, "\": \"String\"");
if (type == (1 << mvt_double)) {
state.json_write_string("Number");
} else if (type == (1 << mvt_bool)) {
state.json_write_string("Boolean");
} else if (type == (1 << mvt_string)) {
state.json_write_string("String");
} else {
state.json_write_string("Mixed");
}
} else {
aprintf(&buf, "\": \"Mixed\"");
state.json_write_string(f->second);
}
}
aprintf(&buf, "} }");
state.nospace = true;
state.json_end_hash();
state.json_end_hash();
}
aprintf(&buf, " ]");
state.json_end_array();
if (do_tilestats && elements > 0) {
aprintf(&buf, ",\"tilestats\": %s", tilestats(layermap, elements).c_str());
state.nospace = true;
state.json_write_string("tilestats");
tilestats(layermap, elements, state);
}
aprintf(&buf, "}");
state.nospace = true;
state.json_end_hash();
}
sql = sqlite3_mprintf("INSERT INTO metadata (name, value) VALUES ('json', %Q);", buf.c_str());
@ -487,41 +492,48 @@ void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fnam
if (outdir != NULL) {
std::string metadata = std::string(outdir) + "/metadata.json";
FILE *fp = fopen(metadata.c_str(), "w");
if (fp == NULL) {
perror(metadata.c_str());
exit(EXIT_FAILURE);
}
fprintf(fp, "{\n");
sqlite3_stmt *stmt;
bool first = true;
if (sqlite3_prepare_v2(db, "SELECT name, value from metadata;", -1, &stmt, NULL) == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
std::string key, value;
const char *k = (const char *) sqlite3_column_text(stmt, 0);
const char *v = (const char *) sqlite3_column_text(stmt, 1);
if (k == NULL || v == NULL) {
fprintf(stderr, "Corrupt mbtiles file: null metadata\n");
exit(EXIT_FAILURE);
}
quote(key, k);
quote(value, v);
if (!first) {
fprintf(fp, ",\n");
}
fprintf(fp, " \"%s\": \"%s\"", key.c_str(), value.c_str());
first = false;
struct stat st;
if (stat(metadata.c_str(), &st) == 0) {
// Leave existing metadata in place with --allow-existing
} else {
FILE *fp = fopen(metadata.c_str(), "w");
if (fp == NULL) {
perror(metadata.c_str());
exit(EXIT_FAILURE);
}
sqlite3_finalize(stmt);
}
fprintf(fp, "\n}\n");
fclose(fp);
json_writer state(fp);
state.json_write_hash();
state.json_write_newline();
sqlite3_stmt *stmt;
bool first = true;
if (sqlite3_prepare_v2(db, "SELECT name, value from metadata;", -1, &stmt, NULL) == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
std::string key, value;
const char *k = (const char *) sqlite3_column_text(stmt, 0);
const char *v = (const char *) sqlite3_column_text(stmt, 1);
if (k == NULL || v == NULL) {
fprintf(stderr, "Corrupt mbtiles file: null metadata\n");
exit(EXIT_FAILURE);
}
state.json_comma_newline();
state.json_write_string(k);
state.json_write_string(v);
first = false;
}
sqlite3_finalize(stmt);
}
state.json_write_newline();
state.json_end_hash();
state.json_write_newline();
fclose(fp);
}
}
if (outdb == NULL) {
@ -554,7 +566,7 @@ std::map<std::string, layermap_entry> merge_layermaps(std::vector<std::map<std::
for (size_t i = 0; i < maps.size(); i++) {
for (auto map = maps[i].begin(); map != maps[i].end(); ++map) {
if (map->second.points + map->second.lines + map->second.polygons == 0) {
if (map->second.points + map->second.lines + map->second.polygons + map->second.retain == 0) {
continue;
}
@ -568,6 +580,7 @@ std::map<std::string, layermap_entry> merge_layermaps(std::vector<std::map<std::
auto out_entry = out.find(layername);
out_entry->second.minzoom = map->second.minzoom;
out_entry->second.maxzoom = map->second.maxzoom;
out_entry->second.description = map->second.description;
}
auto out_entry = out.find(layername);
@ -592,7 +605,7 @@ std::map<std::string, layermap_entry> merge_layermaps(std::vector<std::map<std::
if (pt == fk2->second.sample_values.end() || *pt != val) { // not found
fk2->second.sample_values.insert(pt, val);
if (fk2->second.sample_values.size() > 1000) {
if (fk2->second.sample_values.size() > max_tilestats_sample_values) {
fk2->second.sample_values.pop_back();
}
}
@ -626,6 +639,10 @@ std::map<std::string, layermap_entry> merge_layermaps(std::vector<std::map<std::
}
void add_to_file_keys(std::map<std::string, type_and_string_stats> &file_keys, std::string const &attrib, type_and_string const &val) {
if (val.type == mvt_null) {
return;
}
auto fka = file_keys.find(attrib);
if (fka == file_keys.end()) {
file_keys.insert(std::pair<std::string, type_and_string_stats>(attrib, type_and_string_stats()));
@ -652,7 +669,7 @@ void add_to_file_keys(std::map<std::string, type_and_string_stats> &file_keys, s
if (pt == fka->second.sample_values.end() || *pt != val) { // not found
fka->second.sample_values.insert(pt, val);
if (fka->second.sample_values.size() > 1000) {
if (fka->second.sample_values.size() > max_tilestats_sample_values) {
fka->second.sample_values.pop_back();
}
}

View File

@ -5,6 +5,10 @@
#include <map>
#include "mvt.hpp"
extern size_t max_tilestats_attributes;
extern size_t max_tilestats_sample_values;
extern size_t max_tilestats_values;
struct type_and_string {
int type = 0;
std::string string = "";
@ -25,10 +29,12 @@ struct layermap_entry {
std::map<std::string, type_and_string_stats> file_keys{};
int minzoom = 0;
int maxzoom = 0;
std::string description = "";
size_t points = 0;
size_t lines = 0;
size_t polygons = 0;
size_t retain = 0; // keep for tilestats, even if no features directly here
layermap_entry(size_t _id) {
id = _id;
@ -39,12 +45,10 @@ sqlite3 *mbtiles_open(char *dbname, char **argv, int forcetable);
void mbtiles_write_tile(sqlite3 *outdb, int z, int tx, int ty, const char *data, int size);
void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fname, int minzoom, int maxzoom, double minlat, double minlon, double maxlat, double maxlon, double midlat, double midlon, int forcetable, const char *attribution, std::map<std::string, layermap_entry> const &layermap, bool vector, const char *description, bool do_tilestats);
void mbtiles_write_metadata(sqlite3 *outdb, const char *outdir, const char *fname, int minzoom, int maxzoom, double minlat, double minlon, double maxlat, double maxlon, double midlat, double midlon, int forcetable, const char *attribution, std::map<std::string, layermap_entry> const &layermap, bool vector, const char *description, bool do_tilestats, std::map<std::string, std::string> const &attribute_descriptions, std::string const &program, std::string const &commandline);
void mbtiles_close(sqlite3 *outdb, const char *pgm);
void aprintf(std::string *buf, const char *format, ...);
std::map<std::string, layermap_entry> merge_layermaps(std::vector<std::map<std::string, layermap_entry> > const &maps);
std::map<std::string, layermap_entry> merge_layermaps(std::vector<std::map<std::string, layermap_entry> > const &maps, bool trunc);

View File

@ -1,12 +1,18 @@
#ifndef MEMFILE_HPP
#define MEMFILE_HPP
#include <atomic>
struct memfile {
int fd = 0;
char *map = NULL;
long long len = 0;
std::atomic<long long> len;
long long off = 0;
unsigned long tree = 0;
memfile()
: len(0) {
}
};
struct memfile *memfile_open(int fd);

78
mvt.cpp
View File

@ -34,25 +34,49 @@ int decompress(std::string const &input, std::string &output) {
inflate_s.avail_in = 0;
inflate_s.next_in = Z_NULL;
if (inflateInit2(&inflate_s, 32 + 15) != Z_OK) {
fprintf(stderr, "error: %s\n", inflate_s.msg);
fprintf(stderr, "Decompression error: %s\n", inflate_s.msg);
}
inflate_s.next_in = (Bytef *) input.data();
inflate_s.avail_in = input.size();
size_t length = 0;
do {
output.resize(length + 2 * input.size());
inflate_s.avail_out = 2 * input.size();
inflate_s.next_out = (Bytef *) (output.data() + length);
int ret = inflate(&inflate_s, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) {
fprintf(stderr, "error: %s\n", inflate_s.msg);
inflate_s.next_out = (Bytef *) output.data();
inflate_s.avail_out = output.size();
while (true) {
size_t existing_output = inflate_s.next_out - (Bytef *) output.data();
output.resize(existing_output + 2 * inflate_s.avail_in + 100);
inflate_s.next_out = (Bytef *) output.data() + existing_output;
inflate_s.avail_out = output.size() - existing_output;
int ret = inflate(&inflate_s, 0);
if (ret < 0) {
fprintf(stderr, "Decompression error: ");
if (ret == Z_DATA_ERROR) {
fprintf(stderr, "data error");
}
if (ret == Z_STREAM_ERROR) {
fprintf(stderr, "stream error");
}
if (ret == Z_MEM_ERROR) {
fprintf(stderr, "out of memory");
}
if (ret == Z_BUF_ERROR) {
fprintf(stderr, "no data in buffer");
}
fprintf(stderr, "\n");
return 0;
}
length += (2 * input.size() - inflate_s.avail_out);
} while (inflate_s.avail_out == 0);
if (ret == Z_STREAM_END) {
break;
}
// ret must be Z_OK or Z_NEED_DICT;
// continue decompresing
}
output.resize(inflate_s.next_out - (Bytef *) output.data());
inflateEnd(&inflate_s);
output.resize(length);
return 1;
}
@ -90,7 +114,9 @@ bool mvt_tile::decode(std::string &message, bool &was_compressed) {
if (is_compressed(message)) {
std::string uncompressed;
decompress(message, uncompressed);
if (decompress(message, uncompressed) == 0) {
exit(EXIT_FAILURE);
}
src = uncompressed;
was_compressed = true;
} else {
@ -122,6 +148,9 @@ bool mvt_tile::decode(std::string &message, bool &was_compressed) {
protozero::pbf_reader value_reader(layer_reader.get_message());
mvt_value value;
value.type = mvt_null;
value.numeric_value.null_value = 0;
while (value_reader.next()) {
switch (value_reader.tag()) {
case 1: /* string */
@ -303,6 +332,12 @@ std::string mvt_tile::encode() {
value_writer.add_sint64(6, pbv.numeric_value.sint_value);
} else if (pbv.type == mvt_bool) {
value_writer.add_bool(7, pbv.numeric_value.bool_value);
} else if (pbv.type == mvt_null) {
fprintf(stderr, "Internal error: trying to write null attribute to tile\n");
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Internal error: trying to write undefined attribute type to tile\n");
exit(EXIT_FAILURE);
}
layer_writer.add_message(4, value_string);
@ -321,7 +356,7 @@ std::string mvt_tile::encode() {
std::vector<uint32_t> geometry;
int px = 0, py = 0;
long long px = 0, py = 0;
int cmd_idx = -1;
int cmd = -1;
int length = 0;
@ -346,8 +381,13 @@ std::string mvt_tile::encode() {
long long wwx = geom[g].x;
long long wwy = geom[g].y;
int dx = wwx - px;
int dy = wwy - py;
long long dx = wwx - px;
long long dy = wwy - py;
if (dx < INT_MIN || dx > INT_MAX || dy < INT_MIN || dy > INT_MAX) {
fprintf(stderr, "Internal error: Geometry delta is too big: %lld,%lld\n", dx, dy);
exit(EXIT_FAILURE);
}
geometry.push_back(protozero::encode_zigzag32(dx));
geometry.push_back(protozero::encode_zigzag32(dy));
@ -388,7 +428,8 @@ bool mvt_value::operator<(const mvt_value &o) const {
(type == mvt_int && numeric_value.int_value < o.numeric_value.int_value) ||
(type == mvt_uint && numeric_value.uint_value < o.numeric_value.uint_value) ||
(type == mvt_sint && numeric_value.sint_value < o.numeric_value.sint_value) ||
(type == mvt_bool && numeric_value.bool_value < o.numeric_value.bool_value)) {
(type == mvt_bool && numeric_value.bool_value < o.numeric_value.bool_value) ||
(type == mvt_null && numeric_value.null_value < o.numeric_value.null_value)) {
return true;
}
}
@ -442,6 +483,8 @@ std::string mvt_value::toString() {
return std::to_string(numeric_value.uint_value);
} else if (type == mvt_bool) {
return numeric_value.bool_value ? "true" : "false";
} else if (type == mvt_null) {
return "null";
} else {
return "unknown";
}
@ -591,6 +634,7 @@ mvt_value stringified_to_mvt_value(int type, const char *s) {
tv.numeric_value.bool_value = (s[0] == 't');
} else if (type == mvt_null) {
tv.type = mvt_null;
tv.numeric_value.null_value = 0;
} else {
tv.type = mvt_string;
tv.string_value = s;

View File

@ -48,6 +48,7 @@ struct mvt_feature {
int /* mvt_geometry_type */ type = 0;
unsigned long long id = 0;
bool has_id = false;
bool dropped = false;
mvt_feature() {
has_id = false;
@ -76,6 +77,7 @@ struct mvt_value {
unsigned long long uint_value;
long long sint_value;
bool bool_value;
int null_value;
} numeric_value;
bool operator<(const mvt_value &o) const;

View File

@ -5,7 +5,7 @@
#define A_REVERSE ((int) 'r')
#define A_REORDER ((int) 'o')
#define A_LINE_DROP ((int) 'l')
#define A_DEBUG_POLYGON ((int) 'D')
#define A_DEBUG_POLYGON ((int) '@')
#define A_POLYGON_DROP ((int) 'p')
#define A_DETECT_SHARED_BORDERS ((int) 'b')
#define A_PREFER_RADIX_SORT ((int) 'R')
@ -15,13 +15,20 @@
#define A_DROP_DENSEST_AS_NEEDED ((int) 's')
#define A_DROP_FRACTION_AS_NEEDED ((int) 'd')
#define A_DROP_SMALLEST_AS_NEEDED ((int) 'n')
#define A_COALESCE_DENSEST_AS_NEEDED ((int) 'S')
#define A_COALESCE_SMALLEST_AS_NEEDED ((int) 'N')
#define A_COALESCE_FRACTION_AS_NEEDED ((int) 'D')
#define A_GRID_LOW_ZOOMS ((int) 'L')
#define A_DETECT_WRAPAROUND ((int) 'w')
#define A_EXTEND_ZOOMS ((int) 'e')
#define A_CLUSTER_DENSEST_AS_NEEDED ((int) 'C')
#define A_GENERATE_IDS ((int) 'i')
#define A_CONVERT_NUMERIC_IDS ((int) 'I')
#define A_HILBERT ((int) 'h')
#define P_SIMPLIFY ((int) 's')
#define P_SIMPLIFY_LOW ((int) 'S')
#define P_SIMPLIFY_SHARED_NODES ((int) 'n')
#define P_FEATURE_LIMIT ((int) 'f')
#define P_KILOBYTE_LIMIT ((int) 'k')
#define P_DYNAMIC_DROP ((int) 'd')
@ -32,6 +39,9 @@
#define P_TINY_POLYGON_REDUCTION ((int) 't')
#define P_TILE_COMPRESSION ((int) 'C')
#define P_TILE_STATS ((int) 'g')
#define P_USE_SOURCE_POLYGON_WINDING ((int) 'w')
#define P_REVERSE_SOURCE_POLYGON_WINDING ((int) 'W')
#define P_EMPTY_CSV_COLUMNS ((int) 'e')
extern int prevent[256];
extern int additional[256];

View File

@ -51,8 +51,9 @@ void *run_writer(void *a) {
exit(EXIT_FAILURE);
}
json_writer state(fp);
for (size_t i = 0; i < wa->layers->size(); i++) {
layer_to_geojson(fp, (*(wa->layers))[i], wa->z, wa->x, wa->y, false, true, false, 0, 0, 0, true);
layer_to_geojson((*(wa->layers))[i], wa->z, wa->x, wa->y, false, true, false, true, 0, 0, 0, true, state);
}
if (fclose(fp) != 0) {
@ -258,7 +259,11 @@ std::vector<mvt_layer> parse_layers(int fd, int z, unsigned x, unsigned y, std::
std::string s;
stringify_value(properties->values[i], tp, s, "Filter output", jp->line, j);
if (tp >= 0) {
// Nulls can be excluded here because this is the postfilter
// and it is nearly time to create the vector representation
if (tp >= 0 && tp != mvt_null) {
mvt_value v = stringified_to_mvt_value(tp, s.c_str());
l->second.tag(feature, std::string(properties->keys[i]->string), v);
@ -392,7 +397,6 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
sf.bbox[0] = sf.bbox[1] = LLONG_MAX;
sf.bbox[2] = sf.bbox[3] = LLONG_MIN;
sf.extent = 0;
sf.m = 0;
sf.metapos = 0;
sf.has_id = false;
@ -415,9 +419,14 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
}
json_object *extent = json_hash_get(tippecanoe, "extent");
if (extent != NULL && sequence->type == JSON_NUMBER) {
if (extent != NULL && extent->type == JSON_NUMBER) {
sf.extent = extent->number;
}
json_object *dropped = json_hash_get(tippecanoe, "dropped");
if (dropped != NULL && dropped->type == JSON_TRUE) {
sf.dropped = true;
}
}
for (size_t i = 0; i < dv.size(); i++) {
@ -488,7 +497,10 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std::
stringify_value(properties->values[i], v.type, v.s, "Filter output", jp->line, j);
if (v.type >= 0) {
// Nulls can be excluded here because the expression evaluation filter
// would have already run before prefiltering
if (v.type >= 0 && v.type != mvt_null) {
sf.full_keys.push_back(std::string(properties->keys[i]->string));
sf.full_values.push_back(v);

View File

@ -2,8 +2,12 @@
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <atomic>
#include "projection.hpp"
unsigned long long (*encode_index)(unsigned int wx, unsigned int wy) = NULL;
void (*decode_index)(unsigned long long index, unsigned *wx, unsigned *wy) = NULL;
struct projection projections[] = {
{"EPSG:4326", lonlat2tile, tile2lonlat, "urn:ogc:def:crs:OGC:1.3:CRS84"},
{"EPSG:3857", epsg3857totile, tiletoepsg3857, "urn:ogc:def:crs:EPSG::3857"},
@ -14,6 +18,23 @@ struct projection *projection = &projections[0];
// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
void lonlat2tile(double lon, double lat, int zoom, long long *x, long long *y) {
// Place infinite and NaN coordinates off the edge of the Mercator plane
int lat_class = fpclassify(lat);
int lon_class = fpclassify(lon);
bool bad_lon = false;
if (lat_class == FP_INFINITE || lat_class == FP_NAN) {
lat = 89.9;
}
if (lon_class == FP_INFINITE || lon_class == FP_NAN) {
// Keep these far enough from the plane that they don't get
// moved back into it by 360-degree offsetting
lon = 720;
bad_lon = true;
}
// Must limit latitude somewhere to prevent overflow.
// 89.9 degrees latitude is 0.621 worlds beyond the edge of the flat earth,
// hopefully far enough out that there are few expectations about the shape.
@ -24,10 +45,10 @@ void lonlat2tile(double lon, double lat, int zoom, long long *x, long long *y) {
lat = 89.9;
}
if (lon < -360) {
if (lon < -360 && !bad_lon) {
lon = -360;
}
if (lon > 360) {
if (lon > 360 && !bad_lon) {
lon = 360;
}
@ -49,6 +70,18 @@ void tile2lonlat(long long x, long long y, int zoom, double *lon, double *lat) {
}
void epsg3857totile(double ix, double iy, int zoom, long long *x, long long *y) {
// Place infinite and NaN coordinates off the edge of the Mercator plane
int iy_class = fpclassify(iy);
int ix_class = fpclassify(ix);
if (iy_class == FP_INFINITE || iy_class == FP_NAN) {
iy = 40000000.0;
}
if (ix_class == FP_INFINITE || ix_class == FP_NAN) {
ix = 40000000.0;
}
*x = ix * (1LL << 31) / 6378137.0 / M_PI + (1LL << 31);
*y = ((1LL << 32) - 1) - (iy * (1LL << 31) / 6378137.0 / M_PI + (1LL << 31));
@ -68,7 +101,60 @@ void tiletoepsg3857(long long ix, long long iy, int zoom, double *ox, double *oy
*oy = ((1LL << 32) - 1 - iy - (1LL << 31)) * M_PI * 6378137.0 / (1LL << 31);
}
unsigned long long encode(unsigned int wx, unsigned int wy) {
// https://en.wikipedia.org/wiki/Hilbert_curve
void hilbert_rot(unsigned long long n, unsigned *x, unsigned *y, unsigned long long rx, unsigned long long ry) {
if (ry == 0) {
if (rx == 1) {
*x = n - 1 - *x;
*y = n - 1 - *y;
}
unsigned t = *x;
*x = *y;
*y = t;
}
}
unsigned long long hilbert_xy2d(unsigned long long n, unsigned x, unsigned y) {
unsigned long long d = 0;
unsigned long long rx, ry;
for (unsigned long long s = n / 2; s > 0; s /= 2) {
rx = (x & s) != 0;
ry = (y & s) != 0;
d += s * s * ((3 * rx) ^ ry);
hilbert_rot(s, &x, &y, rx, ry);
}
return d;
}
void hilbert_d2xy(unsigned long long n, unsigned long long d, unsigned *x, unsigned *y) {
unsigned long long rx, ry;
unsigned long long t = d;
*x = *y = 0;
for (unsigned long long s = 1; s < n; s *= 2) {
rx = 1 & (t / 2);
ry = 1 & (t ^ rx);
hilbert_rot(s, x, y, rx, ry);
*x += s * rx;
*y += s * ry;
t /= 4;
}
}
unsigned long long encode_hilbert(unsigned int wx, unsigned int wy) {
return hilbert_xy2d(1LL << 32, wx, wy);
}
void decode_hilbert(unsigned long long index, unsigned *wx, unsigned *wy) {
hilbert_d2xy(1LL << 32, index, wx, wy);
}
unsigned long long encode_quadkey(unsigned int wx, unsigned int wy) {
unsigned long long out = 0;
int i;
@ -83,11 +169,11 @@ unsigned long long encode(unsigned int wx, unsigned int wy) {
return out;
}
static unsigned char decodex[256];
static unsigned char decodey[256];
static std::atomic<unsigned char> decodex[256];
static std::atomic<unsigned char> decodey[256];
void decode(unsigned long long index, unsigned *wx, unsigned *wy) {
static int initialized = 0;
void decode_quadkey(unsigned long long index, unsigned *wx, unsigned *wy) {
static std::atomic<int> initialized(0);
if (!initialized) {
for (size_t ix = 0; ix < 256; ix++) {
size_t xx = 0, yy = 0;

View File

@ -5,8 +5,6 @@ void lonlat2tile(double lon, double lat, int zoom, long long *x, long long *y);
void epsg3857totile(double ix, double iy, int zoom, long long *x, long long *y);
void tile2lonlat(long long x, long long y, int zoom, double *lon, double *lat);
void tiletoepsg3857(long long x, long long y, int zoom, double *ox, double *oy);
unsigned long long encode(unsigned int wx, unsigned int wy);
void decode(unsigned long long index, unsigned *wx, unsigned *wy);
void set_projection_or_exit(const char *optarg);
struct projection {
@ -19,4 +17,13 @@ struct projection {
extern struct projection *projection;
extern struct projection projections[];
extern unsigned long long (*encode_index)(unsigned int wx, unsigned int wy);
extern void (*decode_index)(unsigned long long index, unsigned *wx, unsigned *wy);
unsigned long long encode_quadkey(unsigned int wx, unsigned int wy);
void decode_quadkey(unsigned long long index, unsigned *wx, unsigned *wy);
unsigned long long encode_hilbert(unsigned int wx, unsigned int wy);
void decode_hilbert(unsigned long long index, unsigned *wx, unsigned *wy);
#endif

View File

@ -53,7 +53,7 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna
size_t i;
for (i = 0; i < j->length; i++) {
if (within == GEOM_POINT) {
if (i == 0 || mb_geometry[t] == GEOM_MULTIPOINT) {
if (i == 0 || mb_geometry[t] == VT_POINT) {
op = VT_MOVETO;
} else {
op = VT_LINETO;
@ -80,12 +80,12 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna
}
}
draw d(op, x, y);
out.push_back(draw(op, x, y));
} else {
fprintf(stderr, "%s:%d: malformed point\n", fname, line);
json_context(j);
json_context(feature);
exit(EXIT_FAILURE);
}
}

View File

@ -30,17 +30,17 @@ size_t fwrite_check(const void *ptr, size_t size, size_t nitems, FILE *stream, c
return w;
}
void serialize_int(FILE *out, int n, long long *fpos, const char *fname) {
void serialize_int(FILE *out, int n, std::atomic<long long> *fpos, const char *fname) {
serialize_long_long(out, n, fpos, fname);
}
void serialize_long_long(FILE *out, long long n, long long *fpos, const char *fname) {
void serialize_long_long(FILE *out, long long n, std::atomic<long long> *fpos, const char *fname) {
unsigned long long zigzag = protozero::encode_zigzag64(n);
serialize_ulong_long(out, zigzag, fpos, fname);
}
void serialize_ulong_long(FILE *out, unsigned long long zigzag, long long *fpos, const char *fname) {
void serialize_ulong_long(FILE *out, unsigned long long zigzag, std::atomic<long long> *fpos, const char *fname) {
while (1) {
unsigned char b = zigzag & 0x7F;
if ((zigzag >> 7) != 0) {
@ -62,12 +62,12 @@ void serialize_ulong_long(FILE *out, unsigned long long zigzag, long long *fpos,
}
}
void serialize_byte(FILE *out, signed char n, long long *fpos, const char *fname) {
void serialize_byte(FILE *out, signed char n, std::atomic<long long> *fpos, const char *fname) {
fwrite_check(&n, sizeof(signed char), 1, out, fname);
*fpos += sizeof(signed char);
}
void serialize_uint(FILE *out, unsigned n, long long *fpos, const char *fname) {
void serialize_uint(FILE *out, unsigned n, std::atomic<long long> *fpos, const char *fname) {
fwrite_check(&n, sizeof(unsigned), 1, out, fname);
*fpos += sizeof(unsigned);
}
@ -112,14 +112,14 @@ void deserialize_byte(char **f, signed char *n) {
*f += sizeof(signed char);
}
int deserialize_long_long_io(FILE *f, long long *n, long long *geompos) {
int deserialize_long_long_io(FILE *f, long long *n, std::atomic<long long> *geompos) {
unsigned long long zigzag = 0;
int ret = deserialize_ulong_long_io(f, &zigzag, geompos);
*n = protozero::decode_zigzag64(zigzag);
return ret;
}
int deserialize_ulong_long_io(FILE *f, unsigned long long *zigzag, long long *geompos) {
int deserialize_ulong_long_io(FILE *f, unsigned long long *zigzag, std::atomic<long long> *geompos) {
*zigzag = 0;
int shift = 0;
@ -143,14 +143,14 @@ int deserialize_ulong_long_io(FILE *f, unsigned long long *zigzag, long long *ge
return 1;
}
int deserialize_int_io(FILE *f, int *n, long long *geompos) {
int deserialize_int_io(FILE *f, int *n, std::atomic<long long> *geompos) {
long long ll = 0;
int ret = deserialize_long_long_io(f, &ll, geompos);
*n = ll;
return ret;
}
int deserialize_uint_io(FILE *f, unsigned *n, long long *geompos) {
int deserialize_uint_io(FILE *f, unsigned *n, std::atomic<long long> *geompos) {
if (fread(n, sizeof(unsigned), 1, f) != 1) {
return 0;
}
@ -158,7 +158,7 @@ int deserialize_uint_io(FILE *f, unsigned *n, long long *geompos) {
return 1;
}
int deserialize_byte_io(FILE *f, signed char *n, long long *geompos) {
int deserialize_byte_io(FILE *f, signed char *n, std::atomic<long long> *geompos) {
int c = getc(f);
if (c == EOF) {
return 0;
@ -168,7 +168,7 @@ int deserialize_byte_io(FILE *f, signed char *n, long long *geompos) {
return 1;
}
static void write_geometry(drawvec const &dv, long long *fpos, FILE *out, const char *fname, long long wx, long long wy) {
static void write_geometry(drawvec const &dv, std::atomic<long long> *fpos, FILE *out, const char *fname, long long wx, long long wy) {
for (size_t i = 0; i < dv.size(); i++) {
if (dv[i].op == VT_MOVETO || dv[i].op == VT_LINETO) {
serialize_byte(out, dv[i].op, fpos, fname);
@ -182,7 +182,8 @@ static void write_geometry(drawvec const &dv, long long *fpos, FILE *out, const
}
}
void serialize_feature(FILE *geomfile, serial_feature *sf, long long *geompos, const char *fname, long long wx, long long wy, bool include_minzoom) {
// called from generating the next zoom level
void serialize_feature(FILE *geomfile, serial_feature *sf, std::atomic<long long> *geompos, const char *fname, long long wx, long long wy, bool include_minzoom) {
serialize_byte(geomfile, sf->t, geompos, fname);
long long layer = 0;
@ -219,19 +220,15 @@ void serialize_feature(FILE *geomfile, serial_feature *sf, long long *geompos, c
serialize_long_long(geomfile, sf->extent, geompos, fname);
}
serialize_int(geomfile, sf->m, geompos, fname);
if (sf->m != 0) {
serialize_long_long(geomfile, sf->metapos, geompos, fname);
}
serialize_long_long(geomfile, sf->metapos, geompos, fname);
if (sf->metapos < 0 && sf->m != sf->keys.size()) {
fprintf(stderr, "Internal error: feature said to have %lld attributes but only %lld found\n", (long long) sf->m, (long long) sf->keys.size());
exit(EXIT_FAILURE);
}
if (sf->metapos < 0) {
serialize_long_long(geomfile, sf->keys.size(), geompos, fname);
for (size_t i = 0; i < sf->keys.size(); i++) {
serialize_long_long(geomfile, sf->keys[i], geompos, fname);
serialize_long_long(geomfile, sf->values[i], geompos, fname);
for (size_t i = 0; i < sf->keys.size(); i++) {
serialize_long_long(geomfile, sf->keys[i], geompos, fname);
serialize_long_long(geomfile, sf->values[i], geompos, fname);
}
}
if (include_minzoom) {
@ -239,7 +236,7 @@ void serialize_feature(FILE *geomfile, serial_feature *sf, long long *geompos, c
}
}
serial_feature deserialize_feature(FILE *geoms, long long *geompos_in, char *metabase, long long *meta_off, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y) {
serial_feature deserialize_feature(FILE *geoms, std::atomic<long long> *geompos_in, char *metabase, long long *meta_off, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y) {
serial_feature sf;
deserialize_byte_io(geoms, &sf.t, geompos_in);
@ -285,19 +282,14 @@ serial_feature deserialize_feature(FILE *geoms, long long *geompos_in, char *met
sf.layer >>= 6;
sf.metapos = 0;
{
int m;
deserialize_int_io(geoms, &m, geompos_in);
sf.m = m;
}
if (sf.m != 0) {
deserialize_long_long_io(geoms, &sf.metapos, geompos_in);
}
deserialize_long_long_io(geoms, &sf.metapos, geompos_in);
if (sf.metapos >= 0) {
char *meta = metabase + sf.metapos + meta_off[sf.segment];
long long count;
deserialize_long_long(&meta, &count);
for (size_t i = 0; i < sf.m; i++) {
for (long long i = 0; i < count; i++) {
long long k, v;
deserialize_long_long(&meta, &k);
deserialize_long_long(&meta, &v);
@ -305,7 +297,10 @@ serial_feature deserialize_feature(FILE *geoms, long long *geompos_in, char *met
sf.values.push_back(v);
}
} else {
for (size_t i = 0; i < sf.m; i++) {
long long count;
deserialize_long_long_io(geoms, &count, geompos_in);
for (long long i = 0; i < count; i++) {
long long k, v;
deserialize_long_long_io(geoms, &k, geompos_in);
deserialize_long_long_io(geoms, &v, geompos_in);
@ -323,6 +318,7 @@ static long long scale_geometry(struct serialization_state *sst, long long *bbox
long long offset = 0;
long long prev = 0;
bool has_prev = false;
double scale = 1.0 / (1 << geometry_scale);
for (size_t i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO || geom[i].op == VT_LINETO) {
@ -359,7 +355,7 @@ static long long scale_geometry(struct serialization_state *sst, long long *bbox
}
if (!*(sst->initialized)) {
if (x < 0 || x >= (1LL << 32) || y < 0 || y >= (1LL < 32)) {
if (x < 0 || x >= (1LL << 32) || y < 0 || y >= (1LL << 32)) {
*(sst->initial_x) = 1LL << 31;
*(sst->initial_y) = 1LL << 31;
} else {
@ -370,14 +366,35 @@ static long long scale_geometry(struct serialization_state *sst, long long *bbox
*(sst->initialized) = 1;
}
geom[i].x = x >> geometry_scale;
geom[i].y = y >> geometry_scale;
if (additional[A_GRID_LOW_ZOOMS]) {
// If we are gridding, snap to the maxzoom grid in case the incoming data
// is already supposed to be aligned to tile boundaries (but is not, exactly,
// because of rounding error during projection).
geom[i].x = std::round(x * scale);
geom[i].y = std::round(y * scale);
} else {
geom[i].x = x >> geometry_scale;
geom[i].y = y >> geometry_scale;
}
}
}
return geom.size();
}
static std::string strip_zeroes(std::string s) {
// Doesn't do anything special with '-' followed by leading zeros
// since integer IDs must be positive
while (s.size() > 0 && s[0] == '0') {
s.erase(s.begin());
}
return s;
}
// called from frontends
int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
struct reader *r = &(*sst->readers)[sst->segment];
@ -393,11 +410,57 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
sf.geometry = fix_polygon(sf.geometry);
}
for (auto &c : clipbboxes) {
if (sf.t == VT_POLYGON) {
sf.geometry = simple_clip_poly(sf.geometry, c.minx >> geometry_scale, c.miny >> geometry_scale, c.maxx >> geometry_scale, c.maxy >> geometry_scale);
} else if (sf.t == VT_LINE) {
sf.geometry = clip_lines(sf.geometry, c.minx >> geometry_scale, c.miny >> geometry_scale, c.maxx >> geometry_scale, c.maxy >> geometry_scale);
sf.geometry = remove_noop(sf.geometry, sf.t, 0);
} else if (sf.t == VT_POINT) {
sf.geometry = clip_point(sf.geometry, c.minx >> geometry_scale, c.miny >> geometry_scale, c.maxx >> geometry_scale, c.maxy >> geometry_scale);
}
sf.bbox[0] = LLONG_MAX;
sf.bbox[1] = LLONG_MAX;
sf.bbox[2] = LLONG_MIN;
sf.bbox[3] = LLONG_MIN;
for (auto &g : sf.geometry) {
long long x = g.x << geometry_scale;
long long y = g.y << geometry_scale;
if (x < sf.bbox[0]) {
sf.bbox[0] = x;
}
if (y < sf.bbox[1]) {
sf.bbox[1] = y;
}
if (x > sf.bbox[2]) {
sf.bbox[2] = x;
}
if (y > sf.bbox[3]) {
sf.bbox[3] = y;
}
}
}
if (sf.geometry.size() == 0) {
// Feature was clipped away
return 1;
}
if (!sf.has_id) {
if (additional[A_GENERATE_IDS]) {
sf.has_id = true;
sf.id = sf.seq + 1;
}
}
if (sst->want_dist) {
std::vector<unsigned long long> locs;
for (size_t i = 0; i < sf.geometry.size(); i++) {
if (sf.geometry[i].op == VT_MOVETO || sf.geometry[i].op == VT_LINETO) {
locs.push_back(encode(sf.geometry[i].x << geometry_scale, sf.geometry[i].y << geometry_scale));
locs.push_back(encode_index(sf.geometry[i].x << geometry_scale, sf.geometry[i].y << geometry_scale));
}
}
std::sort(locs.begin(), locs.end());
@ -432,7 +495,7 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
inline_meta = false;
if (prevent[P_CLIPPING]) {
static volatile long long warned = 0;
static std::atomic<long long> warned(0);
long long extent = ((sf.bbox[2] - sf.bbox[0]) / ((1LL << (32 - sst->maxzoom)) + 1)) * ((sf.bbox[3] - sf.bbox[1]) / ((1LL << (32 - sst->maxzoom)) + 1));
if (extent > warned) {
fprintf(stderr, "Warning: %s:%d: Large unclipped (-pc) feature may be duplicated across %lld tiles\n", sst->fname, sst->line, extent);
@ -473,7 +536,11 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
}
}
sf.extent = (long long) extent;
if (extent <= LLONG_MAX) {
sf.extent = (long long) extent;
} else {
sf.extent = LLONG_MAX;
}
if (!prevent[P_INPUT_ORDER]) {
sf.seq = 0;
@ -485,9 +552,9 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
// and then mask to bring it back into the addressable area
long long midx = (sf.bbox[0] / 2 + sf.bbox[2] / 2) & ((1LL << 32) - 1);
long long midy = (sf.bbox[1] / 2 + sf.bbox[3] / 2) & ((1LL << 32) - 1);
bbox_index = encode(midx, midy);
bbox_index = encode_index(midx, midy);
if (additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_CALCULATE_FEATURE_DENSITY] || additional[A_INCREASE_GAMMA_AS_NEEDED] || sst->uses_gamma) {
if (additional[A_DROP_DENSEST_AS_NEEDED] || additional[A_COALESCE_DENSEST_AS_NEEDED] || additional[A_CLUSTER_DENSEST_AS_NEEDED] || additional[A_CALCULATE_FEATURE_DENSITY] || additional[A_INCREASE_GAMMA_AS_NEEDED] || sst->uses_gamma || cluster_distance != 0) {
sf.index = bbox_index;
} else {
sf.index = 0;
@ -516,65 +583,56 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
}
for (ssize_t i = (ssize_t) sf.full_keys.size() - 1; i >= 0; i--) {
coerce_value(sf.full_keys[i], sf.full_values[i].type, sf.full_values[i].s, sst->attribute_types);
if (sf.full_keys[i] == attribute_for_id) {
if (sf.full_values[i].type != mvt_double && !additional[A_CONVERT_NUMERIC_IDS]) {
static bool warned = false;
if (!warned) {
fprintf(stderr, "Warning: Attribute \"%s\"=\"%s\" as feature ID is not a number\n", sf.full_keys[i].c_str(), sf.full_values[i].s.c_str());
warned = true;
}
} else {
char *err;
long long id_value = strtoull(sf.full_values[i].s.c_str(), &err, 10);
if (err != NULL && *err != '\0') {
static bool warned_frac = false;
if (!warned_frac) {
fprintf(stderr, "Warning: Can't represent non-integer feature ID %s\n", sf.full_values[i].s.c_str());
warned_frac = true;
}
} else if (std::to_string(id_value) != strip_zeroes(sf.full_values[i].s)) {
static bool warned = false;
if (!warned) {
fprintf(stderr, "Warning: Can't represent too-large feature ID %s\n", sf.full_values[i].s.c_str());
warned = true;
}
} else {
sf.id = id_value;
sf.has_id = true;
sf.full_keys.erase(sf.full_keys.begin() + i);
sf.full_values.erase(sf.full_values.begin() + i);
continue;
}
}
}
if (sst->exclude_all) {
if (sst->include->count(sf.full_keys[i]) == 0) {
sf.full_keys.erase(sf.full_keys.begin() + i);
sf.full_values.erase(sf.full_values.begin() + i);
sf.m--;
continue;
}
} else if (sst->exclude->count(sf.full_keys[i]) != 0) {
sf.full_keys.erase(sf.full_keys.begin() + i);
sf.full_values.erase(sf.full_values.begin() + i);
sf.m--;
continue;
}
coerce_value(sf.full_keys[i], sf.full_values[i].type, sf.full_values[i].s, sst->attribute_types);
}
if (sst->filter != NULL) {
std::map<std::string, mvt_value> attributes;
for (size_t i = 0; i < sf.full_keys.size(); i++) {
std::string key = sf.full_keys[i];
mvt_value val = stringified_to_mvt_value(sf.full_values[i].type, sf.full_values[i].s.c_str());
attributes.insert(std::pair<std::string, mvt_value>(key, val));
}
if (sf.has_id) {
mvt_value v;
v.type = mvt_uint;
v.numeric_value.uint_value = sf.id;
attributes.insert(std::pair<std::string, mvt_value>("$id", v));
}
mvt_value v;
v.type = mvt_string;
if (sf.t == mvt_point) {
v.string_value = "Point";
} else if (sf.t == mvt_linestring) {
v.string_value = "LineString";
} else if (sf.t == mvt_polygon) {
v.string_value = "Polygon";
}
attributes.insert(std::pair<std::string, mvt_value>("$type", v));
if (!evaluate(attributes, sf.layername, sst->filter)) {
return 0;
}
}
for (ssize_t i = (ssize_t) sf.full_keys.size() - 1; i >= 0; i--) {
if (sf.full_values[i].type == mvt_null) {
sf.full_keys.erase(sf.full_keys.begin() + i);
sf.full_values.erase(sf.full_values.begin() + i);
sf.m--;
}
}
if (!sst->filters) {
@ -596,6 +654,7 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
}
} else {
sf.metapos = r->metapos;
serialize_long_long(r->metafile, sf.full_keys.size(), &r->metapos, sst->fname);
for (size_t i = 0; i < sf.full_keys.size(); i++) {
serialize_long_long(r->metafile, addpool(r->poolfile, r->treefile, sf.full_keys[i].c_str(), mvt_string), &r->metapos, sst->fname);
serialize_long_long(r->metafile, addpool(r->poolfile, r->treefile, sf.full_values[i].s.c_str(), sf.full_values[i].type), &r->metapos, sst->fname);
@ -629,7 +688,7 @@ int serialize_feature(struct serialization_state *sst, serial_feature &sf) {
if (*(sst->progress_seq) % 10000 == 0) {
checkdisk(sst->readers);
if (!quiet && !quiet_progress) {
if (!quiet && !quiet_progress && progress_time()) {
fprintf(stderr, "Read %.2f million features\r", *sst->progress_seq / 1000000.0);
}
}

View File

@ -3,7 +3,9 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <atomic>
#include <sys/stat.h>
#include "geometry.hpp"
#include "mbtiles.hpp"
@ -11,12 +13,12 @@
size_t fwrite_check(const void *ptr, size_t size, size_t nitems, FILE *stream, const char *fname);
void serialize_int(FILE *out, int n, long long *fpos, const char *fname);
void serialize_long_long(FILE *out, long long n, long long *fpos, const char *fname);
void serialize_ulong_long(FILE *out, unsigned long long n, long long *fpos, const char *fname);
void serialize_byte(FILE *out, signed char n, long long *fpos, const char *fname);
void serialize_uint(FILE *out, unsigned n, long long *fpos, const char *fname);
void serialize_string(FILE *out, const char *s, long long *fpos, const char *fname);
void serialize_int(FILE *out, int n, std::atomic<long long> *fpos, const char *fname);
void serialize_long_long(FILE *out, long long n, std::atomic<long long> *fpos, const char *fname);
void serialize_ulong_long(FILE *out, unsigned long long n, std::atomic<long long> *fpos, const char *fname);
void serialize_byte(FILE *out, signed char n, std::atomic<long long> *fpos, const char *fname);
void serialize_uint(FILE *out, unsigned n, std::atomic<long long> *fpos, const char *fname);
void serialize_string(FILE *out, const char *s, std::atomic<long long> *fpos, const char *fname);
void deserialize_int(char **f, int *n);
void deserialize_long_long(char **f, long long *n);
@ -24,11 +26,11 @@ void deserialize_ulong_long(char **f, unsigned long long *n);
void deserialize_uint(char **f, unsigned *n);
void deserialize_byte(char **f, signed char *n);
int deserialize_int_io(FILE *f, int *n, long long *geompos);
int deserialize_long_long_io(FILE *f, long long *n, long long *geompos);
int deserialize_ulong_long_io(FILE *f, unsigned long long *n, long long *geompos);
int deserialize_uint_io(FILE *f, unsigned *n, long long *geompos);
int deserialize_byte_io(FILE *f, signed char *n, long long *geompos);
int deserialize_int_io(FILE *f, int *n, std::atomic<long long> *geompos);
int deserialize_long_long_io(FILE *f, long long *n, std::atomic<long long> *geompos);
int deserialize_ulong_long_io(FILE *f, unsigned long long *n, std::atomic<long long> *geompos);
int deserialize_uint_io(FILE *f, unsigned *n, std::atomic<long long> *geompos);
int deserialize_byte_io(FILE *f, signed char *n, std::atomic<long long> *geompos);
struct serial_val {
int type = 0;
@ -56,9 +58,9 @@ struct serial_feature {
unsigned long long index = 0;
long long extent = 0;
size_t m = 0;
std::vector<long long> keys{};
std::vector<long long> values{};
// If >= 0, metadata is external
long long metapos = 0;
// XXX This isn't serialized. Should it be here?
@ -66,10 +68,11 @@ struct serial_feature {
std::vector<std::string> full_keys{};
std::vector<serial_val> full_values{};
std::string layername = "";
bool dropped = false;
};
void serialize_feature(FILE *geomfile, serial_feature *sf, long long *geompos, const char *fname, long long wx, long long wy, bool include_minzoom);
serial_feature deserialize_feature(FILE *geoms, long long *geompos_in, char *metabase, long long *meta_off, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y);
void serialize_feature(FILE *geomfile, serial_feature *sf, std::atomic<long long> *geompos, const char *fname, long long wx, long long wy, bool include_minzoom);
serial_feature deserialize_feature(FILE *geoms, std::atomic<long long> *geompos_in, char *metabase, long long *meta_off, unsigned z, unsigned tx, unsigned ty, unsigned *initial_x, unsigned *initial_y);
struct reader {
int metafd = -1;
@ -84,9 +87,9 @@ struct reader {
FILE *geomfile = NULL;
FILE *indexfile = NULL;
long long metapos = 0;
long long geompos = 0;
long long indexpos = 0;
std::atomic<long long> metapos;
std::atomic<long long> geompos;
std::atomic<long long> indexpos;
long long file_bbox[4] = {0, 0, 0, 0};
@ -94,14 +97,48 @@ struct reader {
struct stat metast {};
char *geom_map = NULL;
reader()
: metapos(0), geompos(0), indexpos(0) {
}
reader(reader const &r) {
metafd = r.metafd;
poolfd = r.poolfd;
treefd = r.treefd;
geomfd = r.geomfd;
indexfd = r.indexfd;
metafile = r.metafile;
poolfile = r.poolfile;
treefile = r.treefile;
geomfile = r.geomfile;
indexfile = r.indexfile;
long long p = r.metapos;
metapos = p;
p = r.geompos;
geompos = p;
p = r.indexpos;
indexpos = p;
memcpy(file_bbox, r.file_bbox, sizeof(file_bbox));
geomst = r.geomst;
metast = r.metast;
geom_map = r.geom_map;
}
};
struct serialization_state {
const char *fname = NULL; // source file name
int line = 0; // user-oriented location within source for error reports
volatile long long *layer_seq = NULL; // sequence within current layer
volatile long long *progress_seq = NULL; // overall sequence for progress indicator
std::atomic<long long> *layer_seq = NULL; // sequence within current layer
std::atomic<long long> *progress_seq = NULL; // overall sequence for progress indicator
std::vector<struct reader> *readers = NULL; // array of data for each input thread
int segment = 0; // the current input thread
@ -126,7 +163,6 @@ struct serialization_state {
std::set<std::string> *exclude = NULL;
std::set<std::string> *include = NULL;
int exclude_all = 0;
json_object *filter = NULL;
};
int serialize_feature(struct serialization_state *sst, serial_feature &sf);

100
tests/accumulate/in.json Normal file
View File

@ -0,0 +1,100 @@
{ "type": "Feature", "properties": { "thesum": 1, "themax": 1, "themin": 1, "theproduct": 1, "themean": 1, "theconcat": 1, "thecomma": 1 }, "geometry": { "type": "Point", "coordinates": [ 134.198884,-54.297477 ] } }
{ "type": "Feature", "properties": { "thesum": 2, "themax": 2, "themin": 2, "theproduct": 2, "themean": 2, "theconcat": 2, "thecomma": 2 }, "geometry": { "type": "Point", "coordinates": [ 14.059736,46.728490 ] } }
{ "type": "Feature", "properties": { "thesum": 3, "themax": 3, "themin": 3, "theproduct": 3, "themean": 3, "theconcat": 3, "thecomma": 3 }, "geometry": { "type": "Point", "coordinates": [ -147.369727,84.781281 ] } }
{ "type": "Feature", "properties": { "thesum": 4, "themax": 4, "themin": 4, "theproduct": 4, "themean": 4, "theconcat": 4, "thecomma": 4 }, "geometry": { "type": "Point", "coordinates": [ -66.234387,89.199903 ] } }
{ "type": "Feature", "properties": { "thesum": 5, "themax": 5, "themin": 5, "theproduct": 5, "themean": 5, "theconcat": 5, "thecomma": 5 }, "geometry": { "type": "Point", "coordinates": [ -153.412664,29.072260 ] } }
{ "type": "Feature", "properties": { "thesum": 6, "themax": 6, "themin": 6, "theproduct": 6, "themean": 6, "theconcat": 6, "thecomma": 6 }, "geometry": { "type": "Point", "coordinates": [ 170.262110,-59.450058 ] } }
{ "type": "Feature", "properties": { "thesum": 7, "themax": 7, "themin": 7, "theproduct": 7, "themean": 7, "theconcat": 7, "thecomma": 7 }, "geometry": { "type": "Point", "coordinates": [ 126.605140,8.723849 ] } }
{ "type": "Feature", "properties": { "thesum": 8, "themax": 8, "themin": 8, "theproduct": 8, "themean": 8, "theconcat": 8, "thecomma": 8 }, "geometry": { "type": "Point", "coordinates": [ 161.440413,-40.375296 ] } }
{ "type": "Feature", "properties": { "thesum": 9, "themax": 9, "themin": 9, "theproduct": 9, "themean": 9, "theconcat": 9, "thecomma": 9 }, "geometry": { "type": "Point", "coordinates": [ -168.588146,-52.640848 ] } }
{ "type": "Feature", "properties": { "thesum": 10, "themax": 10, "themin": 10, "theproduct": 10, "themean": 10, "theconcat": 10, "thecomma": 10 }, "geometry": { "type": "Point", "coordinates": [ 87.732615,-76.468219 ] } }
{ "type": "Feature", "properties": { "thesum": 11, "themax": 11, "themin": 11, "theproduct": 11, "themean": 11, "theconcat": 11, "thecomma": 11 }, "geometry": { "type": "Point", "coordinates": [ 30.857236,80.182977 ] } }
{ "type": "Feature", "properties": { "thesum": 12, "themax": 12, "themin": 12, "theproduct": 12, "themean": 12, "theconcat": 12, "thecomma": 12 }, "geometry": { "type": "Point", "coordinates": [ -145.428454,26.334493 ] } }
{ "type": "Feature", "properties": { "thesum": 13, "themax": 13, "themin": 13, "theproduct": 13, "themean": 13, "theconcat": 13, "thecomma": 13 }, "geometry": { "type": "Point", "coordinates": [ -3.709986,47.351847 ] } }
{ "type": "Feature", "properties": { "thesum": 14, "themax": 14, "themin": 14, "theproduct": 14, "themean": 14, "theconcat": 14, "thecomma": 14 }, "geometry": { "type": "Point", "coordinates": [ -145.079976,80.547441 ] } }
{ "type": "Feature", "properties": { "thesum": 15, "themax": 15, "themin": 15, "theproduct": 15, "themean": 15, "theconcat": 15, "thecomma": 15 }, "geometry": { "type": "Point", "coordinates": [ 14.666648,-65.254575 ] } }
{ "type": "Feature", "properties": { "thesum": 16, "themax": 16, "themin": 16, "theproduct": 16, "themean": 16, "theconcat": 16, "thecomma": 16 }, "geometry": { "type": "Point", "coordinates": [ 24.659014,60.295014 ] } }
{ "type": "Feature", "properties": { "thesum": 17, "themax": 17, "themin": 17, "theproduct": 17, "themean": 17, "theconcat": 17, "thecomma": 17 }, "geometry": { "type": "Point", "coordinates": [ 110.427380,38.364152 ] } }
{ "type": "Feature", "properties": { "thesum": 18, "themax": 18, "themin": 18, "theproduct": 18, "themean": 18, "theconcat": 18, "thecomma": 18 }, "geometry": { "type": "Point", "coordinates": [ 6.564431,-44.802836 ] } }
{ "type": "Feature", "properties": { "thesum": 19, "themax": 19, "themin": 19, "theproduct": 19, "themean": 19, "theconcat": 19, "thecomma": 19 }, "geometry": { "type": "Point", "coordinates": [ -25.148684,-41.191936 ] } }
{ "type": "Feature", "properties": { "thesum": 20, "themax": 20, "themin": 20, "theproduct": 20, "themean": 20, "theconcat": 20, "thecomma": 20 }, "geometry": { "type": "Point", "coordinates": [ 94.640674,87.473404 ] } }
{ "type": "Feature", "properties": { "thesum": 21, "themax": 21, "themin": 21, "theproduct": 21, "themean": 21, "theconcat": 21, "thecomma": 21 }, "geometry": { "type": "Point", "coordinates": [ -15.166749,44.154022 ] } }
{ "type": "Feature", "properties": { "thesum": 22, "themax": 22, "themin": 22, "theproduct": 22, "themean": 22, "theconcat": 22, "thecomma": 22 }, "geometry": { "type": "Point", "coordinates": [ -83.839224,-22.324076 ] } }
{ "type": "Feature", "properties": { "thesum": 23, "themax": 23, "themin": 23, "theproduct": 23, "themean": 23, "theconcat": 23, "thecomma": 23 }, "geometry": { "type": "Point", "coordinates": [ -131.431059,-48.656317 ] } }
{ "type": "Feature", "properties": { "thesum": 24, "themax": 24, "themin": 24, "theproduct": 24, "themean": 24, "theconcat": 24, "thecomma": 24 }, "geometry": { "type": "Point", "coordinates": [ 13.458676,-81.541789 ] } }
{ "type": "Feature", "properties": { "thesum": 25, "themax": 25, "themin": 25, "theproduct": 25, "themean": 25, "theconcat": 25, "thecomma": 25 }, "geometry": { "type": "Point", "coordinates": [ 49.375287,54.035848 ] } }
{ "type": "Feature", "properties": { "thesum": 26, "themax": 26, "themin": 26, "theproduct": 26, "themean": 26, "theconcat": 26, "thecomma": 26 }, "geometry": { "type": "Point", "coordinates": [ 44.023761,42.750924 ] } }
{ "type": "Feature", "properties": { "thesum": 27, "themax": 27, "themin": 27, "theproduct": 27, "themean": 27, "theconcat": 27, "thecomma": 27 }, "geometry": { "type": "Point", "coordinates": [ 23.815303,87.689971 ] } }
{ "type": "Feature", "properties": { "thesum": 28, "themax": 28, "themin": 28, "theproduct": 28, "themean": 28, "theconcat": 28, "thecomma": 28 }, "geometry": { "type": "Point", "coordinates": [ -108.418101,69.859222 ] } }
{ "type": "Feature", "properties": { "thesum": 29, "themax": 29, "themin": 29, "theproduct": 29, "themean": 29, "theconcat": 29, "thecomma": 29 }, "geometry": { "type": "Point", "coordinates": [ -162.422461,-72.828993 ] } }
{ "type": "Feature", "properties": { "thesum": 30, "themax": 30, "themin": 30, "theproduct": 30, "themean": 30, "theconcat": 30, "thecomma": 30 }, "geometry": { "type": "Point", "coordinates": [ 41.555960,87.834643 ] } }
{ "type": "Feature", "properties": { "thesum": 31, "themax": 31, "themin": 31, "theproduct": 31, "themean": 31, "theconcat": 31, "thecomma": 31 }, "geometry": { "type": "Point", "coordinates": [ 151.433696,-2.049808 ] } }
{ "type": "Feature", "properties": { "thesum": 32, "themax": 32, "themin": 32, "theproduct": 32, "themean": 32, "theconcat": 32, "thecomma": 32 }, "geometry": { "type": "Point", "coordinates": [ -156.347397,-54.157799 ] } }
{ "type": "Feature", "properties": { "thesum": 33, "themax": 33, "themin": 33, "theproduct": 33, "themean": 33, "theconcat": 33, "thecomma": 33 }, "geometry": { "type": "Point", "coordinates": [ 177.449262,76.384948 ] } }
{ "type": "Feature", "properties": { "thesum": 34, "themax": 34, "themin": 34, "theproduct": 34, "themean": 34, "theconcat": 34, "thecomma": 34 }, "geometry": { "type": "Point", "coordinates": [ 67.516237,89.283900 ] } }
{ "type": "Feature", "properties": { "thesum": 35, "themax": 35, "themin": 35, "theproduct": 35, "themean": 35, "theconcat": 35, "thecomma": 35 }, "geometry": { "type": "Point", "coordinates": [ 57.957991,-82.230182 ] } }
{ "type": "Feature", "properties": { "thesum": 36, "themax": 36, "themin": 36, "theproduct": 36, "themean": 36, "theconcat": 36, "thecomma": 36 }, "geometry": { "type": "Point", "coordinates": [ 152.745823,-78.389341 ] } }
{ "type": "Feature", "properties": { "thesum": 37, "themax": 37, "themin": 37, "theproduct": 37, "themean": 37, "theconcat": 37, "thecomma": 37 }, "geometry": { "type": "Point", "coordinates": [ -79.735349,80.847381 ] } }
{ "type": "Feature", "properties": { "thesum": 38, "themax": 38, "themin": 38, "theproduct": 38, "themean": 38, "theconcat": 38, "thecomma": 38 }, "geometry": { "type": "Point", "coordinates": [ -176.469083,-1.175014 ] } }
{ "type": "Feature", "properties": { "thesum": 39, "themax": 39, "themin": 39, "theproduct": 39, "themean": 39, "theconcat": 39, "thecomma": 39 }, "geometry": { "type": "Point", "coordinates": [ 20.369644,-44.945809 ] } }
{ "type": "Feature", "properties": { "thesum": 40, "themax": 40, "themin": 40, "theproduct": 40, "themean": 40, "theconcat": 40, "thecomma": 40 }, "geometry": { "type": "Point", "coordinates": [ 75.300338,89.728838 ] } }
{ "type": "Feature", "properties": { "thesum": 41, "themax": 41, "themin": 41, "theproduct": 41, "themean": 41, "theconcat": 41, "thecomma": 41 }, "geometry": { "type": "Point", "coordinates": [ -60.903503,-89.434640 ] } }
{ "type": "Feature", "properties": { "thesum": 42, "themax": 42, "themin": 42, "theproduct": 42, "themean": 42, "theconcat": 42, "thecomma": 42 }, "geometry": { "type": "Point", "coordinates": [ -116.214566,-78.600594 ] } }
{ "type": "Feature", "properties": { "thesum": 43, "themax": 43, "themin": 43, "theproduct": 43, "themean": 43, "theconcat": 43, "thecomma": 43 }, "geometry": { "type": "Point", "coordinates": [ -168.143210,-37.381940 ] } }
{ "type": "Feature", "properties": { "thesum": 44, "themax": 44, "themin": 44, "theproduct": 44, "themean": 44, "theconcat": 44, "thecomma": 44 }, "geometry": { "type": "Point", "coordinates": [ 146.600367,-65.112907 ] } }
{ "type": "Feature", "properties": { "thesum": 45, "themax": 45, "themin": 45, "theproduct": 45, "themean": 45, "theconcat": 45, "thecomma": 45 }, "geometry": { "type": "Point", "coordinates": [ -144.960448,89.877412 ] } }
{ "type": "Feature", "properties": { "thesum": 46, "themax": 46, "themin": 46, "theproduct": 46, "themean": 46, "theconcat": 46, "thecomma": 46 }, "geometry": { "type": "Point", "coordinates": [ 37.779538,-9.255682 ] } }
{ "type": "Feature", "properties": { "thesum": 47, "themax": 47, "themin": 47, "theproduct": 47, "themean": 47, "theconcat": 47, "thecomma": 47 }, "geometry": { "type": "Point", "coordinates": [ 141.921366,-86.191382 ] } }
{ "type": "Feature", "properties": { "thesum": 48, "themax": 48, "themin": 48, "theproduct": 48, "themean": 48, "theconcat": 48, "thecomma": 48 }, "geometry": { "type": "Point", "coordinates": [ 3.757458,-46.957098 ] } }
{ "type": "Feature", "properties": { "thesum": 49, "themax": 49, "themin": 49, "theproduct": 49, "themean": 49, "theconcat": 49, "thecomma": 49 }, "geometry": { "type": "Point", "coordinates": [ -178.557808,-17.999930 ] } }
{ "type": "Feature", "properties": { "thesum": 50, "themax": 50, "themin": 50, "theproduct": 50, "themean": 50, "theconcat": 50, "thecomma": 50 }, "geometry": { "type": "Point", "coordinates": [ -94.775598,89.666291 ] } }
{ "type": "Feature", "properties": { "thesum": 51, "themax": 51, "themin": 51, "theproduct": 51, "themean": 51, "theconcat": 51, "thecomma": 51 }, "geometry": { "type": "Point", "coordinates": [ -105.311977,25.819445 ] } }
{ "type": "Feature", "properties": { "thesum": 52, "themax": 52, "themin": 52, "theproduct": 52, "themean": 52, "theconcat": 52, "thecomma": 52 }, "geometry": { "type": "Point", "coordinates": [ 116.462344,-73.172234 ] } }
{ "type": "Feature", "properties": { "thesum": 53, "themax": 53, "themin": 53, "theproduct": 53, "themean": 53, "theconcat": 53, "thecomma": 53 }, "geometry": { "type": "Point", "coordinates": [ -84.902185,62.166503 ] } }
{ "type": "Feature", "properties": { "thesum": 54, "themax": 54, "themin": 54, "theproduct": 54, "themean": 54, "theconcat": 54, "thecomma": 54 }, "geometry": { "type": "Point", "coordinates": [ -141.394664,-11.763473 ] } }
{ "type": "Feature", "properties": { "thesum": 55, "themax": 55, "themin": 55, "theproduct": 55, "themean": 55, "theconcat": 55, "thecomma": 55 }, "geometry": { "type": "Point", "coordinates": [ 96.026399,83.713544 ] } }
{ "type": "Feature", "properties": { "thesum": 56, "themax": 56, "themin": 56, "theproduct": 56, "themean": 56, "theconcat": 56, "thecomma": 56 }, "geometry": { "type": "Point", "coordinates": [ -154.653153,-89.307708 ] } }
{ "type": "Feature", "properties": { "thesum": 57, "themax": 57, "themin": 57, "theproduct": 57, "themean": 57, "theconcat": 57, "thecomma": 57 }, "geometry": { "type": "Point", "coordinates": [ -71.769818,83.010189 ] } }
{ "type": "Feature", "properties": { "thesum": 58, "themax": 58, "themin": 58, "theproduct": 58, "themean": 58, "theconcat": 58, "thecomma": 58 }, "geometry": { "type": "Point", "coordinates": [ 141.629089,-84.969764 ] } }
{ "type": "Feature", "properties": { "thesum": 59, "themax": 59, "themin": 59, "theproduct": 59, "themean": 59, "theconcat": 59, "thecomma": 59 }, "geometry": { "type": "Point", "coordinates": [ -146.893857,-72.900555 ] } }
{ "type": "Feature", "properties": { "thesum": 60, "themax": 60, "themin": 60, "theproduct": 60, "themean": 60, "theconcat": 60, "thecomma": 60 }, "geometry": { "type": "Point", "coordinates": [ 13.616243,86.468765 ] } }
{ "type": "Feature", "properties": { "thesum": 61, "themax": 61, "themin": 61, "theproduct": 61, "themean": 61, "theconcat": 61, "thecomma": 61 }, "geometry": { "type": "Point", "coordinates": [ 146.239761,-77.415130 ] } }
{ "type": "Feature", "properties": { "thesum": 62, "themax": 62, "themin": 62, "theproduct": 62, "themean": 62, "theconcat": 62, "thecomma": 62 }, "geometry": { "type": "Point", "coordinates": [ 120.720040,34.052368 ] } }
{ "type": "Feature", "properties": { "thesum": 63, "themax": 63, "themin": 63, "theproduct": 63, "themean": 63, "theconcat": 63, "thecomma": 63 }, "geometry": { "type": "Point", "coordinates": [ -50.738121,-49.044879 ] } }
{ "type": "Feature", "properties": { "thesum": 64, "themax": 64, "themin": 64, "theproduct": 64, "themean": 64, "theconcat": 64, "thecomma": 64 }, "geometry": { "type": "Point", "coordinates": [ 159.682795,-17.137421 ] } }
{ "type": "Feature", "properties": { "thesum": 65, "themax": 65, "themin": 65, "theproduct": 65, "themean": 65, "theconcat": 65, "thecomma": 65 }, "geometry": { "type": "Point", "coordinates": [ -166.439086,2.775299 ] } }
{ "type": "Feature", "properties": { "thesum": 66, "themax": 66, "themin": 66, "theproduct": 66, "themean": 66, "theconcat": 66, "thecomma": 66 }, "geometry": { "type": "Point", "coordinates": [ -68.075084,-6.863559 ] } }
{ "type": "Feature", "properties": { "thesum": 67, "themax": 67, "themin": 67, "theproduct": 67, "themean": 67, "theconcat": 67, "thecomma": 67 }, "geometry": { "type": "Point", "coordinates": [ -177.446873,22.270257 ] } }
{ "type": "Feature", "properties": { "thesum": 68, "themax": 68, "themin": 68, "theproduct": 68, "themean": 68, "theconcat": 68, "thecomma": 68 }, "geometry": { "type": "Point", "coordinates": [ 116.851469,-89.159093 ] } }
{ "type": "Feature", "properties": { "thesum": 69, "themax": 69, "themin": 69, "theproduct": 69, "themean": 69, "theconcat": 69, "thecomma": 69 }, "geometry": { "type": "Point", "coordinates": [ 113.612595,13.841587 ] } }
{ "type": "Feature", "properties": { "thesum": 70, "themax": 70, "themin": 70, "theproduct": 70, "themean": 70, "theconcat": 70, "thecomma": 70 }, "geometry": { "type": "Point", "coordinates": [ 147.030951,-21.627240 ] } }
{ "type": "Feature", "properties": { "thesum": 71, "themax": 71, "themin": 71, "theproduct": 71, "themean": 71, "theconcat": 71, "thecomma": 71 }, "geometry": { "type": "Point", "coordinates": [ -171.838003,-55.021829 ] } }
{ "type": "Feature", "properties": { "thesum": 72, "themax": 72, "themin": 72, "theproduct": 72, "themean": 72, "theconcat": 72, "thecomma": 72 }, "geometry": { "type": "Point", "coordinates": [ -179.320808,-69.030987 ] } }
{ "type": "Feature", "properties": { "thesum": 73, "themax": 73, "themin": 73, "theproduct": 73, "themean": 73, "theconcat": 73, "thecomma": 73 }, "geometry": { "type": "Point", "coordinates": [ -41.291951,-0.546778 ] } }
{ "type": "Feature", "properties": { "thesum": 74, "themax": 74, "themin": 74, "theproduct": 74, "themean": 74, "theconcat": 74, "thecomma": 74 }, "geometry": { "type": "Point", "coordinates": [ -159.602264,33.516804 ] } }
{ "type": "Feature", "properties": { "thesum": 75, "themax": 75, "themin": 75, "theproduct": 75, "themean": 75, "theconcat": 75, "thecomma": 75 }, "geometry": { "type": "Point", "coordinates": [ -157.220701,-62.925493 ] } }
{ "type": "Feature", "properties": { "thesum": 76, "themax": 76, "themin": 76, "theproduct": 76, "themean": 76, "theconcat": 76, "thecomma": 76 }, "geometry": { "type": "Point", "coordinates": [ 35.449285,-21.548332 ] } }
{ "type": "Feature", "properties": { "thesum": 77, "themax": 77, "themin": 77, "theproduct": 77, "themean": 77, "theconcat": 77, "thecomma": 77 }, "geometry": { "type": "Point", "coordinates": [ 101.921779,85.807116 ] } }
{ "type": "Feature", "properties": { "thesum": 78, "themax": 78, "themin": 78, "theproduct": 78, "themean": 78, "theconcat": 78, "thecomma": 78 }, "geometry": { "type": "Point", "coordinates": [ -128.051674,83.348143 ] } }
{ "type": "Feature", "properties": { "thesum": 79, "themax": 79, "themin": 79, "theproduct": 79, "themean": 79, "theconcat": 79, "thecomma": 79 }, "geometry": { "type": "Point", "coordinates": [ 53.387503,-84.129458 ] } }
{ "type": "Feature", "properties": { "thesum": 80, "themax": 80, "themin": 80, "theproduct": 80, "themean": 80, "theconcat": 80, "thecomma": 80 }, "geometry": { "type": "Point", "coordinates": [ 58.273040,-53.030862 ] } }
{ "type": "Feature", "properties": { "thesum": 81, "themax": 81, "themin": 81, "theproduct": 81, "themean": 81, "theconcat": 81, "thecomma": 81 }, "geometry": { "type": "Point", "coordinates": [ 125.294919,18.287339 ] } }
{ "type": "Feature", "properties": { "thesum": 82, "themax": 82, "themin": 82, "theproduct": 82, "themean": 82, "theconcat": 82, "thecomma": 82 }, "geometry": { "type": "Point", "coordinates": [ 31.960448,55.594735 ] } }
{ "type": "Feature", "properties": { "thesum": 83, "themax": 83, "themin": 83, "theproduct": 83, "themean": 83, "theconcat": 83, "thecomma": 83 }, "geometry": { "type": "Point", "coordinates": [ 43.356826,-79.995205 ] } }
{ "type": "Feature", "properties": { "thesum": 84, "themax": 84, "themin": 84, "theproduct": 84, "themean": 84, "theconcat": 84, "thecomma": 84 }, "geometry": { "type": "Point", "coordinates": [ -117.349281,13.354257 ] } }
{ "type": "Feature", "properties": { "thesum": 85, "themax": 85, "themin": 85, "theproduct": 85, "themean": 85, "theconcat": 85, "thecomma": 85 }, "geometry": { "type": "Point", "coordinates": [ 7.392891,-80.387558 ] } }
{ "type": "Feature", "properties": { "thesum": 86, "themax": 86, "themin": 86, "theproduct": 86, "themean": 86, "theconcat": 86, "thecomma": 86 }, "geometry": { "type": "Point", "coordinates": [ -0.255971,-32.692982 ] } }
{ "type": "Feature", "properties": { "thesum": 87, "themax": 87, "themin": 87, "theproduct": 87, "themean": 87, "theconcat": 87, "thecomma": 87 }, "geometry": { "type": "Point", "coordinates": [ 165.528504,-69.862641 ] } }
{ "type": "Feature", "properties": { "thesum": 88, "themax": 88, "themin": 88, "theproduct": 88, "themean": 88, "theconcat": 88, "thecomma": 88 }, "geometry": { "type": "Point", "coordinates": [ -137.105444,-88.260877 ] } }
{ "type": "Feature", "properties": { "thesum": 89, "themax": 89, "themin": 89, "theproduct": 89, "themean": 89, "theconcat": 89, "thecomma": 89 }, "geometry": { "type": "Point", "coordinates": [ 28.112105,24.529585 ] } }
{ "type": "Feature", "properties": { "thesum": 90, "themax": 90, "themin": 90, "theproduct": 90, "themean": 90, "theconcat": 90, "thecomma": 90 }, "geometry": { "type": "Point", "coordinates": [ -29.013503,48.460714 ] } }
{ "type": "Feature", "properties": { "thesum": 91, "themax": 91, "themin": 91, "theproduct": 91, "themean": 91, "theconcat": 91, "thecomma": 91 }, "geometry": { "type": "Point", "coordinates": [ 114.967139,84.177181 ] } }
{ "type": "Feature", "properties": { "thesum": 92, "themax": 92, "themin": 92, "theproduct": 92, "themean": 92, "theconcat": 92, "thecomma": 92 }, "geometry": { "type": "Point", "coordinates": [ -63.363328,58.006985 ] } }
{ "type": "Feature", "properties": { "thesum": 93, "themax": 93, "themin": 93, "theproduct": 93, "themean": 93, "theconcat": 93, "thecomma": 93 }, "geometry": { "type": "Point", "coordinates": [ 169.765226,17.852955 ] } }
{ "type": "Feature", "properties": { "thesum": 94, "themax": 94, "themin": 94, "theproduct": 94, "themean": 94, "theconcat": 94, "thecomma": 94 }, "geometry": { "type": "Point", "coordinates": [ -132.507302,18.086814 ] } }
{ "type": "Feature", "properties": { "thesum": 95, "themax": 95, "themin": 95, "theproduct": 95, "themean": 95, "theconcat": 95, "thecomma": 95 }, "geometry": { "type": "Point", "coordinates": [ -56.678179,-62.556708 ] } }
{ "type": "Feature", "properties": { "thesum": 96, "themax": 96, "themin": 96, "theproduct": 96, "themean": 96, "theconcat": 96, "thecomma": 96 }, "geometry": { "type": "Point", "coordinates": [ 174.715105,-76.783064 ] } }
{ "type": "Feature", "properties": { "thesum": 97, "themax": 97, "themin": 97, "theproduct": 97, "themean": 97, "theconcat": 97, "thecomma": 97 }, "geometry": { "type": "Point", "coordinates": [ -19.142632,85.007238 ] } }
{ "type": "Feature", "properties": { "thesum": 98, "themax": 98, "themin": 98, "theproduct": 98, "themean": 98, "theconcat": 98, "thecomma": 98 }, "geometry": { "type": "Point", "coordinates": [ 58.241524,86.371735 ] } }
{ "type": "Feature", "properties": { "thesum": 99, "themax": 99, "themin": 99, "theproduct": 99, "themean": 99, "theconcat": 99, "thecomma": 99 }, "geometry": { "type": "Point", "coordinates": [ -27.756470,53.336764 ] } }
{ "type": "Feature", "properties": { "thesum": 100, "themax": 100, "themin": 100, "theproduct": 100, "themean": 100, "theconcat": 100, "thecomma": 100 }, "geometry": { "type": "Point", "coordinates": [ -123.948513,-81.873970 ] } }

File diff suppressed because one or more lines are too long

View File

@ -3,6 +3,7 @@
"center": "0.000000,0.000000,0",
"description": "tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/attribute-type/out/-z0_-Tinttype@int_-Tfloattype@float_-Tbooltype@bool_-Tstringtype@string.json.check.mbtiles -z0 -Tinttype:int -Tfloattype:float -Tbooltype:bool -Tstringtype:string tests/attribute-type/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {\"booltype\": \"Boolean\", \"expect\": \"Mixed\", \"floattype\": \"Number\", \"inttype\": \"Number\", \"stringtype\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 39,\"geometry\": \"Point\",\"attributeCount\": 5,\"attributes\": [{\"attribute\": \"booltype\",\"count\": 2,\"type\": \"boolean\",\"values\": [false,true]},{\"attribute\": \"expect\",\"count\": 14,\"type\": \"mixed\",\"values\": [0,\"2\",\"2.5\",3,5,5.6,6,\"[2,3]\",\"false\",false,\"null\",\"something\",\"true\",true],\"min\": 0,\"max\": 6},{\"attribute\": \"floattype\",\"count\": 4,\"type\": \"number\",\"values\": [0,3,5,5.6],\"min\": 0,\"max\": 5.6},{\"attribute\": \"inttype\",\"count\": 5,\"type\": \"number\",\"values\": [0,0.000000,3.000000,5,6.000000],\"min\": 0,\"max\": 6},{\"attribute\": \"stringtype\",\"count\": 7,\"type\": \"string\",\"values\": [\"2\",\"2.5\",\"[2,3]\",\"false\",\"null\",\"something\",\"true\"]}]}]}}",
"maxzoom": "0",
"minzoom": "0",

File diff suppressed because one or more lines are too long

177
tests/coalesce-id/in.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,249 @@
scalerank,natscale,labelrank,featurecla,name,namepar,namealt,diffascii,nameascii,adm0cap,capalt,capin,worldcity,megacity,sov0name,sov_a3,adm0name,adm0_a3,adm1name,iso_a2,note,latitude,longitude,changed,namediff,diffnote,pop_max,pop_min,pop_other,rank_max,rank_min,geonameid,meganame,ls_name,ls_match,checkme,min_zoom
8,10,3,Admin-0 capital,Vatican City,,,0,Vatican City,1.00000000000,,,1.00000000000,0,Vatican (Holy Sea),VAT,Vatican (Holy See),VAT,Lazio,VA,,41.90001222640,12.44780838890,4.00000000000,0,Changed scale rank.,832,832,562430,2,2,6691831.00000000000,,Vatican City,1,0,7.0
7,20,0,Admin-0 capital,San Marino,,,0,San Marino,1.00000000000,,,0.00000000000,0,San Marino,SMR,San Marino,SMR,,SM,,43.91715008450,12.46667028670,0.00000000000,0,,29579,29000,0,7,7,3168070.00000000000,,San Marino,1,5,6.1
7,20,0,Admin-0 capital,Vaduz,,,0,Vaduz,1.00000000000,,,0.00000000000,0,Liechtenstein,LIE,Liechtenstein,LIE,,LI,,47.13372377430,9.51666947291,0.00000000000,0,,36281,5342,33009,7,5,3042030.00000000000,,Vaduz,1,0,6.7
6,30,8,Admin-0 capital alt,Lobamba,,,0,Lobamba,0.00000000000,1,Legislative and,0.00000000000,0,Swaziland,SWZ,Swaziland,SWZ,Manzini,SZ,,-26.46666746140,31.19999710970,4.00000000000,0,Changed scale rank.,9782,4557,0,5,4,935048.00000000000,,Lobamba,1,5,6.0
6,30,8,Admin-0 capital,Luxembourg,,,0,Luxembourg,1.00000000000,,,0.00000000000,0,Luxembourg,LUX,Luxembourg,LUX,Luxembourg,LU,,49.61166037910,6.13000280623,4.00000000000,0,Changed scale rank.,107260,76684,106219,9,8,2960316.00000000000,,Luxembourg,1,0,6.0
6,30,0,Admin-0 capital,Palikir,,,0,Palikir,1.00000000000,,,0.00000000000,0,Federated States of Micronesia,FSM,Federated States of Micronesia,FSM,,FM,,6.91664369601,158.14997432400,4.00000000000,0,Changed scale rank.,4645,4645,0,4,4,2081986.00000000000,,Palikir,1,5,6.0
6,30,0,Admin-0 capital,Majuro,,,0,Majuro,1.00000000000,,,0.00000000000,0,Marshall Islands,MHL,Marshall Islands,MHL,,MH,,7.10300431122,171.38000017600,4.00000000000,0,Changed scale rank.,25400,20500,0,7,7,2113779.00000000000,,Majuro,1,5,6.0
6,30,0,Admin-0 capital,Funafuti,,,0,Funafuti,1.00000000000,,,0.00000000000,0,Tuvalu,TUV,Tuvalu,TUV,,TV,,-8.51665199904,179.21664709400,4.00000000000,0,Population from GeoNames. Changed scale rank.,4749,4749,0,4,4,2110394.00000000000,,Funafuti,0,5,6.0
6,30,0,Admin-0 capital,Melekeok,,,0,Melekeok,1.00000000000,,,0.00000000000,0,Palau,PLW,Palau,PLW,,PW,,7.48739617298,134.62654846700,4.00000000000,0,Location adjusted. Changed scale rank.,7026,7026,0,5,5,1559804.00000000000,,Melekeok,1,5,6.0
6,30,0,Admin-0 capital alt,Bir Lehlou,,,0,Bir Lehlou,0.00000000000,1,Claimed as inte,0.00000000000,0,Western Sahara,SAH,Western Sahara,SAH,,EH,,26.11916668600,-9.65252221825,4.00000000000,1,Added place.,500,200,0,2,1,-1.00000000000,,,2,0,6.0
6,30,0,Admin-0 capital,Monaco,,,0,Monaco,1.00000000000,,,0.00000000000,0,Monaco,MCO,Monaco,MCO,,MC,,43.73964568790,7.40691317347,4.00000000000,0,Location adjusted. Changed scale rank.,36371,36371,102371,7,7,2993458.00000000000,,Monaco,1,0,5.1
6,30,0,Admin-0 capital,Tarawa,,,0,Tarawa,1.00000000000,,,0.00000000000,0,Kiribati,KIR,Kiribati,KIR,,KI,,1.33818750562,173.01757082900,4.00000000000,0,Location adjusted. Changed scale rank.,28802,22534,0,7,7,2110079.00000000000,,Tarawa,1,5,6.0
6,30,0,Admin-0 capital,Moroni,,,0,Moroni,1.00000000000,,,0.00000000000,0,Comoros,COM,Comoros,COM,,KM,,-11.70415769570,43.24024409870,4.00000000000,0,Changed scale rank.,128698,42872,0,9,7,921772.00000000000,,Moroni,1,5,6.0
6,30,0,Admin-0 capital,Andorra,,,0,Andorra,1.00000000000,,,0.00000000000,0,Andorra,AND,Andorra,AND,,AD,,42.50000144350,1.51648596051,4.00000000000,0,Changed scale rank.,53998,22256,53371,8,7,3130067.00000000000,,Andorra,1,5,6.0
4,50,8,Admin-0 capital,Port-of-Spain,,,0,Port-of-Spain,1.00000000000,,,0.00000000000,0,Trinidad and Tobago,TTO,Trinidad and Tobago,TTO,Port of Spain,TT,,10.65199708960,-61.51703088540,4.00000000000,0,Changed scale rank.,294934,49031,419082,10,7,3573890.00000000000,,Port-of-Spain,1,5,5.1
4,50,0,Admin-0 capital,Kigali,,,0,Kigali,1.00000000000,,,0.00000000000,1,Rwanda,RWA,Rwanda,RWA,Kigali City,RW,,-1.95359006868,30.06053177770,4.00000000000,0,Changed scale rank.,860000,745261,1152904,11,11,202061.00000000000,Kigali,Kigali,1,0,5.1
4,50,8,Admin-0 capital,Mbabane,,,0,Mbabane,1.00000000000,,Administrative,0.00000000000,0,Swaziland,SWZ,Swaziland,SWZ,Hhohho,SZ,,-26.31665077840,31.13333451210,4.00000000000,0,Changed scale rank.,90138,76218,89979,8,8,934985.00000000000,,Mbabane,1,0,5.6
4,50,5,Admin-0 capital,Juba,,,0,Juba,0.00000000000,,,0.00000000000,0,South Sudan,SSD,South Sudan,SSD,Central Equatoria,SS,,4.82997519828,31.58002559280,20.00000000000,0,Changed country.,111975,111975,111975,9,9,373303.00000000000,,Juba,1,0,5.1
4,50,8,Admin-0 capital alt,The Hague,,,0,The Hague,0.00000000000,1,"Official, legis",0.00000000000,0,Kingdom of the Netherlands,NLD,Netherlands,NLD,Zuid-Holland,NL,,52.08003684400,4.26996130231,0.00000000000,0,,1406000,501725,688599,12,11,2747373.00000000000,,The Hague,1,0,5.6
4,50,8,Admin-0 capital,Ljubljana,,,0,Ljubljana,1.00000000000,,,0.00000000000,0,Slovenia,SVN,Slovenia,SVN,Osrednjeslovenska,SI,,46.05528830880,14.51496903350,4.00000000000,0,Changed scale rank.,314807,255115,256316,10,10,3196359.00000000000,,Ljubljana,1,0,5.6
4,50,7,Admin-0 capital,Bratislava,,,0,Bratislava,1.00000000000,,,0.00000000000,0,Slovakia,SVK,Slovakia,SVK,Bratislavský,SK,,48.15001833000,17.11698075220,4.00000000000,0,Changed scale rank.,423737,373687,361489,10,10,3060972.00000000000,,Bratislava,1,0,5.1
4,50,8,Admin-0 capital,Doha,,,0,Doha,1.00000000000,,,0.00000000000,0,Qatar,QAT,Qatar,QAT,Ad Dawhah,QA,,25.28655600890,51.53296789430,4.00000000000,0,Location adjusted. Changed scale rank.,1450000,731310,0,12,11,290030.00000000000,,Doha,1,5,5.6
4,50,8,Admin-0 capital,Podgorica,,,0,Podgorica,1.00000000000,,,0.00000000000,0,Montenegro,MNE,Montenegro,MNE,Podgorica,ME,,42.46597251290,19.26630692410,4.00000000000,0,Location adjusted. Changed scale rank.,145850,136473,0,9,9,3193044.00000000000,,Podgorica,1,0,5.6
4,50,6,Admin-0 capital alt,Sri Jawewardenepura Kotte,,,0,Sri Jawewardenepura Kotte,0.00000000000,1,Legislative cap,0.00000000000,0,Sri Lanka,LKA,Sri Lanka,LKA,Colombo,LK,,6.90000388481,79.94999304090,4.00000000000,1,Name changed.,115826,115826,2456292,9,9,1238992.00000000000,,Kotte,1,0,5.6
4,50,5,Admin-0 capital alt,Baguio City,,,0,Baguio City,0.00000000000,1,,0.00000000000,0,Philippines,PHL,Philippines,PHL,Benguet,PH,,16.42999066060,120.56994258500,40.00000000000,0,Changed scale rank.,447824,272714,164877,10,10,1728930.00000000000,,Baguio City,1,0,5.6
4,50,5,Admin-0 capital alt,Dodoma,,,0,Dodoma,0.00000000000,1,Offical capital,0.00000000000,0,United Republic of Tanzania,TZA,Tanzania,TZA,Dodoma,TZ,,-6.18330605177,35.75000362010,4.00000000000,0,Location adjusted.,218269,180541,0,10,9,160196.00000000000,,Dodoma,1,0,5.6
4,50,7,Admin-0 capital,Bern,,,0,Bern,1.00000000000,,,0.00000000000,0,Switzerland,CHE,Switzerland,CHE,Bern,CH,,46.91668275870,7.46697546248,4.00000000000,0,Changed scale rank.,275329,121631,267814,10,9,2661552.00000000000,,Bern,1,0,5.6
4,50,5,Admin-0 capital alt,Laayoune,,,0,Laayoune,0.00000000000,1,Claimed as capi,0.00000000000,0,Morocco,MAR,Morocco,MAR,Laâyoune - Boujdour - Sakia El Hamra,MA,,27.14998231910,-13.20000594220,0.00000000000,0,,188084,176365,176365,9,9,2462881.00000000000,,Laayoune,1,0,5.6
4,50,8,Admin-0 capital,Pristina,,,0,Pristina,1.00000000000,,,0.00000000000,0,Kosovo,KOS,Kosovo,KOS,Pristina,-99,,42.66670961410,21.16598425160,4.00000000000,0,Changed scale rank.,465186,198214,261783,10,9,786714.00000000000,,Pristina,1,0,5.6
4,50,8,Admin-0 capital,Roseau,,,0,Roseau,1.00000000000,,,0.00000000000,0,Dominica,DMA,Dominica,DMA,Saint George,DM,,15.30101564430,-61.38701298180,4.00000000000,0,Changed scale rank.,23336,16571,23336,7,6,3575635.00000000000,,Roseau,1,5,5.1
4,50,8,Admin-0 capital,Djibouti,,,0,Djibouti,1.00000000000,,,0.00000000000,0,Djibouti,DJI,Djibouti,DJI,Djibouti,DJ,,11.59501446430,43.14800166710,4.00000000000,0,Changed scale rank.,923000,604013,335001,11,11,223817.00000000000,,Djibouti,1,0,5.6
4,50,6,Admin-0 capital alt,Putrajaya,,,0,Putrajaya,0.00000000000,1,Administrative,0.00000000000,0,Malaysia,MYS,Malaysia,MYS,Selangor,MY,,2.91401979462,101.70194698000,0.00000000000,0,,67964,50000,956431,8,7,6697380.00000000000,,Putrajaya,1,5,5.6
4,50,2,Admin-0 capital alt,Kyoto,,,0,Kyoto,0.00000000000,1,Official capita,0.00000000000,1,Japan,JPN,Japan,JPN,Kyoto,JP,,35.02999228820,135.74999792400,0.00000000000,0,,1805000,1459640,1827367,12,12,1857910.00000000000,Kyoto,Kyoto,1,0,5.1
4,50,8,Admin-0 capital,Banjul,,,0,Banjul,1.00000000000,,,0.00000000000,0,"Gambia, The",GMB,The Gambia,GMB,Banjul,GM,,13.45387646030,-16.59170148920,4.00000000000,0,Location adjusted. Changed scale rank.,43094,34589,581300,7,7,2413876.00000000000,,Banjul,1,0,5.6
4,50,8,Admin-0 capital,Skopje,,,0,Skopje,1.00000000000,,,0.00000000000,0,Macedonia,MKD,Macedonia,MKD,Centar,MK,,42.00000612290,21.43346146510,4.00000000000,0,Changed scale rank.,494087,474889,491890,10,10,785842.00000000000,,Skopje,1,5,5.6
4,50,8,Admin-0 capital,Bridgetown,,,0,Bridgetown,1.00000000000,,,0.00000000000,0,Barbados,BRB,Barbados,BRB,Saint Michael,BB,,13.10200258280,-59.61652673510,4.00000000000,0,Changed scale rank.,191152,96578,191814,9,8,2075807.00000000000,,Bridgetown,1,5,5.6
4,50,8,Admin-0 capital alt,Porto-Novo,,,0,Porto-Novo,0.00000000000,1,Official capita,0.00000000000,0,Benin,BEN,Benin,BEN,Ouémé,BJ,,6.48331097302,2.61662552757,0.00000000000,0,,300000,234168,806945,10,10,2392087.00000000000,,Porto-Novo,1,0,5.6
4,50,8,Admin-0 capital,Bujumbura,,,0,Bujumbura,1.00000000000,,,0.00000000000,0,Burundi,BDI,Burundi,BDI,Bujumbura Mairie,BI,,-3.37608722037,29.36000606150,4.00000000000,0,Changed scale rank.,331700,331700,1208361,10,10,425378.00000000000,,Bujumbura,1,0,5.6
4,50,0,Admin-0 capital,Kingstown,,,0,Kingstown,1.00000000000,,,0.00000000000,0,Saint Vincent and the Grenadines,VCT,Saint Vincent and the Grenadines,VCT,,VC,,13.14827882790,-61.21206242030,4.00000000000,0,Location adjusted. Changed scale rank.,49485,24518,0,7,7,4359981.00000000000,,Kingstown,1,5,5.1
4,50,0,Admin-0 capital,Castries,,,0,Castries,1.00000000000,,,0.00000000000,0,Saint Lucia,LCA,Saint Lucia,LCA,,LC,,14.00197348930,-61.00000818040,4.00000000000,0,Changed scale rank.,37963,10634,0,7,6,3028258.00000000000,,Castries,1,5,5.6
4,50,0,Admin-0 capital,Basseterre,,,0,Basseterre,1.00000000000,,,0.00000000000,0,Saint Kitts and Nevis,KNA,Saint Kitts and Nevis,KNA,,KN,,17.30203045550,-62.71700931970,4.00000000000,0,Changed scale rank.,21887,15500,21887,7,6,3575551.00000000000,,Basseterre,1,5,5.6
4,50,0,Admin-0 capital,Port Louis,,,0,Port Louis,1.00000000000,,,0.00000000000,0,Mauritius,MUS,Mauritius,MUS,,MU,,-20.16663857140,57.49999385460,4.00000000000,0,Changed scale rank.,595491,148416,304613,11,9,934154.00000000000,,Port Louis,1,5,5.6
4,50,0,Admin-0 capital,Saint George's,,,0,Saint George's,1.00000000000,,,0.00000000000,0,Grenada,GRD,Grenada,GRD,,GD,,12.05263340170,-61.74164322610,4.00000000000,0,Changed scale rank.,33734,27343,27343,7,7,3579925.00000000000,,Saint Georgee۪s,1,5,5.1
4,50,0,Admin-0 capital,Manama,,,0,Manama,1.00000000000,,,0.00000000000,0,Bahrain,BHR,Bahrain,BHR,,BH,,26.23613629050,50.58305171590,4.00000000000,0,Changed scale rank.,563920,157474,563666,11,9,290340.00000000000,,Manama,1,5,5.6
4,50,0,Admin-0 capital,Saint John's,,,0,Saint John's,1.00000000000,,,0.00000000000,0,Antigua and Barbuda,ATG,Antigua and Barbuda,ATG,,AG,,17.11803651830,-61.85003381510,4.00000000000,0,Changed scale rank.,35499,24226,0,7,7,3576022.00000000000,,Saint John's,1,5,5.1
3,110,8,Admin-0 capital,Montevideo,,,0,Montevideo,1.00000000000,,,0.00000000000,1,Uruguay,URY,Uruguay,URY,Montevideo,UY,,-34.85804156620,-56.17105228840,0.00000000000,0,,1513000,5324,1276128,12,5,5038018.00000000000,Montevideo,Montevideo,1,0,4.0
3,110,8,Admin-0 capital,Lomé,,Lome,0,Lome,1.00000000000,,,0.00000000000,1,Togo,TGO,Togo,TGO,Maritime,TG,,6.13193707166,1.22275711936,0.00000000000,0,,1452000,749700,1256715,12,11,2365267.00000000000,Lomi,Lome,1,0,5.0
3,110,7,Admin-0 capital,Tunis,,,0,Tunis,1.00000000000,,,0.00000000000,0,Tunisia,TUN,Tunisia,TUN,Tunis,TN,,36.80277813620,10.17967809920,0.00000000000,0,,2412500,728453,1675117,12,11,2464470.00000000000,,Tunis,1,0,5.0
3,110,8,Admin-0 capital,Abu Dhabi,,,0,Abu Dhabi,1.00000000000,,,0.00000000000,0,United Arab Emirates,ARE,United Arab Emirates,ARE,Abu Dhabi,AE,,24.46668357240,54.36659338260,0.00000000000,0,,603492,560230,560230,11,11,292968.00000000000,,Abu Dhabi,1,0,5.0
3,110,8,Admin-0 capital,Ashgabat,,,0,Ashgabat,1.00000000000,,,0.00000000000,0,Turkmenistan,TKM,Turkmenistan,TKM,Ahal,TM,,37.94999493310,58.38329911180,0.00000000000,0,,727700,577982,556048,11,11,162183.00000000000,,Ashgabat,1,0,5.0
3,110,6,Admin-0 capital,Lusaka,,,0,Lusaka,1.00000000000,,,0.00000000000,1,Zambia,ZMB,Zambia,ZMB,Lusaka,ZM,,-15.41664426790,28.28332759470,0.00000000000,0,,1328000,1267440,1240558,12,12,909137.00000000000,Lusaka,Lusaka,1,0,4.0
3,110,6,Admin-0 capital,Harare,,,0,Harare,1.00000000000,,,0.00000000000,1,Zimbabwe,ZWE,Zimbabwe,ZWE,Harare,ZW,,-17.81778969440,31.04470943070,0.00000000000,0,,1572000,1542813,1831877,12,12,890299.00000000000,Harare,Harare,1,0,4.0
3,110,8,Admin-0 capital,Dili,,,0,Dili,1.00000000000,,,0.00000000000,0,East Timor,TLS,East Timor,TLS,Dili,TL,,-8.55938840855,125.57945593200,0.00000000000,0,,234331,193563,55154,10,9,1645457.00000000000,,Dili,1,0,5.0
3,110,8,Admin-0 capital,Port Vila,,,0,Port Vila,1.00000000000,,,0.00000000000,0,Vanuatu,VUT,Vanuatu,VUT,Shefa,VU,,-17.73335040400,168.31664058400,0.00000000000,0,,44040,35901,7702,7,7,2135171.00000000000,,Port-Vila,1,0,4.0
3,110,8,Admin-0 capital,Tegucigalpa,,,0,Tegucigalpa,1.00000000000,,,0.00000000000,1,Honduras,HND,Honduras,HND,Francisco Morazán,HN,,14.10204490050,-87.21752933930,0.00000000000,0,,946000,850848,1014546,11,11,3600949.00000000000,Tegucigalpa,Tegucigalpa,1,0,5.0
3,110,8,Admin-0 capital,Georgetown,,,0,Georgetown,1.00000000000,,,0.00000000000,0,Guyana,GUY,Guyana,GUY,East Berbice-Corentyne,GY,,6.80197369275,-58.16702864750,0.00000000000,0,,264350,235017,264350,10,10,3378644.00000000000,,Georgetown1,1,5,4.0
3,110,8,Admin-0 capital,Reykjavík,,,1,Reykjavik,1.00000000000,,,0.00000000000,0,Iceland,ISL,Iceland,ISL,Suðurnes,IS,,64.15002361970,-21.95001448720,0.00000000000,0,,166212,113906,160116,9,9,3413829.00000000000,,Reykjavik,1,0,3.7
3,110,8,Admin-0 capital,Port-au-Prince,,,0,Port-au-Prince,1.00000000000,,,0.00000000000,1,Haiti,HTI,Haiti,HTI,Ouest,HT,,18.54102459610,-72.33603458830,0.00000000000,0,,1998000,1234742,2385397,12,12,3718426.00000000000,Port-au-Prince,Port-au-Prince,1,0,5.0
3,110,5,Admin-0 capital,Kampala,,,0,Kampala,1.00000000000,,,0.00000000000,1,Uganda,UGA,Uganda,UGA,Kampala,UG,,0.31665895477,32.58332352570,0.00000000000,0,,1420000,1353189,2153702,12,12,232422.00000000000,Kampala,Kampala,1,0,5.0
3,110,8,Admin-0 capital,Paramaribo,,,0,Paramaribo,1.00000000000,,,0.00000000000,0,Suriname,SUR,Suriname,SUR,Paramaribo,SR,,5.83503012992,-55.16703088540,0.00000000000,0,,254169,223757,248161,10,10,3383330.00000000000,,Paramaribo,1,5,5.0
3,110,6,Admin-0 capital,Niamey,,,0,Niamey,1.00000000000,,,0.00000000000,1,Niger,NER,Niger,NER,Niamey,NE,,13.51670595190,2.11665604514,0.00000000000,0,,915000,742791,715325,11,11,2440485.00000000000,Niamey,Niamey,1,0,5.0
3,110,8,Admin-0 capital,Dushanbe,,,0,Dushanbe,1.00000000000,,,0.00000000000,0,Tajikistan,TJK,Tajikistan,TJK,Tadzhikistan Territories,TJ,,38.56003521630,68.77387935270,0.00000000000,0,,1086244,679400,1081361,12,11,1221874.00000000000,,Dushanbe,1,0,5.0
3,110,7,Admin-0 capital,Asunción,,Asuncion,1,Asuncion,1.00000000000,,,0.00000000000,1,Paraguay,PRY,Paraguay,PRY,Asunción,PY,,-25.29640297570,-57.64150516930,0.00000000000,0,,1870000,11693,636771,12,6,1730025.00000000000,Asuncian,Asuncion,1,5,4.0
3,110,8,Admin-0 capital,Managua,,,0,Managua,1.00000000000,,,0.00000000000,1,Nicaragua,NIC,Nicaragua,NIC,Managua,NI,,12.15301658010,-86.26849166030,0.00000000000,0,,920000,920000,1088194,11,11,3617763.00000000000,Managua,Managua,1,0,5.0
3,110,8,Admin-0 capital,Freetown,,,0,Freetown,1.00000000000,,,0.00000000000,1,Sierra Leone,SLE,Sierra Leone,SLE,Western,SL,,8.47001141249,-13.23421574040,0.00000000000,0,,827000,13768,1074640,11,6,2408770.00000000000,Freetown,Freetown,1,0,5.0
3,110,2,Admin-0 capital,Islamabad,,,0,Islamabad,1.00000000000,,,0.00000000000,1,Pakistan,PAK,Pakistan,PAK,F.C.T.,PK,,33.69999595030,73.16663447970,0.00000000000,0,,780000,601600,893673,11,11,1176615.00000000000,Islamabad,Islamabad,1,0,5.0
3,110,6,Admin-0 capital,Kathmandu,,,0,Kathmandu,1.00000000000,,,0.00000000000,1,Nepal,NPL,Nepal,NPL,Bhaktapur,NP,,27.71669191390,85.31664221080,0.00000000000,0,,895000,895000,1099610,11,11,1283240.00000000000,Kathmandu,Kathmandu,1,0,5.0
3,110,3,Admin-0 capital,Bloemfontein,,,0,Bloemfontein,1.00000000000,,Judicial capita,0.00000000000,0,South Africa,ZAF,South Africa,ZAF,Orange Free State,ZA,,-29.11999387740,26.22991288120,4.00000000000,0,Changed scale rank.,463064,456669,456513,10,10,1018725.00000000000,,Bloemfontein,1,0,5.0
3,110,3,Admin-0 capital,Pretoria,,,0,Pretoria,1.00000000000,,Administrative,0.00000000000,1,South Africa,ZAF,South Africa,ZAF,Gauteng,ZA,,-25.70692055380,28.22942907580,0.00000000000,0,,1338000,1338000,1443084,12,12,964137.00000000000,Pretoria,Pretoria,1,0,5.0
3,110,8,Admin-0 capital,Port Moresby,,,0,Port Moresby,1.00000000000,,,0.00000000000,0,Papua New Guinea,PNG,Papua New Guinea,PNG,Central,PG,,-9.46470782587,147.19250362100,0.00000000000,0,,283733,251136,251304,10,10,2088122.00000000000,,Port Moresby,1,0,4.0
3,110,8,Admin-0 capital,Honiara,,,0,Honiara,1.00000000000,,,0.00000000000,0,Solomon Islands,SLB,Solomon Islands,SLB,Guadalcanal,SB,,-9.43799429509,159.94976573400,0.00000000000,0,,76328,56298,76328,8,8,2108502.00000000000,,Honiara,1,0,5.0
3,110,8,Admin-0 capital,Panama City,,Ciudad de Panam,0,Panama City,1.00000000000,,,0.00000000000,1,Panama,PAN,Panama,PAN,Panama,PA,,8.96801719048,-79.53303715180,0.00000000000,0,,1281000,408168,939725,12,10,3703443.00000000000,Ciudad de Panam,Panama City1,1,0,5.0
3,110,5,Admin-0 capital,Rabat,,,0,Rabat,1.00000000000,,,0.00000000000,1,Morocco,MAR,Morocco,MAR,Rabat - Salé - Zemmour - Zaer,MA,,34.02529909160,-6.83613082013,0.00000000000,0,,1705000,1655753,2029349,12,12,2538475.00000000000,Rabat,Rabat,1,0,5.0
3,110,8,Admin-0 capital,Chișinău,,,0,Chisinau,1.00000000000,,,0.00000000000,0,Moldova,MDA,Moldova,MDA,Chisinau,MD,,47.00502361970,28.85771113970,0.00000000000,0,,688134,635994,664472,11,11,618426.00000000000,,Chisinau,1,5,5.0
3,110,6,Admin-0 capital,Maputo,,,0,Maputo,1.00000000000,,,0.00000000000,1,Mozambique,MOZ,Mozambique,MOZ,Maputo,MZ,,-25.95527748740,32.58916296260,0.00000000000,0,,1446000,1191613,1365454,12,12,1040652.00000000000,Maputo,Maputo,1,0,5.0
3,110,8,Admin-0 capital,Mogadishu,,Muqdisho,0,Mogadishu,1.00000000000,,,0.00000000000,1,Somalia,SOM,Somalia,SOM,Banaadir,SO,,2.06668133433,45.36667761110,0.00000000000,0,,1100000,875388,849392,12,11,53654.00000000000,Muqdisho,Mogadishu,1,5,4.0
3,110,8,Admin-0 capital,Muscat,,,0,Muscat,1.00000000000,,,0.00000000000,0,Oman,OMN,Oman,OMN,Muscat,OM,,23.61332480770,58.59331213260,0.00000000000,0,,734697,586861,586861,11,11,287286.00000000000,,Muscat,1,0,5.0
3,110,6,Admin-0 capital,Colombo,,,0,Colombo,1.00000000000,,"De facto, admin",0.00000000000,0,Sri Lanka,LKA,Sri Lanka,LKA,Colombo,LK,,6.93196575818,79.85775060930,0.00000000000,0,,217000,217000,2490974,10,10,3465927.00000000000,,Colombo,1,5,5.0
3,110,7,Admin-0 capital,Ulaanbaatar,,,0,Ulaanbaatar,1.00000000000,,,0.00000000000,1,Mongolia,MNG,Mongolia,MNG,Ulaanbaatar,MN,,47.91667339990,106.91661576200,0.00000000000,0,,885000,769612,765359,11,11,2028462.00000000000,Ulaanbaatar,Ulaanbaatar,1,0,4.0
3,110,6,Admin-0 capital,Windhoek,,,0,Windhoek,1.00000000000,,,0.00000000000,0,Namibia,NAM,Namibia,NAM,Khomas,NA,,-22.57000608440,17.08354610050,0.00000000000,0,,268132,262796,262796,10,10,3352136.00000000000,,Windhoek,1,0,5.0
3,110,2,Admin-0 capital,Abuja,,,0,Abuja,1.00000000000,,Official and ad,0.00000000000,1,Nigeria,NGA,Nigeria,NGA,Federal Capital Territory,NG,,9.08333314914,7.53332800155,4.00000000000,0,Changed scale rank.,1576000,162135,0,12,9,2322794.00000000000,Abuja,Abuja,1,5,4.0
3,110,8,Admin-0 capital,Bissau,,,0,Bissau,1.00000000000,,,0.00000000000,0,Guinea Bissau,GNB,Guinea Bissau,GNB,Bissau,GW,,11.86502382300,-15.59836084130,0.00000000000,0,,403339,388028,403339,10,10,2374775.00000000000,,Bissau,1,0,5.0
3,110,8,Admin-0 capital,Amman,,,0,Amman,1.00000000000,,,0.00000000000,1,Jordan,JOR,Jordan,JOR,Amman,JO,,31.95002524720,35.93329992550,0.00000000000,0,,1060000,1060000,2633729,12,12,250441.00000000000,Amman,Amman,1,0,5.0
3,110,8,Admin-0 capital,Vilnius,,,0,Vilnius,1.00000000000,,,0.00000000000,0,Lithuania,LTU,Lithuania,LTU,Vilniaus,LT,,54.68336631180,25.31663529330,0.00000000000,0,,542366,507029,494356,11,11,593116.00000000000,,Vilnius,1,0,5.0
3,110,8,Admin-0 capital,Riga,,,0,Riga,1.00000000000,,,0.00000000000,0,Latvia,LVA,Latvia,LVA,Riga,LV,,56.95002382320,24.09996537140,0.00000000000,0,,742572,705033,0,11,11,456172.00000000000,,Riga,1,0,4.0
3,110,8,Admin-0 capital,Bishkek,,,0,Bishkek,1.00000000000,,,0.00000000000,1,Kyrgyzstan,KGZ,Kyrgyzstan,KGZ,Bishkek,KG,,42.87307944650,74.58520422250,0.00000000000,0,,837000,804212,781714,11,11,1528675.00000000000,Bishkek,Bishkek,1,5,5.0
3,110,8,Admin-0 capital,Maseru,,,0,Maseru,1.00000000000,,,0.00000000000,0,Lesotho,LSO,Lesotho,LSO,Maseru,LS,,-29.31667437870,27.48327307000,0.00000000000,0,,361324,118355,356225,10,9,932505.00000000000,,Maseru,1,0,5.0
3,110,6,Admin-0 capital,Antananarivo,,,0,Antananarivo,1.00000000000,,,0.00000000000,1,Madagascar,MDG,Madagascar,MDG,Antananarivo,MG,,-18.91663735060,47.51662390010,0.00000000000,0,,1697000,1391433,1844658,12,12,1070940.00000000000,Antananarivo,Antananarivo,1,0,5.0
3,110,7,Admin-0 capital,Quito,,,0,Quito,1.00000000000,,,0.00000000000,1,Ecuador,ECU,Ecuador,ECU,Pichincha,EC,,-0.21498818065,-78.50005110850,0.00000000000,0,,1701000,1399814,1435528,12,12,3652462.00000000000,Quito,Quito,1,0,4.0
3,110,8,Admin-0 capital,San José,,San Jose,1,San Jose,1.00000000000,,,0.00000000000,1,Costa Rica,CRI,Costa Rica,CRI,San José,CR,,9.93501242974,-84.08405135270,0.00000000000,0,,1284000,1724,1434681,12,3,3669623.00000000000,San Josi,San Jose1,1,5,5.0
3,110,8,Admin-0 capital,San Salvador,,,0,San Salvador,1.00000000000,,,0.00000000000,1,El Salvador,SLV,El Salvador,SLV,San Salvador,SV,,13.71000164690,-89.20304122080,0.00000000000,0,,1433000,2807,2139587,12,4,1690681.00000000000,San Salvador,San Salvador,1,5,5.0
3,110,8,Admin-0 capital,Kingston,,,0,Kingston,1.00000000000,,,0.00000000000,0,Jamaica,JAM,Jamaica,JAM,Kingston,JM,,17.97707662380,-76.76743371370,4.00000000000,0,Location adjusted.,937700,664973,18171,11,11,3489854.00000000000,,Kingston1,1,5,5.0
3,110,7,Admin-0 capital,Ndjamena,,N'Djamnna,0,Ndjamena,1.00000000000,,,0.00000000000,1,Chad,TCD,Chad,TCD,Hadjer-Lamis,TD,,12.11309653620,15.04914831410,0.00000000000,0,,989000,681387,686347,11,11,2427123.00000000000,N'Djam-na,Ndjamena,1,0,5.0
3,110,8,Admin-0 capital,Malabo,,,0,Malabo,1.00000000000,,,0.00000000000,0,Equatorial Guinea,GNQ,Equatorial Guinea,GNQ,Bioko Norte,GQ,,3.75001527803,8.78327754582,4.00000000000,0,Location adjusted.,155963,155963,0,9,9,2309527.00000000000,,Malabo,1,0,5.0
3,110,8,Admin-0 capital,Asmara,,,0,Asmara,1.00000000000,,,0.00000000000,0,Eritrea,ERI,Eritrea,ERI,Anseba,ER,,15.33333925270,38.93332352580,0.00000000000,0,,620802,563930,587094,11,11,343300.00000000000,,Asmara,1,0,5.0
3,110,8,Admin-0 capital,Zagreb,,,0,Zagreb,1.00000000000,,,0.00000000000,0,Croatia,HRV,Croatia,HRV,Grad Zagreb,HR,,45.80000673330,15.99999466820,0.00000000000,0,,722526,698966,690638,11,11,3186886.00000000000,,Zagreb,1,0,5.0
3,110,8,Admin-0 capital,Tallinn,,,0,Tallinn,1.00000000000,,,0.00000000000,0,Estonia,EST,Estonia,EST,Harju,EE,,59.43387737950,24.72804072950,0.00000000000,0,,394024,340027,317949,10,10,588409.00000000000,,Tallinn,1,0,5.0
3,110,8,Admin-0 capital,Lilongwe,,,0,Lilongwe,1.00000000000,,,0.00000000000,0,Malawi,MWI,Malawi,MWI,Lilongwe,MW,,-13.98329506550,33.78330196000,0.00000000000,0,,646750,646750,1061388,11,11,927967.00000000000,,Lilongwe,1,0,5.0
3,110,8,Admin-0 capital,Guatemala,,Ciudad de Guatemala (Guatemala City),0,Guatemala,1.00000000000,,,0.00000000000,1,Guatemala,GTM,Guatemala,GTM,Guatemala,GT,,14.62113466280,-90.52696557790,0.00000000000,0,,1024000,994938,2391150,12,11,3598132.00000000000,Ciudad de Guatemala (Guatemala City),Guatemala,1,0,5.0
3,110,7,Admin-0 capital,Libreville,,,0,Libreville,1.00000000000,,,0.00000000000,0,Gabon,GAB,Gabon,GAB,Estuaire,GA,,0.38538860972,9.45796504582,0.00000000000,0,,578156,483355,483522,11,10,2399697.00000000000,,Libreville,1,0,5.0
3,110,8,Admin-0 capital,Suva,,,0,Suva,1.00000000000,,,0.00000000000,0,Fiji,FJI,Fiji,FJI,Central,FJ,,-18.13301593140,178.44170731500,4.00000000000,0,Location adjusted.,175399,88271,0,9,8,2198148.00000000000,,Suva,1,0,5.0
3,110,3,Admin-0 capital alt,Valparaíso,,Valparaiso,1,Valparaiso,0.00000000000,1,Legislative cap,0.00000000000,1,Chile,CHL,Chile,CHL,Valparaíso,CL,,-33.04776446660,-71.62101363290,4.00000000000,0,Changed scale rank.,854000,15938,130815,11,6,3445575.00000000000,Valpara so,Valparaiso2,1,0,5.0
3,110,7,Admin-0 capital,Nouakchott,,,0,Nouakchott,1.00000000000,,,0.00000000000,0,Mauritania,MRT,Mauritania,MRT,Nouakchott,MR,,18.08642702120,-15.97534041490,0.00000000000,0,,742144,661400,742144,11,11,2377450.00000000000,,Nouakchott,1,0,5.0
3,110,6,Admin-0 capital,Bamako,,,0,Bamako,1.00000000000,,,0.00000000000,1,Mali,MLI,Mali,MLI,Bamako,ML,,12.65001466770,-8.00003910464,0.00000000000,0,,1494000,1297281,1301407,12,12,2460596.00000000000,Bamako,Bamako,1,0,4.0
3,110,8,Admin-0 capital,Beirut,,Bayrut,0,Beirut,1.00000000000,,,0.00000000000,1,Lebanon,LBN,Lebanon,LBN,Beirut,LB,,33.87197511700,35.50970821000,0.00000000000,0,,1846000,1712125,1661980,12,12,276781.00000000000,Bayrut,Beirut,1,5,5.0
3,110,8,Admin-0 capital,Tbilisi,,T'Bilisi,0,Tbilisi,1.00000000000,,,0.00000000000,1,Georgia,GEO,Georgia,GEO,Tbilisi,GE,,41.72500998850,44.79079544960,0.00000000000,0,,1100000,1005257,977179,12,12,611717.00000000000,Tbilisi,Tbilisi,1,0,5.0
3,110,6,Admin-0 capital,Astana,,,0,Astana,1.00000000000,,,0.00000000000,0,Kazakhstan,KAZ,Kazakhstan,KAZ,Aqmola,KZ,,51.18112530430,71.42777420950,0.00000000000,0,,345604,325021,317445,10,10,1526273.00000000000,,Astana,1,0,4.0
3,110,8,Admin-0 capital,Vientiane,,,0,Vientiane,1.00000000000,,,0.00000000000,0,Laos,LAO,Laos,LAO,Vientiane [prefecture],LA,,17.96669272760,102.59998002000,0.00000000000,0,,754000,570348,469811,11,11,1651944.00000000000,,Vientiane,1,0,5.0
3,110,7,Admin-0 capital,Brazzaville,,,0,Brazzaville,1.00000000000,,,0.00000000000,1,Congo (Brazzaville),COG,Congo (Brazzaville),COG,Pool,CG,,-4.25918577181,15.28468949250,0.00000000000,0,,1355000,1163890,1174778,12,12,2260535.00000000000,Brazzaville,Brazzaville,1,0,5.0
3,110,8,Admin-0 capital,Conakry,,,0,Conakry,1.00000000000,,,0.00000000000,1,Guinea,GIN,Guinea,GIN,Conakry,GN,,9.53152284641,-13.68023502750,0.00000000000,0,,1494000,1494000,1498020,12,12,2422465.00000000000,Conakry,Conakry,1,5,5.0
3,110,8,Admin-0 capital,Yamoussoukro,,,0,Yamoussoukro,1.00000000000,1,Official capita,0.00000000000,0,Ivory Coast,CIV,Ivory Coast,CIV,Lacs,CI,,6.81838096000,-5.27550256491,4.00000000000,0,Changed scale rank.,206499,194530,206499,10,9,2279755.00000000000,,Yamoussoukro,1,0,5.0
3,110,2,Admin-0 capital,Ottawa,,Ottawa-Gatineau,0,Ottawa,1.00000000000,,,0.00000000000,1,Canada,CAN,Canada,CAN,Ontario,CA,,45.41669679670,-75.70001530120,0.00000000000,0,,1145000,812129,872781,12,11,6094817.00000000000,Ottawa-Gatineau,Ottawa,1,5,3.0
3,110,8,Admin-0 capital,Belgrade,Beograd,,0,Belgrade,1.00000000000,,,0.00000000000,1,Republic of Serbia,SRB,Serbia,SRB,Grad Beograd,RS,,44.81864544580,20.46799068060,0.00000000000,0,,1099000,1099000,1271541,12,12,792680.00000000000,Beograd,Belgrade,1,0,5.0
3,110,8,Admin-0 capital,Bandar Seri Begawan,,,0,Bandar Seri Begawan,1.00000000000,,,0.00000000000,0,Brunei,BRN,Brunei,BRN,Brunei and Muara,BN,,4.88333111462,114.93328405700,0.00000000000,0,,296500,140000,222513,10,9,1820906.00000000000,,Bandar Seri Begawan,1,0,5.0
3,110,6,Admin-0 capital,Sucre,,,0,Sucre,1.00000000000,,Official (const,0.00000000000,0,Bolivia,BOL,Bolivia,BOL,Chuquisaca,BO,,-19.04097084670,-65.25951562670,0.00000000000,0,,224838,221736,221736,10,10,3903987.00000000000,,Sucre,1,0,4.7
3,110,8,Admin-0 capital,Belmopan,,,0,Belmopan,1.00000000000,,,0.00000000000,0,Belize,BLZ,Belize,BLZ,Cayo,BZ,,17.25203350720,-88.76707299980,0.00000000000,0,,15220,13381,15220,6,6,3582672.00000000000,,Belmopan,1,0,5.0
3,110,7,Admin-0 capital,Bangui,,,0,Bangui,1.00000000000,,,0.00000000000,0,Central African Republic,CAF,Central African Republic,CAF,Bangui,CF,,4.36664430635,18.55828812530,0.00000000000,0,,831925,622771,782274,11,11,2389853.00000000000,,Bangui,1,0,5.0
3,110,6,Admin-0 capital,Yaounde,,Yaounde,0,Yaounde,1.00000000000,,,0.00000000000,1,Cameroon,CMR,Cameroon,CMR,Centre,CM,,3.86670066214,11.51665075550,0.00000000000,0,,1611000,1060587,1060747,12,12,2220957.00000000000,Yaound,Yaounde,1,0,5.0
3,110,8,Admin-0 capital,Tirana,,,0,Tirana,1.00000000000,,,0.00000000000,0,Albania,ALB,Albania,ALB,Durrës,AL,,41.32754070950,19.81888301460,0.00000000000,0,,895350,421286,517792,11,10,3183875.00000000000,,Tirana,1,0,5.0
3,110,8,Admin-0 capital,Yerevan,,,0,Yerevan,1.00000000000,,,0.00000000000,1,Armenia,ARM,Armenia,ARM,Erevan,AM,,40.18115073550,44.51355139040,0.00000000000,0,,1102000,1093485,1154748,12,12,616052.00000000000,Yerevan,Yerevan,1,5,5.0
3,110,8,Admin-0 capital,Baku,,,0,Baku,1.00000000000,,,0.00000000000,1,Azerbaijan,AZE,Azerbaijan,AZE,Baki,AZ,,40.39527203270,49.86221716190,0.00000000000,0,,2122300,1892000,1518801,12,12,587084.00000000000,Baku,Baku,1,0,5.0
3,110,8,Admin-0 capital,Phnom Penh,,Phnum Penh,0,Phnom Penh,1.00000000000,,,0.00000000000,1,Cambodia,KHM,Cambodia,KHM,Phnom Penh,KH,,11.55003012990,104.91663448000,0.00000000000,0,,1466000,1466000,1604086,12,12,1821306.00000000000,Phnum Penh,Phnom Penh,1,5,5.0
3,110,6,Admin-0 capital,La Paz,,,0,La Paz,1.00000000000,,Administrative,0.00000000000,1,Bolivia,BOL,Bolivia,BOL,La Paz,BO,,-16.49797361370,-68.14998519050,0.00000000000,0,,1590000,812799,4400,12,11,3911925.00000000000,La Paz,La Paz3,1,0,4.0
3,110,8,Admin-0 capital,Cotonou,,,0,Cotonou,1.00000000000,,"De facto, admin",0.00000000000,1,Benin,BEN,Benin,BEN,Ouémé,BJ,,6.40000856417,2.51999059918,0.00000000000,0,,762000,690584,1060640,11,11,2394819.00000000000,Cotonou,Cotonou,1,0,5.0
3,110,7,Admin-0 capital,Sofia,,,0,Sofia,1.00000000000,,,0.00000000000,1,Bulgaria,BGR,Bulgaria,BGR,Grad Sofiya,BG,,42.68334942530,23.31665401070,0.00000000000,0,,1185000,874827,871735,12,11,727011.00000000000,Sofia,Sofia,1,0,5.0
3,110,6,Admin-0 capital,Minsk,,,0,Minsk,1.00000000000,,,0.00000000000,1,Belarus,BLR,Belarus,BLR,Minsk,BY,,53.89997743640,27.56662715530,0.00000000000,0,,1805000,1577138,1557919,12,12,625144.00000000000,Minsk,Minsk,1,0,5.0
3,110,8,Admin-0 capital,Thimphu,,,0,Thimphu,1.00000000000,,,0.00000000000,0,Bhutan,BTN,Bhutan,BTN,Thimphu,BT,,27.47298585920,89.63901403700,4.00000000000,0,Location adjusted.,98676,79185,0,8,8,1252416.00000000000,,Thimphu,1,0,5.0
3,110,7,Admin-0 capital,Gaborone,,,0,Gaborone,1.00000000000,,,0.00000000000,0,Botswana,BWA,Botswana,BWA,South-East,BW,,-24.64631345740,25.91194779330,0.00000000000,0,,208411,159243,158896,10,9,933773.00000000000,,Gaborone,1,0,5.0
3,110,3,Admin-0 capital,Canberra,,,0,Canberra,1.00000000000,,,0.00000000000,0,Australia,AUS,Australia,AUS,Australian Capital Territory,AU,,-35.28302854540,149.12902624400,4.00000000000,0,Location adjusted.,327700,234032,0,10,10,2172517.00000000000,,Canberra,1,0,4.0
3,110,8,Admin-0 capital,Ouagadougou,,,0,Ouagadougou,1.00000000000,,,0.00000000000,1,Burkina Faso,BFA,Burkina Faso,BFA,Kadiogo,BF,,12.37031597790,-1.52472375630,0.00000000000,0,,1149000,835457,713874,12,11,2357048.00000000000,Ouagadougou,Ouagadougou,1,0,5.0
3,110,8,Admin-0 capital,Sarajevo,,,0,Sarajevo,1.00000000000,,,0.00000000000,0,Bosnia and Herzegovina,BIH,Bosnia and Herzegovina,BIH,Sarajevo,BA,,43.85002239900,18.38300166700,0.00000000000,0,,696731,628902,627065,11,11,3191281.00000000000,,Sarajevo,1,5,5.0
3,110,5,Admin-0 capital,Naypyidaw,,Nay Pyi Taw,0,Naypyidaw,1.00000000000,,,0.00000000000,1,Myanmar,MMR,Myanmar,MMR,Mandalay,MM,,19.76655702610,96.11861852920,4.00000000000,0,Location adjusted.,930000,194824,0,11,9,6611854.00000000000,Nay Pyi Taw,Naypyidaw,1,0,5.0
3,110,0,Admin-0 capital,Nukualofa,,,0,Nukualofa,1.00000000000,,,0.00000000000,0,Tonga,TON,Tonga,TON,,TO,,-21.13851235670,-175.22056447800,4.00000000000,0,Location adjusted.,42620,23658,42620,7,7,4032402.00000000000,,Nukualofa,1,5,5.0
3,110,0,Admin-0 capital,Hargeysa,,,0,Hargeysa,1.00000000000,,,0.00000000000,0,Somaliland,SOL,Somaliland,SOL,,-99,,9.56002239882,44.06531001670,4.00000000000,0,Changed scale rank.,477876,247018,247018,10,10,57289.00000000000,,Hargeysa,1,5,5.0
3,110,0,Admin-0 capital,Victoria,,,0,Victoria,1.00000000000,,,0.00000000000,0,Seychelles,SYC,Seychelles,SYC,,SC,,-4.61663165397,55.44998978560,0.00000000000,0,,33576,22881,33737,7,7,241131.00000000000,,Victoria4,1,5,5.0
3,110,0,Admin-0 capital,São Tomé,,,1,Sao Tome,1.00000000000,,,0.00000000000,0,Sao Tome and Principe,STP,Sao Tome and Principe,STP,,ST,,0.33340211883,6.73332515323,0.00000000000,0,,88219,56166,88219,8,8,3388092.00000000000,,Sao Tome,1,5,5.0
3,110,0,Admin-0 capital,Apia,,,0,Apia,1.00000000000,,,0.00000000000,0,Samoa,WSM,Samoa,WSM,,WS,,-13.84154504240,-171.73864160900,4.00000000000,0,Location adjusted.,61916,37708,0,8,7,3689793.00000000000,,Apia,1,5,5.0
3,110,0,Admin-0 capital,Valletta,,,0,Valletta,1.00000000000,,,0.00000000000,0,Malta,MLT,Malta,MLT,,MT,,35.89973248190,14.51471065130,0.00000000000,0,,368250,6966,336174,10,5,2562305.00000000000,,Valletta,1,5,5.0
3,110,0,Admin-0 capital,Malé,,,1,Male,1.00000000000,,,0.00000000000,0,Maldives,MDV,Maldives,MDV,,MV,,4.16670818981,73.49994746800,0.00000000000,0,,112927,103693,0,9,9,3174186.00000000000,,Male,1,5,5.0
3,110,0,Admin-0 capital,Jerusalem,,,0,Jerusalem,1.00000000000,,De facto capita,0.00000000000,0,Israel,IS1,Israel,ISR,Jerusalem,IL,,31.77840781560,35.20662593460,0.00000000000,0,,1029300,801000,1072567,12,11,281184.00000000000,,Jerusalem,1,0,3.7
3,110,0,Admin-0 capital,Praia,,,0,Praia,1.00000000000,,,0.00000000000,0,Cape Verde,CPV,Cape Verde,CPV,,CV,,14.91669801730,-23.51668888500,0.00000000000,0,,113364,88859,89205,9,8,3374333.00000000000,,Praia,1,5,5.0
3,110,0,Admin-0 capital,Nassau,,,0,Nassau,1.00000000000,,,0.00000000000,0,"Bahamas, The",BHS,The Bahamas,BHS,,BS,,25.08339011540,-77.35004378430,0.00000000000,0,,227940,160966,0,10,9,3571824.00000000000,,Nassau,1,5,5.0
3,110,0,Admin-0 capital,Nicosia,,,0,Nicosia,1.00000000000,,Capital of both,0.00000000000,0,Cyprus,CYP,Cyprus,CYP,,CY,,35.16667645170,33.36663488640,0.00000000000,0,,224300,200452,222985,10,10,146268.00000000000,,Nicosia,1,5,5.0
3,110,8,Admin-0 capital,Wellington,,,0,Wellington,1.00000000000,,,0.00000000000,0,New Zealand,NZL,New Zealand,NZL,Manawatu-Wanganui,NZ,Wellington metropolitan area,-41.29998785369,174.78326585928,0.00000000000,0,,393400,393400,0,10,9,2144168.00000000000,,Wellington,1,0,4.0
2,200,5,Admin-0 capital,Hanoi,,H,0,Hanoi,1.00000000000,,,0.00000000000,1,Vietnam,VNM,Vietnam,VNM,Thái Nguyên,VN,,21.03332724910,105.85001420000,5.00000000000,0,Changed scale rank.,4378000,1431270,5466347,12,12,1581130.00000000000,Hh Noi,Hanoi,1,0,4.0
2,200,5,Admin-0 capital,Ankara,,,0,Ankara,1.00000000000,,,0.00000000000,1,Turkey,TUR,Turkey,TUR,Ankara,TR,,39.92723858550,32.86439164100,5.00000000000,0,Changed scale rank.,3716000,3307379,3267576,12,12,323786.00000000000,Ankara,Ankara,1,0,4.0
2,200,6,Admin-0 capital,Budapest,,,0,Budapest,1.00000000000,,,1.00000000000,1,Hungary,HUN,Hungary,HUN,Budapest,HU,,47.50000632640,19.08332067740,4.00000000000,0,Changed scale rank.,1679000,1679000,1718895,12,12,3054643.00000000000,Budapest,Budapest,1,0,4.7
2,200,6,Admin-0 capital,Sanaa,,Sana'a',0,Sanaa,1.00000000000,,,0.00000000000,1,Yemen,YEM,Yemen,YEM,Amanat Al Asimah,YE,,15.35473329570,44.20659338260,5.00000000000,0,Changed scale rank.,2008000,1835853,1742507,12,12,71137.00000000000,Sana'a',Sanaa,1,0,4.0
2,200,6,Admin-0 capital,Bucharest,Bucuresti,,0,Bucharest,1.00000000000,,,1.00000000000,1,Romania,ROU,Romania,ROU,Bucharest,RO,,44.43337180490,26.09994665400,4.00000000000,0,Changed scale rank.,1942000,1742194,1636574,12,12,683506.00000000000,Bucuresti,Bucharest,1,0,4.0
2,200,6,Admin-0 capital,Damascus,,Dimashq,0,Damascus,1.00000000000,,,0.00000000000,1,Syria,SYR,Syria,SYR,Damascus,SY,,33.50003399560,36.29999588900,5.00000000000,0,Changed scale rank.,2466000,2466000,3344577,12,12,170654.00000000000,Dimashq,Damascus,1,0,4.7
2,200,6,Admin-0 capital,Lisbon,Lisboa,,0,Lisbon,1.00000000000,,,1.00000000000,1,Portugal,PRT,Portugal,PRT,Lisboa,PT,,38.72272287790,-9.14486630549,4.00000000000,0,Location adjusted. Changed scale rank.,2812000,517802,1795582,12,11,2267057.00000000000,Lisboa,Lisbon,1,0,4.0
2,200,5,Admin-0 capital,Khartoum,,Al-Khartum,0,Khartoum,1.00000000000,,,0.00000000000,1,Sudan,SDN,Sudan,SDN,Khartoum,SD,,15.58807822570,32.53417923860,5.00000000000,0,Changed scale rank.,4754000,1974647,2325931,12,12,379252.00000000000,Al-Khartum,Khartoum,1,0,4.0
2,200,7,Admin-0 capital,Oslo,,,0,Oslo,1.00000000000,,,1.00000000000,1,Kingdom of Norway,NOR,Norway,NOR,Oslo,NO,,59.91669028640,10.74997920600,4.00000000000,0,Changed scale rank.,835000,580000,701804,11,11,3143244.00000000000,Oslo,Oslo,1,0,4.0
2,200,5,Admin-0 capital,Warsaw,Warszawa,,0,Warsaw,1.00000000000,,,1.00000000000,1,Poland,POL,Poland,POL,Masovian,PL,,52.25000062980,20.99999955110,4.00000000000,0,Changed scale rank.,1707000,1702139,2012431,12,12,756135.00000000000,Warszawa,Warsaw,1,0,4.0
2,200,6,Admin-0 capital,Pyongyang,,P'yongyang,0,Pyongyang,1.00000000000,,,0.00000000000,1,"Korea, North",PRK,North Korea,PRK,P'yongyang,KP,,39.01943869940,125.75469071400,5.00000000000,0,Changed scale rank.,3300000,2498797,2483216,12,12,1871859.00000000000,P'yongyang,Pyongyang,1,0,4.7
2,200,5,Admin-0 capital,Dar es Salaam,,,0,Dar es Salaam,1.00000000000,,De facto capita,0.00000000000,1,United Republic of Tanzania,TZA,Tanzania,TZA,Dar-Es-Salaam,TZ,,-6.80001259474,39.26834183630,5.00000000000,0,Changed scale rank.,2930000,2698652,2757835,12,12,160263.00000000000,Dar es Salaam,Dar es Salaam,1,0,4.0
2,200,8,Admin-0 capital,Dublin,,,0,Dublin,1.00000000000,,,1.00000000000,1,Ireland,IRL,Ireland,IRL,Dublin,IE,,53.33306113600,-6.24890568178,0.00000000000,0,,1059000,968976,22478,12,11,2964574.00000000000,Dublin,Dublin2,1,0,4.0
2,200,8,Admin-0 capital,Monrovia,,,0,Monrovia,1.00000000000,,,0.00000000000,1,Liberia,LBR,Liberia,LBR,Montserrado,LR,,6.31055665987,-10.80475162910,0.00000000000,0,,1041000,785662,806416,12,11,2274895.00000000000,Monrovia,Monrovia,1,0,4.0
2,200,6,Admin-0 capital,Kuala Lumpur,,,0,Kuala Lumpur,1.00000000000,,Official and le,1.00000000000,1,Malaysia,MYS,Malaysia,MYS,Selangor,MY,,3.16666587210,101.69998327500,0.00000000000,0,,1448000,1448000,2667990,12,12,1735161.00000000000,Kuala Lumpur,Kuala Lumpur,1,0,4.0
2,200,6,Admin-0 capital,Havana,,La Habana,0,Havana,1.00000000000,,,0.00000000000,1,Cuba,CUB,Cuba,CUB,Ciudad de la Habana,CU,,23.13195884090,-82.36418217130,5.00000000000,0,Changed scale rank.,2174000,1990917,1930305,12,12,3553478.00000000000,La Habana,Havana,1,0,4.0
2,200,7,Admin-0 capital,Prague,Praha,,0,Prague,1.00000000000,,,1.00000000000,1,Czech Republic,CZE,Czech Republic,CZE,Prague,CZ,,50.08333701490,14.46597977570,4.00000000000,0,Changed scale rank.,1162000,2087,1088042,12,4,4548393.00000000000,Praha,Prague,1,0,4.7
2,200,8,Admin-0 capital,Kuwait,,Al Kuwayt|Kuwait City,0,Kuwait,1.00000000000,,,0.00000000000,1,Kuwait,KWT,Kuwait,KWT,Al Kuwayt,KW,,29.36971763000,47.97830114620,5.00000000000,0,Changed scale rank.,2063000,60064,1682968,12,8,285787.00000000000,Al Kuwayt (Kuwait City),Kuwait,1,5,4.0
2,200,8,Admin-0 capital,Santo Domingo,,,0,Santo Domingo,1.00000000000,,,0.00000000000,1,Dominican Republic,DOM,Dominican Republic,DOM,Distrito Nacional,DO,,18.47007285460,-69.90008508470,5.00000000000,0,Changed scale rank.,2154000,2873,3322037,12,4,3668373.00000000000,Santo Domingo,Santo Domingo,1,5,4.0
2,200,6,Admin-0 capital,Accra,,,0,Accra,1.00000000000,,,0.00000000000,1,Ghana,GHA,Ghana,GHA,Greater Accra,GH,,5.55003460583,-0.21671574035,5.00000000000,0,Changed scale rank.,2121000,1963264,2334371,12,12,2306104.00000000000,Accra,Accra,1,0,4.0
2,200,7,Admin-0 capital,Tripoli,,,0,Tripoli,1.00000000000,,,0.00000000000,1,Libya,LBY,Libya,LBY,Tajura' wa an Nawahi al Arba,LY,,32.89250001940,13.18001175810,5.00000000000,0,Changed scale rank.,2189000,229398,1149981,12,10,-1.00000000000,Tarabulus,Tripoli1,1,0,4.0
2,200,8,Admin-0 capital alt,Tel Aviv-Yafo,,Tel Aviv-Jaffa,0,Tel Aviv-Yafo,0.00000000000,1,While Jerulsale,0.00000000000,1,Israel,IS1,Israel,ISR,Tel Aviv,IL,,32.07999147440,34.77001175820,4.00000000000,0,Changed scale rank.,3112000,378358,2306851,12,10,293394.00000000000,Tel Aviv-Yafo,Tel Aviv-Yafo,1,0,4.0
2,200,7,Admin-0 capital,Helsinki,,,0,Helsinki,1.00000000000,,,1.00000000000,1,Finland,FIN,Finland,FIN,Southern Finland,FI,,60.17556337400,24.93412634150,4.00000000000,0,Changed scale rank.,1115000,558457,762958,12,11,658225.00000000000,Helsinki,Helsinki,1,0,4.0
2,200,8,Admin-0 capital,København,Copenhagen,,1,Kobenhavn,1.00000000000,,,1.00000000000,1,Denmark,DNK,Denmark,DNK,Hovedstaden,DK,,55.67856419040,12.56348574730,0.00000000000,0,,1085000,1085000,1038288,12,12,2618425.00000000000,K,Copenhagen,1,0,4.0
2,200,8,Admin-0 capital,Abidjan,,,0,Abidjan,1.00000000000,,"De facto, admin",0.00000000000,1,Ivory Coast,CIV,Ivory Coast,CIV,Lagunes,CI,,5.31999696749,-4.04004825989,5.00000000000,0,Changed scale rank.,3802000,3190395,3181637,12,12,2293538.00000000000,Abidjan,Abidjan,1,0,4.0
2,200,1,Admin-0 capital,Brasília,,Brasilia,0,Brasilia,1.00000000000,,,0.00000000000,1,Brazil,BRA,Brazil,BRA,Distrito Federal,BR,,-15.78334023150,-47.91605228840,5.00000000000,0,Changed scale rank.,3716996,2562963,1772679,12,12,3469058.00000000000,Brasglia,Brasilia,1,0,3.7
2,200,8,Admin-0 capital,Brussels,,Bruxelles-Brussel,0,Brussels,1.00000000000,,,1.00000000000,1,Belgium,BEL,Belgium,BEL,Brussels,BE,,50.83331707670,4.33331660830,0.00000000000,0,,1743000,1019022,1490164,12,12,2800866.00000000000,Bruxelles-Brussel,Brussels,1,5,4.7
2,200,2,Admin-0 capital,Dhaka,,,0,Dhaka,1.00000000000,,,0.00000000000,1,Bangladesh,BGD,Bangladesh,BGD,Dhaka,BD,,23.72305971170,90.40857946670,5.00000000000,0,Changed scale rank.,12797394,7000940,14995538,14,13,1185241.00000000000,Dhaka,Dhaka,1,0,4.0
2,200,6,Admin-0 capital,Luanda,,,0,Luanda,1.00000000000,,,0.00000000000,1,Angola,AGO,Angola,AGO,Luanda,AO,,-8.83828611363,13.23442704130,5.00000000000,0,Changed scale rank.,5172900,1951272,1951272,13,12,2240449.00000000000,Luanda,Luanda,1,0,4.0
2,200,5,Admin-0 capital,Algiers,,El Djazacr,0,Algiers,1.00000000000,,,0.00000000000,1,Algeria,DZA,Algeria,DZA,Alger,DZ,,36.76306479800,3.05055252952,5.00000000000,0,Changed scale rank.,3354000,1977663,3332619,12,12,2507480.00000000000,El Djazasr,Algiers,1,5,4.0
2,200,5,Admin-0 capital,Rangoon,,Yangon,0,Rangoon,0.00000000000,,Former capital,0.00000000000,1,Myanmar,MMR,Myanmar,MMR,Yangon,MM,,16.78335410460,96.16667761130,5.00000000000,0,Changed scale rank.,4088000,3301820,3124090,12,12,1298824.00000000000,Yangon,Rangoon,1,0,4.0
1,300,1,Populated place,San Francisco,,San Francisco-Oakland,0,San Francisco,0.00000000000,,,1.00000000000,1,United States,USA,United States of America,USA,California,US,,37.74000775050,-122.45997766300,0.00000000000,0,,3450000,732072,27400,12,11,5391959.00000000000,San Francisco-Oakland,San Francisco1,1,0,2.7
1,300,1,Admin-1 capital,Denver,,Denver-Aurora,0,Denver,0.00000000000,,,0.00000000000,1,United States,USA,United States of America,USA,Colorado,US,,39.73918804840,-104.98401595200,5.00000000000,0,Changed scale rank.,2313000,1548599,1521278,12,12,5419384.00000000000,Denver-Aurora,Denver,1,0,3.7
1,300,1,Populated place,Houston,,,0,Houston,0.00000000000,,,0.00000000000,1,United States,USA,United States of America,USA,Texas,US,,29.81997438460,-95.33997929050,5.00000000000,0,Changed scale rank.,4459000,3647574,3607616,12,12,4699066.00000000000,Houston,Houston,1,0,3.0
1,300,1,Populated place,Miami,,,0,Miami,0.00000000000,,,1.00000000000,1,United States,USA,United States of America,USA,Florida,US,,25.78761069640,-80.22410608080,0.00000000000,0,,5585000,382894,1037811,13,10,4164138.00000000000,Miami,Miami,1,0,2.1
1,300,1,Admin-1 capital,Atlanta,,,0,Atlanta,0.00000000000,,,1.00000000000,1,United States,USA,United States of America,USA,Georgia,US,,33.83001385400,-84.39994938330,0.00000000000,0,,4506000,422908,2874096,12,10,4180439.00000000000,Atlanta,Atlanta,1,0,3.0
1,300,1,Populated place,Chicago,,,0,Chicago,0.00000000000,,,1.00000000000,1,United States,USA,United States of America,USA,Illinois,US,,41.82999066070,-87.75005497410,0.00000000000,0,,8990000,2841952,3635101,13,12,4887398.00000000000,Chicago,Chicago,1,0,3.0
1,300,6,Admin-0 capital,Caracas,,,0,Caracas,1.00000000000,,,1.00000000000,1,Venezuela,VEN,Venezuela,VEN,Distrito Capital,VE,,10.50099855440,-66.91703719240,4.00000000000,0,Changed scale rank.,2985000,1815679,2764555,12,12,3646738.00000000000,Caracas,Caracas,1,0,3.0
1,300,5,Admin-0 capital,Kiev,,Kyiv,0,Kiev,1.00000000000,,,0.00000000000,1,Ukraine,UKR,Ukraine,UKR,Kiev,UA,,50.43336732900,30.51662796910,5.00000000000,0,Changed scale rank.,2709000,1662508,1611692,12,12,703448.00000000000,Kyiv,Kiev,1,0,3.7
1,300,8,Admin-1 capital,Dubai,Dubayy,,0,Dubai,0.00000000000,,,1.00000000000,1,United Arab Emirates,ARE,United Arab Emirates,ARE,Dubay,AE,,25.22999615380,55.27997432340,1.00000000000,1,Name changed.,1379000,1137347,1166878,12,12,292223.00000000000,Dubayy,Dubayy,1,0,3.7
1,300,6,Admin-0 capital,Tashkent,,,0,Tashkent,1.00000000000,,,0.00000000000,1,Uzbekistan,UZB,Uzbekistan,UZB,Tashkent,UZ,,41.31170188300,69.29493281950,5.00000000000,0,Changed scale rank.,2184000,1978028,2806287,12,12,1512569.00000000000,Tashkent,Tashkent,1,0,3.7
1,300,3,Admin-0 capital,Madrid,,,0,Madrid,1.00000000000,,,1.00000000000,1,Kingdom of Spain,ESP,Spain,ESP,Comunidad de Madrid,ES,,40.40002626450,-3.68335168600,0.00000000000,0,,5567000,50437,3673427,13,8,3117735.00000000000,Madrid,Madrid,1,0,3.0
1,300,7,Admin-1 capital,Geneva,,,0,Geneva,0.00000000000,,,1.00000000000,0,Switzerland,CHE,Switzerland,CHE,Genève,CH,,46.21000754710,6.14002803409,4.00000000000,0,Changed scale rank.,1240000,192385,508284,12,9,2660646.00000000000,,Geneva,1,0,3.7
1,300,7,Admin-0 capital,Stockholm,,,0,Stockholm,1.00000000000,,,1.00000000000,1,Sweden,SWE,Sweden,SWE,Stockholm,SE,,59.35075995430,18.09733473280,4.00000000000,0,Location adjusted.,1264000,1253309,0,12,12,2673730.00000000000,Stockholm,Stockholm,1,0,3.0
1,300,5,Admin-0 capital,Bangkok,,Krung Thep,0,Bangkok,1.00000000000,,,1.00000000000,1,Thailand,THA,Thailand,THA,Bangkok Metropolis,TH,,13.74999920550,100.51664465200,0.00000000000,0,,6704000,5104476,5082758,13,13,1609350.00000000000,Krung Thep,Bangkok,1,0,3.0
1,300,5,Admin-0 capital,Lima,,,0,Lima,1.00000000000,,,0.00000000000,1,Peru,PER,Peru,PER,Lima,PE,,-12.04801267610,-77.05006209480,5.00000000000,0,Changed scale rank.,8012000,6758234,6068380,13,13,3936456.00000000000,Lima,Lima2,1,0,3.0
1,300,8,Admin-0 capital,Dakar,,,0,Dakar,1.00000000000,,,0.00000000000,1,Senegal,SEN,Senegal,SEN,Dakar,SN,,14.71583172500,-17.47313012840,5.00000000000,0,Changed scale rank.,2604000,2476400,2470140,12,12,2253354.00000000000,Dakar,Dakar,1,0,3.0
1,300,3,Admin-0 capital,Johannesburg,,,0,Johannesburg,0.00000000000,,,1.00000000000,1,South Africa,ZAF,South Africa,ZAF,Gauteng,ZA,,-26.17004474000,28.03000972360,4.00000000000,0,Changed feature class.,3435000,2026469,3852246,12,12,993800.00000000000,Johannesburg,Johannesburg,1,0,3.0
1,300,8,Admin-0 capital,Amsterdam,,,0,Amsterdam,1.00000000000,,De facto capita,1.00000000000,1,Kingdom of the Netherlands,NLD,Netherlands,NLD,Noord-Holland,NL,,52.34996868810,4.91664017601,0.00000000000,0,,1031000,741636,962488,12,11,2759794.00000000000,Amsterdam,Amsterdam,1,0,3.7
1,300,5,Admin-1 capital,Casablanca,,Dar-el-Beida,0,Casablanca,0.00000000000,,,1.00000000000,1,Morocco,MAR,Morocco,MAR,Grand Casablanca,MA,,33.59997621560,-7.61636743309,4.00000000000,0,Changed scale rank.,3181000,3144909,3718797,12,12,2553604.00000000000,Dar-el-Beida,Casablanca,1,0,3.7
1,300,3,Admin-0 capital,Seoul,,,0,Seoul,1.00000000000,,,1.00000000000,1,"Korea, South",KOR,South Korea,KOR,Seoul,KR,,37.56634909980,126.99973099700,0.00000000000,0,,9796000,9796000,12018058,13,13,1835848.00000000000,Seoul,Seoul,1,0,3.0
1,300,5,Admin-0 capital,Manila,,,0,Manila,1.00000000000,,"Official, de fa",1.00000000000,1,Philippines,PHL,Philippines,PHL,Metropolitan Manila,PH,,14.60415895480,120.98221716200,0.00000000000,0,,11100000,3077575,2381280,14,12,1701668.00000000000,Manila,Manila,1,0,2.7
1,300,2,Admin-1 capital,Monterrey,,,0,Monterrey,0.00000000000,,,0.00000000000,1,Mexico,MEX,Mexico,MEX,Nuevo León,MX,,25.66999513650,-100.32998478400,5.00000000000,0,Changed scale rank.,3712000,1122874,3225636,12,12,3995465.00000000000,Monterrey,Monterrey,1,0,3.7
1,300,3,Admin-0 capital,Berlin,,,0,Berlin,1.00000000000,,,1.00000000000,1,Germany,DEU,Germany,DEU,Berlin,DE,,52.52181866360,13.40154862330,0.00000000000,0,,3406000,3094014,3013258,12,12,2950159.00000000000,Berlin,Berlin,1,0,2.7
1,300,1,Admin-1 capital,Ürümqi,,rumqi|Wulumqi,0,Urumqi,0.00000000000,,,0.00000000000,1,China,CHN,China,CHN,Xinjiang Uygur,CN,,43.80501222640,87.57500565490,5.00000000000,0,Changed scale rank.,2151000,1508225,2044401,12,12,1529102.00000000000,Cramqi (Wulumqi),Urumqi,1,0,3.7
1,300,1,Admin-1 capital,Chengdu,,,0,Chengdu,0.00000000000,,,0.00000000000,1,China,CHN,China,CHN,Sichuan,CN,,30.67000001930,104.07001949000,5.00000000000,0,Changed scale rank.,4123000,3950437,11622929,12,12,1815286.00000000000,Chengdu,Chengdu,1,0,3.0
1,300,2,Admin-1 region capital,Ōsaka,,Osaka-Kobe,0,Osaka,0.00000000000,,,1.00000000000,1,Japan,JPN,Japan,JPN,Osaka,JP,,34.75003521630,135.46014481500,4.00000000000,0,Changed feature to Admin-0 region capital.,11294000,2592413,9630783,14,12,1853909.00000000000,Osaka-Kobe,Osaka,1,5,3.0
1,300,3,Admin-0 capital,Kinshasa,,,0,Kinshasa,1.00000000000,,,0.00000000000,1,Congo (Kinshasa),COD,Congo (Kinshasa),COD,Kinshasa City,CD,,-4.32972410189,15.31497188180,5.00000000000,0,Changed scale rank.,7843000,5565703,4738154,13,13,2314302.00000000000,Kinshasa,Kinshasa,1,0,3.0
1,300,1,Admin-0 capital,New Delhi,,,0,New Delhi,1.00000000000,,,1.00000000000,0,India,IND,India,IND,Delhi,IN,,28.60002300920,77.19998002010,0.00000000000,0,,317797,317797,8060107,10,10,1261481.00000000000,,New Delhi,1,0,2.1
1,300,1,Admin-1 capital,Bangalore,,Bengaluru,0,Bangalore,0.00000000000,,,0.00000000000,1,India,IND,India,IND,Karnataka,IN,,12.96999513650,77.56000972380,3.00000000000,1,Name changed. Changed scale rank.,6787000,5104047,8102712,13,13,1277333.00000000000,Bangalore,Bangalore,1,0,3.7
1,300,6,Admin-0 capital,Athens,Athenai,Athinai,0,Athens,1.00000000000,,,1.00000000000,1,Greece,GRC,Greece,GRC,Attiki,GR,,37.98332623190,23.73332108430,4.00000000000,0,Changed scale rank.,3242000,729137,112572,12,11,264371.00000000000,Athnnai,Athens2,1,0,3.7
1,300,5,Admin-0 capital,Baghdad,,,0,Baghdad,1.00000000000,,,0.00000000000,1,Iraq,IRQ,Iraq,IRQ,Baghdad,IQ,,33.33864849750,44.39386877320,5.00000000000,0,Changed scale rank.,5054000,5054000,4959534,13,13,98182.00000000000,Baghdad,Baghdad,1,0,3.7
1,300,3,Admin-0 capital,Addis Ababa,,,0,Addis Ababa,1.00000000000,,,0.00000000000,1,Ethiopia,ETH,Ethiopia,ETH,Addis Ababa,ET,,9.03331036268,38.70000443400,5.00000000000,0,Changed scale rank.,3100000,2757729,3013653,12,12,344979.00000000000,Addis Ababa,Addis Ababa,1,5,3.0
1,300,5,Admin-0 capital,Tehran,,,0,Tehran,1.00000000000,,,0.00000000000,1,Iran,IRN,Iran,IRN,Tehran,IR,,35.67194276840,51.42434403360,5.00000000000,0,Changed scale rank.,7873000,7153309,8209012,13,13,112931.00000000000,Tehran,Tehran,1,0,3.0
1,300,2,Populated place,Vancouver,,,0,Vancouver,0.00000000000,,,0.00000000000,1,Canada,CAN,Canada,CAN,British Columbia,CA,,49.27341658410,-123.12164421800,5.00000000000,0,Changed scale rank.,2313328,603502,482002,12,11,6173331.00000000000,Vancouver,Vancouver2,1,0,2.1
1,300,2,Admin-1 capital,Toronto,,,0,Toronto,0.00000000000,,,1.00000000000,1,Canada,CAN,Canada,CAN,Ontario,CA,,43.69997987780,-79.42002079440,0.00000000000,0,,5213000,3934421,3749229,13,12,6167865.00000000000,Toronto,Toronto,1,0,2.1
1,300,3,Admin-0 capital,Buenos Aires,,,0,Buenos Aires,1.00000000000,,,1.00000000000,1,Argentina,ARG,Argentina,ARG,Ciudad de Buenos Aires,AR,,-34.60250160850,-58.39753137370,0.00000000000,0,,12795000,10929146,10271457,14,14,3435910.00000000000,Buenos Aires,Buenos Aires,1,0,2.1
1,300,5,Admin-0 capital,Kabul,,,0,Kabul,1.00000000000,,,0.00000000000,1,Afghanistan,AFG,Afghanistan,AFG,Kabul,AF,,34.51669028630,69.18326004930,5.00000000000,0,Changed scale rank.,3277000,3043532,3475519,12,12,1138958.00000000000,Kabul,Kabul,1,0,3.7
1,300,7,Admin-0 capital,Vienna,Wien,,0,Vienna,1.00000000000,,,1.00000000000,1,Austria,AUT,Austria,AUT,Wien,AT,,48.20001527820,16.36663895540,0.00000000000,0,,2400000,1731000,1480886,12,12,2761369.00000000000,Wien,Vienna,1,0,3.7
1,300,3,Admin-1 capital,Melbourne,,,0,Melbourne,0.00000000000,,,1.00000000000,1,Australia,AUS,Australia,AUS,Victoria,AU,,-37.82003131230,144.97501623500,4.00000000000,0,Changed feature class. Changed scale rank.,4170000,93625,1805353,12,8,2158177.00000000000,Melbourne,Melbourne2,1,0,3.0
1,300,8,Admin-0 capital,Taipei,,,0,Taipei,1.00000000000,,,1.00000000000,1,Taiwan,TWN,Taiwan,TWN,Taipei City,TW,,25.03583333333,121.56833333333,1.00000000000,0,Corrected coordinates.,6900273,2618772,5698241,13,12,1668341.00000000000,Taipei,Taipei,1,0,3.7
1,300,8,Admin-1 capital,Auckland,,,0,Auckland,0.00000000000,,,1.00000000000,1,New Zealand,NZL,New Zealand,NZL,Auckland,NZ,Auckland metropolitan area,-36.84805489493,174.76302698708,4.00000000000,0,Changed scale rank.,1377200,395982,0,12,10,2193733.00000000000,Auckland,Auckland,1,0,3.0
0,600,1,Populated place,Los Angeles,,Los Angeles-Long Beach-Santa Ana,0,Los Angeles,0.00000000000,,,1.00000000000,1,United States,USA,United States of America,USA,California,US,,33.98997825020,-118.17998051100,0.00000000000,0,,12500000,3694820,142265,14,12,5368361.00000000000,Los Angeles-Long Beach-Santa Ana,Los Angeles1,1,0,2.0
0,600,1,Admin-0 capital,"Washington, D.C.",,Washington D.C.,0,"Washington, D.C.",1.00000000000,,,1.00000000000,1,United States,USA,United States of America,USA,District of Columbia,US,,38.89954937650,-77.00941858080,0.00000000000,0,,4338000,552433,2175991,12,11,4140963.00000000000,"Washington, D.C.","Washington, D.C.",1,5,2.1
0,600,1,Populated place,New York,,New York-Newark,0,New York,0.00000000000,,UN Headquarters,1.00000000000,1,United States,USA,United States of America,USA,New York,US,,40.74997906400,-73.98001692880,0.00000000000,0,,19040000,8008278,9292603,14,13,5128581.00000000000,New York-Newark,New York,1,0,1.7
0,600,5,Admin-0 capital,London,,,0,London,1.00000000000,,,1.00000000000,1,United Kingdom,GBR,United Kingdom,GBR,Westminster,GB,,51.49999472970,-0.11672184386,0.00000000000,0,,8567000,7421209,326670,13,13,2643743.00000000000,London,London2,1,5,1.7
0,600,5,Admin-1 capital,Istanbul,,,0,Istanbul,0.00000000000,,,1.00000000000,1,Turkey,TUR,Turkey,TUR,Istanbul,TR,,41.10499615380,29.01000158560,0.00000000000,0,,10061000,9945610,9651488,14,13,745044.00000000000,Istanbul,Istanbul,1,0,3.0
0,600,5,Admin-0 capital,Riyadh,,Ar-Riyadh,0,Riyadh,1.00000000000,,,1.00000000000,1,Saudi Arabia,SAU,Saudi Arabia,SAU,Ar Riyad,SA,,24.64083314920,46.77274165730,4.00000000000,0,Changed scale rank.,4465000,4205961,5148778,12,12,108410.00000000000,Ar-Riyadh,Riyadh,1,0,3.7
0,600,3,Admin-0 capital,Cape Town,,,0,Cape Town,1.00000000000,1,Legislative cap,1.00000000000,1,South Africa,ZAF,South Africa,ZAF,Western Cape,ZA,,-33.92001096720,18.43498815780,4.00000000000,0,Changed scale rank.,3215000,2432858,2401318,12,12,3369157.00000000000,Cape Town,Cape Town,1,0,1.7
0,600,2,Admin-0 capital,Moscow,Moskva,,0,Moscow,1.00000000000,,,1.00000000000,1,Russia,RUS,Russia,RUS,Moskva,RU,,55.75216412260,37.61552282590,0.00000000000,0,,10452000,10452000,10585385,14,14,524901.00000000000,Moskva,Moscow,1,0,1.7
0,600,2,Admin-0 capital,Mexico City,,Ciudad de M,0,Mexico City,1.00000000000,,,1.00000000000,1,Mexico,MEX,Mexico,MEX,Distrito Federal,MX,,19.44244244280,-99.13098820170,0.00000000000,0,,19028000,10811002,10018444,14,14,3530597.00000000000,Ciudad de Mdxico,Mexico City,1,0,2.1
0,600,2,Admin-0 capital alt,Lagos,,,0,Lagos,0.00000000000,1,Former capital,1.00000000000,1,Nigeria,NGA,Nigeria,NGA,Lagos,NG,,6.44326165348,3.39153107121,4.00000000000,0,Location adjusted. Changed scale rank.,9466000,1536,6567892,13,3,2332459.00000000000,Lagos,Lagos,1,0,2.0
0,600,3,Admin-0 capital,Rome,,,0,Rome,1.00000000000,,,1.00000000000,1,Italy,ITA,Italy,ITA,Lazio,IT,,41.89595562650,12.48325842150,0.00000000000,0,,3339000,35452,2050212,12,7,3169070.00000000000,Rome,Rome,1,0,2.7
0,600,1,Admin-0 capital,Beijing,,,0,Beijing,1.00000000000,,,1.00000000000,1,China,CHN,China,CHN,Beijing,CN,,39.92889223130,116.38828568400,0.00000000000,0,,11106000,7480601,9033231,14,13,1816670.00000000000,Beijing,Beijing,1,0,1.7
0,600,5,Admin-0 capital,Nairobi,,,0,Nairobi,1.00000000000,,,1.00000000000,1,Kenya,KEN,Kenya,KEN,Nairobi,KE,,-1.28334674185,36.81665685910,4.00000000000,0,Changed scale rank.,3010000,2750547,3400962,12,12,184745.00000000000,Nairobi,Nairobi,1,0,2.0
0,600,1,Admin-0 capital,Jakarta,,,0,Jakarta,1.00000000000,,,1.00000000000,1,Indonesia,IDN,Indonesia,IDN,Jakarta Raya,ID,,-6.17441770541,106.82943762100,0.00000000000,0,,9125000,8540121,9129613,13,13,1642911.00000000000,Jakarta,Jakarta,1,0,2.1
0,600,5,Admin-0 capital,Bogota,,Bogota,0,Bogota,1.00000000000,,,1.00000000000,1,Colombia,COL,Colombia,COL,Bogota,CO,,4.59642356253,-74.08334395520,0.00000000000,0,,7772000,6333661,5754084,13,13,3688689.00000000000,Bogota,Bogota,1,0,2.1
0,600,3,Admin-0 capital,Cairo,,Al-Qahirah,0,Cairo,1.00000000000,,,1.00000000000,1,Egypt,EGY,Egypt,EGY,Al Qahirah,EG,,30.04996034650,31.24996821970,0.00000000000,0,,11893000,7734614,13720557,14,13,360630.00000000000,Al-Qahirah,Cairo,1,5,1.7
0,600,1,Admin-1 capital,Shanghai,,,0,Shanghai,0.00000000000,,,1.00000000000,1,China,CHN,China,CHN,Shanghai,CN,,31.21645245260,121.43650467800,0.00000000000,0,,14987000,14608512,16803572,14,14,1796236.00000000000,Shanghai,Shanghai,1,0,2.0
0,600,2,Admin-0 capital,Tokyo,,,0,Tokyo,1.00000000000,,De facto capita,1.00000000000,1,Japan,JPN,Japan,JPN,Tokyo,JP,,35.68501690580,139.75140742900,0.00000000000,0,,35676000,8336599,12945252,14,13,1850147.00000000000,Tokyo,Tokyo,1,0,1.7
0,600,1,Admin-1 capital,Mumbai,Bombay,,0,Mumbai,0.00000000000,,,1.00000000000,1,India,IND,India,IND,Maharashtra,IN,,19.01699037570,72.85698929740,0.00000000000,0,,18978000,12691836,12426085,14,14,1275339.00000000000,Mumbai,Mumbai,1,0,1.7
0,600,3,Admin-0 capital,Paris,,,0,Paris,1.00000000000,,,1.00000000000,1,French Republic,FRA,France,FRA,Île-de-France,FR,,48.86669293120,2.33333532574,0.00000000000,0,,9904000,11177,7142744,13,6,2988507.00000000000,Paris,Paris,1,0,1.7
0,600,3,Admin-0 capital,Santiago,,,0,Santiago,1.00000000000,,"Official, admin",1.00000000000,1,Chile,CHL,Chile,CHL,Región Metropolitana de Santiago,CL,,-33.45001381550,-70.66704085460,4.00000000000,0,Changed scale rank.,5720000,46611,3066651,13,7,3449741.00000000000,Santiago,Santiago3,1,0,2.0
0,600,1,Admin-1 capital,Kolkata,Calcutta,,0,Kolkata,0.00000000000,,,0.00000000000,1,India,IND,India,IND,West Bengal,IN,,22.49496929830,88.32467565810,4.00000000000,1,Name changed. Changed scale rank.,14787000,4631392,7783716,14,12,1275004.00000000000,Kolkata,Calcutta,1,0,3.7
0,600,1,Admin-1 capital,Rio de Janeiro,,,0,Rio de Janeiro,0.00000000000,,,1.00000000000,1,Brazil,BRA,Brazil,BRA,Rio de Janeiro,BR,,-22.92502317420,-43.22502079420,0.00000000000,0,,11748000,2010175,1821489,14,12,3451190.00000000000,Rio de Janeiro,Rio de Janeiro,1,0,1.7
0,600,1,Admin-1 capital,São Paulo,,Sao Paulo|Sio Paulo,0,Sao Paulo,0.00000000000,,,1.00000000000,1,Brazil,BRA,Brazil,BRA,São Paulo,BR,,-23.55867958700,-46.62501998040,0.00000000000,0,,18845000,10021295,11522944,14,14,3448439.00000000000,S,Sao Paolo,1,0,3.0
0,600,3,Admin-1 capital,Sydney,,,0,Sydney,0.00000000000,,,1.00000000000,1,Australia,AUS,Australia,AUS,New South Wales,AU,,-33.92001096720,151.18517980900,4.00000000000,0,Changed feature class.,4630000,3641422,2669348,12,12,2147714.00000000000,Sydney,Sydney1,1,0,
0,600,0,Admin-0 capital,Singapore,,,0,Singapore,1.00000000000,,,1.00000000000,1,Singapore,SGP,Singapore,SGP,,SG,,1.29303346649,103.85582067800,0.00000000000,0,,5183700,3289529,3314179,13,12,1880252.00000000000,Singapore,Singapore,1,5,2.1
0,600,0,Admin-0 region capital,Hong Kong,,,0,Hong Kong,0.00000000000,,,1.00000000000,1,China,CHN,Hong Kong S.A.R.,HKG,,HK,,22.30498089500,114.18500931700,0.00000000000,0,,7206000,4551579,4549026,13,12,1819729.00000000000,Hong Kong,Hong Kong,1,0,3.0
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
0,600,0,Admin-0 region capital,Hong Kong,,,0,Hong Kong,0.00000000000,,,1.00000000000,1,China,CHN,Hong Kong S.A.R.,HKG,,HK,,nan,114.18500931700,0.00000000000,0,,7206000,4551579,4549026,13,12,1819729.00000000000,Hong Kong,Hong Kong,1,0,3.0
0,600,0,Admin-0 region capital,Hong Kong,,,0,Hong Kong,0.00000000000,,,1.00000000000,1,China,CHN,Hong Kong S.A.R.,HKG,,HK,,inf,114.18500931700,0.00000000000,0,,7206000,4551579,4549026,13,12,1819729.00000000000,Hong Kong,Hong Kong,1,0,3.0
0,600,0,Admin-0 region capital,Hong Kong,,,0,Hong Kong,0.00000000000,,,1.00000000000,1,China,CHN,Hong Kong S.A.R.,HKG,,HK,,22.30498089500,nan,0.00000000000,0,,7206000,4551579,4549026,13,12,1819729.00000000000,Hong Kong,Hong Kong,1,0,3.0
0,600,0,Admin-0 region capital,Hong Kong,,,0,Hong Kong,0.00000000000,,,1.00000000000,1,China,CHN,Hong Kong S.A.R.,HKG,,HK,,22.30498089500,inf,0.00000000000,0,,7206000,4551579,4549026,13,12,1819729.00000000000,Hong Kong,Hong Kong,1,0,3.0
1 scalerank natscale labelrank featurecla name namepar namealt diffascii nameascii adm0cap capalt capin worldcity megacity sov0name sov_a3 adm0name adm0_a3 adm1name iso_a2 note latitude longitude changed namediff diffnote pop_max pop_min pop_other rank_max rank_min geonameid meganame ls_name ls_match checkme min_zoom
2 8 10 3 Admin-0 capital Vatican City 0 Vatican City 1.00000000000 1.00000000000 0 Vatican (Holy Sea) VAT Vatican (Holy See) VAT Lazio VA 41.90001222640 12.44780838890 4.00000000000 0 Changed scale rank. 832 832 562430 2 2 6691831.00000000000 Vatican City 1 0 7.0
3 7 20 0 Admin-0 capital San Marino 0 San Marino 1.00000000000 0.00000000000 0 San Marino SMR San Marino SMR SM 43.91715008450 12.46667028670 0.00000000000 0 29579 29000 0 7 7 3168070.00000000000 San Marino 1 5 6.1
4 7 20 0 Admin-0 capital Vaduz 0 Vaduz 1.00000000000 0.00000000000 0 Liechtenstein LIE Liechtenstein LIE LI 47.13372377430 9.51666947291 0.00000000000 0 36281 5342 33009 7 5 3042030.00000000000 Vaduz 1 0 6.7
5 6 30 8 Admin-0 capital alt Lobamba 0 Lobamba 0.00000000000 1 Legislative and 0.00000000000 0 Swaziland SWZ Swaziland SWZ Manzini SZ -26.46666746140 31.19999710970 4.00000000000 0 Changed scale rank. 9782 4557 0 5 4 935048.00000000000 Lobamba 1 5 6.0
6 6 30 8 Admin-0 capital Luxembourg 0 Luxembourg 1.00000000000 0.00000000000 0 Luxembourg LUX Luxembourg LUX Luxembourg LU 49.61166037910 6.13000280623 4.00000000000 0 Changed scale rank. 107260 76684 106219 9 8 2960316.00000000000 Luxembourg 1 0 6.0
7 6 30 0 Admin-0 capital Palikir 0 Palikir 1.00000000000 0.00000000000 0 Federated States of Micronesia FSM Federated States of Micronesia FSM FM 6.91664369601 158.14997432400 4.00000000000 0 Changed scale rank. 4645 4645 0 4 4 2081986.00000000000 Palikir 1 5 6.0
8 6 30 0 Admin-0 capital Majuro 0 Majuro 1.00000000000 0.00000000000 0 Marshall Islands MHL Marshall Islands MHL MH 7.10300431122 171.38000017600 4.00000000000 0 Changed scale rank. 25400 20500 0 7 7 2113779.00000000000 Majuro 1 5 6.0
9 6 30 0 Admin-0 capital Funafuti 0 Funafuti 1.00000000000 0.00000000000 0 Tuvalu TUV Tuvalu TUV TV -8.51665199904 179.21664709400 4.00000000000 0 Population from GeoNames. Changed scale rank. 4749 4749 0 4 4 2110394.00000000000 Funafuti 0 5 6.0
10 6 30 0 Admin-0 capital Melekeok 0 Melekeok 1.00000000000 0.00000000000 0 Palau PLW Palau PLW PW 7.48739617298 134.62654846700 4.00000000000 0 Location adjusted. Changed scale rank. 7026 7026 0 5 5 1559804.00000000000 Melekeok 1 5 6.0
11 6 30 0 Admin-0 capital alt Bir Lehlou 0 Bir Lehlou 0.00000000000 1 Claimed as inte 0.00000000000 0 Western Sahara SAH Western Sahara SAH EH 26.11916668600 -9.65252221825 4.00000000000 1 Added place. 500 200 0 2 1 -1.00000000000 2 0 6.0
12 6 30 0 Admin-0 capital Monaco 0 Monaco 1.00000000000 0.00000000000 0 Monaco MCO Monaco MCO MC 43.73964568790 7.40691317347 4.00000000000 0 Location adjusted. Changed scale rank. 36371 36371 102371 7 7 2993458.00000000000 Monaco 1 0 5.1
13 6 30 0 Admin-0 capital Tarawa 0 Tarawa 1.00000000000 0.00000000000 0 Kiribati KIR Kiribati KIR KI 1.33818750562 173.01757082900 4.00000000000 0 Location adjusted. Changed scale rank. 28802 22534 0 7 7 2110079.00000000000 Tarawa 1 5 6.0
14 6 30 0 Admin-0 capital Moroni 0 Moroni 1.00000000000 0.00000000000 0 Comoros COM Comoros COM KM -11.70415769570 43.24024409870 4.00000000000 0 Changed scale rank. 128698 42872 0 9 7 921772.00000000000 Moroni 1 5 6.0
15 6 30 0 Admin-0 capital Andorra 0 Andorra 1.00000000000 0.00000000000 0 Andorra AND Andorra AND AD 42.50000144350 1.51648596051 4.00000000000 0 Changed scale rank. 53998 22256 53371 8 7 3130067.00000000000 Andorra 1 5 6.0
16 4 50 8 Admin-0 capital Port-of-Spain 0 Port-of-Spain 1.00000000000 0.00000000000 0 Trinidad and Tobago TTO Trinidad and Tobago TTO Port of Spain TT 10.65199708960 -61.51703088540 4.00000000000 0 Changed scale rank. 294934 49031 419082 10 7 3573890.00000000000 Port-of-Spain 1 5 5.1
17 4 50 0 Admin-0 capital Kigali 0 Kigali 1.00000000000 0.00000000000 1 Rwanda RWA Rwanda RWA Kigali City RW -1.95359006868 30.06053177770 4.00000000000 0 Changed scale rank. 860000 745261 1152904 11 11 202061.00000000000 Kigali Kigali 1 0 5.1
18 4 50 8 Admin-0 capital Mbabane 0 Mbabane 1.00000000000 Administrative 0.00000000000 0 Swaziland SWZ Swaziland SWZ Hhohho SZ -26.31665077840 31.13333451210 4.00000000000 0 Changed scale rank. 90138 76218 89979 8 8 934985.00000000000 Mbabane 1 0 5.6
19 4 50 5 Admin-0 capital Juba 0 Juba 0.00000000000 0.00000000000 0 South Sudan SSD South Sudan SSD Central Equatoria SS 4.82997519828 31.58002559280 20.00000000000 0 Changed country. 111975 111975 111975 9 9 373303.00000000000 Juba 1 0 5.1
20 4 50 8 Admin-0 capital alt The Hague 0 The Hague 0.00000000000 1 Official, legis 0.00000000000 0 Kingdom of the Netherlands NLD Netherlands NLD Zuid-Holland NL 52.08003684400 4.26996130231 0.00000000000 0 1406000 501725 688599 12 11 2747373.00000000000 The Hague 1 0 5.6
21 4 50 8 Admin-0 capital Ljubljana 0 Ljubljana 1.00000000000 0.00000000000 0 Slovenia SVN Slovenia SVN Osrednjeslovenska SI 46.05528830880 14.51496903350 4.00000000000 0 Changed scale rank. 314807 255115 256316 10 10 3196359.00000000000 Ljubljana 1 0 5.6
22 4 50 7 Admin-0 capital Bratislava 0 Bratislava 1.00000000000 0.00000000000 0 Slovakia SVK Slovakia SVK Bratislavský SK 48.15001833000 17.11698075220 4.00000000000 0 Changed scale rank. 423737 373687 361489 10 10 3060972.00000000000 Bratislava 1 0 5.1
23 4 50 8 Admin-0 capital Doha 0 Doha 1.00000000000 0.00000000000 0 Qatar QAT Qatar QAT Ad Dawhah QA 25.28655600890 51.53296789430 4.00000000000 0 Location adjusted. Changed scale rank. 1450000 731310 0 12 11 290030.00000000000 Doha 1 5 5.6
24 4 50 8 Admin-0 capital Podgorica 0 Podgorica 1.00000000000 0.00000000000 0 Montenegro MNE Montenegro MNE Podgorica ME 42.46597251290 19.26630692410 4.00000000000 0 Location adjusted. Changed scale rank. 145850 136473 0 9 9 3193044.00000000000 Podgorica 1 0 5.6
25 4 50 6 Admin-0 capital alt Sri Jawewardenepura Kotte 0 Sri Jawewardenepura Kotte 0.00000000000 1 Legislative cap 0.00000000000 0 Sri Lanka LKA Sri Lanka LKA Colombo LK 6.90000388481 79.94999304090 4.00000000000 1 Name changed. 115826 115826 2456292 9 9 1238992.00000000000 Kotte 1 0 5.6
26 4 50 5 Admin-0 capital alt Baguio City 0 Baguio City 0.00000000000 1 0.00000000000 0 Philippines PHL Philippines PHL Benguet PH 16.42999066060 120.56994258500 40.00000000000 0 Changed scale rank. 447824 272714 164877 10 10 1728930.00000000000 Baguio City 1 0 5.6
27 4 50 5 Admin-0 capital alt Dodoma 0 Dodoma 0.00000000000 1 Offical capital 0.00000000000 0 United Republic of Tanzania TZA Tanzania TZA Dodoma TZ -6.18330605177 35.75000362010 4.00000000000 0 Location adjusted. 218269 180541 0 10 9 160196.00000000000 Dodoma 1 0 5.6
28 4 50 7 Admin-0 capital Bern 0 Bern 1.00000000000 0.00000000000 0 Switzerland CHE Switzerland CHE Bern CH 46.91668275870 7.46697546248 4.00000000000 0 Changed scale rank. 275329 121631 267814 10 9 2661552.00000000000 Bern 1 0 5.6
29 4 50 5 Admin-0 capital alt Laayoune 0 Laayoune 0.00000000000 1 Claimed as capi 0.00000000000 0 Morocco MAR Morocco MAR Laâyoune - Boujdour - Sakia El Hamra MA 27.14998231910 -13.20000594220 0.00000000000 0 188084 176365 176365 9 9 2462881.00000000000 Laayoune 1 0 5.6
30 4 50 8 Admin-0 capital Pristina 0 Pristina 1.00000000000 0.00000000000 0 Kosovo KOS Kosovo KOS Pristina -99 42.66670961410 21.16598425160 4.00000000000 0 Changed scale rank. 465186 198214 261783 10 9 786714.00000000000 Pristina 1 0 5.6
31 4 50 8 Admin-0 capital Roseau 0 Roseau 1.00000000000 0.00000000000 0 Dominica DMA Dominica DMA Saint George DM 15.30101564430 -61.38701298180 4.00000000000 0 Changed scale rank. 23336 16571 23336 7 6 3575635.00000000000 Roseau 1 5 5.1
32 4 50 8 Admin-0 capital Djibouti 0 Djibouti 1.00000000000 0.00000000000 0 Djibouti DJI Djibouti DJI Djibouti DJ 11.59501446430 43.14800166710 4.00000000000 0 Changed scale rank. 923000 604013 335001 11 11 223817.00000000000 Djibouti 1 0 5.6
33 4 50 6 Admin-0 capital alt Putrajaya 0 Putrajaya 0.00000000000 1 Administrative 0.00000000000 0 Malaysia MYS Malaysia MYS Selangor MY 2.91401979462 101.70194698000 0.00000000000 0 67964 50000 956431 8 7 6697380.00000000000 Putrajaya 1 5 5.6
34 4 50 2 Admin-0 capital alt Kyoto 0 Kyoto 0.00000000000 1 Official capita 0.00000000000 1 Japan JPN Japan JPN Kyoto JP 35.02999228820 135.74999792400 0.00000000000 0 1805000 1459640 1827367 12 12 1857910.00000000000 Kyoto Kyoto 1 0 5.1
35 4 50 8 Admin-0 capital Banjul 0 Banjul 1.00000000000 0.00000000000 0 Gambia, The GMB The Gambia GMB Banjul GM 13.45387646030 -16.59170148920 4.00000000000 0 Location adjusted. Changed scale rank. 43094 34589 581300 7 7 2413876.00000000000 Banjul 1 0 5.6
36 4 50 8 Admin-0 capital Skopje 0 Skopje 1.00000000000 0.00000000000 0 Macedonia MKD Macedonia MKD Centar MK 42.00000612290 21.43346146510 4.00000000000 0 Changed scale rank. 494087 474889 491890 10 10 785842.00000000000 Skopje 1 5 5.6
37 4 50 8 Admin-0 capital Bridgetown 0 Bridgetown 1.00000000000 0.00000000000 0 Barbados BRB Barbados BRB Saint Michael BB 13.10200258280 -59.61652673510 4.00000000000 0 Changed scale rank. 191152 96578 191814 9 8 2075807.00000000000 Bridgetown 1 5 5.6
38 4 50 8 Admin-0 capital alt Porto-Novo 0 Porto-Novo 0.00000000000 1 Official capita 0.00000000000 0 Benin BEN Benin BEN Ouémé BJ 6.48331097302 2.61662552757 0.00000000000 0 300000 234168 806945 10 10 2392087.00000000000 Porto-Novo 1 0 5.6
39 4 50 8 Admin-0 capital Bujumbura 0 Bujumbura 1.00000000000 0.00000000000 0 Burundi BDI Burundi BDI Bujumbura Mairie BI -3.37608722037 29.36000606150 4.00000000000 0 Changed scale rank. 331700 331700 1208361 10 10 425378.00000000000 Bujumbura 1 0 5.6
40 4 50 0 Admin-0 capital Kingstown 0 Kingstown 1.00000000000 0.00000000000 0 Saint Vincent and the Grenadines VCT Saint Vincent and the Grenadines VCT VC 13.14827882790 -61.21206242030 4.00000000000 0 Location adjusted. Changed scale rank. 49485 24518 0 7 7 4359981.00000000000 Kingstown 1 5 5.1
41 4 50 0 Admin-0 capital Castries 0 Castries 1.00000000000 0.00000000000 0 Saint Lucia LCA Saint Lucia LCA LC 14.00197348930 -61.00000818040 4.00000000000 0 Changed scale rank. 37963 10634 0 7 6 3028258.00000000000 Castries 1 5 5.6
42 4 50 0 Admin-0 capital Basseterre 0 Basseterre 1.00000000000 0.00000000000 0 Saint Kitts and Nevis KNA Saint Kitts and Nevis KNA KN 17.30203045550 -62.71700931970 4.00000000000 0 Changed scale rank. 21887 15500 21887 7 6 3575551.00000000000 Basseterre 1 5 5.6
43 4 50 0 Admin-0 capital Port Louis 0 Port Louis 1.00000000000 0.00000000000 0 Mauritius MUS Mauritius MUS MU -20.16663857140 57.49999385460 4.00000000000 0 Changed scale rank. 595491 148416 304613 11 9 934154.00000000000 Port Louis 1 5 5.6
44 4 50 0 Admin-0 capital Saint George's 0 Saint George's 1.00000000000 0.00000000000 0 Grenada GRD Grenada GRD GD 12.05263340170 -61.74164322610 4.00000000000 0 Changed scale rank. 33734 27343 27343 7 7 3579925.00000000000 Saint Georgee۪s 1 5 5.1
45 4 50 0 Admin-0 capital Manama 0 Manama 1.00000000000 0.00000000000 0 Bahrain BHR Bahrain BHR BH 26.23613629050 50.58305171590 4.00000000000 0 Changed scale rank. 563920 157474 563666 11 9 290340.00000000000 Manama 1 5 5.6
46 4 50 0 Admin-0 capital Saint John's 0 Saint John's 1.00000000000 0.00000000000 0 Antigua and Barbuda ATG Antigua and Barbuda ATG AG 17.11803651830 -61.85003381510 4.00000000000 0 Changed scale rank. 35499 24226 0 7 7 3576022.00000000000 Saint John's 1 5 5.1
47 3 110 8 Admin-0 capital Montevideo 0 Montevideo 1.00000000000 0.00000000000 1 Uruguay URY Uruguay URY Montevideo UY -34.85804156620 -56.17105228840 0.00000000000 0 1513000 5324 1276128 12 5 5038018.00000000000 Montevideo Montevideo 1 0 4.0
48 3 110 8 Admin-0 capital Lomé Lome 0 Lome 1.00000000000 0.00000000000 1 Togo TGO Togo TGO Maritime TG 6.13193707166 1.22275711936 0.00000000000 0 1452000 749700 1256715 12 11 2365267.00000000000 Lomi Lome 1 0 5.0
49 3 110 7 Admin-0 capital Tunis 0 Tunis 1.00000000000 0.00000000000 0 Tunisia TUN Tunisia TUN Tunis TN 36.80277813620 10.17967809920 0.00000000000 0 2412500 728453 1675117 12 11 2464470.00000000000 Tunis 1 0 5.0
50 3 110 8 Admin-0 capital Abu Dhabi 0 Abu Dhabi 1.00000000000 0.00000000000 0 United Arab Emirates ARE United Arab Emirates ARE Abu Dhabi AE 24.46668357240 54.36659338260 0.00000000000 0 603492 560230 560230 11 11 292968.00000000000 Abu Dhabi 1 0 5.0
51 3 110 8 Admin-0 capital Ashgabat 0 Ashgabat 1.00000000000 0.00000000000 0 Turkmenistan TKM Turkmenistan TKM Ahal TM 37.94999493310 58.38329911180 0.00000000000 0 727700 577982 556048 11 11 162183.00000000000 Ashgabat 1 0 5.0
52 3 110 6 Admin-0 capital Lusaka 0 Lusaka 1.00000000000 0.00000000000 1 Zambia ZMB Zambia ZMB Lusaka ZM -15.41664426790 28.28332759470 0.00000000000 0 1328000 1267440 1240558 12 12 909137.00000000000 Lusaka Lusaka 1 0 4.0
53 3 110 6 Admin-0 capital Harare 0 Harare 1.00000000000 0.00000000000 1 Zimbabwe ZWE Zimbabwe ZWE Harare ZW -17.81778969440 31.04470943070 0.00000000000 0 1572000 1542813 1831877 12 12 890299.00000000000 Harare Harare 1 0 4.0
54 3 110 8 Admin-0 capital Dili 0 Dili 1.00000000000 0.00000000000 0 East Timor TLS East Timor TLS Dili TL -8.55938840855 125.57945593200 0.00000000000 0 234331 193563 55154 10 9 1645457.00000000000 Dili 1 0 5.0
55 3 110 8 Admin-0 capital Port Vila 0 Port Vila 1.00000000000 0.00000000000 0 Vanuatu VUT Vanuatu VUT Shefa VU -17.73335040400 168.31664058400 0.00000000000 0 44040 35901 7702 7 7 2135171.00000000000 Port-Vila 1 0 4.0
56 3 110 8 Admin-0 capital Tegucigalpa 0 Tegucigalpa 1.00000000000 0.00000000000 1 Honduras HND Honduras HND Francisco Morazán HN 14.10204490050 -87.21752933930 0.00000000000 0 946000 850848 1014546 11 11 3600949.00000000000 Tegucigalpa Tegucigalpa 1 0 5.0
57 3 110 8 Admin-0 capital Georgetown 0 Georgetown 1.00000000000 0.00000000000 0 Guyana GUY Guyana GUY East Berbice-Corentyne GY 6.80197369275 -58.16702864750 0.00000000000 0 264350 235017 264350 10 10 3378644.00000000000 Georgetown1 1 5 4.0
58 3 110 8 Admin-0 capital Reykjavík 1 Reykjavik 1.00000000000 0.00000000000 0 Iceland ISL Iceland ISL Suðurnes IS 64.15002361970 -21.95001448720 0.00000000000 0 166212 113906 160116 9 9 3413829.00000000000 Reykjavik 1 0 3.7
59 3 110 8 Admin-0 capital Port-au-Prince 0 Port-au-Prince 1.00000000000 0.00000000000 1 Haiti HTI Haiti HTI Ouest HT 18.54102459610 -72.33603458830 0.00000000000 0 1998000 1234742 2385397 12 12 3718426.00000000000 Port-au-Prince Port-au-Prince 1 0 5.0
60 3 110 5 Admin-0 capital Kampala 0 Kampala 1.00000000000 0.00000000000 1 Uganda UGA Uganda UGA Kampala UG 0.31665895477 32.58332352570 0.00000000000 0 1420000 1353189 2153702 12 12 232422.00000000000 Kampala Kampala 1 0 5.0
61 3 110 8 Admin-0 capital Paramaribo 0 Paramaribo 1.00000000000 0.00000000000 0 Suriname SUR Suriname SUR Paramaribo SR 5.83503012992 -55.16703088540 0.00000000000 0 254169 223757 248161 10 10 3383330.00000000000 Paramaribo 1 5 5.0
62 3 110 6 Admin-0 capital Niamey 0 Niamey 1.00000000000 0.00000000000 1 Niger NER Niger NER Niamey NE 13.51670595190 2.11665604514 0.00000000000 0 915000 742791 715325 11 11 2440485.00000000000 Niamey Niamey 1 0 5.0
63 3 110 8 Admin-0 capital Dushanbe 0 Dushanbe 1.00000000000 0.00000000000 0 Tajikistan TJK Tajikistan TJK Tadzhikistan Territories TJ 38.56003521630 68.77387935270 0.00000000000 0 1086244 679400 1081361 12 11 1221874.00000000000 Dushanbe 1 0 5.0
64 3 110 7 Admin-0 capital Asunción Asuncion 1 Asuncion 1.00000000000 0.00000000000 1 Paraguay PRY Paraguay PRY Asunción PY -25.29640297570 -57.64150516930 0.00000000000 0 1870000 11693 636771 12 6 1730025.00000000000 Asuncian Asuncion 1 5 4.0
65 3 110 8 Admin-0 capital Managua 0 Managua 1.00000000000 0.00000000000 1 Nicaragua NIC Nicaragua NIC Managua NI 12.15301658010 -86.26849166030 0.00000000000 0 920000 920000 1088194 11 11 3617763.00000000000 Managua Managua 1 0 5.0
66 3 110 8 Admin-0 capital Freetown 0 Freetown 1.00000000000 0.00000000000 1 Sierra Leone SLE Sierra Leone SLE Western SL 8.47001141249 -13.23421574040 0.00000000000 0 827000 13768 1074640 11 6 2408770.00000000000 Freetown Freetown 1 0 5.0
67 3 110 2 Admin-0 capital Islamabad 0 Islamabad 1.00000000000 0.00000000000 1 Pakistan PAK Pakistan PAK F.C.T. PK 33.69999595030 73.16663447970 0.00000000000 0 780000 601600 893673 11 11 1176615.00000000000 Islamabad Islamabad 1 0 5.0
68 3 110 6 Admin-0 capital Kathmandu 0 Kathmandu 1.00000000000 0.00000000000 1 Nepal NPL Nepal NPL Bhaktapur NP 27.71669191390 85.31664221080 0.00000000000 0 895000 895000 1099610 11 11 1283240.00000000000 Kathmandu Kathmandu 1 0 5.0
69 3 110 3 Admin-0 capital Bloemfontein 0 Bloemfontein 1.00000000000 Judicial capita 0.00000000000 0 South Africa ZAF South Africa ZAF Orange Free State ZA -29.11999387740 26.22991288120 4.00000000000 0 Changed scale rank. 463064 456669 456513 10 10 1018725.00000000000 Bloemfontein 1 0 5.0
70 3 110 3 Admin-0 capital Pretoria 0 Pretoria 1.00000000000 Administrative 0.00000000000 1 South Africa ZAF South Africa ZAF Gauteng ZA -25.70692055380 28.22942907580 0.00000000000 0 1338000 1338000 1443084 12 12 964137.00000000000 Pretoria Pretoria 1 0 5.0
71 3 110 8 Admin-0 capital Port Moresby 0 Port Moresby 1.00000000000 0.00000000000 0 Papua New Guinea PNG Papua New Guinea PNG Central PG -9.46470782587 147.19250362100 0.00000000000 0 283733 251136 251304 10 10 2088122.00000000000 Port Moresby 1 0 4.0
72 3 110 8 Admin-0 capital Honiara 0 Honiara 1.00000000000 0.00000000000 0 Solomon Islands SLB Solomon Islands SLB Guadalcanal SB -9.43799429509 159.94976573400 0.00000000000 0 76328 56298 76328 8 8 2108502.00000000000 Honiara 1 0 5.0
73 3 110 8 Admin-0 capital Panama City Ciudad de Panam 0 Panama City 1.00000000000 0.00000000000 1 Panama PAN Panama PAN Panama PA 8.96801719048 -79.53303715180 0.00000000000 0 1281000 408168 939725 12 10 3703443.00000000000 Ciudad de Panam Panama City1 1 0 5.0
74 3 110 5 Admin-0 capital Rabat 0 Rabat 1.00000000000 0.00000000000 1 Morocco MAR Morocco MAR Rabat - Salé - Zemmour - Zaer MA 34.02529909160 -6.83613082013 0.00000000000 0 1705000 1655753 2029349 12 12 2538475.00000000000 Rabat Rabat 1 0 5.0
75 3 110 8 Admin-0 capital Chișinău 0 Chisinau 1.00000000000 0.00000000000 0 Moldova MDA Moldova MDA Chisinau MD 47.00502361970 28.85771113970 0.00000000000 0 688134 635994 664472 11 11 618426.00000000000 Chisinau 1 5 5.0
76 3 110 6 Admin-0 capital Maputo 0 Maputo 1.00000000000 0.00000000000 1 Mozambique MOZ Mozambique MOZ Maputo MZ -25.95527748740 32.58916296260 0.00000000000 0 1446000 1191613 1365454 12 12 1040652.00000000000 Maputo Maputo 1 0 5.0
77 3 110 8 Admin-0 capital Mogadishu Muqdisho 0 Mogadishu 1.00000000000 0.00000000000 1 Somalia SOM Somalia SOM Banaadir SO 2.06668133433 45.36667761110 0.00000000000 0 1100000 875388 849392 12 11 53654.00000000000 Muqdisho Mogadishu 1 5 4.0
78 3 110 8 Admin-0 capital Muscat 0 Muscat 1.00000000000 0.00000000000 0 Oman OMN Oman OMN Muscat OM 23.61332480770 58.59331213260 0.00000000000 0 734697 586861 586861 11 11 287286.00000000000 Muscat 1 0 5.0
79 3 110 6 Admin-0 capital Colombo 0 Colombo 1.00000000000 De facto, admin 0.00000000000 0 Sri Lanka LKA Sri Lanka LKA Colombo LK 6.93196575818 79.85775060930 0.00000000000 0 217000 217000 2490974 10 10 3465927.00000000000 Colombo 1 5 5.0
80 3 110 7 Admin-0 capital Ulaanbaatar 0 Ulaanbaatar 1.00000000000 0.00000000000 1 Mongolia MNG Mongolia MNG Ulaanbaatar MN 47.91667339990 106.91661576200 0.00000000000 0 885000 769612 765359 11 11 2028462.00000000000 Ulaanbaatar Ulaanbaatar 1 0 4.0
81 3 110 6 Admin-0 capital Windhoek 0 Windhoek 1.00000000000 0.00000000000 0 Namibia NAM Namibia NAM Khomas NA -22.57000608440 17.08354610050 0.00000000000 0 268132 262796 262796 10 10 3352136.00000000000 Windhoek 1 0 5.0
82 3 110 2 Admin-0 capital Abuja 0 Abuja 1.00000000000 Official and ad 0.00000000000 1 Nigeria NGA Nigeria NGA Federal Capital Territory NG 9.08333314914 7.53332800155 4.00000000000 0 Changed scale rank. 1576000 162135 0 12 9 2322794.00000000000 Abuja Abuja 1 5 4.0
83 3 110 8 Admin-0 capital Bissau 0 Bissau 1.00000000000 0.00000000000 0 Guinea Bissau GNB Guinea Bissau GNB Bissau GW 11.86502382300 -15.59836084130 0.00000000000 0 403339 388028 403339 10 10 2374775.00000000000 Bissau 1 0 5.0
84 3 110 8 Admin-0 capital Amman 0 Amman 1.00000000000 0.00000000000 1 Jordan JOR Jordan JOR Amman JO 31.95002524720 35.93329992550 0.00000000000 0 1060000 1060000 2633729 12 12 250441.00000000000 Amman Amman 1 0 5.0
85 3 110 8 Admin-0 capital Vilnius 0 Vilnius 1.00000000000 0.00000000000 0 Lithuania LTU Lithuania LTU Vilniaus LT 54.68336631180 25.31663529330 0.00000000000 0 542366 507029 494356 11 11 593116.00000000000 Vilnius 1 0 5.0
86 3 110 8 Admin-0 capital Riga 0 Riga 1.00000000000 0.00000000000 0 Latvia LVA Latvia LVA Riga LV 56.95002382320 24.09996537140 0.00000000000 0 742572 705033 0 11 11 456172.00000000000 Riga 1 0 4.0
87 3 110 8 Admin-0 capital Bishkek 0 Bishkek 1.00000000000 0.00000000000 1 Kyrgyzstan KGZ Kyrgyzstan KGZ Bishkek KG 42.87307944650 74.58520422250 0.00000000000 0 837000 804212 781714 11 11 1528675.00000000000 Bishkek Bishkek 1 5 5.0
88 3 110 8 Admin-0 capital Maseru 0 Maseru 1.00000000000 0.00000000000 0 Lesotho LSO Lesotho LSO Maseru LS -29.31667437870 27.48327307000 0.00000000000 0 361324 118355 356225 10 9 932505.00000000000 Maseru 1 0 5.0
89 3 110 6 Admin-0 capital Antananarivo 0 Antananarivo 1.00000000000 0.00000000000 1 Madagascar MDG Madagascar MDG Antananarivo MG -18.91663735060 47.51662390010 0.00000000000 0 1697000 1391433 1844658 12 12 1070940.00000000000 Antananarivo Antananarivo 1 0 5.0
90 3 110 7 Admin-0 capital Quito 0 Quito 1.00000000000 0.00000000000 1 Ecuador ECU Ecuador ECU Pichincha EC -0.21498818065 -78.50005110850 0.00000000000 0 1701000 1399814 1435528 12 12 3652462.00000000000 Quito Quito 1 0 4.0
91 3 110 8 Admin-0 capital San José San Jose 1 San Jose 1.00000000000 0.00000000000 1 Costa Rica CRI Costa Rica CRI San José CR 9.93501242974 -84.08405135270 0.00000000000 0 1284000 1724 1434681 12 3 3669623.00000000000 San Josi San Jose1 1 5 5.0
92 3 110 8 Admin-0 capital San Salvador 0 San Salvador 1.00000000000 0.00000000000 1 El Salvador SLV El Salvador SLV San Salvador SV 13.71000164690 -89.20304122080 0.00000000000 0 1433000 2807 2139587 12 4 1690681.00000000000 San Salvador San Salvador 1 5 5.0
93 3 110 8 Admin-0 capital Kingston 0 Kingston 1.00000000000 0.00000000000 0 Jamaica JAM Jamaica JAM Kingston JM 17.97707662380 -76.76743371370 4.00000000000 0 Location adjusted. 937700 664973 18171 11 11 3489854.00000000000 Kingston1 1 5 5.0
94 3 110 7 Admin-0 capital Ndjamena N'Djamnna 0 Ndjamena 1.00000000000 0.00000000000 1 Chad TCD Chad TCD Hadjer-Lamis TD 12.11309653620 15.04914831410 0.00000000000 0 989000 681387 686347 11 11 2427123.00000000000 N'Djam-na Ndjamena 1 0 5.0
95 3 110 8 Admin-0 capital Malabo 0 Malabo 1.00000000000 0.00000000000 0 Equatorial Guinea GNQ Equatorial Guinea GNQ Bioko Norte GQ 3.75001527803 8.78327754582 4.00000000000 0 Location adjusted. 155963 155963 0 9 9 2309527.00000000000 Malabo 1 0 5.0
96 3 110 8 Admin-0 capital Asmara 0 Asmara 1.00000000000 0.00000000000 0 Eritrea ERI Eritrea ERI Anseba ER 15.33333925270 38.93332352580 0.00000000000 0 620802 563930 587094 11 11 343300.00000000000 Asmara 1 0 5.0
97 3 110 8 Admin-0 capital Zagreb 0 Zagreb 1.00000000000 0.00000000000 0 Croatia HRV Croatia HRV Grad Zagreb HR 45.80000673330 15.99999466820 0.00000000000 0 722526 698966 690638 11 11 3186886.00000000000 Zagreb 1 0 5.0
98 3 110 8 Admin-0 capital Tallinn 0 Tallinn 1.00000000000 0.00000000000 0 Estonia EST Estonia EST Harju EE 59.43387737950 24.72804072950 0.00000000000 0 394024 340027 317949 10 10 588409.00000000000 Tallinn 1 0 5.0
99 3 110 8 Admin-0 capital Lilongwe 0 Lilongwe 1.00000000000 0.00000000000 0 Malawi MWI Malawi MWI Lilongwe MW -13.98329506550 33.78330196000 0.00000000000 0 646750 646750 1061388 11 11 927967.00000000000 Lilongwe 1 0 5.0
100 3 110 8 Admin-0 capital Guatemala Ciudad de Guatemala (Guatemala City) 0 Guatemala 1.00000000000 0.00000000000 1 Guatemala GTM Guatemala GTM Guatemala GT 14.62113466280 -90.52696557790 0.00000000000 0 1024000 994938 2391150 12 11 3598132.00000000000 Ciudad de Guatemala (Guatemala City) Guatemala 1 0 5.0
101 3 110 7 Admin-0 capital Libreville 0 Libreville 1.00000000000 0.00000000000 0 Gabon GAB Gabon GAB Estuaire GA 0.38538860972 9.45796504582 0.00000000000 0 578156 483355 483522 11 10 2399697.00000000000 Libreville 1 0 5.0
102 3 110 8 Admin-0 capital Suva 0 Suva 1.00000000000 0.00000000000 0 Fiji FJI Fiji FJI Central FJ -18.13301593140 178.44170731500 4.00000000000 0 Location adjusted. 175399 88271 0 9 8 2198148.00000000000 Suva 1 0 5.0
103 3 110 3 Admin-0 capital alt Valparaíso Valparaiso 1 Valparaiso 0.00000000000 1 Legislative cap 0.00000000000 1 Chile CHL Chile CHL Valparaíso CL -33.04776446660 -71.62101363290 4.00000000000 0 Changed scale rank. 854000 15938 130815 11 6 3445575.00000000000 Valpara so Valparaiso2 1 0 5.0
104 3 110 7 Admin-0 capital Nouakchott 0 Nouakchott 1.00000000000 0.00000000000 0 Mauritania MRT Mauritania MRT Nouakchott MR 18.08642702120 -15.97534041490 0.00000000000 0 742144 661400 742144 11 11 2377450.00000000000 Nouakchott 1 0 5.0
105 3 110 6 Admin-0 capital Bamako 0 Bamako 1.00000000000 0.00000000000 1 Mali MLI Mali MLI Bamako ML 12.65001466770 -8.00003910464 0.00000000000 0 1494000 1297281 1301407 12 12 2460596.00000000000 Bamako Bamako 1 0 4.0
106 3 110 8 Admin-0 capital Beirut Bayrut 0 Beirut 1.00000000000 0.00000000000 1 Lebanon LBN Lebanon LBN Beirut LB 33.87197511700 35.50970821000 0.00000000000 0 1846000 1712125 1661980 12 12 276781.00000000000 Bayrut Beirut 1 5 5.0
107 3 110 8 Admin-0 capital Tbilisi T'Bilisi 0 Tbilisi 1.00000000000 0.00000000000 1 Georgia GEO Georgia GEO Tbilisi GE 41.72500998850 44.79079544960 0.00000000000 0 1100000 1005257 977179 12 12 611717.00000000000 Tbilisi Tbilisi 1 0 5.0
108 3 110 6 Admin-0 capital Astana 0 Astana 1.00000000000 0.00000000000 0 Kazakhstan KAZ Kazakhstan KAZ Aqmola KZ 51.18112530430 71.42777420950 0.00000000000 0 345604 325021 317445 10 10 1526273.00000000000 Astana 1 0 4.0
109 3 110 8 Admin-0 capital Vientiane 0 Vientiane 1.00000000000 0.00000000000 0 Laos LAO Laos LAO Vientiane [prefecture] LA 17.96669272760 102.59998002000 0.00000000000 0 754000 570348 469811 11 11 1651944.00000000000 Vientiane 1 0 5.0
110 3 110 7 Admin-0 capital Brazzaville 0 Brazzaville 1.00000000000 0.00000000000 1 Congo (Brazzaville) COG Congo (Brazzaville) COG Pool CG -4.25918577181 15.28468949250 0.00000000000 0 1355000 1163890 1174778 12 12 2260535.00000000000 Brazzaville Brazzaville 1 0 5.0
111 3 110 8 Admin-0 capital Conakry 0 Conakry 1.00000000000 0.00000000000 1 Guinea GIN Guinea GIN Conakry GN 9.53152284641 -13.68023502750 0.00000000000 0 1494000 1494000 1498020 12 12 2422465.00000000000 Conakry Conakry 1 5 5.0
112 3 110 8 Admin-0 capital Yamoussoukro 0 Yamoussoukro 1.00000000000 1 Official capita 0.00000000000 0 Ivory Coast CIV Ivory Coast CIV Lacs CI 6.81838096000 -5.27550256491 4.00000000000 0 Changed scale rank. 206499 194530 206499 10 9 2279755.00000000000 Yamoussoukro 1 0 5.0
113 3 110 2 Admin-0 capital Ottawa Ottawa-Gatineau 0 Ottawa 1.00000000000 0.00000000000 1 Canada CAN Canada CAN Ontario CA 45.41669679670 -75.70001530120 0.00000000000 0 1145000 812129 872781 12 11 6094817.00000000000 Ottawa-Gatineau Ottawa 1 5 3.0
114 3 110 8 Admin-0 capital Belgrade Beograd 0 Belgrade 1.00000000000 0.00000000000 1 Republic of Serbia SRB Serbia SRB Grad Beograd RS 44.81864544580 20.46799068060 0.00000000000 0 1099000 1099000 1271541 12 12 792680.00000000000 Beograd Belgrade 1 0 5.0
115 3 110 8 Admin-0 capital Bandar Seri Begawan 0 Bandar Seri Begawan 1.00000000000 0.00000000000 0 Brunei BRN Brunei BRN Brunei and Muara BN 4.88333111462 114.93328405700 0.00000000000 0 296500 140000 222513 10 9 1820906.00000000000 Bandar Seri Begawan 1 0 5.0
116 3 110 6 Admin-0 capital Sucre 0 Sucre 1.00000000000 Official (const 0.00000000000 0 Bolivia BOL Bolivia BOL Chuquisaca BO -19.04097084670 -65.25951562670 0.00000000000 0 224838 221736 221736 10 10 3903987.00000000000 Sucre 1 0 4.7
117 3 110 8 Admin-0 capital Belmopan 0 Belmopan 1.00000000000 0.00000000000 0 Belize BLZ Belize BLZ Cayo BZ 17.25203350720 -88.76707299980 0.00000000000 0 15220 13381 15220 6 6 3582672.00000000000 Belmopan 1 0 5.0
118 3 110 7 Admin-0 capital Bangui 0 Bangui 1.00000000000 0.00000000000 0 Central African Republic CAF Central African Republic CAF Bangui CF 4.36664430635 18.55828812530 0.00000000000 0 831925 622771 782274 11 11 2389853.00000000000 Bangui 1 0 5.0
119 3 110 6 Admin-0 capital Yaounde Yaounde 0 Yaounde 1.00000000000 0.00000000000 1 Cameroon CMR Cameroon CMR Centre CM 3.86670066214 11.51665075550 0.00000000000 0 1611000 1060587 1060747 12 12 2220957.00000000000 Yaound Yaounde 1 0 5.0
120 3 110 8 Admin-0 capital Tirana 0 Tirana 1.00000000000 0.00000000000 0 Albania ALB Albania ALB Durrës AL 41.32754070950 19.81888301460 0.00000000000 0 895350 421286 517792 11 10 3183875.00000000000 Tirana 1 0 5.0
121 3 110 8 Admin-0 capital Yerevan 0 Yerevan 1.00000000000 0.00000000000 1 Armenia ARM Armenia ARM Erevan AM 40.18115073550 44.51355139040 0.00000000000 0 1102000 1093485 1154748 12 12 616052.00000000000 Yerevan Yerevan 1 5 5.0
122 3 110 8 Admin-0 capital Baku 0 Baku 1.00000000000 0.00000000000 1 Azerbaijan AZE Azerbaijan AZE Baki AZ 40.39527203270 49.86221716190 0.00000000000 0 2122300 1892000 1518801 12 12 587084.00000000000 Baku Baku 1 0 5.0
123 3 110 8 Admin-0 capital Phnom Penh Phnum Penh 0 Phnom Penh 1.00000000000 0.00000000000 1 Cambodia KHM Cambodia KHM Phnom Penh KH 11.55003012990 104.91663448000 0.00000000000 0 1466000 1466000 1604086 12 12 1821306.00000000000 Phnum Penh Phnom Penh 1 5 5.0
124 3 110 6 Admin-0 capital La Paz 0 La Paz 1.00000000000 Administrative 0.00000000000 1 Bolivia BOL Bolivia BOL La Paz BO -16.49797361370 -68.14998519050 0.00000000000 0 1590000 812799 4400 12 11 3911925.00000000000 La Paz La Paz3 1 0 4.0
125 3 110 8 Admin-0 capital Cotonou 0 Cotonou 1.00000000000 De facto, admin 0.00000000000 1 Benin BEN Benin BEN Ouémé BJ 6.40000856417 2.51999059918 0.00000000000 0 762000 690584 1060640 11 11 2394819.00000000000 Cotonou Cotonou 1 0 5.0
126 3 110 7 Admin-0 capital Sofia 0 Sofia 1.00000000000 0.00000000000 1 Bulgaria BGR Bulgaria BGR Grad Sofiya BG 42.68334942530 23.31665401070 0.00000000000 0 1185000 874827 871735 12 11 727011.00000000000 Sofia Sofia 1 0 5.0
127 3 110 6 Admin-0 capital Minsk 0 Minsk 1.00000000000 0.00000000000 1 Belarus BLR Belarus BLR Minsk BY 53.89997743640 27.56662715530 0.00000000000 0 1805000 1577138 1557919 12 12 625144.00000000000 Minsk Minsk 1 0 5.0
128 3 110 8 Admin-0 capital Thimphu 0 Thimphu 1.00000000000 0.00000000000 0 Bhutan BTN Bhutan BTN Thimphu BT 27.47298585920 89.63901403700 4.00000000000 0 Location adjusted. 98676 79185 0 8 8 1252416.00000000000 Thimphu 1 0 5.0
129 3 110 7 Admin-0 capital Gaborone 0 Gaborone 1.00000000000 0.00000000000 0 Botswana BWA Botswana BWA South-East BW -24.64631345740 25.91194779330 0.00000000000 0 208411 159243 158896 10 9 933773.00000000000 Gaborone 1 0 5.0
130 3 110 3 Admin-0 capital Canberra 0 Canberra 1.00000000000 0.00000000000 0 Australia AUS Australia AUS Australian Capital Territory AU -35.28302854540 149.12902624400 4.00000000000 0 Location adjusted. 327700 234032 0 10 10 2172517.00000000000 Canberra 1 0 4.0
131 3 110 8 Admin-0 capital Ouagadougou 0 Ouagadougou 1.00000000000 0.00000000000 1 Burkina Faso BFA Burkina Faso BFA Kadiogo BF 12.37031597790 -1.52472375630 0.00000000000 0 1149000 835457 713874 12 11 2357048.00000000000 Ouagadougou Ouagadougou 1 0 5.0
132 3 110 8 Admin-0 capital Sarajevo 0 Sarajevo 1.00000000000 0.00000000000 0 Bosnia and Herzegovina BIH Bosnia and Herzegovina BIH Sarajevo BA 43.85002239900 18.38300166700 0.00000000000 0 696731 628902 627065 11 11 3191281.00000000000 Sarajevo 1 5 5.0
133 3 110 5 Admin-0 capital Naypyidaw Nay Pyi Taw 0 Naypyidaw 1.00000000000 0.00000000000 1 Myanmar MMR Myanmar MMR Mandalay MM 19.76655702610 96.11861852920 4.00000000000 0 Location adjusted. 930000 194824 0 11 9 6611854.00000000000 Nay Pyi Taw Naypyidaw 1 0 5.0
134 3 110 0 Admin-0 capital Nukualofa 0 Nukualofa 1.00000000000 0.00000000000 0 Tonga TON Tonga TON TO -21.13851235670 -175.22056447800 4.00000000000 0 Location adjusted. 42620 23658 42620 7 7 4032402.00000000000 Nukualofa 1 5 5.0
135 3 110 0 Admin-0 capital Hargeysa 0 Hargeysa 1.00000000000 0.00000000000 0 Somaliland SOL Somaliland SOL -99 9.56002239882 44.06531001670 4.00000000000 0 Changed scale rank. 477876 247018 247018 10 10 57289.00000000000 Hargeysa 1 5 5.0
136 3 110 0 Admin-0 capital Victoria 0 Victoria 1.00000000000 0.00000000000 0 Seychelles SYC Seychelles SYC SC -4.61663165397 55.44998978560 0.00000000000 0 33576 22881 33737 7 7 241131.00000000000 Victoria4 1 5 5.0
137 3 110 0 Admin-0 capital São Tomé 1 Sao Tome 1.00000000000 0.00000000000 0 Sao Tome and Principe STP Sao Tome and Principe STP ST 0.33340211883 6.73332515323 0.00000000000 0 88219 56166 88219 8 8 3388092.00000000000 Sao Tome 1 5 5.0
138 3 110 0 Admin-0 capital Apia 0 Apia 1.00000000000 0.00000000000 0 Samoa WSM Samoa WSM WS -13.84154504240 -171.73864160900 4.00000000000 0 Location adjusted. 61916 37708 0 8 7 3689793.00000000000 Apia 1 5 5.0
139 3 110 0 Admin-0 capital Valletta 0 Valletta 1.00000000000 0.00000000000 0 Malta MLT Malta MLT MT 35.89973248190 14.51471065130 0.00000000000 0 368250 6966 336174 10 5 2562305.00000000000 Valletta 1 5 5.0
140 3 110 0 Admin-0 capital Malé 1 Male 1.00000000000 0.00000000000 0 Maldives MDV Maldives MDV MV 4.16670818981 73.49994746800 0.00000000000 0 112927 103693 0 9 9 3174186.00000000000 Male 1 5 5.0
141 3 110 0 Admin-0 capital Jerusalem 0 Jerusalem 1.00000000000 De facto capita 0.00000000000 0 Israel IS1 Israel ISR Jerusalem IL 31.77840781560 35.20662593460 0.00000000000 0 1029300 801000 1072567 12 11 281184.00000000000 Jerusalem 1 0 3.7
142 3 110 0 Admin-0 capital Praia 0 Praia 1.00000000000 0.00000000000 0 Cape Verde CPV Cape Verde CPV CV 14.91669801730 -23.51668888500 0.00000000000 0 113364 88859 89205 9 8 3374333.00000000000 Praia 1 5 5.0
143 3 110 0 Admin-0 capital Nassau 0 Nassau 1.00000000000 0.00000000000 0 Bahamas, The BHS The Bahamas BHS BS 25.08339011540 -77.35004378430 0.00000000000 0 227940 160966 0 10 9 3571824.00000000000 Nassau 1 5 5.0
144 3 110 0 Admin-0 capital Nicosia 0 Nicosia 1.00000000000 Capital of both 0.00000000000 0 Cyprus CYP Cyprus CYP CY 35.16667645170 33.36663488640 0.00000000000 0 224300 200452 222985 10 10 146268.00000000000 Nicosia 1 5 5.0
145 3 110 8 Admin-0 capital Wellington 0 Wellington 1.00000000000 0.00000000000 0 New Zealand NZL New Zealand NZL Manawatu-Wanganui NZ Wellington metropolitan area -41.29998785369 174.78326585928 0.00000000000 0 393400 393400 0 10 9 2144168.00000000000 Wellington 1 0 4.0
146 2 200 5 Admin-0 capital Hanoi H 0 Hanoi 1.00000000000 0.00000000000 1 Vietnam VNM Vietnam VNM Thái Nguyên VN 21.03332724910 105.85001420000 5.00000000000 0 Changed scale rank. 4378000 1431270 5466347 12 12 1581130.00000000000 Hh Noi Hanoi 1 0 4.0
147 2 200 5 Admin-0 capital Ankara 0 Ankara 1.00000000000 0.00000000000 1 Turkey TUR Turkey TUR Ankara TR 39.92723858550 32.86439164100 5.00000000000 0 Changed scale rank. 3716000 3307379 3267576 12 12 323786.00000000000 Ankara Ankara 1 0 4.0
148 2 200 6 Admin-0 capital Budapest 0 Budapest 1.00000000000 1.00000000000 1 Hungary HUN Hungary HUN Budapest HU 47.50000632640 19.08332067740 4.00000000000 0 Changed scale rank. 1679000 1679000 1718895 12 12 3054643.00000000000 Budapest Budapest 1 0 4.7
149 2 200 6 Admin-0 capital Sanaa Sana'a' 0 Sanaa 1.00000000000 0.00000000000 1 Yemen YEM Yemen YEM Amanat Al Asimah YE 15.35473329570 44.20659338260 5.00000000000 0 Changed scale rank. 2008000 1835853 1742507 12 12 71137.00000000000 Sana'a' Sanaa 1 0 4.0
150 2 200 6 Admin-0 capital Bucharest Bucuresti 0 Bucharest 1.00000000000 1.00000000000 1 Romania ROU Romania ROU Bucharest RO 44.43337180490 26.09994665400 4.00000000000 0 Changed scale rank. 1942000 1742194 1636574 12 12 683506.00000000000 Bucuresti Bucharest 1 0 4.0
151 2 200 6 Admin-0 capital Damascus Dimashq 0 Damascus 1.00000000000 0.00000000000 1 Syria SYR Syria SYR Damascus SY 33.50003399560 36.29999588900 5.00000000000 0 Changed scale rank. 2466000 2466000 3344577 12 12 170654.00000000000 Dimashq Damascus 1 0 4.7
152 2 200 6 Admin-0 capital Lisbon Lisboa 0 Lisbon 1.00000000000 1.00000000000 1 Portugal PRT Portugal PRT Lisboa PT 38.72272287790 -9.14486630549 4.00000000000 0 Location adjusted. Changed scale rank. 2812000 517802 1795582 12 11 2267057.00000000000 Lisboa Lisbon 1 0 4.0
153 2 200 5 Admin-0 capital Khartoum Al-Khartum 0 Khartoum 1.00000000000 0.00000000000 1 Sudan SDN Sudan SDN Khartoum SD 15.58807822570 32.53417923860 5.00000000000 0 Changed scale rank. 4754000 1974647 2325931 12 12 379252.00000000000 Al-Khartum Khartoum 1 0 4.0
154 2 200 7 Admin-0 capital Oslo 0 Oslo 1.00000000000 1.00000000000 1 Kingdom of Norway NOR Norway NOR Oslo NO 59.91669028640 10.74997920600 4.00000000000 0 Changed scale rank. 835000 580000 701804 11 11 3143244.00000000000 Oslo Oslo 1 0 4.0
155 2 200 5 Admin-0 capital Warsaw Warszawa 0 Warsaw 1.00000000000 1.00000000000 1 Poland POL Poland POL Masovian PL 52.25000062980 20.99999955110 4.00000000000 0 Changed scale rank. 1707000 1702139 2012431 12 12 756135.00000000000 Warszawa Warsaw 1 0 4.0
156 2 200 6 Admin-0 capital Pyongyang P'yongyang 0 Pyongyang 1.00000000000 0.00000000000 1 Korea, North PRK North Korea PRK P'yongyang KP 39.01943869940 125.75469071400 5.00000000000 0 Changed scale rank. 3300000 2498797 2483216 12 12 1871859.00000000000 P'yongyang Pyongyang 1 0 4.7
157 2 200 5 Admin-0 capital Dar es Salaam 0 Dar es Salaam 1.00000000000 De facto capita 0.00000000000 1 United Republic of Tanzania TZA Tanzania TZA Dar-Es-Salaam TZ -6.80001259474 39.26834183630 5.00000000000 0 Changed scale rank. 2930000 2698652 2757835 12 12 160263.00000000000 Dar es Salaam Dar es Salaam 1 0 4.0
158 2 200 8 Admin-0 capital Dublin 0 Dublin 1.00000000000 1.00000000000 1 Ireland IRL Ireland IRL Dublin IE 53.33306113600 -6.24890568178 0.00000000000 0 1059000 968976 22478 12 11 2964574.00000000000 Dublin Dublin2 1 0 4.0
159 2 200 8 Admin-0 capital Monrovia 0 Monrovia 1.00000000000 0.00000000000 1 Liberia LBR Liberia LBR Montserrado LR 6.31055665987 -10.80475162910 0.00000000000 0 1041000 785662 806416 12 11 2274895.00000000000 Monrovia Monrovia 1 0 4.0
160 2 200 6 Admin-0 capital Kuala Lumpur 0 Kuala Lumpur 1.00000000000 Official and le 1.00000000000 1 Malaysia MYS Malaysia MYS Selangor MY 3.16666587210 101.69998327500 0.00000000000 0 1448000 1448000 2667990 12 12 1735161.00000000000 Kuala Lumpur Kuala Lumpur 1 0 4.0
161 2 200 6 Admin-0 capital Havana La Habana 0 Havana 1.00000000000 0.00000000000 1 Cuba CUB Cuba CUB Ciudad de la Habana CU 23.13195884090 -82.36418217130 5.00000000000 0 Changed scale rank. 2174000 1990917 1930305 12 12 3553478.00000000000 La Habana Havana 1 0 4.0
162 2 200 7 Admin-0 capital Prague Praha 0 Prague 1.00000000000 1.00000000000 1 Czech Republic CZE Czech Republic CZE Prague CZ 50.08333701490 14.46597977570 4.00000000000 0 Changed scale rank. 1162000 2087 1088042 12 4 4548393.00000000000 Praha Prague 1 0 4.7
163 2 200 8 Admin-0 capital Kuwait Al Kuwayt|Kuwait City 0 Kuwait 1.00000000000 0.00000000000 1 Kuwait KWT Kuwait KWT Al Kuwayt KW 29.36971763000 47.97830114620 5.00000000000 0 Changed scale rank. 2063000 60064 1682968 12 8 285787.00000000000 Al Kuwayt (Kuwait City) Kuwait 1 5 4.0
164 2 200 8 Admin-0 capital Santo Domingo 0 Santo Domingo 1.00000000000 0.00000000000 1 Dominican Republic DOM Dominican Republic DOM Distrito Nacional DO 18.47007285460 -69.90008508470 5.00000000000 0 Changed scale rank. 2154000 2873 3322037 12 4 3668373.00000000000 Santo Domingo Santo Domingo 1 5 4.0
165 2 200 6 Admin-0 capital Accra 0 Accra 1.00000000000 0.00000000000 1 Ghana GHA Ghana GHA Greater Accra GH 5.55003460583 -0.21671574035 5.00000000000 0 Changed scale rank. 2121000 1963264 2334371 12 12 2306104.00000000000 Accra Accra 1 0 4.0
166 2 200 7 Admin-0 capital Tripoli 0 Tripoli 1.00000000000 0.00000000000 1 Libya LBY Libya LBY Tajura' wa an Nawahi al Arba LY 32.89250001940 13.18001175810 5.00000000000 0 Changed scale rank. 2189000 229398 1149981 12 10 -1.00000000000 Tarabulus Tripoli1 1 0 4.0
167 2 200 8 Admin-0 capital alt Tel Aviv-Yafo Tel Aviv-Jaffa 0 Tel Aviv-Yafo 0.00000000000 1 While Jerulsale 0.00000000000 1 Israel IS1 Israel ISR Tel Aviv IL 32.07999147440 34.77001175820 4.00000000000 0 Changed scale rank. 3112000 378358 2306851 12 10 293394.00000000000 Tel Aviv-Yafo Tel Aviv-Yafo 1 0 4.0
168 2 200 7 Admin-0 capital Helsinki 0 Helsinki 1.00000000000 1.00000000000 1 Finland FIN Finland FIN Southern Finland FI 60.17556337400 24.93412634150 4.00000000000 0 Changed scale rank. 1115000 558457 762958 12 11 658225.00000000000 Helsinki Helsinki 1 0 4.0
169 2 200 8 Admin-0 capital København Copenhagen 1 Kobenhavn 1.00000000000 1.00000000000 1 Denmark DNK Denmark DNK Hovedstaden DK 55.67856419040 12.56348574730 0.00000000000 0 1085000 1085000 1038288 12 12 2618425.00000000000 K Copenhagen 1 0 4.0
170 2 200 8 Admin-0 capital Abidjan 0 Abidjan 1.00000000000 De facto, admin 0.00000000000 1 Ivory Coast CIV Ivory Coast CIV Lagunes CI 5.31999696749 -4.04004825989 5.00000000000 0 Changed scale rank. 3802000 3190395 3181637 12 12 2293538.00000000000 Abidjan Abidjan 1 0 4.0
171 2 200 1 Admin-0 capital Brasília Brasilia 0 Brasilia 1.00000000000 0.00000000000 1 Brazil BRA Brazil BRA Distrito Federal BR -15.78334023150 -47.91605228840 5.00000000000 0 Changed scale rank. 3716996 2562963 1772679 12 12 3469058.00000000000 Brasglia Brasilia 1 0 3.7
172 2 200 8 Admin-0 capital Brussels Bruxelles-Brussel 0 Brussels 1.00000000000 1.00000000000 1 Belgium BEL Belgium BEL Brussels BE 50.83331707670 4.33331660830 0.00000000000 0 1743000 1019022 1490164 12 12 2800866.00000000000 Bruxelles-Brussel Brussels 1 5 4.7
173 2 200 2 Admin-0 capital Dhaka 0 Dhaka 1.00000000000 0.00000000000 1 Bangladesh BGD Bangladesh BGD Dhaka BD 23.72305971170 90.40857946670 5.00000000000 0 Changed scale rank. 12797394 7000940 14995538 14 13 1185241.00000000000 Dhaka Dhaka 1 0 4.0
174 2 200 6 Admin-0 capital Luanda 0 Luanda 1.00000000000 0.00000000000 1 Angola AGO Angola AGO Luanda AO -8.83828611363 13.23442704130 5.00000000000 0 Changed scale rank. 5172900 1951272 1951272 13 12 2240449.00000000000 Luanda Luanda 1 0 4.0
175 2 200 5 Admin-0 capital Algiers El Djazacr 0 Algiers 1.00000000000 0.00000000000 1 Algeria DZA Algeria DZA Alger DZ 36.76306479800 3.05055252952 5.00000000000 0 Changed scale rank. 3354000 1977663 3332619 12 12 2507480.00000000000 El Djazasr Algiers 1 5 4.0
176 2 200 5 Admin-0 capital Rangoon Yangon 0 Rangoon 0.00000000000 Former capital 0.00000000000 1 Myanmar MMR Myanmar MMR Yangon MM 16.78335410460 96.16667761130 5.00000000000 0 Changed scale rank. 4088000 3301820 3124090 12 12 1298824.00000000000 Yangon Rangoon 1 0 4.0
177 1 300 1 Populated place San Francisco San Francisco-Oakland 0 San Francisco 0.00000000000 1.00000000000 1 United States USA United States of America USA California US 37.74000775050 -122.45997766300 0.00000000000 0 3450000 732072 27400 12 11 5391959.00000000000 San Francisco-Oakland San Francisco1 1 0 2.7
178 1 300 1 Admin-1 capital Denver Denver-Aurora 0 Denver 0.00000000000 0.00000000000 1 United States USA United States of America USA Colorado US 39.73918804840 -104.98401595200 5.00000000000 0 Changed scale rank. 2313000 1548599 1521278 12 12 5419384.00000000000 Denver-Aurora Denver 1 0 3.7
179 1 300 1 Populated place Houston 0 Houston 0.00000000000 0.00000000000 1 United States USA United States of America USA Texas US 29.81997438460 -95.33997929050 5.00000000000 0 Changed scale rank. 4459000 3647574 3607616 12 12 4699066.00000000000 Houston Houston 1 0 3.0
180 1 300 1 Populated place Miami 0 Miami 0.00000000000 1.00000000000 1 United States USA United States of America USA Florida US 25.78761069640 -80.22410608080 0.00000000000 0 5585000 382894 1037811 13 10 4164138.00000000000 Miami Miami 1 0 2.1
181 1 300 1 Admin-1 capital Atlanta 0 Atlanta 0.00000000000 1.00000000000 1 United States USA United States of America USA Georgia US 33.83001385400 -84.39994938330 0.00000000000 0 4506000 422908 2874096 12 10 4180439.00000000000 Atlanta Atlanta 1 0 3.0
182 1 300 1 Populated place Chicago 0 Chicago 0.00000000000 1.00000000000 1 United States USA United States of America USA Illinois US 41.82999066070 -87.75005497410 0.00000000000 0 8990000 2841952 3635101 13 12 4887398.00000000000 Chicago Chicago 1 0 3.0
183 1 300 6 Admin-0 capital Caracas 0 Caracas 1.00000000000 1.00000000000 1 Venezuela VEN Venezuela VEN Distrito Capital VE 10.50099855440 -66.91703719240 4.00000000000 0 Changed scale rank. 2985000 1815679 2764555 12 12 3646738.00000000000 Caracas Caracas 1 0 3.0
184 1 300 5 Admin-0 capital Kiev Kyiv 0 Kiev 1.00000000000 0.00000000000 1 Ukraine UKR Ukraine UKR Kiev UA 50.43336732900 30.51662796910 5.00000000000 0 Changed scale rank. 2709000 1662508 1611692 12 12 703448.00000000000 Kyiv Kiev 1 0 3.7
185 1 300 8 Admin-1 capital Dubai Dubayy 0 Dubai 0.00000000000 1.00000000000 1 United Arab Emirates ARE United Arab Emirates ARE Dubay AE 25.22999615380 55.27997432340 1.00000000000 1 Name changed. 1379000 1137347 1166878 12 12 292223.00000000000 Dubayy Dubayy 1 0 3.7
186 1 300 6 Admin-0 capital Tashkent 0 Tashkent 1.00000000000 0.00000000000 1 Uzbekistan UZB Uzbekistan UZB Tashkent UZ 41.31170188300 69.29493281950 5.00000000000 0 Changed scale rank. 2184000 1978028 2806287 12 12 1512569.00000000000 Tashkent Tashkent 1 0 3.7
187 1 300 3 Admin-0 capital Madrid 0 Madrid 1.00000000000 1.00000000000 1 Kingdom of Spain ESP Spain ESP Comunidad de Madrid ES 40.40002626450 -3.68335168600 0.00000000000 0 5567000 50437 3673427 13 8 3117735.00000000000 Madrid Madrid 1 0 3.0
188 1 300 7 Admin-1 capital Geneva 0 Geneva 0.00000000000 1.00000000000 0 Switzerland CHE Switzerland CHE Genève CH 46.21000754710 6.14002803409 4.00000000000 0 Changed scale rank. 1240000 192385 508284 12 9 2660646.00000000000 Geneva 1 0 3.7
189 1 300 7 Admin-0 capital Stockholm 0 Stockholm 1.00000000000 1.00000000000 1 Sweden SWE Sweden SWE Stockholm SE 59.35075995430 18.09733473280 4.00000000000 0 Location adjusted. 1264000 1253309 0 12 12 2673730.00000000000 Stockholm Stockholm 1 0 3.0
190 1 300 5 Admin-0 capital Bangkok Krung Thep 0 Bangkok 1.00000000000 1.00000000000 1 Thailand THA Thailand THA Bangkok Metropolis TH 13.74999920550 100.51664465200 0.00000000000 0 6704000 5104476 5082758 13 13 1609350.00000000000 Krung Thep Bangkok 1 0 3.0
191 1 300 5 Admin-0 capital Lima 0 Lima 1.00000000000 0.00000000000 1 Peru PER Peru PER Lima PE -12.04801267610 -77.05006209480 5.00000000000 0 Changed scale rank. 8012000 6758234 6068380 13 13 3936456.00000000000 Lima Lima2 1 0 3.0
192 1 300 8 Admin-0 capital Dakar 0 Dakar 1.00000000000 0.00000000000 1 Senegal SEN Senegal SEN Dakar SN 14.71583172500 -17.47313012840 5.00000000000 0 Changed scale rank. 2604000 2476400 2470140 12 12 2253354.00000000000 Dakar Dakar 1 0 3.0
193 1 300 3 Admin-0 capital Johannesburg 0 Johannesburg 0.00000000000 1.00000000000 1 South Africa ZAF South Africa ZAF Gauteng ZA -26.17004474000 28.03000972360 4.00000000000 0 Changed feature class. 3435000 2026469 3852246 12 12 993800.00000000000 Johannesburg Johannesburg 1 0 3.0
194 1 300 8 Admin-0 capital Amsterdam 0 Amsterdam 1.00000000000 De facto capita 1.00000000000 1 Kingdom of the Netherlands NLD Netherlands NLD Noord-Holland NL 52.34996868810 4.91664017601 0.00000000000 0 1031000 741636 962488 12 11 2759794.00000000000 Amsterdam Amsterdam 1 0 3.7
195 1 300 5 Admin-1 capital Casablanca Dar-el-Beida 0 Casablanca 0.00000000000 1.00000000000 1 Morocco MAR Morocco MAR Grand Casablanca MA 33.59997621560 -7.61636743309 4.00000000000 0 Changed scale rank. 3181000 3144909 3718797 12 12 2553604.00000000000 Dar-el-Beida Casablanca 1 0 3.7
196 1 300 3 Admin-0 capital Seoul 0 Seoul 1.00000000000 1.00000000000 1 Korea, South KOR South Korea KOR Seoul KR 37.56634909980 126.99973099700 0.00000000000 0 9796000 9796000 12018058 13 13 1835848.00000000000 Seoul Seoul 1 0 3.0
197 1 300 5 Admin-0 capital Manila 0 Manila 1.00000000000 Official, de fa 1.00000000000 1 Philippines PHL Philippines PHL Metropolitan Manila PH 14.60415895480 120.98221716200 0.00000000000 0 11100000 3077575 2381280 14 12 1701668.00000000000 Manila Manila 1 0 2.7
198 1 300 2 Admin-1 capital Monterrey 0 Monterrey 0.00000000000 0.00000000000 1 Mexico MEX Mexico MEX Nuevo León MX 25.66999513650 -100.32998478400 5.00000000000 0 Changed scale rank. 3712000 1122874 3225636 12 12 3995465.00000000000 Monterrey Monterrey 1 0 3.7
199 1 300 3 Admin-0 capital Berlin 0 Berlin 1.00000000000 1.00000000000 1 Germany DEU Germany DEU Berlin DE 52.52181866360 13.40154862330 0.00000000000 0 3406000 3094014 3013258 12 12 2950159.00000000000 Berlin Berlin 1 0 2.7
200 1 300 1 Admin-1 capital Ürümqi rumqi|Wulumqi 0 Urumqi 0.00000000000 0.00000000000 1 China CHN China CHN Xinjiang Uygur CN 43.80501222640 87.57500565490 5.00000000000 0 Changed scale rank. 2151000 1508225 2044401 12 12 1529102.00000000000 Cramqi (Wulumqi) Urumqi 1 0 3.7
201 1 300 1 Admin-1 capital Chengdu 0 Chengdu 0.00000000000 0.00000000000 1 China CHN China CHN Sichuan CN 30.67000001930 104.07001949000 5.00000000000 0 Changed scale rank. 4123000 3950437 11622929 12 12 1815286.00000000000 Chengdu Chengdu 1 0 3.0
202 1 300 2 Admin-1 region capital Ōsaka Osaka-Kobe 0 Osaka 0.00000000000 1.00000000000 1 Japan JPN Japan JPN Osaka JP 34.75003521630 135.46014481500 4.00000000000 0 Changed feature to Admin-0 region capital. 11294000 2592413 9630783 14 12 1853909.00000000000 Osaka-Kobe Osaka 1 5 3.0
203 1 300 3 Admin-0 capital Kinshasa 0 Kinshasa 1.00000000000 0.00000000000 1 Congo (Kinshasa) COD Congo (Kinshasa) COD Kinshasa City CD -4.32972410189 15.31497188180 5.00000000000 0 Changed scale rank. 7843000 5565703 4738154 13 13 2314302.00000000000 Kinshasa Kinshasa 1 0 3.0
204 1 300 1 Admin-0 capital New Delhi 0 New Delhi 1.00000000000 1.00000000000 0 India IND India IND Delhi IN 28.60002300920 77.19998002010 0.00000000000 0 317797 317797 8060107 10 10 1261481.00000000000 New Delhi 1 0 2.1
205 1 300 1 Admin-1 capital Bangalore Bengaluru 0 Bangalore 0.00000000000 0.00000000000 1 India IND India IND Karnataka IN 12.96999513650 77.56000972380 3.00000000000 1 Name changed. Changed scale rank. 6787000 5104047 8102712 13 13 1277333.00000000000 Bangalore Bangalore 1 0 3.7
206 1 300 6 Admin-0 capital Athens Athenai Athinai 0 Athens 1.00000000000 1.00000000000 1 Greece GRC Greece GRC Attiki GR 37.98332623190 23.73332108430 4.00000000000 0 Changed scale rank. 3242000 729137 112572 12 11 264371.00000000000 Athnnai Athens2 1 0 3.7
207 1 300 5 Admin-0 capital Baghdad 0 Baghdad 1.00000000000 0.00000000000 1 Iraq IRQ Iraq IRQ Baghdad IQ 33.33864849750 44.39386877320 5.00000000000 0 Changed scale rank. 5054000 5054000 4959534 13 13 98182.00000000000 Baghdad Baghdad 1 0 3.7
208 1 300 3 Admin-0 capital Addis Ababa 0 Addis Ababa 1.00000000000 0.00000000000 1 Ethiopia ETH Ethiopia ETH Addis Ababa ET 9.03331036268 38.70000443400 5.00000000000 0 Changed scale rank. 3100000 2757729 3013653 12 12 344979.00000000000 Addis Ababa Addis Ababa 1 5 3.0
209 1 300 5 Admin-0 capital Tehran 0 Tehran 1.00000000000 0.00000000000 1 Iran IRN Iran IRN Tehran IR 35.67194276840 51.42434403360 5.00000000000 0 Changed scale rank. 7873000 7153309 8209012 13 13 112931.00000000000 Tehran Tehran 1 0 3.0
210 1 300 2 Populated place Vancouver 0 Vancouver 0.00000000000 0.00000000000 1 Canada CAN Canada CAN British Columbia CA 49.27341658410 -123.12164421800 5.00000000000 0 Changed scale rank. 2313328 603502 482002 12 11 6173331.00000000000 Vancouver Vancouver2 1 0 2.1
211 1 300 2 Admin-1 capital Toronto 0 Toronto 0.00000000000 1.00000000000 1 Canada CAN Canada CAN Ontario CA 43.69997987780 -79.42002079440 0.00000000000 0 5213000 3934421 3749229 13 12 6167865.00000000000 Toronto Toronto 1 0 2.1
212 1 300 3 Admin-0 capital Buenos Aires 0 Buenos Aires 1.00000000000 1.00000000000 1 Argentina ARG Argentina ARG Ciudad de Buenos Aires AR -34.60250160850 -58.39753137370 0.00000000000 0 12795000 10929146 10271457 14 14 3435910.00000000000 Buenos Aires Buenos Aires 1 0 2.1
213 1 300 5 Admin-0 capital Kabul 0 Kabul 1.00000000000 0.00000000000 1 Afghanistan AFG Afghanistan AFG Kabul AF 34.51669028630 69.18326004930 5.00000000000 0 Changed scale rank. 3277000 3043532 3475519 12 12 1138958.00000000000 Kabul Kabul 1 0 3.7
214 1 300 7 Admin-0 capital Vienna Wien 0 Vienna 1.00000000000 1.00000000000 1 Austria AUT Austria AUT Wien AT 48.20001527820 16.36663895540 0.00000000000 0 2400000 1731000 1480886 12 12 2761369.00000000000 Wien Vienna 1 0 3.7
215 1 300 3 Admin-1 capital Melbourne 0 Melbourne 0.00000000000 1.00000000000 1 Australia AUS Australia AUS Victoria AU -37.82003131230 144.97501623500 4.00000000000 0 Changed feature class. Changed scale rank. 4170000 93625 1805353 12 8 2158177.00000000000 Melbourne Melbourne2 1 0 3.0
216 1 300 8 Admin-0 capital Taipei 0 Taipei 1.00000000000 1.00000000000 1 Taiwan TWN Taiwan TWN Taipei City TW 25.03583333333 121.56833333333 1.00000000000 0 Corrected coordinates. 6900273 2618772 5698241 13 12 1668341.00000000000 Taipei Taipei 1 0 3.7
217 1 300 8 Admin-1 capital Auckland 0 Auckland 0.00000000000 1.00000000000 1 New Zealand NZL New Zealand NZL Auckland NZ Auckland metropolitan area -36.84805489493 174.76302698708 4.00000000000 0 Changed scale rank. 1377200 395982 0 12 10 2193733.00000000000 Auckland Auckland 1 0 3.0
218 0 600 1 Populated place Los Angeles Los Angeles-Long Beach-Santa Ana 0 Los Angeles 0.00000000000 1.00000000000 1 United States USA United States of America USA California US 33.98997825020 -118.17998051100 0.00000000000 0 12500000 3694820 142265 14 12 5368361.00000000000 Los Angeles-Long Beach-Santa Ana Los Angeles1 1 0 2.0
219 0 600 1 Admin-0 capital Washington, D.C. Washington D.C. 0 Washington, D.C. 1.00000000000 1.00000000000 1 United States USA United States of America USA District of Columbia US 38.89954937650 -77.00941858080 0.00000000000 0 4338000 552433 2175991 12 11 4140963.00000000000 Washington, D.C. Washington, D.C. 1 5 2.1
220 0 600 1 Populated place New York New York-Newark 0 New York 0.00000000000 UN Headquarters 1.00000000000 1 United States USA United States of America USA New York US 40.74997906400 -73.98001692880 0.00000000000 0 19040000 8008278 9292603 14 13 5128581.00000000000 New York-Newark New York 1 0 1.7
221 0 600 5 Admin-0 capital London 0 London 1.00000000000 1.00000000000 1 United Kingdom GBR United Kingdom GBR Westminster GB 51.49999472970 -0.11672184386 0.00000000000 0 8567000 7421209 326670 13 13 2643743.00000000000 London London2 1 5 1.7
222 0 600 5 Admin-1 capital Istanbul 0 Istanbul 0.00000000000 1.00000000000 1 Turkey TUR Turkey TUR Istanbul TR 41.10499615380 29.01000158560 0.00000000000 0 10061000 9945610 9651488 14 13 745044.00000000000 Istanbul Istanbul 1 0 3.0
223 0 600 5 Admin-0 capital Riyadh Ar-Riyadh 0 Riyadh 1.00000000000 1.00000000000 1 Saudi Arabia SAU Saudi Arabia SAU Ar Riyad SA 24.64083314920 46.77274165730 4.00000000000 0 Changed scale rank. 4465000 4205961 5148778 12 12 108410.00000000000 Ar-Riyadh Riyadh 1 0 3.7
224 0 600 3 Admin-0 capital Cape Town 0 Cape Town 1.00000000000 1 Legislative cap 1.00000000000 1 South Africa ZAF South Africa ZAF Western Cape ZA -33.92001096720 18.43498815780 4.00000000000 0 Changed scale rank. 3215000 2432858 2401318 12 12 3369157.00000000000 Cape Town Cape Town 1 0 1.7
225 0 600 2 Admin-0 capital Moscow Moskva 0 Moscow 1.00000000000 1.00000000000 1 Russia RUS Russia RUS Moskva RU 55.75216412260 37.61552282590 0.00000000000 0 10452000 10452000 10585385 14 14 524901.00000000000 Moskva Moscow 1 0 1.7
226 0 600 2 Admin-0 capital Mexico City Ciudad de M 0 Mexico City 1.00000000000 1.00000000000 1 Mexico MEX Mexico MEX Distrito Federal MX 19.44244244280 -99.13098820170 0.00000000000 0 19028000 10811002 10018444 14 14 3530597.00000000000 Ciudad de Mdxico Mexico City 1 0 2.1
227 0 600 2 Admin-0 capital alt Lagos 0 Lagos 0.00000000000 1 Former capital 1.00000000000 1 Nigeria NGA Nigeria NGA Lagos NG 6.44326165348 3.39153107121 4.00000000000 0 Location adjusted. Changed scale rank. 9466000 1536 6567892 13 3 2332459.00000000000 Lagos Lagos 1 0 2.0
228 0 600 3 Admin-0 capital Rome 0 Rome 1.00000000000 1.00000000000 1 Italy ITA Italy ITA Lazio IT 41.89595562650 12.48325842150 0.00000000000 0 3339000 35452 2050212 12 7 3169070.00000000000 Rome Rome 1 0 2.7
229 0 600 1 Admin-0 capital Beijing 0 Beijing 1.00000000000 1.00000000000 1 China CHN China CHN Beijing CN 39.92889223130 116.38828568400 0.00000000000 0 11106000 7480601 9033231 14 13 1816670.00000000000 Beijing Beijing 1 0 1.7
230 0 600 5 Admin-0 capital Nairobi 0 Nairobi 1.00000000000 1.00000000000 1 Kenya KEN Kenya KEN Nairobi KE -1.28334674185 36.81665685910 4.00000000000 0 Changed scale rank. 3010000 2750547 3400962 12 12 184745.00000000000 Nairobi Nairobi 1 0 2.0
231 0 600 1 Admin-0 capital Jakarta 0 Jakarta 1.00000000000 1.00000000000 1 Indonesia IDN Indonesia IDN Jakarta Raya ID -6.17441770541 106.82943762100 0.00000000000 0 9125000 8540121 9129613 13 13 1642911.00000000000 Jakarta Jakarta 1 0 2.1
232 0 600 5 Admin-0 capital Bogota Bogota 0 Bogota 1.00000000000 1.00000000000 1 Colombia COL Colombia COL Bogota CO 4.59642356253 -74.08334395520 0.00000000000 0 7772000 6333661 5754084 13 13 3688689.00000000000 Bogota Bogota 1 0 2.1
233 0 600 3 Admin-0 capital Cairo Al-Qahirah 0 Cairo 1.00000000000 1.00000000000 1 Egypt EGY Egypt EGY Al Qahirah EG 30.04996034650 31.24996821970 0.00000000000 0 11893000 7734614 13720557 14 13 360630.00000000000 Al-Qahirah Cairo 1 5 1.7
234 0 600 1 Admin-1 capital Shanghai 0 Shanghai 0.00000000000 1.00000000000 1 China CHN China CHN Shanghai CN 31.21645245260 121.43650467800 0.00000000000 0 14987000 14608512 16803572 14 14 1796236.00000000000 Shanghai Shanghai 1 0 2.0
235 0 600 2 Admin-0 capital Tokyo 0 Tokyo 1.00000000000 De facto capita 1.00000000000 1 Japan JPN Japan JPN Tokyo JP 35.68501690580 139.75140742900 0.00000000000 0 35676000 8336599 12945252 14 13 1850147.00000000000 Tokyo Tokyo 1 0 1.7
236 0 600 1 Admin-1 capital Mumbai Bombay 0 Mumbai 0.00000000000 1.00000000000 1 India IND India IND Maharashtra IN 19.01699037570 72.85698929740 0.00000000000 0 18978000 12691836 12426085 14 14 1275339.00000000000 Mumbai Mumbai 1 0 1.7
237 0 600 3 Admin-0 capital Paris 0 Paris 1.00000000000 1.00000000000 1 French Republic FRA France FRA Île-de-France FR 48.86669293120 2.33333532574 0.00000000000 0 9904000 11177 7142744 13 6 2988507.00000000000 Paris Paris 1 0 1.7
238 0 600 3 Admin-0 capital Santiago 0 Santiago 1.00000000000 Official, admin 1.00000000000 1 Chile CHL Chile CHL Región Metropolitana de Santiago CL -33.45001381550 -70.66704085460 4.00000000000 0 Changed scale rank. 5720000 46611 3066651 13 7 3449741.00000000000 Santiago Santiago3 1 0 2.0
239 0 600 1 Admin-1 capital Kolkata Calcutta 0 Kolkata 0.00000000000 0.00000000000 1 India IND India IND West Bengal IN 22.49496929830 88.32467565810 4.00000000000 1 Name changed. Changed scale rank. 14787000 4631392 7783716 14 12 1275004.00000000000 Kolkata Calcutta 1 0 3.7
240 0 600 1 Admin-1 capital Rio de Janeiro 0 Rio de Janeiro 0.00000000000 1.00000000000 1 Brazil BRA Brazil BRA Rio de Janeiro BR -22.92502317420 -43.22502079420 0.00000000000 0 11748000 2010175 1821489 14 12 3451190.00000000000 Rio de Janeiro Rio de Janeiro 1 0 1.7
241 0 600 1 Admin-1 capital São Paulo Sao Paulo|Sio Paulo 0 Sao Paulo 0.00000000000 1.00000000000 1 Brazil BRA Brazil BRA São Paulo BR -23.55867958700 -46.62501998040 0.00000000000 0 18845000 10021295 11522944 14 14 3448439.00000000000 S Sao Paolo 1 0 3.0
242 0 600 3 Admin-1 capital Sydney 0 Sydney 0.00000000000 1.00000000000 1 Australia AUS Australia AUS New South Wales AU -33.92001096720 151.18517980900 4.00000000000 0 Changed feature class. 4630000 3641422 2669348 12 12 2147714.00000000000 Sydney Sydney1 1 0
243 0 600 0 Admin-0 capital Singapore 0 Singapore 1.00000000000 1.00000000000 1 Singapore SGP Singapore SGP SG 1.29303346649 103.85582067800 0.00000000000 0 5183700 3289529 3314179 13 12 1880252.00000000000 Singapore Singapore 1 5 2.1
244 0 600 0 Admin-0 region capital Hong Kong 0 Hong Kong 0.00000000000 1.00000000000 1 China CHN Hong Kong S.A.R. HKG HK 22.30498089500 114.18500931700 0.00000000000 0 7206000 4551579 4549026 13 12 1819729.00000000000 Hong Kong Hong Kong 1 0 3.0
245
246 0 600 0 Admin-0 region capital Hong Kong 0 Hong Kong 0.00000000000 1.00000000000 1 China CHN Hong Kong S.A.R. HKG HK nan 114.18500931700 0.00000000000 0 7206000 4551579 4549026 13 12 1819729.00000000000 Hong Kong Hong Kong 1 0 3.0
247 0 600 0 Admin-0 region capital Hong Kong 0 Hong Kong 0.00000000000 1.00000000000 1 China CHN Hong Kong S.A.R. HKG HK inf 114.18500931700 0.00000000000 0 7206000 4551579 4549026 13 12 1819729.00000000000 Hong Kong Hong Kong 1 0 3.0
248 0 600 0 Admin-0 region capital Hong Kong 0 Hong Kong 0.00000000000 1.00000000000 1 China CHN Hong Kong S.A.R. HKG HK 22.30498089500 nan 0.00000000000 0 7206000 4551579 4549026 13 12 1819729.00000000000 Hong Kong Hong Kong 1 0 3.0
249 0 600 0 Admin-0 region capital Hong Kong 0 Hong Kong 0.00000000000 1.00000000000 1 China CHN Hong Kong S.A.R. HKG HK 22.30498089500 inf 0.00000000000 0 7206000 4551579 4549026 13 12 1819729.00000000000 Hong Kong Hong Kong 1 0 3.0

File diff suppressed because one or more lines are too long

502
tests/csv/out.mbtiles.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -3,6 +3,7 @@
"center": "-135.000000,75.782195,2",
"description": "tests/curve/out/-z2.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/curve/out/-z2.json.check.mbtiles -z2 tests/curve/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 2, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 2,\"geometry\": \"Polygon\",\"attributeCount\": 0,\"attributes\": []}]}}",
"maxzoom": "2",
"minzoom": "0",

View File

@ -3,6 +3,7 @@
"center": "-135.000000,75.782195,2",
"description": "tests/curve/out/-z2_--no-clipping.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/curve/out/-z2_--no-clipping.json.check.mbtiles -z2 --no-clipping tests/curve/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 2, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 2,\"geometry\": \"Polygon\",\"attributeCount\": 0,\"attributes\": []}]}}",
"maxzoom": "2",
"minzoom": "0",

View File

@ -3,6 +3,7 @@
"center": "45.000000,33.256630,2",
"description": "tests/curve/out/-z2_--no-duplication.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/curve/out/-z2_--no-duplication.json.check.mbtiles -z2 --no-duplication tests/curve/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 2, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 2,\"geometry\": \"Polygon\",\"attributeCount\": 0,\"attributes\": []}]}}",
"maxzoom": "2",
"minzoom": "0",

View File

@ -1,4 +1,6 @@
{"type":"FeatureCollection","features":[
{"type":"FeatureCollection",
"crs": { "type": "name", "properties": { } },
"features":[
{"type":"Feature","properties":{
"boolean": true,
"otherboolean": false,
@ -9,6 +11,78 @@
"prêt": "ready"
},"geometry":{"type":"Polygon","coordinates":[[[-189.492187,64.774125],[-182.460937,67.339860],[-169.101562,68.269386],[-156.09375,68.138851],[-144.492187,66.089364],[-134.648437,62.431074],[-131.835937,55.379110],[-133.59375,48.690960],[-146.25,38.548165],[-169.453124,34.885930],[-184.218749,37.160316],[-198.28125,45.336701],[-203.203125,54.977613],[-196.523437,62.431074],[-189.492187,64.774125]],[[-177.890625,62.593340],[-185.976562,58.813741],[-188.4375,54.367758],[-185.976562,47.279229],[-177.539062,44.339565],[-164.882812,43.325177],[-153.28125,46.558860],[-144.492187,51.179342],[-143.789062,57.136239],[-148.007812,61.100788],[-158.554687,63.860035],[-169.453124,64.472793],[-177.890625,62.593340]]]}},
{
"type": "Feature",
"properties": {"where": "-180"},
"geometry": {
"type": "LineString",
"coordinates": [
[ -180, 20 ],
[ -180, 50 ]
]
}
},
{
"type": "Feature",
"properties": {"where": "180"},
"geometry": {
"type": "LineString",
"coordinates": [
[ 180, 10 ],
[ 180, 30 ]
]
}
},
{
"type": "Feature",
"properties": {"where": "-173, duplicated"},
"geometry": {
"type": "LineString",
"coordinates": [
[ -173, 10 ],
[ -173, 30 ]
]
}
},
{
"type": "Feature",
"properties": {"where": "-172, not duplicated"},
"geometry": {
"type": "LineString",
"coordinates": [
[ -172, 10 ],
[ -172, 30 ]
]
}
},
{
"type": "Feature",
"properties": {"where": "173, duplicated"},
"geometry": {
"type": "LineString",
"coordinates": [
[ 173, 10 ],
[ 173, 30 ]
]
}
},
{
"type": "Feature",
"properties": {"where": "172, not duplicated"},
"geometry": {
"type": "LineString",
"coordinates": [
[ 172, 10 ],
[ 172, 30 ]
]
}
},
{
"type": "Feature",
"tippecanoe": { "maxzoom": 2 },
@ -50,6 +124,26 @@
]
]
}
},
{
"type": "Feature",
"tippecanoe": { "minzoom": 1e1 },
"properties": { "zoom": "nothing, since 10 > 5"},
"geometry": {
"type": "LineString",
"coordinates": [ [ 0, 0 ], [ 1, 1 ] ]
}
},
{
"type": "Feature",
"tippecanoe": { "maxzoom": 1e1},
"properties": { "zoom": "0-5, since 10 > 5"},
"geometry": {
"type": "LineString",
"coordinates": [ [ 0, 0 ], [ 1, 1 ] ]
}
}
]}

View File

@ -1,9 +1,10 @@
{ "type": "FeatureCollection", "properties": {
"bounds": "-180.000000,34.885930,180.000000,68.269386",
"center": "-151.875000,64.059828,5",
"bounds": "-180.000000,0.000000,180.000000,68.269386",
"center": "-174.375000,16.560724,5",
"description": "tests/dateline/out/-z5.json.check.mbtiles",
"format": "pbf",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 5, \"fields\": {\"\": \"String\", \"boolean\": \"Boolean\", \"escape\": \"String\", \"otherboolean\": \"Boolean\", \"prêt\": \"String\", \"stringify\": \"String\", \"zoom\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 3,\"geometry\": \"LineString\",\"attributeCount\": 7,\"attributes\": [{\"attribute\": \"\",\"count\": 1,\"type\": \"string\",\"values\": [\"something for nothing\"]},{\"attribute\": \"boolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]},{\"attribute\": \"escape\",\"count\": 1,\"type\": \"string\",\"values\": [\"foo\\u0001bar,ü\\\"\\\\/\\u0008\\u000c\\u000a\\u000d\\u0009→🐂🐳\"]},{\"attribute\": \"otherboolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [false]},{\"attribute\": \"prêt\",\"count\": 1,\"type\": \"string\",\"values\": [\"ready\"]},{\"attribute\": \"stringify\",\"count\": 1,\"type\": \"string\",\"values\": [\"[\\\"yes\\\",27,27,1.4e+27,{\\\"foo\\\":\\\"bar\\\"}]\"]},{\"attribute\": \"zoom\",\"count\": 2,\"type\": \"string\",\"values\": [\"3-5\",\"z0-2\"]}]}]}}",
"generator_options": "./tippecanoe -q -a@ -f -o tests/dateline/out/-z5.json.check.mbtiles -z5 tests/dateline/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 5, \"fields\": {\"\": \"String\", \"boolean\": \"Boolean\", \"escape\": \"String\", \"otherboolean\": \"Boolean\", \"prêt\": \"String\", \"stringify\": \"String\", \"where\": \"String\", \"zoom\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 11,\"geometry\": \"LineString\",\"attributeCount\": 8,\"attributes\": [{\"attribute\": \"\",\"count\": 1,\"type\": \"string\",\"values\": [\"something for nothing\"]},{\"attribute\": \"boolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]},{\"attribute\": \"escape\",\"count\": 1,\"type\": \"string\",\"values\": [\"foo\\u0001bar,ü\\\"\\\\/\\u0008\\u000c\\u000a\\u000d\\u0009→🐂🐳\"]},{\"attribute\": \"otherboolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [false]},{\"attribute\": \"prêt\",\"count\": 1,\"type\": \"string\",\"values\": [\"ready\"]},{\"attribute\": \"stringify\",\"count\": 1,\"type\": \"string\",\"values\": [\"[\\\"yes\\\",27,27,1.4e+27,{\\\"foo\\\":\\\"bar\\\"}]\"]},{\"attribute\": \"where\",\"count\": 6,\"type\": \"string\",\"values\": [\"-172, not duplicated\",\"-173, duplicated\",\"-180\",\"172, not duplicated\",\"173, duplicated\",\"180\"]},{\"attribute\": \"zoom\",\"count\": 4,\"type\": \"string\",\"values\": [\"0-5, since 10 > 5\",\"3-5\",\"nothing, since 10 > 5\",\"z0-2\"]}]}]}}",
"maxzoom": "5",
"minzoom": "0",
"name": "tests/dateline/out/-z5.json.check.mbtiles",
@ -12,29 +13,83 @@
}, "features": [
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -187.031250, 50.457504 ], [ -185.976562, 47.279229 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.689872 ], [ -185.976562, 58.813742 ], [ -187.031250, 56.992883 ], [ -187.031250, 65.730626 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.542167 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -184.218750, 37.160317 ], [ -187.031250, 38.891033 ], [ -187.031250, 50.457504 ] ] ], [ [ [ 187.031250, 63.704722 ], [ 182.109375, 62.593341 ], [ 180.000000, 61.689872 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 182.460938, 44.339565 ], [ 187.031250, 44.024422 ], [ 187.031250, 35.460670 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.542167 ], [ 187.031250, 68.007571 ], [ 187.031250, 63.704722 ] ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -187.031250, 56.992883 ], [ -187.031250, 65.730626 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.542167 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -184.218750, 37.160317 ], [ -187.031250, 38.891033 ], [ -187.031250, 50.457504 ], [ -185.976562, 47.279229 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.689872 ], [ -185.976562, 58.813742 ], [ -187.031250, 56.992883 ] ] ], [ [ [ 187.031250, 44.024422 ], [ 187.031250, 35.460670 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.542167 ], [ 187.031250, 68.007571 ], [ 187.031250, 63.704722 ], [ 182.109375, 62.593341 ], [ 180.000000, 61.689872 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 182.460938, 44.339565 ], [ 187.031250, 44.024422 ] ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -180.000000, 20.055931 ], [ -180.000000, 50.007739 ] ], [ [ 180.000000, 20.055931 ], [ 180.000000, 50.007739 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 180.000000, 10.055403 ], [ 180.000000, 30.069094 ] ], [ [ -180.000000, 10.055403 ], [ -180.000000, 30.069094 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -173.056641, 10.055403 ], [ -173.056641, 30.069094 ] ], [ [ 186.943359, 10.055403 ], [ 186.943359, 30.069094 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.055403 ], [ -172.001953, 30.069094 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.054628 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.914062, 10.055403 ], [ 171.914062, 30.069094 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 172.968750, 10.055403 ], [ 172.968750, 30.069094 ] ], [ [ -187.031250, 10.055403 ], [ -187.031250, 30.069094 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -183.515625, 46.437857 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.669024 ], [ -183.515625, 60.020952 ], [ -183.515625, 66.981666 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.525373 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -183.515625, 37.055177 ], [ -183.515625, 46.437857 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -183.515625, 60.020952 ], [ -183.515625, 66.981666 ], [ -182.460938, 67.339861 ], [ -180.000000, 67.525373 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -183.515625, 37.055177 ], [ -183.515625, 46.437857 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.669024 ], [ -183.515625, 60.020952 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.014645 ], [ -180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.012130 ], [ -180.000000, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.012695, 10.012130 ], [ -173.012695, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.012130 ], [ -172.001953, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 183.515625, 62.915233 ], [ 182.109375, 62.593341 ], [ 180.000000, 61.669024 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 182.460938, 44.339565 ], [ 183.515625, 44.276671 ], [ 183.515625, 35.995785 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.525373 ], [ 183.515625, 67.776025 ], [ 183.515625, 62.915233 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 183.515625, 44.276671 ], [ 183.515625, 35.995785 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.525373 ], [ 183.515625, 67.776025 ], [ 183.515625, 62.915233 ], [ 182.109375, 62.593341 ], [ 180.000000, 61.669024 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 182.460938, 44.339565 ], [ 183.515625, 44.276671 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.014645 ], [ 180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.012130 ], [ 180.000000, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.958008, 10.012130 ], [ 171.958008, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.968750, 10.012130 ], [ 172.968750, 30.031055 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 0, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -181.757812, 45.828799 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.658595 ], [ -181.757812, 60.844911 ], [ -181.757812, 67.204032 ], [ -150.688477, 67.204032 ], [ -146.821289, 66.513260 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -181.757812, 36.791691 ], [ -181.757812, 45.828799 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -181.757812, 60.844911 ], [ -181.757812, 67.204032 ], [ -150.688477, 67.204032 ], [ -146.821289, 66.513260 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -181.757812, 36.791691 ], [ -181.757812, 45.828799 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.658595 ], [ -181.757812, 60.844911 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.014645 ], [ -180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.012130 ], [ -180.000000, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.012695, 10.012130 ], [ -173.012695, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.012130 ], [ -172.001953, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
] }
@ -46,9 +101,41 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 1, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 1, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 3, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 181.757812, 62.441242 ], [ 180.000000, 61.658595 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 181.757812, 44.590467 ], [ 181.757812, 36.261992 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 177.143555, 67.204032 ], [ 181.757812, 67.204032 ], [ 181.757812, 62.441242 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 181.757812, 44.590467 ], [ 181.757812, 36.261992 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 177.143555, 67.204032 ], [ 181.757812, 67.204032 ], [ 181.757812, 62.441242 ], [ 180.000000, 61.658595 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 181.757812, 44.590467 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.014645 ], [ 180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.012130 ], [ 180.000000, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.979980, 10.012130 ], [ 171.979980, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.990723, 10.012130 ], [ 172.990723, 30.012031 ] ] } }
] }
] }
,
@ -61,12 +148,22 @@
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 0, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -142.613525, 41.640078 ], [ -143.404541, 40.979898 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.518466 ], [ -180.878906, 36.659606 ], [ -180.878906, 41.640078 ], [ -142.613525, 41.640078 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.004322 ], [ -180.000000, 40.979898 ], [ -180.000000, 41.640078 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.001310 ], [ -180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.001310 ], [ -173.001709, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.001310 ], [ -172.001953, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 0, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.878906, 45.521744 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.653379 ], [ -180.878906, 61.249102 ], [ -180.878906, 66.861082 ], [ -148.754883, 66.861082 ], [ -146.821289, 66.513260 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.573106 ], [ -134.648438, 62.431074 ], [ -134.121094, 61.217379 ], [ -134.121094, 48.305121 ], [ -135.000000, 47.650588 ], [ -144.195557, 40.313043 ], [ -180.878906, 40.313043 ], [ -180.878906, 45.521744 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.878906, 61.249102 ], [ -180.878906, 66.861082 ], [ -148.754883, 66.861082 ], [ -146.821289, 66.513260 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.573106 ], [ -134.648438, 62.431074 ], [ -134.121094, 61.217379 ], [ -134.121094, 48.305121 ], [ -135.000000, 47.650588 ], [ -144.195557, 40.313043 ], [ -180.878906, 40.313043 ], [ -180.878906, 45.521744 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.653379 ], [ -180.878906, 61.249102 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 40.313043 ], [ -180.000000, 40.979898 ], [ -180.000000, 50.000678 ] ] } }
] }
] }
,
@ -82,12 +179,36 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.867920, 0.878872 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.878906, 0.889857 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ], [ 0.878906, 46.619261 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.867920, 0.878872 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -0.878906, 46.012224 ], [ 0.000000, 46.316584 ], [ 16.171875, 51.618017 ] ] } }
@ -97,12 +218,22 @@
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 7, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.878906, 41.640078 ], [ 180.878906, 36.385913 ], [ 180.000000, 36.518466 ], [ 175.781250, 37.160317 ], [ 169.420166, 40.979898 ], [ 168.288574, 41.640078 ], [ 180.878906, 41.640078 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.004322 ], [ 180.000000, 40.979898 ], [ 180.000000, 41.640078 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.001310 ], [ 180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.990967, 10.001310 ], [ 171.990967, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.990723, 10.001310 ], [ 172.990723, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 7, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.878906, 62.047288 ], [ 180.000000, 61.653379 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.878906, 44.902578 ], [ 180.878906, 40.313043 ], [ 170.562744, 40.313043 ], [ 169.420166, 40.979898 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 176.165771, 66.861082 ], [ 180.878906, 66.861082 ], [ 180.878906, 62.047288 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.878906, 44.902578 ], [ 180.878906, 40.313043 ], [ 170.562744, 40.313043 ], [ 169.420166, 40.979898 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 176.165771, 66.861082 ], [ 180.878906, 66.861082 ], [ 180.878906, 62.047288 ], [ 180.000000, 61.653379 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.878906, 44.902578 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 40.313043 ], [ 180.000000, 40.979898 ], [ 180.000000, 50.000678 ] ] } }
] }
] }
,
@ -112,21 +243,43 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.004322 ], [ -180.000000, 21.943046 ], [ -180.000000, 22.350076 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.001310 ], [ -180.000000, 21.943046 ], [ -180.000000, 22.350076 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.001310 ], [ -173.001709, 21.943046 ], [ -173.001709, 22.350076 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.001310 ], [ -172.001953, 21.943046 ], [ -172.001953, 22.350076 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.060547, 41.310824 ], [ -157.060547, 36.866438 ], [ -157.500000, 36.796090 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.518466 ], [ -180.439453, 36.589068 ], [ -180.439453, 41.310824 ], [ -157.060547, 41.310824 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.534847 ], [ -180.000000, 21.943046 ], [ -180.000000, 40.979898 ], [ -180.000000, 41.310824 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.534847 ], [ -180.000000, 21.943046 ], [ -180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 21.534847 ], [ -173.001709, 21.943046 ], [ -173.001709, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 21.534847 ], [ -172.001953, 21.943046 ], [ -172.001953, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.060547, 45.525592 ], [ -157.060547, 40.647304 ], [ -180.439453, 40.647304 ], [ -180.439453, 45.367584 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -157.500000, 45.406164 ], [ -157.060547, 45.525592 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 40.647304 ], [ -180.000000, 40.979898 ], [ -180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.060547, 66.687784 ], [ -157.060547, 63.484863 ], [ -157.500000, 63.597448 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.650771 ], [ -180.439453, 61.451896 ], [ -180.439453, 66.687784 ], [ -157.060547, 66.687784 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.060547, 63.484863 ], [ -157.500000, 63.597448 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.650771 ], [ -180.439453, 61.451896 ], [ -180.439453, 66.687784 ], [ -157.060547, 66.687784 ], [ -157.060547, 63.484863 ] ] ] } }
] }
] }
,
@ -144,13 +297,13 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 1, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -134.560547, 56.022948 ], [ -134.560547, 47.978891 ], [ -135.000000, 47.650588 ], [ -143.800049, 40.647304 ], [ -157.939453, 40.647304 ], [ -157.939453, 45.282617 ], [ -157.500000, 45.406164 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.959351, 55.776573 ], [ -143.931885, 56.022948 ], [ -134.560547, 56.022948 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.939453, 45.282617 ], [ -157.500000, 45.406164 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.959351, 55.776573 ], [ -143.931885, 56.022948 ], [ -134.560547, 56.022948 ], [ -134.560547, 47.978891 ], [ -135.000000, 47.650588 ], [ -143.800049, 40.647304 ], [ -157.939453, 40.647304 ], [ -157.939453, 45.282617 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 1, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -147.782593, 66.687784 ], [ -146.815796, 66.513260 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.570575 ], [ -134.648438, 62.431074 ], [ -134.560547, 62.232115 ], [ -134.560547, 55.528631 ], [ -143.992310, 55.528631 ], [ -143.959351, 55.776573 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -157.500000, 63.597448 ], [ -157.939453, 63.707156 ], [ -157.939453, 66.687784 ], [ -147.782593, 66.687784 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.939453, 63.707156 ], [ -157.939453, 66.687784 ], [ -147.782593, 66.687784 ], [ -146.815796, 66.513260 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.570575 ], [ -134.648438, 62.431074 ], [ -134.560547, 62.232115 ], [ -134.560547, 55.528631 ], [ -143.992310, 55.528631 ], [ -143.959351, 55.776573 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -157.500000, 63.597448 ], [ -157.939453, 63.707156 ] ] ] } }
] }
] }
,
@ -172,12 +325,36 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.433960, 0.439449 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.439453, 0.444942 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ], [ 0.439453, 46.468133 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.433960, 0.439449 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.005197 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -0.439453, 46.164614 ], [ 0.000000, 46.316584 ], [ 16.171875, 51.618017 ] ] } }
@ -196,15 +373,37 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.004322 ], [ 180.000000, 21.943046 ], [ 180.000000, 22.350076 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.001310 ], [ 180.000000, 21.943046 ], [ 180.000000, 22.350076 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.996460, 10.001310 ], [ 171.996460, 21.943046 ], [ 171.996460, 22.350076 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.996216, 10.001310 ], [ 172.996216, 21.943046 ], [ 172.996216, 22.350076 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.439453, 41.310824 ], [ 180.439453, 36.452218 ], [ 180.000000, 36.518466 ], [ 175.781250, 37.160317 ], [ 169.425659, 40.979898 ], [ 168.859863, 41.310824 ], [ 180.439453, 41.310824 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.534847 ], [ 180.000000, 21.943046 ], [ 180.000000, 40.979898 ], [ 180.000000, 41.310824 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.534847 ], [ 180.000000, 21.943046 ], [ 180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.996460, 21.534847 ], [ 171.996460, 21.943046 ], [ 171.996460, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.996216, 21.534847 ], [ 172.996216, 21.943046 ], [ 172.996216, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.439453, 45.058001 ], [ 180.439453, 40.647304 ], [ 169.991455, 40.647304 ], [ 169.425659, 40.979898 ], [ 161.718750, 45.336702 ], [ 157.500000, 53.719466 ], [ 157.060547, 54.511516 ], [ 157.060547, 55.304138 ], [ 157.648315, 56.022948 ], [ 172.441406, 56.022948 ], [ 172.309570, 55.776573 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.439453, 45.058001 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 40.647304 ], [ 180.000000, 40.979898 ], [ 180.000000, 50.000678 ] ] } }
] }
] }
,
@ -220,27 +419,71 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.001310 ], [ -180.000000, 11.178402 ], [ -180.000000, 11.393879 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.001310 ], [ -173.001709, 11.178402 ], [ -173.001709, 11.393879 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.001310 ], [ -172.001953, 11.178402 ], [ -172.001953, 11.393879 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 14 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.001741 ], [ -180.000000, 21.943046 ], [ -180.000000, 22.146708 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.962764 ], [ -180.000000, 11.178402 ], [ -180.000000, 21.943046 ], [ -180.000000, 22.146708 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.962764 ], [ -173.001709, 11.178402 ], [ -173.001709, 21.943046 ], [ -173.001709, 22.146708 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.962764 ], [ -172.001953, 11.178402 ], [ -172.001953, 21.943046 ], [ -172.001953, 22.146708 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 13 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.739091 ], [ -180.000000, 21.943046 ], [ -180.000000, 31.952162 ], [ -180.000000, 32.138409 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.739091 ], [ -180.000000, 21.943046 ], [ -180.000000, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 21.739091 ], [ -173.001709, 21.943046 ], [ -173.001709, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 21.739091 ], [ -172.001953, 21.943046 ], [ -172.001953, 30.000138 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.530273, 41.145570 ], [ -168.530273, 35.036743 ], [ -168.750000, 35.000754 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.520673 ], [ -180.219727, 36.553775 ], [ -180.219727, 41.145570 ], [ -168.530273, 41.145570 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 31.765537 ], [ -180.000000, 31.952162 ], [ -180.000000, 40.979898 ], [ -180.000000, 41.145570 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.530273, 43.620171 ], [ -168.530273, 40.813809 ], [ -180.219727, 40.813809 ], [ -180.219727, 45.290347 ], [ -177.539062, 44.339565 ], [ -168.750000, 43.638063 ], [ -168.530273, 43.620171 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.219727, 45.290347 ], [ -177.539062, 44.339565 ], [ -168.750000, 43.638063 ], [ -168.530273, 43.620171 ], [ -168.530273, 40.813809 ], [ -180.219727, 40.813809 ], [ -180.219727, 45.290347 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 40.813809 ], [ -180.000000, 40.979898 ], [ -180.000000, 48.922499 ], [ -180.000000, 49.066668 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 48.777913 ], [ -180.000000, 48.922499 ], [ -180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -179.868164, 61.710706 ], [ -180.219727, 61.551493 ], [ -180.219727, 61.710706 ], [ -179.868164, 61.710706 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.219727, 61.551493 ], [ -180.219727, 61.710706 ], [ -179.868164, 61.710706 ], [ -180.219727, 61.551493 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.530273, 66.600676 ], [ -168.530273, 64.421851 ], [ -168.750000, 64.433707 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.650771 ], [ -180.219727, 61.551493 ], [ -180.219727, 66.600676 ], [ -168.530273, 66.600676 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.530273, 64.421851 ], [ -168.750000, 64.433707 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.650771 ], [ -180.219727, 61.551493 ], [ -180.219727, 66.600676 ], [ -168.530273, 66.600676 ], [ -168.530273, 64.421851 ] ] ] } }
] }
] }
,
@ -264,7 +507,7 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 1, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.280273, 66.600676 ], [ -157.280273, 63.541211 ], [ -157.500000, 63.596226 ], [ -158.554688, 63.860036 ], [ -168.750000, 64.433707 ], [ -168.969727, 64.446742 ], [ -168.969727, 66.600676 ], [ -157.280273, 66.600676 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.969727, 64.446742 ], [ -168.969727, 66.600676 ], [ -157.280273, 66.600676 ], [ -157.280273, 63.541211 ], [ -157.500000, 63.596226 ], [ -158.554688, 63.860036 ], [ -168.750000, 64.433707 ], [ -168.969727, 64.446742 ] ] ] } }
] }
] }
,
@ -282,7 +525,7 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.030273, 49.066668 ], [ -146.030273, 40.813809 ], [ -157.719727, 40.813809 ], [ -157.719727, 45.344424 ], [ -157.500000, 45.406164 ], [ -153.281250, 46.558860 ], [ -148.612061, 49.066668 ], [ -146.030273, 49.066668 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.719727, 45.344424 ], [ -157.500000, 45.406164 ], [ -153.281250, 46.558860 ], [ -148.612061, 49.066668 ], [ -146.030273, 49.066668 ], [ -146.030273, 40.813809 ], [ -157.719727, 40.813809 ], [ -157.719727, 45.344424 ] ] ] } }
] }
] }
,
@ -300,7 +543,7 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -147.296448, 66.600676 ], [ -146.813049, 66.513260 ], [ -146.250000, 66.411253 ], [ -146.030273, 66.371654 ], [ -146.030273, 61.501734 ], [ -149.482727, 61.501734 ], [ -149.869995, 61.606396 ], [ -157.500000, 63.597448 ], [ -157.719727, 63.652355 ], [ -157.719727, 66.600676 ], [ -147.296448, 66.600676 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.719727, 63.652355 ], [ -157.719727, 66.600676 ], [ -147.296448, 66.600676 ], [ -146.813049, 66.513260 ], [ -146.250000, 66.411253 ], [ -146.030273, 66.371654 ], [ -146.030273, 61.501734 ], [ -149.482727, 61.501734 ], [ -149.869995, 61.606396 ], [ -157.500000, 63.597448 ], [ -157.719727, 63.652355 ] ] ] } }
] }
] }
,
@ -324,13 +567,13 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -134.780273, 55.899956 ], [ -134.780273, 48.777913 ], [ -146.469727, 48.777913 ], [ -146.469727, 50.176898 ], [ -144.492188, 51.179343 ], [ -143.962097, 55.776573 ], [ -143.945618, 55.899956 ], [ -134.780273, 55.899956 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.469727, 50.176898 ], [ -144.492188, 51.179343 ], [ -143.962097, 55.776573 ], [ -143.945618, 55.899956 ], [ -134.780273, 55.899956 ], [ -134.780273, 48.777913 ], [ -146.469727, 48.777913 ], [ -146.469727, 50.176898 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -134.780273, 61.710706 ], [ -134.780273, 55.652798 ], [ -143.975830, 55.652798 ], [ -143.959351, 55.776573 ], [ -143.789062, 57.136239 ], [ -146.250000, 59.505061 ], [ -146.469727, 59.709327 ], [ -146.469727, 61.710706 ], [ -134.780273, 61.710706 ] ] ] } }
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.469727, 59.709327 ], [ -146.469727, 61.710706 ], [ -134.780273, 61.710706 ], [ -134.780273, 55.652798 ], [ -143.975830, 55.652798 ], [ -143.959351, 55.776573 ], [ -143.789062, 57.136239 ], [ -146.250000, 59.505061 ], [ -146.469727, 59.709327 ] ] ] } }
] }
] }
,
@ -370,12 +613,36 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 16 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.216980, 0.219726 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.219727, 0.222473 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ], [ 0.219727, 46.392411 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 16 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.216980, 0.219726 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.002451 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -0.219727, 46.240652 ], [ 0.000000, 46.316584 ], [ 7.734375, 48.922499 ], [ 8.173828, 49.066668 ] ] } }
@ -430,21 +697,61 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.001310 ], [ 180.000000, 11.178402 ], [ 180.000000, 11.393879 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.999207, 10.001310 ], [ 171.999207, 11.178402 ], [ 171.999207, 11.393879 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.998962, 10.001310 ], [ 172.998962, 11.178402 ], [ 172.998962, 11.393879 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 14 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.001741 ], [ 180.000000, 21.943046 ], [ 180.000000, 22.146708 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.962764 ], [ 180.000000, 11.178402 ], [ 180.000000, 21.943046 ], [ 180.000000, 22.146708 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.999207, 10.962764 ], [ 171.999207, 11.178402 ], [ 171.999207, 21.943046 ], [ 171.999207, 22.146708 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.998962, 10.962764 ], [ 172.998962, 11.178402 ], [ 172.998962, 21.943046 ], [ 172.998962, 22.146708 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 13 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.739091 ], [ 180.000000, 21.943046 ], [ 180.000000, 31.952162 ], [ 180.000000, 32.138409 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.739091 ], [ 180.000000, 21.943046 ], [ 180.000000, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.999207, 21.739091 ], [ 171.999207, 21.943046 ], [ 171.999207, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.998962, 21.739091 ], [ 172.998962, 21.943046 ], [ 172.998962, 30.000138 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.219727, 41.145570 ], [ 180.219727, 36.487557 ], [ 180.000000, 36.520673 ], [ 175.781250, 37.160317 ], [ 169.425659, 40.979898 ], [ 169.142761, 41.145570 ], [ 180.219727, 41.145570 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 31.765537 ], [ 180.000000, 31.952162 ], [ 180.000000, 40.979898 ], [ 180.000000, 41.145570 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.219727, 45.135555 ], [ 180.219727, 40.813809 ], [ 169.708557, 40.813809 ], [ 169.425659, 40.979898 ], [ 168.750000, 41.376809 ], [ 168.530273, 41.504464 ], [ 168.530273, 49.066668 ], [ 173.435669, 49.066668 ], [ 173.485107, 48.922499 ], [ 174.023438, 47.279229 ], [ 180.219727, 45.135555 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 40.813809 ], [ 180.000000, 40.979898 ], [ 180.000000, 48.922499 ], [ 180.000000, 49.066668 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 172.375488, 55.899956 ], [ 172.309570, 55.776573 ], [ 171.562500, 54.367759 ], [ 173.485107, 48.922499 ], [ 173.531799, 48.777913 ], [ 168.530273, 48.777913 ], [ 168.530273, 55.899956 ], [ 172.375488, 55.899956 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 48.777913 ], [ 180.000000, 48.922499 ], [ 180.000000, 50.000678 ] ] } }
] }
] }
,

View File

@ -0,0 +1,677 @@
{ "type": "FeatureCollection", "properties": {
"bounds": "-180.000000,0.000000,180.000000,68.269386",
"center": "174.375000,44.951199,5",
"description": "tests/dateline/out/-z5_-b0.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/dateline/out/-z5_-b0.json.check.mbtiles -z5 -b0 tests/dateline/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 5, \"fields\": {\"\": \"String\", \"boolean\": \"Boolean\", \"escape\": \"String\", \"otherboolean\": \"Boolean\", \"prêt\": \"String\", \"stringify\": \"String\", \"where\": \"String\", \"zoom\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 11,\"geometry\": \"LineString\",\"attributeCount\": 8,\"attributes\": [{\"attribute\": \"\",\"count\": 1,\"type\": \"string\",\"values\": [\"something for nothing\"]},{\"attribute\": \"boolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]},{\"attribute\": \"escape\",\"count\": 1,\"type\": \"string\",\"values\": [\"foo\\u0001bar,ü\\\"\\\\/\\u0008\\u000c\\u000a\\u000d\\u0009→🐂🐳\"]},{\"attribute\": \"otherboolean\",\"count\": 1,\"type\": \"boolean\",\"values\": [false]},{\"attribute\": \"prêt\",\"count\": 1,\"type\": \"string\",\"values\": [\"ready\"]},{\"attribute\": \"stringify\",\"count\": 1,\"type\": \"string\",\"values\": [\"[\\\"yes\\\",27,27,1.4e+27,{\\\"foo\\\":\\\"bar\\\"}]\"]},{\"attribute\": \"where\",\"count\": 6,\"type\": \"string\",\"values\": [\"-172, not duplicated\",\"-173, duplicated\",\"-180\",\"172, not duplicated\",\"173, duplicated\",\"180\"]},{\"attribute\": \"zoom\",\"count\": 4,\"type\": \"string\",\"values\": [\"0-5, since 10 > 5\",\"3-5\",\"nothing, since 10 > 5\",\"z0-2\"]}]}]}}",
"maxzoom": "5",
"minzoom": "0",
"name": "tests/dateline/out/-z5_-b0.json.check.mbtiles",
"type": "overlay",
"version": "2"
}, "features": [
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -180.000000, 61.689872 ], [ -180.000000, 67.542167 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -180.000000, 45.213004 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.689872 ] ] ], [ [ [ 180.000000, 45.213004 ], [ 180.000000, 36.527295 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.542167 ], [ 180.000000, 61.689872 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.000000, 45.213004 ] ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ -180.000000, 20.055931 ], [ -180.000000, 50.007739 ] ], [ [ 180.000000, 20.055931 ], [ 180.000000, 50.007739 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [ 180.000000, 10.055403 ], [ 180.000000, 30.069094 ] ], [ [ -180.000000, 10.055403 ], [ -180.000000, 30.069094 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.056641, 10.055403 ], [ -173.056641, 30.069094 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.055403 ], [ -172.001953, 30.069094 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.054628 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.914062, 10.055403 ], [ 171.914062, 30.069094 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.968750, 10.055403 ], [ 172.968750, 30.069094 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.000000, 61.669024 ], [ -180.000000, 67.525373 ], [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -180.000000, 45.213004 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.669024 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.014645 ], [ -180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.012130 ], [ -180.000000, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.012695, 10.012130 ], [ -173.012695, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.012130 ], [ -172.001953, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 45.213004 ], [ 180.000000, 36.527295 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.525373 ], [ 180.000000, 61.669024 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.000000, 45.213004 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.014645 ], [ 180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.012130 ], [ 180.000000, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.966797, 1.010690 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.958008, 10.012130 ], [ 171.958008, 30.031055 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.968750, 10.012130 ], [ 172.968750, 30.031055 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 0, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.000000, 61.658595 ], [ -180.000000, 66.513260 ], [ -146.821289, 66.513260 ], [ -144.492188, 66.089364 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.527295 ], [ -180.000000, 45.213004 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.658595 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.014645 ], [ -180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.012130 ], [ -180.000000, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.012695, 10.012130 ], [ -173.012695, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.012130 ], [ -172.001953, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "zoom": "z0-2" }, "geometry": { "type": "LineString", "coordinates": [ [ -112.851562, 55.178868 ], [ -117.773438, 44.590467 ], [ -104.414062, 51.179343 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -146.821289, 66.513260 ], [ -180.000000, 66.513260 ], [ -180.000000, 67.516972 ], [ -169.101562, 68.269387 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.988770, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 3, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 45.213004 ], [ 180.000000, 36.527295 ], [ 175.781250, 37.160317 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 180.000000, 66.513260 ], [ 180.000000, 61.658595 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.000000, 45.213004 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.014645 ], [ 180.000000, 50.007739 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.012130 ], [ 180.000000, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.979980, 10.012130 ], [ 171.979980, 30.012031 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.990723, 10.012130 ], [ 172.990723, 30.012031 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 3, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 67.516972 ], [ 180.000000, 66.513260 ], [ 175.187988, 66.513260 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.516972 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 0, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -143.404541, 40.979898 ], [ -146.250000, 38.548165 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.518466 ], [ -180.000000, 40.979898 ], [ -143.404541, 40.979898 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.004322 ], [ -180.000000, 40.979898 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.001310 ], [ -180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.001310 ], [ -173.001709, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.001310 ], [ -172.001953, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 0, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.000000, 61.653379 ], [ -180.000000, 66.513260 ], [ -146.821289, 66.513260 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.573106 ], [ -135.000000, 47.650588 ], [ -143.404541, 40.979898 ], [ -180.000000, 40.979898 ], [ -180.000000, 45.213004 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.653379 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 40.979898 ], [ -180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 0, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -169.101562, 68.269387 ], [ -156.093750, 68.138852 ], [ -146.821289, 66.513260 ], [ -180.000000, 66.513260 ], [ -180.000000, 67.516972 ], [ -169.101562, 68.269387 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 1, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -135.000000, 62.573106 ], [ -134.648438, 62.431074 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -135.000000, 47.650588 ], [ -135.000000, 62.573106 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 3, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.010690 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 46.316584 ], [ 16.171875, 51.618017 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 7, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 40.979898 ], [ 180.000000, 36.518466 ], [ 175.781250, 37.160317 ], [ 169.420166, 40.979898 ], [ 180.000000, 40.979898 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.004322 ], [ 180.000000, 40.979898 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.001310 ], [ 180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.990967, 10.001310 ], [ 171.990967, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.990723, 10.001310 ], [ 172.990723, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 7, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 45.213004 ], [ 180.000000, 40.979898 ], [ 169.420166, 40.979898 ], [ 161.718750, 45.336702 ], [ 156.796875, 54.977614 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.187988, 66.513260 ], [ 180.000000, 66.513260 ], [ 180.000000, 61.653379 ], [ 174.023438, 58.813742 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.000000, 45.213004 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 40.979898 ], [ 180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 7, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 67.516972 ], [ 180.000000, 66.513260 ], [ 175.187988, 66.513260 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.516972 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.004322 ], [ -180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.001310 ], [ -180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.001310 ], [ -173.001709, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.001310 ], [ -172.001953, 21.943046 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 40.979898 ], [ -157.500000, 36.796090 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.518466 ], [ -180.000000, 40.979898 ], [ -157.500000, 40.979898 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.943046 ], [ -180.000000, 40.979898 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.943046 ], [ -180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 21.943046 ], [ -173.001709, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 21.943046 ], [ -172.001953, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 45.406164 ], [ -157.500000, 40.979898 ], [ -180.000000, 40.979898 ], [ -180.000000, 45.213004 ], [ -177.539062, 44.339565 ], [ -164.882812, 43.325178 ], [ -157.500000, 45.406164 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 40.979898 ], [ -180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 63.597448 ], [ -158.554688, 63.860036 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.650771 ], [ -180.000000, 66.513260 ], [ -157.500000, 66.513260 ], [ -157.500000, 63.597448 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 0, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -169.101562, 68.269387 ], [ -157.500000, 68.153165 ], [ -157.500000, 66.513260 ], [ -180.000000, 66.513260 ], [ -180.000000, 67.514872 ], [ -169.101562, 68.269387 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 1, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -143.404541, 40.979898 ], [ -146.250000, 38.548165 ], [ -157.500000, 36.796090 ], [ -157.500000, 40.979898 ], [ -143.404541, 40.979898 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 1, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 45.406164 ], [ -153.281250, 46.558860 ], [ -144.492188, 51.179343 ], [ -143.959351, 55.776573 ], [ -135.000000, 55.776573 ], [ -135.000000, 47.650588 ], [ -143.404541, 40.979898 ], [ -157.500000, 40.979898 ], [ -157.500000, 45.406164 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 1, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 63.597448 ], [ -157.500000, 66.513260 ], [ -146.815796, 66.513260 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.570575 ], [ -135.000000, 55.776573 ], [ -143.959351, 55.776573 ], [ -143.789062, 57.136239 ], [ -148.007812, 61.100789 ], [ -157.500000, 63.597448 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 1, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 68.153165 ], [ -156.093750, 68.138852 ], [ -146.815796, 66.513260 ], [ -157.500000, 66.513260 ], [ -157.500000, 68.153165 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 2, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -131.984253, 55.776573 ], [ -131.835938, 55.379110 ], [ -133.593750, 48.690960 ], [ -135.000000, 47.650588 ], [ -135.000000, 55.776573 ], [ -131.984253, 55.776573 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 2, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -135.000000, 62.570575 ], [ -134.648438, 62.431074 ], [ -131.984253, 55.776573 ], [ -135.000000, 55.776573 ], [ -135.000000, 62.570575 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 7, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.005197 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 46.316584 ], [ 16.171875, 51.618017 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 14, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 157.500000, 55.776573 ], [ 157.500000, 53.719466 ], [ 156.796875, 54.977614 ], [ 157.445068, 55.776573 ], [ 157.500000, 55.776573 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 14, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 157.500000, 55.841398 ], [ 157.500000, 55.776573 ], [ 157.445068, 55.776573 ], [ 157.500000, 55.841398 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.004322 ], [ 180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.001310 ], [ 180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.996460, 10.001310 ], [ 171.996460, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.996216, 10.001310 ], [ 172.996216, 21.943046 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 40.979898 ], [ 180.000000, 36.518466 ], [ 175.781250, 37.160317 ], [ 169.425659, 40.979898 ], [ 180.000000, 40.979898 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.943046 ], [ 180.000000, 40.979898 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.943046 ], [ 180.000000, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.996460, 21.943046 ], [ 171.996460, 30.002517 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.996216, 21.943046 ], [ 172.996216, 30.002517 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 45.213004 ], [ 180.000000, 40.979898 ], [ 169.425659, 40.979898 ], [ 161.718750, 45.336702 ], [ 157.500000, 53.719466 ], [ 157.500000, 55.776573 ], [ 172.309570, 55.776573 ], [ 171.562500, 54.367759 ], [ 174.023438, 47.279229 ], [ 180.000000, 45.213004 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 40.979898 ], [ 180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 66.513260 ], [ 180.000000, 61.650771 ], [ 174.023438, 58.813742 ], [ 172.309570, 55.776573 ], [ 157.500000, 55.776573 ], [ 157.500000, 55.841398 ], [ 163.476562, 62.431074 ], [ 170.507812, 64.774125 ], [ 175.193481, 66.513260 ], [ 180.000000, 66.513260 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 15, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 67.514872 ], [ 180.000000, 66.513260 ], [ 175.193481, 66.513260 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.514872 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 10.001310 ], [ -180.000000, 11.178402 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 10.001310 ], [ -173.001709, 11.178402 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 10.001310 ], [ -172.001953, 11.178402 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 14 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 20.001741 ], [ -180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 11.178402 ], [ -180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 11.178402 ], [ -173.001709, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 11.178402 ], [ -172.001953, 21.943046 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 13 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.943046 ], [ -180.000000, 31.952162 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 21.943046 ], [ -180.000000, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -173.001709, 21.943046 ], [ -173.001709, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "-172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ -172.001953, 21.943046 ], [ -172.001953, 30.000138 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.750000, 40.979898 ], [ -168.750000, 35.000754 ], [ -169.453125, 34.885931 ], [ -180.000000, 36.518466 ], [ -180.000000, 40.979898 ], [ -168.750000, 40.979898 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 31.952162 ], [ -180.000000, 40.979898 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -180.000000, 45.213004 ], [ -177.539062, 44.339565 ], [ -168.750000, 43.638063 ], [ -168.750000, 40.979898 ], [ -180.000000, 40.979898 ], [ -180.000000, 45.213004 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 40.979898 ], [ -180.000000, 48.922499 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ -180.000000, 48.922499 ], [ -180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.750000, 64.433707 ], [ -169.453125, 64.472794 ], [ -177.890625, 62.593341 ], [ -180.000000, 61.650771 ], [ -180.000000, 66.513260 ], [ -168.750000, 66.513260 ], [ -168.750000, 64.433707 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 0, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -169.101562, 68.269387 ], [ -168.750000, 68.266336 ], [ -168.750000, 66.513260 ], [ -180.000000, 66.513260 ], [ -180.000000, 67.514872 ], [ -169.101562, 68.269387 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 1, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 40.979898 ], [ -157.500000, 36.796090 ], [ -168.750000, 35.000754 ], [ -168.750000, 40.979898 ], [ -157.500000, 40.979898 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 1, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 45.404235 ], [ -157.500000, 40.979898 ], [ -168.750000, 40.979898 ], [ -168.750000, 43.638063 ], [ -164.882812, 43.325178 ], [ -157.500000, 45.404235 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 1, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.750000, 64.433707 ], [ -168.750000, 66.513260 ], [ -157.500000, 66.513260 ], [ -157.500000, 63.596226 ], [ -158.554688, 63.860036 ], [ -168.750000, 64.433707 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 1, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -168.750000, 68.266336 ], [ -157.500000, 68.153165 ], [ -157.500000, 66.513260 ], [ -168.750000, 66.513260 ], [ -168.750000, 68.266336 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.250000, 40.979898 ], [ -146.250000, 38.548165 ], [ -157.500000, 36.796090 ], [ -157.500000, 40.979898 ], [ -146.250000, 40.979898 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 45.404235 ], [ -153.281250, 46.558860 ], [ -148.886719, 48.922499 ], [ -146.250000, 48.922499 ], [ -146.250000, 40.979898 ], [ -157.500000, 40.979898 ], [ -157.500000, 45.404235 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.250000, 50.289339 ], [ -146.250000, 48.922499 ], [ -148.886719, 48.922499 ], [ -146.250000, 50.289339 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.250000, 59.505061 ], [ -148.007812, 61.100789 ], [ -149.869995, 61.606396 ], [ -146.250000, 61.606396 ], [ -146.250000, 59.505061 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 63.596226 ], [ -157.500000, 66.513260 ], [ -146.813049, 66.513260 ], [ -146.250000, 66.411253 ], [ -146.250000, 61.606396 ], [ -149.869995, 61.606396 ], [ -157.500000, 63.596226 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 2, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -157.500000, 68.153165 ], [ -156.093750, 68.138852 ], [ -146.813049, 66.513260 ], [ -157.500000, 66.513260 ], [ -157.500000, 68.153165 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -143.404541, 40.979898 ], [ -146.250000, 38.548165 ], [ -146.250000, 40.979898 ], [ -143.404541, 40.979898 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -135.000000, 48.922499 ], [ -135.000000, 47.650588 ], [ -143.404541, 40.979898 ], [ -146.250000, 40.979898 ], [ -146.250000, 48.922499 ], [ -135.000000, 48.922499 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.250000, 50.289339 ], [ -144.492188, 51.179343 ], [ -143.959351, 55.776573 ], [ -135.000000, 55.776573 ], [ -135.000000, 48.922499 ], [ -146.250000, 48.922499 ], [ -146.250000, 50.289339 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.250000, 59.505061 ], [ -146.250000, 61.606396 ], [ -135.000000, 61.606396 ], [ -135.000000, 55.776573 ], [ -143.959351, 55.776573 ], [ -143.789062, 57.136239 ], [ -146.250000, 59.505061 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 3, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -146.250000, 66.411253 ], [ -144.492188, 66.089364 ], [ -135.000000, 62.570575 ], [ -135.000000, 61.606396 ], [ -146.250000, 61.606396 ], [ -146.250000, 66.411253 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 4, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -133.538818, 48.922499 ], [ -133.593750, 48.690960 ], [ -135.000000, 47.650588 ], [ -135.000000, 48.922499 ], [ -133.538818, 48.922499 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 4, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -131.981506, 55.776573 ], [ -131.835938, 55.379110 ], [ -133.538818, 48.922499 ], [ -135.000000, 48.922499 ], [ -135.000000, 55.776573 ], [ -131.981506, 55.776573 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 4, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -134.288635, 61.606396 ], [ -131.981506, 55.776573 ], [ -135.000000, 55.776573 ], [ -135.000000, 61.606396 ], [ -134.288635, 61.606396 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 4, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -135.000000, 62.570575 ], [ -134.648438, 62.431074 ], [ -134.288635, 61.606396 ], [ -135.000000, 61.606396 ], [ -135.000000, 62.570575 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 15, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ -2.109375, 45.583290 ], [ 0.000000, 46.316584 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "0-5, since 10 > 5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 0.000000 ], [ 0.999756, 1.002451 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ 0.000000, 46.316584 ], [ 7.734375, 48.922499 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 16, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ 7.734375, 48.922499 ], [ 11.250000, 50.064192 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 17, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "zoom": "3-5" }, "geometry": { "type": "LineString", "coordinates": [ [ 11.250000, 50.064192 ], [ 16.171875, 51.618017 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 29, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 157.500000, 55.776573 ], [ 157.500000, 53.719466 ], [ 156.796875, 54.977614 ], [ 157.447815, 55.776573 ], [ 157.500000, 55.776573 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 29, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 157.500000, 55.839856 ], [ 157.500000, 55.776573 ], [ 157.447815, 55.776573 ], [ 157.500000, 55.839856 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 30, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 168.750000, 48.922499 ], [ 168.750000, 41.376809 ], [ 161.718750, 45.336702 ], [ 159.999390, 48.922499 ], [ 168.750000, 48.922499 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 30, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 168.750000, 55.776573 ], [ 168.750000, 48.922499 ], [ 159.999390, 48.922499 ], [ 157.500000, 53.719466 ], [ 157.500000, 55.776573 ], [ 168.750000, 55.776573 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 30, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 168.750000, 61.606396 ], [ 168.750000, 55.776573 ], [ 157.500000, 55.776573 ], [ 157.500000, 55.839856 ], [ 162.660828, 61.606396 ], [ 168.750000, 61.606396 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 30, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 168.750000, 64.206377 ], [ 168.750000, 61.606396 ], [ 162.660828, 61.606396 ], [ 163.476562, 62.431074 ], [ 168.750000, 64.206377 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 15 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 10.001310 ], [ 180.000000, 11.178402 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.999207, 10.001310 ], [ 171.999207, 11.178402 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.998962, 10.001310 ], [ 172.998962, 11.178402 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 14 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 20.001741 ], [ 180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 11.178402 ], [ 180.000000, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.999207, 11.178402 ], [ 171.999207, 21.943046 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.998962, 11.178402 ], [ 172.998962, 21.943046 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 13 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.943046 ], [ 180.000000, 31.952162 ] ] } }
,
{ "type": "Feature", "properties": { "where": "180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 21.943046 ], [ 180.000000, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "172, not duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 171.999207, 21.943046 ], [ 171.999207, 30.000138 ] ] } }
,
{ "type": "Feature", "properties": { "where": "173, duplicated" }, "geometry": { "type": "LineString", "coordinates": [ [ 172.998962, 21.943046 ], [ 172.998962, 30.000138 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 12 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 40.979898 ], [ 180.000000, 36.518466 ], [ 175.781250, 37.160317 ], [ 169.428406, 40.979898 ], [ 180.000000, 40.979898 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 31.952162 ], [ 180.000000, 40.979898 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 11 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 45.213004 ], [ 180.000000, 40.979898 ], [ 169.428406, 40.979898 ], [ 168.750000, 41.376809 ], [ 168.750000, 48.922499 ], [ 173.485107, 48.922499 ], [ 174.023438, 47.279229 ], [ 180.000000, 45.213004 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 40.979898 ], [ 180.000000, 48.922499 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 10 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 172.309570, 55.776573 ], [ 171.562500, 54.367759 ], [ 173.485107, 48.922499 ], [ 168.750000, 48.922499 ], [ 168.750000, 55.776573 ], [ 172.309570, 55.776573 ] ] ] } }
,
{ "type": "Feature", "properties": { "where": "-180" }, "geometry": { "type": "LineString", "coordinates": [ [ 180.000000, 48.922499 ], [ 180.000000, 50.000678 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 179.901123, 61.606396 ], [ 174.023438, 58.813742 ], [ 172.309570, 55.776573 ], [ 168.750000, 55.776573 ], [ 168.750000, 61.606396 ], [ 179.901123, 61.606396 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 66.513260 ], [ 180.000000, 61.650771 ], [ 179.901123, 61.606396 ], [ 168.750000, 61.606396 ], [ 168.750000, 64.206377 ], [ 170.507812, 64.774125 ], [ 175.193481, 66.513260 ], [ 180.000000, 66.513260 ] ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 5, "x": 31, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "boolean": true, "otherboolean": false, "stringify": "[\"yes\",27,27,1.4e+27,{\"foo\":\"bar\"}]", "": "something for nothing", "escape": "foo\u0001bar,ü\"\\/\u0008\u000c\u000a\u000d\u0009→🐂🐳", "prêt": "ready" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 180.000000, 67.514872 ], [ 180.000000, 66.513260 ], [ 175.193481, 66.513260 ], [ 177.539062, 67.339861 ], [ 180.000000, 67.514872 ] ] ] } }
] }
] }
] }

View File

@ -3,6 +3,7 @@
"center": "-122.249782,37.796763,14",
"description": "tests/empty-linestring/out/-ac.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/empty-linestring/out/-ac.json.check.mbtiles -ac tests/empty-linestring/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 14, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 5,\"geometry\": \"LineString\",\"attributeCount\": 0,\"attributes\": []}]}}",
"maxzoom": "14",
"minzoom": "0",

View File

@ -3,6 +3,7 @@
"center": "16.875000,44.951199,5",
"description": "tests/epsg-3857/out/-yNAME_-z5_-sEPSG@3857.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/epsg-3857/out/-yNAME_-z5_-sEPSG@3857.json.check.mbtiles -yNAME -z5 -sEPSG:3857 tests/epsg-3857/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 5, \"fields\": {\"NAME\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 243,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"NAME\",\"count\": 243,\"type\": \"string\",\"values\": [\"Abidjan\",\"Abu Dhabi\",\"Abuja\",\"Accra\",\"Addis Ababa\",\"Algiers\",\"Amman\",\"Amsterdam\",\"Andorra\",\"Ankara\",\"Antananarivo\",\"Apia\",\"Ashgabat\",\"Asmara\",\"Astana\",\"Asuncion\",\"Athens\",\"Atlanta\",\"Auckland\",\"Baghdad\",\"Baguio City\",\"Baku\",\"Bamako\",\"Bandar Seri Begawan\",\"Bangalore\",\"Bangkok\",\"Bangui\",\"Banjul\",\"Basseterre\",\"Beijing\",\"Beirut\",\"Belgrade\",\"Belmopan\",\"Berlin\",\"Bern\",\"Bir Lehlou\",\"Bishkek\",\"Bissau\",\"Bloemfontein\",\"Bogota\",\"Brasilia\",\"Bratislava\",\"Brazzaville\",\"Bridgetown\",\"Brussels\",\"Bucharest\",\"Budapest\",\"Buenos Aires\",\"Bujumbura\",\"Cairo\",\"Canberra\",\"Cape Town\",\"Caracas\",\"Casablanca\",\"Castries\",\"Chengdu\",\"Chicago\",\"Chisinau\",\"Colombo\",\"Conakry\",\"Cotonou\",\"Dakar\",\"Damascus\",\"Dar es Salaam\",\"Denver\",\"Dhaka\",\"Dili\",\"Djibouti\",\"Dodoma\",\"Doha\",\"Dubai\",\"Dublin\",\"Dushanbe\",\"Freetown\",\"Funafuti\",\"Gaborone\",\"Geneva\",\"Georgetown\",\"Guatemala\",\"Hanoi\",\"Harare\",\"Hargeysa\",\"Havana\",\"Helsinki\",\"Hong Kong\",\"Honiara\",\"Houston\",\"Islamabad\",\"Istanbul\",\"Jakarta\",\"Jerusalem\",\"Johannesburg\",\"Juba\",\"Kabul\",\"Kampala\",\"Kathmandu\",\"Khartoum\",\"Kiev\",\"Kigali\",\"Kingston\"]}]}]}}",
"maxzoom": "5",
"minzoom": "0",
@ -14,9 +15,9 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Vancouver" }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.325122 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cotonou" }, "geometry": { "type": "Point", "coordinates": [ 2.460938, 6.402648 ] } }
{ "type": "Feature", "properties": { "NAME": "Malabo" }, "geometry": { "type": "Point", "coordinates": [ 8.701172, 3.776559 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bandar Seri Begawan" }, "geometry": { "type": "Point", "coordinates": [ 114.873047, 4.915833 ] } }
{ "type": "Feature", "properties": { "NAME": "Kinshasa" }, "geometry": { "type": "Point", "coordinates": [ 15.292969, -4.302591 ] } }
] }
] }
,
@ -30,27 +31,29 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Vancouver" }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.296472 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Praia" }, "geometry": { "type": "Point", "coordinates": [ -23.554688, 14.944785 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cotonou" }, "geometry": { "type": "Point", "coordinates": [ 2.504883, 6.402648 ] } }
{ "type": "Feature", "properties": { "NAME": "Conakry" }, "geometry": { "type": "Point", "coordinates": [ -13.710938, 9.535749 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Brazzaville" }, "geometry": { "type": "Point", "coordinates": [ 15.249023, -4.214943 ] } }
{ "type": "Feature", "properties": { "NAME": "Sao Tome" }, "geometry": { "type": "Point", "coordinates": [ 6.723633, 0.351560 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kinshasa" }, "geometry": { "type": "Point", "coordinates": [ 15.292969, -4.302591 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Honiara" }, "geometry": { "type": "Point", "coordinates": [ 159.916992, -9.405710 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Oslo" }, "geometry": { "type": "Point", "coordinates": [ 10.722656, 59.933000 ] } }
{ "type": "Feature", "properties": { "NAME": "London" }, "geometry": { "type": "Point", "coordinates": [ -0.131836, 51.508742 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cotonou" }, "geometry": { "type": "Point", "coordinates": [ 2.504883, 6.402648 ] } }
{ "type": "Feature", "properties": { "NAME": "Geneva" }, "geometry": { "type": "Point", "coordinates": [ 6.108398, 46.225453 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Baku" }, "geometry": { "type": "Point", "coordinates": [ 49.833984, 40.413496 ] } }
{ "type": "Feature", "properties": { "NAME": "Malabo" }, "geometry": { "type": "Point", "coordinates": [ 8.745117, 3.776559 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bandar Seri Begawan" }, "geometry": { "type": "Point", "coordinates": [ 114.916992, 4.915833 ] } }
{ "type": "Feature", "properties": { "NAME": "Kuwait" }, "geometry": { "type": "Point", "coordinates": [ 47.944336, 29.382175 ] } }
] }
] }
,
@ -63,6 +66,8 @@
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 0, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Vancouver" }, "geometry": { "type": "Point", "coordinates": [ -123.134766, 49.282140 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Salvador" }, "geometry": { "type": "Point", "coordinates": [ -89.208984, 13.731381 ] } }
] }
] }
,
@ -74,13 +79,13 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 1, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Chicago" }, "geometry": { "type": "Point", "coordinates": [ -87.758789, 41.836828 ] } }
{ "type": "Feature", "properties": { "NAME": "Guatemala" }, "geometry": { "type": "Point", "coordinates": [ -90.549316, 14.626109 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port-au-Prince" }, "geometry": { "type": "Point", "coordinates": [ -72.355957, 18.562947 ] } }
{ "type": "Feature", "properties": { "NAME": "San Salvador" }, "geometry": { "type": "Point", "coordinates": [ -89.208984, 13.731381 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Praia" }, "geometry": { "type": "Point", "coordinates": [ -23.532715, 14.923554 ] } }
{ "type": "Feature", "properties": { "NAME": "Saint George's" }, "geometry": { "type": "Point", "coordinates": [ -61.743164, 12.060809 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ouagadougou" }, "geometry": { "type": "Point", "coordinates": [ -1.538086, 12.382928 ] } }
{ "type": "Feature", "properties": { "NAME": "Conakry" }, "geometry": { "type": "Point", "coordinates": [ -13.688965, 9.535749 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Quito" }, "geometry": { "type": "Point", "coordinates": [ -78.508301, -0.197754 ] } }
] }
@ -88,43 +93,47 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Brazzaville" }, "geometry": { "type": "Point", "coordinates": [ 15.270996, -4.236856 ] } }
{ "type": "Feature", "properties": { "NAME": "Sao Tome" }, "geometry": { "type": "Point", "coordinates": [ 6.723633, 0.351560 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Pretoria" }, "geometry": { "type": "Point", "coordinates": [ 28.212891, -25.700938 ] } }
{ "type": "Feature", "properties": { "NAME": "Kinshasa" }, "geometry": { "type": "Point", "coordinates": [ 15.292969, -4.324501 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Moroni" }, "geometry": { "type": "Point", "coordinates": [ 43.220215, -11.695273 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 2, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Ouagadougou" }, "geometry": { "type": "Point", "coordinates": [ -1.538086, 12.382928 ] } }
{ "type": "Feature", "properties": { "NAME": "London" }, "geometry": { "type": "Point", "coordinates": [ -0.131836, 51.508742 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Oslo" }, "geometry": { "type": "Point", "coordinates": [ 10.744629, 59.921990 ] } }
{ "type": "Feature", "properties": { "NAME": "Geneva" }, "geometry": { "type": "Point", "coordinates": [ 6.130371, 46.210250 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Marino" }, "geometry": { "type": "Point", "coordinates": [ 12.436523, 43.945372 ] } }
{ "type": "Feature", "properties": { "NAME": "Vatican City" }, "geometry": { "type": "Point", "coordinates": [ 12.436523, 41.918629 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Riga" }, "geometry": { "type": "Point", "coordinates": [ 24.082031, 56.956957 ] } }
{ "type": "Feature", "properties": { "NAME": "Chisinau" }, "geometry": { "type": "Point", "coordinates": [ 28.850098, 47.010226 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cotonou" }, "geometry": { "type": "Point", "coordinates": [ 2.504883, 6.402648 ] } }
{ "type": "Feature", "properties": { "NAME": "Malabo" }, "geometry": { "type": "Point", "coordinates": [ 8.767090, 3.754634 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Jerusalem" }, "geometry": { "type": "Point", "coordinates": [ 35.200195, 31.784217 ] } }
{ "type": "Feature", "properties": { "NAME": "Juba" }, "geometry": { "type": "Point", "coordinates": [ 31.574707, 4.850154 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Baku" }, "geometry": { "type": "Point", "coordinates": [ 49.855957, 40.413496 ] } }
{ "type": "Feature", "properties": { "NAME": "Kuwait" }, "geometry": { "type": "Point", "coordinates": [ 47.966309, 29.382175 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Islamabad" }, "geometry": { "type": "Point", "coordinates": [ 73.146973, 33.706063 ] } }
{ "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte" }, "geometry": { "type": "Point", "coordinates": [ 79.936523, 6.904614 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 3, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Jakarta" }, "geometry": { "type": "Point", "coordinates": [ 106.809082, -6.162401 ] } }
{ "type": "Feature", "properties": { "NAME": "Singapore" }, "geometry": { "type": "Point", "coordinates": [ 103.842773, 1.296276 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Honiara" }, "geometry": { "type": "Point", "coordinates": [ 159.938965, -9.427387 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 3, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Ulaanbaatar" }, "geometry": { "type": "Point", "coordinates": [ 106.896973, 47.931066 ] } }
{ "type": "Feature", "properties": { "NAME": "Thimphu" }, "geometry": { "type": "Point", "coordinates": [ 89.626465, 27.488781 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bandar Seri Begawan" }, "geometry": { "type": "Point", "coordinates": [ 114.916992, 4.893941 ] } }
{ "type": "Feature", "properties": { "NAME": "Kuala Lumpur" }, "geometry": { "type": "Point", "coordinates": [ 101.689453, 3.184394 ] } }
] }
] }
,
@ -137,6 +146,10 @@
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 1, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "San Francisco" }, "geometry": { "type": "Point", "coordinates": [ -122.420654, 37.770715 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Guatemala" }, "geometry": { "type": "Point", "coordinates": [ -90.538330, 14.626109 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Salvador" }, "geometry": { "type": "Point", "coordinates": [ -89.208984, 13.720708 ] } }
] }
] }
,
@ -156,15 +169,17 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 2, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Atlanta" }, "geometry": { "type": "Point", "coordinates": [ -84.407959, 33.833920 ] } }
{ "type": "Feature", "properties": { "NAME": "Guatemala" }, "geometry": { "type": "Point", "coordinates": [ -90.538330, 14.626109 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Belmopan" }, "geometry": { "type": "Point", "coordinates": [ -88.769531, 17.256236 ] } }
{ "type": "Feature", "properties": { "NAME": "Havana" }, "geometry": { "type": "Point", "coordinates": [ -82.375488, 23.140360 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port-au-Prince" }, "geometry": { "type": "Point", "coordinates": [ -72.344971, 18.552532 ] } }
{ "type": "Feature", "properties": { "NAME": "San Salvador" }, "geometry": { "type": "Point", "coordinates": [ -89.208984, 13.720708 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Roseau" }, "geometry": { "type": "Point", "coordinates": [ -61.391602, 15.305380 ] } }
{ "type": "Feature", "properties": { "NAME": "Basseterre" }, "geometry": { "type": "Point", "coordinates": [ -62.720947, 17.308688 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Georgetown" }, "geometry": { "type": "Point", "coordinates": [ -58.172607, 6.806444 ] } }
{ "type": "Feature", "properties": { "NAME": "Saint George's" }, "geometry": { "type": "Point", "coordinates": [ -61.743164, 12.060809 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Paramaribo" }, "geometry": { "type": "Point", "coordinates": [ -55.173340, 5.845545 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Quito" }, "geometry": { "type": "Point", "coordinates": [ -78.508301, -0.208740 ] } }
] }
@ -186,9 +201,11 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Praia" }, "geometry": { "type": "Point", "coordinates": [ -23.521729, 14.923554 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dakar" }, "geometry": { "type": "Point", "coordinates": [ -17.479248, 14.721761 ] } }
{ "type": "Feature", "properties": { "NAME": "Casablanca" }, "geometry": { "type": "Point", "coordinates": [ -7.624512, 33.605470 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ouagadougou" }, "geometry": { "type": "Point", "coordinates": [ -1.527100, 12.382928 ] } }
{ "type": "Feature", "properties": { "NAME": "Conakry" }, "geometry": { "type": "Point", "coordinates": [ -13.688965, 9.535749 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Yamoussoukro" }, "geometry": { "type": "Point", "coordinates": [ -5.284424, 6.828261 ] } }
] }
] }
,
@ -200,47 +217,51 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Brazzaville" }, "geometry": { "type": "Point", "coordinates": [ 15.281982, -4.247812 ] } }
{ "type": "Feature", "properties": { "NAME": "Sao Tome" }, "geometry": { "type": "Point", "coordinates": [ 6.723633, 0.340574 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lusaka" }, "geometry": { "type": "Point", "coordinates": [ 28.278809, -15.411319 ] } }
{ "type": "Feature", "properties": { "NAME": "Kinshasa" }, "geometry": { "type": "Point", "coordinates": [ 15.303955, -4.324501 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lilongwe" }, "geometry": { "type": "Point", "coordinates": [ 33.782959, -13.976715 ] } }
{ "type": "Feature", "properties": { "NAME": "Bujumbura" }, "geometry": { "type": "Point", "coordinates": [ 29.355469, -3.370856 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Pretoria" }, "geometry": { "type": "Point", "coordinates": [ 28.223877, -25.700938 ] } }
{ "type": "Feature", "properties": { "NAME": "Moroni" }, "geometry": { "type": "Point", "coordinates": [ 43.231201, -11.695273 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Maputo" }, "geometry": { "type": "Point", "coordinates": [ 32.585449, -25.948166 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Algiers" }, "geometry": { "type": "Point", "coordinates": [ 3.043213, 36.765292 ] } }
{ "type": "Feature", "properties": { "NAME": "Accra" }, "geometry": { "type": "Point", "coordinates": [ -0.219727, 5.561315 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cotonou" }, "geometry": { "type": "Point", "coordinates": [ 2.515869, 6.402648 ] } }
{ "type": "Feature", "properties": { "NAME": "Valletta" }, "geometry": { "type": "Point", "coordinates": [ 14.512939, 35.906849 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ndjamena" }, "geometry": { "type": "Point", "coordinates": [ 15.040283, 12.125264 ] } }
{ "type": "Feature", "properties": { "NAME": "Malabo" }, "geometry": { "type": "Point", "coordinates": [ 8.778076, 3.754634 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nicosia" }, "geometry": { "type": "Point", "coordinates": [ 33.365479, 35.173808 ] } }
{ "type": "Feature", "properties": { "NAME": "Athens" }, "geometry": { "type": "Point", "coordinates": [ 23.730469, 37.987504 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Jerusalem" }, "geometry": { "type": "Point", "coordinates": [ 35.200195, 31.784217 ] } }
{ "type": "Feature", "properties": { "NAME": "Beirut" }, "geometry": { "type": "Point", "coordinates": [ 35.496826, 33.879537 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sanaa" }, "geometry": { "type": "Point", "coordinates": [ 44.197998, 15.358356 ] } }
{ "type": "Feature", "properties": { "NAME": "Juba" }, "geometry": { "type": "Point", "coordinates": [ 31.574707, 4.839207 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Oslo" }, "geometry": { "type": "Point", "coordinates": [ 10.744629, 59.921990 ] } }
{ "type": "Feature", "properties": { "NAME": "London" }, "geometry": { "type": "Point", "coordinates": [ -0.120850, 51.508742 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Paris" }, "geometry": { "type": "Point", "coordinates": [ 2.329102, 48.871941 ] } }
{ "type": "Feature", "properties": { "NAME": "Amsterdam" }, "geometry": { "type": "Point", "coordinates": [ 4.910889, 52.355474 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Prague" }, "geometry": { "type": "Point", "coordinates": [ 14.458008, 50.085344 ] } }
{ "type": "Feature", "properties": { "NAME": "Geneva" }, "geometry": { "type": "Point", "coordinates": [ 6.130371, 46.210250 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Marino" }, "geometry": { "type": "Point", "coordinates": [ 12.436523, 43.937462 ] } }
{ "type": "Feature", "properties": { "NAME": "Berlin" }, "geometry": { "type": "Point", "coordinates": [ 13.392334, 52.529590 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Belgrade" }, "geometry": { "type": "Point", "coordinates": [ 20.456543, 44.824708 ] } }
{ "type": "Feature", "properties": { "NAME": "Vatican City" }, "geometry": { "type": "Point", "coordinates": [ 12.447510, 41.910453 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Riga" }, "geometry": { "type": "Point", "coordinates": [ 24.093018, 56.950966 ] } }
{ "type": "Feature", "properties": { "NAME": "Pristina" }, "geometry": { "type": "Point", "coordinates": [ 21.159668, 42.674359 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bucharest" }, "geometry": { "type": "Point", "coordinates": [ 26.092529, 44.441624 ] } }
{ "type": "Feature", "properties": { "NAME": "Vilnius" }, "geometry": { "type": "Point", "coordinates": [ 25.312500, 54.686534 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Chisinau" }, "geometry": { "type": "Point", "coordinates": [ 28.850098, 47.010226 ] } }
] }
] }
,
@ -252,45 +273,45 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 5, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Sanaa" }, "geometry": { "type": "Point", "coordinates": [ 44.197998, 15.358356 ] } }
{ "type": "Feature", "properties": { "NAME": "Yerevan" }, "geometry": { "type": "Point", "coordinates": [ 44.505615, 40.187267 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Baku" }, "geometry": { "type": "Point", "coordinates": [ 49.855957, 40.405131 ] } }
{ "type": "Feature", "properties": { "NAME": "Tashkent" }, "geometry": { "type": "Point", "coordinates": [ 69.290771, 41.319076 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kuwait" }, "geometry": { "type": "Point", "coordinates": [ 47.966309, 29.372602 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Abu Dhabi" }, "geometry": { "type": "Point", "coordinates": [ 54.360352, 24.467151 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Islamabad" }, "geometry": { "type": "Point", "coordinates": [ 73.157959, 33.706063 ] } }
{ "type": "Feature", "properties": { "NAME": "New Delhi" }, "geometry": { "type": "Point", "coordinates": [ 77.189941, 28.603814 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Mumbai" }, "geometry": { "type": "Point", "coordinates": [ 72.850342, 19.020577 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dhaka" }, "geometry": { "type": "Point", "coordinates": [ 90.406494, 23.725012 ] } }
{ "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte" }, "geometry": { "type": "Point", "coordinates": [ 79.947510, 6.904614 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 5, "y": 2 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Astana" }, "geometry": { "type": "Point", "coordinates": [ 71.422119, 51.186230 ] } }
{ "type": "Feature", "properties": { "NAME": "Tbilisi" }, "geometry": { "type": "Point", "coordinates": [ 44.780273, 41.730330 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Baku" }, "geometry": { "type": "Point", "coordinates": [ 49.855957, 40.405131 ] } }
{ "type": "Feature", "properties": { "NAME": "Tashkent" }, "geometry": { "type": "Point", "coordinates": [ 69.290771, 41.319076 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 6, "y": 4 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Jakarta" }, "geometry": { "type": "Point", "coordinates": [ 106.820068, -6.162401 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dili" }, "geometry": { "type": "Point", "coordinates": [ 125.573730, -8.559294 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 6, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Dhaka" }, "geometry": { "type": "Point", "coordinates": [ 90.406494, 23.725012 ] } }
{ "type": "Feature", "properties": { "NAME": "Thimphu" }, "geometry": { "type": "Point", "coordinates": [ 89.637451, 27.479035 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Hanoi" }, "geometry": { "type": "Point", "coordinates": [ 105.842285, 21.043491 ] } }
{ "type": "Feature", "properties": { "NAME": "Rangoon" }, "geometry": { "type": "Point", "coordinates": [ 96.163330, 16.794024 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Shanghai" }, "geometry": { "type": "Point", "coordinates": [ 121.431885, 31.222197 ] } }
{ "type": "Feature", "properties": { "NAME": "Kuala Lumpur" }, "geometry": { "type": "Point", "coordinates": [ 101.689453, 3.173425 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bandar Seri Begawan" }, "geometry": { "type": "Point", "coordinates": [ 114.927979, 4.893941 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Osaka" }, "geometry": { "type": "Point", "coordinates": [ 135.450439, 34.759666 ] } }
{ "type": "Feature", "properties": { "NAME": "Pyongyang" }, "geometry": { "type": "Point", "coordinates": [ 125.749512, 39.027719 ] } }
] }
] }
,
@ -310,15 +331,15 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Port Moresby" }, "geometry": { "type": "Point", "coordinates": [ 147.183838, -9.459899 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Funafuti" }, "geometry": { "type": "Point", "coordinates": [ 179.208984, -8.515836 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Wellington" }, "geometry": { "type": "Point", "coordinates": [ 174.781494, -41.294317 ] } }
{ "type": "Feature", "properties": { "NAME": "Honiara" }, "geometry": { "type": "Point", "coordinates": [ 159.938965, -9.427387 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 7, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Osaka" }, "geometry": { "type": "Point", "coordinates": [ 135.450439, 34.759666 ] } }
{ "type": "Feature", "properties": { "NAME": "Melekeok" }, "geometry": { "type": "Point", "coordinates": [ 134.626465, 7.493196 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tokyo" }, "geometry": { "type": "Point", "coordinates": [ 139.746094, 35.692995 ] } }
] }
] }
,
@ -331,6 +352,8 @@
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 2, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "San Francisco" }, "geometry": { "type": "Point", "coordinates": [ -122.420654, 37.770715 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Los Angeles" }, "geometry": { "type": "Point", "coordinates": [ -118.185425, 33.993473 ] } }
] }
] }
,
@ -343,6 +366,8 @@
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 3, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Mexico City" }, "geometry": { "type": "Point", "coordinates": [ -99.135132, 19.445874 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Guatemala" }, "geometry": { "type": "Point", "coordinates": [ -90.532837, 14.626109 ] } }
] }
] }
,
@ -350,7 +375,7 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Denver" }, "geometry": { "type": "Point", "coordinates": [ -104.990845, 39.745210 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Houston" }, "geometry": { "type": "Point", "coordinates": [ -95.344849, 29.826348 ] } }
{ "type": "Feature", "properties": { "NAME": "Monterrey" }, "geometry": { "type": "Point", "coordinates": [ -100.332642, 25.676187 ] } }
] }
] }
,
@ -374,12 +399,10 @@
,
{ "type": "Feature", "properties": { "NAME": "San Salvador" }, "geometry": { "type": "Point", "coordinates": [ -89.208984, 13.715372 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Jose" }, "geometry": { "type": "Point", "coordinates": [ -84.089355, 9.941798 ] } }
{ "type": "Feature", "properties": { "NAME": "Panama City" }, "geometry": { "type": "Point", "coordinates": [ -79.535522, 8.971897 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port-au-Prince" }, "geometry": { "type": "Point", "coordinates": [ -72.339478, 18.547325 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bogota" }, "geometry": { "type": "Point", "coordinates": [ -74.086304, 4.603803 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Quito" }, "geometry": { "type": "Point", "coordinates": [ -78.502808, -0.208740 ] } }
] }
] }
@ -388,9 +411,9 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Atlanta" }, "geometry": { "type": "Point", "coordinates": [ -84.402466, 33.833920 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Miami" }, "geometry": { "type": "Point", "coordinates": [ -80.227661, 25.790000 ] } }
{ "type": "Feature", "properties": { "NAME": "Havana" }, "geometry": { "type": "Point", "coordinates": [ -82.369995, 23.135309 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New York" }, "geometry": { "type": "Point", "coordinates": [ -73.987427, 40.755580 ] } }
{ "type": "Feature", "properties": { "NAME": "Washington, D.C." }, "geometry": { "type": "Point", "coordinates": [ -77.014160, 38.903858 ] } }
] }
] }
,
@ -398,9 +421,7 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Chicago" }, "geometry": { "type": "Point", "coordinates": [ -87.753296, 41.832735 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ottawa" }, "geometry": { "type": "Point", "coordinates": [ -75.706787, 45.421588 ] } }
,
{ "type": "Feature", "properties": { "NAME": "New York" }, "geometry": { "type": "Point", "coordinates": [ -73.987427, 40.755580 ] } }
{ "type": "Feature", "properties": { "NAME": "Toronto" }, "geometry": { "type": "Point", "coordinates": [ -79.425659, 43.703622 ] } }
] }
] }
,
@ -408,7 +429,7 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Asuncion" }, "geometry": { "type": "Point", "coordinates": [ -57.645264, -25.294371 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sao Paulo" }, "geometry": { "type": "Point", "coordinates": [ -46.631470, -23.553917 ] } }
{ "type": "Feature", "properties": { "NAME": "Montevideo" }, "geometry": { "type": "Point", "coordinates": [ -56.173096, -34.854383 ] } }
] }
] }
,
@ -424,11 +445,11 @@
,
{ "type": "Feature", "properties": { "NAME": "Roseau" }, "geometry": { "type": "Point", "coordinates": [ -61.391602, 15.305380 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kingstown" }, "geometry": { "type": "Point", "coordinates": [ -61.215820, 13.149027 ] } }
{ "type": "Feature", "properties": { "NAME": "Saint George's" }, "geometry": { "type": "Point", "coordinates": [ -61.743164, 12.055437 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Caracas" }, "geometry": { "type": "Point", "coordinates": [ -66.923218, 10.504016 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Georgetown" }, "geometry": { "type": "Point", "coordinates": [ -58.167114, 6.806444 ] } }
{ "type": "Feature", "properties": { "NAME": "Paramaribo" }, "geometry": { "type": "Point", "coordinates": [ -55.167847, 5.840081 ] } }
] }
] }
,
@ -448,13 +469,15 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Dakar" }, "geometry": { "type": "Point", "coordinates": [ -17.479248, 14.721761 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Banjul" }, "geometry": { "type": "Point", "coordinates": [ -16.594849, 13.459080 ] } }
{ "type": "Feature", "properties": { "NAME": "Nouakchott" }, "geometry": { "type": "Point", "coordinates": [ -15.979614, 18.088423 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Conakry" }, "geometry": { "type": "Point", "coordinates": [ -13.683472, 9.535749 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Ouagadougou" }, "geometry": { "type": "Point", "coordinates": [ -1.527100, 12.377563 ] } }
{ "type": "Feature", "properties": { "NAME": "Bamako" }, "geometry": { "type": "Point", "coordinates": [ -8.003540, 12.656418 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Yamoussoukro" }, "geometry": { "type": "Point", "coordinates": [ -5.278931, 6.822807 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Accra" }, "geometry": { "type": "Point", "coordinates": [ -0.219727, 5.555848 ] } }
] }
] }
,
@ -464,7 +487,7 @@
,
{ "type": "Feature", "properties": { "NAME": "Casablanca" }, "geometry": { "type": "Point", "coordinates": [ -7.619019, 33.605470 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Madrid" }, "geometry": { "type": "Point", "coordinates": [ -3.685913, 40.405131 ] } }
{ "type": "Feature", "properties": { "NAME": "Bir Lehlou" }, "geometry": { "type": "Point", "coordinates": [ -9.656982, 26.120918 ] } }
] }
] }
,
@ -488,15 +511,15 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 8 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Brazzaville" }, "geometry": { "type": "Point", "coordinates": [ 15.281982, -4.253290 ] } }
{ "type": "Feature", "properties": { "NAME": "Sao Tome" }, "geometry": { "type": "Point", "coordinates": [ 6.729126, 0.335081 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Luanda" }, "geometry": { "type": "Point", "coordinates": [ 13.227539, -8.836223 ] } }
{ "type": "Feature", "properties": { "NAME": "Kinshasa" }, "geometry": { "type": "Point", "coordinates": [ 15.309448, -4.324501 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Niamey" }, "geometry": { "type": "Point", "coordinates": [ 2.109375, 13.523179 ] } }
{ "type": "Feature", "properties": { "NAME": "Accra" }, "geometry": { "type": "Point", "coordinates": [ -0.219727, 5.555848 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Cotonou" }, "geometry": { "type": "Point", "coordinates": [ 2.515869, 6.402648 ] } }
,
@ -512,35 +535,37 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Algiers" }, "geometry": { "type": "Point", "coordinates": [ 3.043213, 36.765292 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tripoli" }, "geometry": { "type": "Point", "coordinates": [ 13.178101, 32.893426 ] } }
{ "type": "Feature", "properties": { "NAME": "Tunis" }, "geometry": { "type": "Point", "coordinates": [ 10.178833, 36.804887 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Valletta" }, "geometry": { "type": "Point", "coordinates": [ 14.512939, 35.902400 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 8, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "The Hague" }, "geometry": { "type": "Point", "coordinates": [ 4.268188, 52.082882 ] } }
{ "type": "Feature", "properties": { "NAME": "London" }, "geometry": { "type": "Point", "coordinates": [ -0.120850, 51.505323 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Brussels" }, "geometry": { "type": "Point", "coordinates": [ 4.328613, 50.837167 ] } }
{ "type": "Feature", "properties": { "NAME": "Amsterdam" }, "geometry": { "type": "Point", "coordinates": [ 4.910889, 52.352119 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Paris" }, "geometry": { "type": "Point", "coordinates": [ 2.329102, 48.871941 ] } }
{ "type": "Feature", "properties": { "NAME": "Luxembourg" }, "geometry": { "type": "Point", "coordinates": [ 6.124878, 49.614269 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bern" }, "geometry": { "type": "Point", "coordinates": [ 7.465210, 46.920255 ] } }
{ "type": "Feature", "properties": { "NAME": "Geneva" }, "geometry": { "type": "Point", "coordinates": [ 6.135864, 46.210250 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Monaco" }, "geometry": { "type": "Point", "coordinates": [ 7.404785, 43.743321 ] } }
{ "type": "Feature", "properties": { "NAME": "Vaduz" }, "geometry": { "type": "Point", "coordinates": [ 9.514160, 47.137425 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Prague" }, "geometry": { "type": "Point", "coordinates": [ 14.463501, 50.085344 ] } }
{ "type": "Feature", "properties": { "NAME": "Berlin" }, "geometry": { "type": "Point", "coordinates": [ 13.397827, 52.526248 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Vienna" }, "geometry": { "type": "Point", "coordinates": [ 16.364136, 48.202710 ] } }
{ "type": "Feature", "properties": { "NAME": "Warsaw" }, "geometry": { "type": "Point", "coordinates": [ 20.994873, 52.254709 ] } }
,
{ "type": "Feature", "properties": { "NAME": "San Marino" }, "geometry": { "type": "Point", "coordinates": [ 12.436523, 43.937462 ] } }
{ "type": "Feature", "properties": { "NAME": "Zagreb" }, "geometry": { "type": "Point", "coordinates": [ 15.996094, 45.801999 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Rome" }, "geometry": { "type": "Point", "coordinates": [ 12.480469, 41.898188 ] } }
{ "type": "Feature", "properties": { "NAME": "Vatican City" }, "geometry": { "type": "Point", "coordinates": [ 12.453003, 41.906365 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sarajevo" }, "geometry": { "type": "Point", "coordinates": [ 18.380127, 43.850374 ] } }
{ "type": "Feature", "properties": { "NAME": "Budapest" }, "geometry": { "type": "Point", "coordinates": [ 19.077759, 47.502359 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Belgrade" }, "geometry": { "type": "Point", "coordinates": [ 20.462036, 44.820812 ] } }
{ "type": "Feature", "properties": { "NAME": "Podgorica" }, "geometry": { "type": "Point", "coordinates": [ 19.264526, 42.468045 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Skopje" }, "geometry": { "type": "Point", "coordinates": [ 21.428833, 42.000325 ] } }
{ "type": "Feature", "properties": { "NAME": "Pristina" }, "geometry": { "type": "Point", "coordinates": [ 21.165161, 42.670320 ] } }
] }
] }
,
@ -566,13 +591,13 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Kampala" }, "geometry": { "type": "Point", "coordinates": [ 32.579956, 0.324095 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kigali" }, "geometry": { "type": "Point", "coordinates": [ 30.053101, -1.949697 ] } }
{ "type": "Feature", "properties": { "NAME": "Bujumbura" }, "geometry": { "type": "Point", "coordinates": [ 29.355469, -3.370856 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lusaka" }, "geometry": { "type": "Point", "coordinates": [ 28.278809, -15.411319 ] } }
{ "type": "Feature", "properties": { "NAME": "Harare" }, "geometry": { "type": "Point", "coordinates": [ 31.041870, -17.811456 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nairobi" }, "geometry": { "type": "Point", "coordinates": [ 36.809692, -1.279801 ] } }
{ "type": "Feature", "properties": { "NAME": "Dar es Salaam" }, "geometry": { "type": "Point", "coordinates": [ 39.265137, -6.795535 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Lilongwe" }, "geometry": { "type": "Point", "coordinates": [ 33.782959, -13.982046 ] } }
{ "type": "Feature", "properties": { "NAME": "Moroni" }, "geometry": { "type": "Point", "coordinates": [ 43.236694, -11.700652 ] } }
] }
] }
,
@ -580,27 +605,27 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Khartoum" }, "geometry": { "type": "Point", "coordinates": [ 32.530518, 15.591293 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kampala" }, "geometry": { "type": "Point", "coordinates": [ 32.579956, 0.324095 ] } }
{ "type": "Feature", "properties": { "NAME": "Juba" }, "geometry": { "type": "Point", "coordinates": [ 31.574707, 4.833733 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sanaa" }, "geometry": { "type": "Point", "coordinates": [ 44.203491, 15.358356 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Hargeysa" }, "geometry": { "type": "Point", "coordinates": [ 44.060669, 9.562834 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Mogadishu" }, "geometry": { "type": "Point", "coordinates": [ 45.362549, 2.070472 ] } }
{ "type": "Feature", "properties": { "NAME": "Addis Ababa" }, "geometry": { "type": "Point", "coordinates": [ 38.693848, 9.037003 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 9, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Istanbul" }, "geometry": { "type": "Point", "coordinates": [ 29.003906, 41.108330 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Athens" }, "geometry": { "type": "Point", "coordinates": [ 23.730469, 37.987504 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Nicosia" }, "geometry": { "type": "Point", "coordinates": [ 33.365479, 35.169318 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tel Aviv-Yafo" }, "geometry": { "type": "Point", "coordinates": [ 34.766235, 32.082575 ] } }
{ "type": "Feature", "properties": { "NAME": "Beirut" }, "geometry": { "type": "Point", "coordinates": [ 35.502319, 33.874976 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Yerevan" }, "geometry": { "type": "Point", "coordinates": [ 44.511108, 40.187267 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Jerusalem" }, "geometry": { "type": "Point", "coordinates": [ 35.205688, 31.779547 ] } }
{ "type": "Feature", "properties": { "NAME": "Amman" }, "geometry": { "type": "Point", "coordinates": [ 35.930786, 31.952162 ] } }
] }
] }
,
@ -610,7 +635,7 @@
,
{ "type": "Feature", "properties": { "NAME": "Kiev" }, "geometry": { "type": "Point", "coordinates": [ 30.514526, 50.436516 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bucharest" }, "geometry": { "type": "Point", "coordinates": [ 26.092529, 44.437702 ] } }
{ "type": "Feature", "properties": { "NAME": "Chisinau" }, "geometry": { "type": "Point", "coordinates": [ 28.855591, 47.006480 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Moscow" }, "geometry": { "type": "Point", "coordinates": [ 37.611694, 55.754941 ] } }
] }
@ -620,8 +645,6 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Helsinki" }, "geometry": { "type": "Point", "coordinates": [ 24.927979, 60.179770 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Riga" }, "geometry": { "type": "Point", "coordinates": [ 24.098511, 56.950966 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Moscow" }, "geometry": { "type": "Point", "coordinates": [ 37.611694, 55.754941 ] } }
] }
] }
@ -630,7 +653,7 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Victoria" }, "geometry": { "type": "Point", "coordinates": [ 55.447998, -4.614753 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Port Louis" }, "geometry": { "type": "Point", "coordinates": [ 57.496948, -20.164255 ] } }
{ "type": "Feature", "properties": { "NAME": "Antananarivo" }, "geometry": { "type": "Point", "coordinates": [ 47.510376, -18.911483 ] } }
] }
] }
,
@ -654,11 +677,17 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 10, "y": 5 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Tbilisi" }, "geometry": { "type": "Point", "coordinates": [ 44.785767, 41.730330 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 11, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Mumbai" }, "geometry": { "type": "Point", "coordinates": [ 72.850342, 19.020577 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Male" }, "geometry": { "type": "Point", "coordinates": [ 73.498535, 4.171115 ] } }
{ "type": "Feature", "properties": { "NAME": "Bangalore" }, "geometry": { "type": "Point", "coordinates": [ 77.557983, 12.972442 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Sri Jawewardenepura Kotte" }, "geometry": { "type": "Point", "coordinates": [ 79.947510, 6.904614 ] } }
] }
@ -668,9 +697,11 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Dushanbe" }, "geometry": { "type": "Point", "coordinates": [ 68.768921, 38.561053 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Islamabad" }, "geometry": { "type": "Point", "coordinates": [ 73.163452, 33.706063 ] } }
{ "type": "Feature", "properties": { "NAME": "Kabul" }, "geometry": { "type": "Point", "coordinates": [ 69.180908, 34.520136 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kathmandu" }, "geometry": { "type": "Point", "coordinates": [ 85.314331, 27.722436 ] } }
{ "type": "Feature", "properties": { "NAME": "New Delhi" }, "geometry": { "type": "Point", "coordinates": [ 77.195435, 28.603814 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Kolkata" }, "geometry": { "type": "Point", "coordinates": [ 88.319092, 22.497332 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dhaka" }, "geometry": { "type": "Point", "coordinates": [ 90.406494, 23.725012 ] } }
] }
@ -680,7 +711,9 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Astana" }, "geometry": { "type": "Point", "coordinates": [ 71.427612, 51.182786 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bishkek" }, "geometry": { "type": "Point", "coordinates": [ 74.580688, 42.875964 ] } }
{ "type": "Feature", "properties": { "NAME": "Tashkent" }, "geometry": { "type": "Point", "coordinates": [ 69.290771, 41.314950 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Urumqi" }, "geometry": { "type": "Point", "coordinates": [ 87.572021, 43.810747 ] } }
] }
] }
,
@ -694,16 +727,20 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Naypyidaw" }, "geometry": { "type": "Point", "coordinates": [ 96.113892, 19.771873 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bangkok" }, "geometry": { "type": "Point", "coordinates": [ 100.513916, 13.752725 ] } }
{ "type": "Feature", "properties": { "NAME": "Rangoon" }, "geometry": { "type": "Point", "coordinates": [ 96.163330, 16.788765 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Hanoi" }, "geometry": { "type": "Point", "coordinates": [ 105.847778, 21.038364 ] } }
{ "type": "Feature", "properties": { "NAME": "Vientiane" }, "geometry": { "type": "Point", "coordinates": [ 102.595825, 17.968283 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Putrajaya" }, "geometry": { "type": "Point", "coordinates": [ 101.700439, 2.915611 ] } }
{ "type": "Feature", "properties": { "NAME": "Kuala Lumpur" }, "geometry": { "type": "Point", "coordinates": [ 101.694946, 3.173425 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Singapore" }, "geometry": { "type": "Point", "coordinates": [ 103.853760, 1.296276 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 12, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Thimphu" }, "geometry": { "type": "Point", "coordinates": [ 89.637451, 27.474161 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Dhaka" }, "geometry": { "type": "Point", "coordinates": [ 90.406494, 23.725012 ] } }
] }
] }
@ -722,9 +759,11 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 13, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Baguio City" }, "geometry": { "type": "Point", "coordinates": [ 120.569458, 16.430816 ] } }
{ "type": "Feature", "properties": { "NAME": "Hong Kong" }, "geometry": { "type": "Point", "coordinates": [ 114.180908, 22.309426 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Bandar Seri Begawan" }, "geometry": { "type": "Point", "coordinates": [ 114.927979, 4.888467 ] } }
{ "type": "Feature", "properties": { "NAME": "Manila" }, "geometry": { "type": "Point", "coordinates": [ 120.975952, 14.610163 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Melekeok" }, "geometry": { "type": "Point", "coordinates": [ 134.626465, 7.487750 ] } }
] }
] }
,
@ -741,8 +780,6 @@
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 14, "y": 9 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Melbourne" }, "geometry": { "type": "Point", "coordinates": [ 144.970093, -37.814124 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Canberra" }, "geometry": { "type": "Point", "coordinates": [ 149.128418, -35.281501 ] } }
] }
] }
,
@ -752,6 +789,12 @@
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 14, "y": 7 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Melekeok" }, "geometry": { "type": "Point", "coordinates": [ 134.626465, 7.487750 ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 4, "x": 14, "y": 6 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Osaka" }, "geometry": { "type": "Point", "coordinates": [ 135.455933, 34.755153 ] } }
@ -786,7 +829,7 @@
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "NAME": "Palikir" }, "geometry": { "type": "Point", "coordinates": [ 158.148193, 6.920974 ] } }
,
{ "type": "Feature", "properties": { "NAME": "Tarawa" }, "geometry": { "type": "Point", "coordinates": [ 173.012695, 1.340210 ] } }
{ "type": "Feature", "properties": { "NAME": "Majuro" }, "geometry": { "type": "Point", "coordinates": [ 171.375732, 7.106344 ] } }
] }
] }
,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
{ "*": [
"all",
[
"attribute-filter",
"NAMEALT",
[ ">=", "$zoom", 2 ]
],
[
"any",
[ "all", [ "==", "SCALERANK", 0 ], [ ">=", "$zoom", 0 ] ],
[ "all", [ "==", "SCALERANK", 1 ], [ ">=", "$zoom", 1 ] ],
[ "all", [ "==", "SCALERANK", 2 ], [ ">=", "$zoom", 2 ] ],
[ "all", [ "==", "SCALERANK", 3 ], [ ">=", "$zoom", 3 ] ],
[ "all", [ "==", "SCALERANK", 4 ], [ ">=", "$zoom", 4 ] ],
[ "all", [ "==", "SCALERANK", 5 ], [ ">=", "$zoom", 5 ] ],
[ "all", [ "==", "SCALERANK", 6 ], [ ">=", "$zoom", 6 ] ],
[ "all", [ "==", "SCALERANK", 7 ], [ ">=", "$zoom", 7 ] ],
[ "all", [ ">=", "SCALERANK", 8 ], [ ">=", "$zoom", 8 ] ]
]
] }

3
tests/filter/null Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
echo '{ "type": "Feature", "properties": { "scalerank": 1, "featurecla": "Admin-0 country", "labelrank": 3.000000, "sovereignt": "Afghanistan", "sov_a3": "AFG", "adm0_dif": 0.000000, "level": 2.000000, "type": "Sovereign country", "admin": "Afghanistan", "adm0_a3": "AFG", "geou_dif": 0.000000, "geounit": "Afghanistan", "gu_a3": "AFG", "su_dif": 0.000000, "subunit": "Afghanistan", "su_a3": "AFG", "brk_diff": 0.000000, "name": "Afghanistan", "name_long": "Afghanistan", "brk_a3": "AFG", "brk_name": "Afghanistan", "brk_group": null, "abbrev": "Afg.", "postal": "AF", "formal_en": "Islamic State of Afghanistan", "formal_fr": null, "note_adm0": null, "note_brk": null, "name_sort": "Afghanistan", "name_alt": null, "mapcolor7": 5.000000, "mapcolor8": 6.000000, "mapcolor9": 8.000000, "mapcolor13": 7.000000, "pop_est": 28400000.000000, "gdp_md_est": 22270.000000, "pop_year": -99.000000, "lastcensus": 1979.000000, "gdp_year": -99.000000, "economy": "7. Least developed region", "income_grp": "5. Low income", "wikipedia": -99.000000, "fips_10": null, "iso_a2": "AF", "iso_a3": "AFG", "iso_n3": "004", "un_a3": "004", "wb_a2": "AF", "wb_a3": "AFG", "woe_id": -99.000000, "adm0_a3_is": "AFG", "adm0_a3_us": "AFG", "adm0_a3_un": -99.000000, "adm0_a3_wb": -99.000000, "continent": "Asia", "region_un": "Asia", "subregion": "Southern Asia", "region_wb": "South Asia", "name_len": 11.000000, "long_len": 11.000000, "abbrev_len": 4.000000, "tiny": -99.000000, "homepart": 1.000000 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 61.210817, 35.650072 ], [ 62.230651, 35.270663 ], [ 62.984662, 35.404040 ], [ 63.193538, 35.857165 ], [ 63.982895, 36.007957 ], [ 64.546479, 36.312073 ], [ 64.746105, 37.111817 ], [ 65.588947, 37.305216 ], [ 65.745630, 37.661164 ], [ 66.217384, 37.393790 ], [ 66.518606, 37.362784 ], [ 67.075782, 37.356143 ], [ 67.829999, 37.144994 ], [ 68.135562, 37.023115 ], [ 68.859445, 37.344335 ], [ 69.196272, 37.151143 ], [ 69.518785, 37.608996 ], [ 70.116578, 37.588222 ], [ 70.270574, 37.735164 ], [ 70.376304, 38.138395 ], [ 70.806820, 38.486281 ], [ 71.348131, 38.258905 ], [ 71.239403, 37.953265 ], [ 71.541917, 37.905774 ], [ 71.448693, 37.065644 ], [ 71.844638, 36.738171 ], [ 72.193040, 36.948287 ], [ 72.636889, 37.047558 ], [ 73.260055, 37.495256 ], [ 73.948695, 37.421566 ], [ 74.980002, 37.419990 ], [ 75.158027, 37.133030 ], [ 74.575892, 37.020841 ], [ 74.067551, 36.836175 ], [ 72.920024, 36.720007 ], [ 71.846291, 36.509942 ], [ 71.262348, 36.074387 ], [ 71.498767, 35.650563 ], [ 71.613076, 35.153203 ], [ 71.115018, 34.733125 ], [ 71.156773, 34.348911 ], [ 70.881803, 33.988855 ], [ 69.930543, 34.020120 ], [ 70.323594, 33.358532 ], [ 69.687147, 33.105498 ], [ 69.262522, 32.501944 ], [ 69.317764, 31.901412 ], [ 68.926676, 31.620189 ], [ 68.556932, 31.713310 ], [ 67.792689, 31.582930 ], [ 67.683393, 31.303154 ], [ 66.938891, 31.304911 ], [ 66.381457, 30.738899 ], [ 66.346472, 29.887943 ], [ 65.046862, 29.472180 ], [ 64.350418, 29.560030 ], [ 64.148002, 29.340819 ], [ 63.550260, 29.468330 ], [ 62.549856, 29.318572 ], [ 60.874248, 29.829238 ], [ 61.781221, 30.735850 ], [ 61.699314, 31.379506 ], [ 60.941944, 31.548074 ], [ 60.863654, 32.182919 ], [ 60.536077, 32.981268 ], [ 60.963700, 33.528832 ], [ 60.528429, 33.676446 ], [ 60.803193, 34.404101 ], [ 61.210817, 35.650072 ] ] ] } }'

View File

@ -1,3 +1,7 @@
{ "type": "LineString", "coordinates": [ [ 2.460937, 46.073230 ], [ 43.242187, 59.9 ] ] }
{ "something": [ { "type": "LineString", "coordinates": [ [ -1.40625, 28.921631 ], [ 26.71875, 17.978733 ], [ 22.148437, -23.563987 ] ] } ] }
{ "something": { "type": "LineString", "coordinates": [ [ 1, 2 ], [ 3, 4 ] ] } }
[ { "type": "LineString", "coordinates": [ [ 5, 6 ], [ 7, 8 ] ] } ]

View File

@ -3,7 +3,8 @@
"center": "22.500000,20.489949,3",
"description": "tests/geometry/out/-z3.json.check.mbtiles",
"format": "pbf",
"json": "{\"vector_layers\": [ { \"id\": \"bare\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {} }, { \"id\": \"geometrycollection\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {\"collection\": \"Boolean\"} }, { \"id\": \"multipoint\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {\"point\": \"String\"} }, { \"id\": \"onebare\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 4,\"layers\": [{\"layer\": \"bare\",\"count\": 2,\"geometry\": \"LineString\",\"attributeCount\": 0,\"attributes\": []},{\"layer\": \"geometrycollection\",\"count\": 2,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"collection\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]}]},{\"layer\": \"multipoint\",\"count\": 1,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"point\",\"count\": 1,\"type\": \"string\",\"values\": [\"multi\"]}]},{\"layer\": \"onebare\",\"count\": 1,\"geometry\": \"LineString\",\"attributeCount\": 0,\"attributes\": []}]}}",
"generator_options": "./tippecanoe -q -a@ -f -o tests/geometry/out/-z3.json.check.mbtiles -z3 tests/geometry/bare.json tests/geometry/geometrycollection.json tests/geometry/multipoint.json tests/geometry/onebare.json",
"json": "{\"vector_layers\": [ { \"id\": \"bare\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {} }, { \"id\": \"geometrycollection\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {\"collection\": \"Boolean\"} }, { \"id\": \"multipoint\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {\"point\": \"String\"} }, { \"id\": \"onebare\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 3, \"fields\": {} } ],\"tilestats\": {\"layerCount\": 4,\"layers\": [{\"layer\": \"bare\",\"count\": 4,\"geometry\": \"LineString\",\"attributeCount\": 0,\"attributes\": []},{\"layer\": \"geometrycollection\",\"count\": 2,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"collection\",\"count\": 1,\"type\": \"boolean\",\"values\": [true]}]},{\"layer\": \"multipoint\",\"count\": 1,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"point\",\"count\": 1,\"type\": \"string\",\"values\": [\"multi\"]}]},{\"layer\": \"onebare\",\"count\": 1,\"geometry\": \"LineString\",\"attributeCount\": 0,\"attributes\": []}]}}",
"maxzoom": "3",
"minzoom": "0",
"name": "tests/geometry/out/-z3.json.check.mbtiles",
@ -14,11 +15,17 @@
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 2.373047, 46.073231 ], [ 43.154297, 59.933000 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.966797, 2.021065 ], [ 2.988281, 4.039618 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 4.921875, 6.053161 ], [ 6.943359, 8.059230 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ -1.406250, 28.921631 ], [ 26.718750, 17.978733 ], [ 22.060547, -23.483401 ] ] } }
] }
,
{ "type": "FeatureCollection", "properties": { "layer": "geometrycollection", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "collection": true }, "geometry": { "type": "LineString", "coordinates": [ [ 100.986328, 0.000000 ], [ 101.953125, 1.054628 ] ] } }
,
{ "type": "Feature", "properties": { "collection": true }, "geometry": { "type": "Point", "coordinates": [ 99.931641, 0.000000 ] } }
] }
,
{ "type": "FeatureCollection", "properties": { "layer": "multipoint", "version": 2, "extent": 4096 }, "features": [
@ -31,6 +38,10 @@
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.966797, 2.021065 ], [ 2.504883, 3.513421 ] ] } }
] }
,
{ "type": "FeatureCollection", "properties": { "layer": "multipoint", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "point": "multi" }, "geometry": { "type": "Point", "coordinates": [ -60.468750, -6.970049 ] } }
] }
@ -40,6 +51,8 @@
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 2.416992, 46.073231 ], [ 3.515625, 46.498392 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.966797, 2.021065 ], [ 2.988281, 4.039618 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ -1.406250, 28.921631 ], [ 0.000000, 28.420391 ], [ 3.515625, 27.098254 ] ] } }
] }
,
@ -54,6 +67,8 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 1, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.966797, 2.021065 ], [ 2.504883, 3.513421 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 25.092773, 3.513421 ], [ 24.741211, 0.000000 ], [ 22.104492, -23.523700 ] ] } }
] }
,
@ -72,6 +87,10 @@
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 2.416992, 46.073231 ], [ 43.198242, 59.910976 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.966797, 2.021065 ], [ 2.988281, 4.039618 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 4.965820, 6.009459 ], [ 6.987305, 8.015716 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ -1.406250, 28.921631 ], [ 0.000000, 28.420391 ], [ 26.718750, 17.978733 ], [ 24.741211, 0.000000 ], [ 24.345703, -3.513421 ] ] } }
] }
,
@ -100,6 +119,8 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 2, "x": 1, "y": 1 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.988770, 2.021065 ], [ 1.757812, 2.767478 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ -1.406250, 28.921631 ], [ 0.000000, 28.401065 ], [ 1.757812, 27.741885 ] ] } }
] }
,
@ -122,6 +143,10 @@
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 2.438965, 46.073231 ], [ 43.220215, 59.910976 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.988770, 2.021065 ], [ 2.988281, 4.017699 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 4.987793, 6.009459 ], [ 6.987305, 8.015716 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ -1.406250, 28.921631 ], [ 0.000000, 28.401065 ], [ 26.718750, 17.978733 ], [ 24.741211, 0.000000 ], [ 24.543457, -1.757537 ] ] } }
] }
,
@ -182,6 +207,10 @@
,
{ "type": "FeatureCollection", "properties": { "zoom": 3, "x": 4, "y": 3 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "bare", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 0.999756, 2.010086 ], [ 2.999268, 4.006740 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ 4.998779, 6.009459 ], [ 6.998291, 8.004837 ] ] } }
,
{ "type": "Feature", "properties": { }, "geometry": { "type": "LineString", "coordinates": [ [ -0.878906, 28.729130 ], [ 0.000000, 28.401065 ], [ 26.718750, 17.978733 ], [ 24.741211, 0.000000 ], [ 24.642334, -0.878872 ] ] } }
] }
] }

1024
tests/grid-aligned/in.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1024
tests/grid-unaligned/in.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "hpa": 103200 }, "geometry": { "type": "MultiLineString", "coordinates": [ [ [254,35], [204,35], [204,30], [254,30], [254,35] ] ] } } ] }

View File

@ -0,0 +1,25 @@
{ "type": "FeatureCollection", "properties": {
"bounds": "-180.000000,30.000000,180.000000,35.000000",
"center": "-90.000000,35.000000,1",
"description": "tests/high-longitude/out/-z1.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/high-longitude/out/-z1.json.check.mbtiles -z1 tests/high-longitude/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 1, \"fields\": {\"hpa\": \"Number\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 1,\"geometry\": \"LineString\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"hpa\",\"count\": 1,\"type\": \"number\",\"values\": [103200],\"min\": 103200,\"max\": 103200}]}]}}",
"maxzoom": "1",
"minzoom": "0",
"name": "tests/high-longitude/out/-z1.json.check.mbtiles",
"type": "overlay",
"version": "2"
}, "features": [
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "hpa": 103200 }, "geometry": { "type": "LineString", "coordinates": [ [ -106.083984, 35.029996 ], [ -156.005859, 35.029996 ], [ -156.005859, 30.069094 ], [ -106.083984, 30.069094 ], [ -106.083984, 35.029996 ] ] } }
] }
] }
,
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "hpa": 103200 }, "geometry": { "type": "LineString", "coordinates": [ [ -106.040039, 35.029996 ], [ -156.005859, 35.029996 ], [ -156.005859, 30.031055 ], [ -106.040039, 30.031055 ], [ -106.040039, 35.029996 ] ] } }
] }
] }
] }

View File

@ -3,6 +3,7 @@
"center": "-121.999912,37.000000,20",
"description": "tests/highzoom/out/-z30.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/highzoom/out/-z30.json.check.mbtiles -z30 tests/highzoom/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 20, \"fields\": {\"name\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 2,\"geometry\": \"Point\",\"attributeCount\": 1,\"attributes\": [{\"attribute\": \"name\",\"count\": 2,\"type\": \"string\",\"values\": [\"London\",\"Santa Cruz\"]}]}]}}",
"maxzoom": "20",
"minzoom": "0",
@ -19,8 +20,6 @@
{ "type": "FeatureCollection", "properties": { "zoom": 1, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "in", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "name": "Santa Cruz" }, "geometry": { "type": "Point", "coordinates": [ -122.036133, 37.020098 ] } }
,
{ "type": "Feature", "properties": { "name": "London" }, "geometry": { "type": "Point", "coordinates": [ 0.000000, 51.508742 ] } }
] }
] }
,

View File

@ -3,6 +3,7 @@
"center": "-122.156982,37.762029,14",
"description": "tests/id/out/-Z11.json.check.mbtiles",
"format": "pbf",
"generator_options": "./tippecanoe -q -a@ -f -o tests/id/out/-Z11.json.check.mbtiles -Z11 tests/id/in.json",
"json": "{\"vector_layers\": [ { \"id\": \"in\", \"description\": \"\", \"minzoom\": 11, \"maxzoom\": 14, \"fields\": {\"FULLNAME\": \"String\", \"LINEARID\": \"String\", \"MTFCC\": \"String\", \"RTTYP\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"in\",\"count\": 8,\"geometry\": \"LineString\",\"attributeCount\": 4,\"attributes\": [{\"attribute\": \"FULLNAME\",\"count\": 3,\"type\": \"string\",\"values\": [\"Macarthur\",\"Macarthur Blvd\",\"Macarthur Fwy\"]},{\"attribute\": \"LINEARID\",\"count\": 8,\"type\": \"string\",\"values\": [\"1102406970092\",\"1102638069562\",\"1102954918511\",\"1103690483032\",\"1104469713187\",\"1104469713198\",\"1104486090991\",\"1105089465114\"]},{\"attribute\": \"MTFCC\",\"count\": 2,\"type\": \"string\",\"values\": [\"S1100\",\"S1400\"]},{\"attribute\": \"RTTYP\",\"count\": 1,\"type\": \"string\",\"values\": [\"M\"]}]}]}}",
"maxzoom": "14",
"minzoom": "11",

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,65 @@
{ "type": "FeatureCollection", "properties": {
"bounds": "-180.000000,-85.051129,180.000000,85.051129",
"center": "-122.104097,37.695438,0",
"description": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
"format": "pbf",
"generator_options": "./tippecanoe -q -f -z0 -n abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json; ./tippecanoe -q -f -z0 -n abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json; ./tippecanoe -q -f -z0 -n abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json; ./tippecanoe -q -f -z0 -n abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json; ./tippecanoe -q -f -z0 -n abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json; ./tippecanoe -q -f -z0 -n abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -o tests/join-population/macarthur.mbtiles tests/join-population/macarthur.json; ./tile-join -f -o tests/join-population/concat.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles tests/join-population/macarthur.mbtiles",
"json": "{\"vector_layers\": [ { \"id\": \"macarthur\", \"description\": \"\", \"minzoom\": 0, \"maxzoom\": 0, \"fields\": {\"FULLNAME\": \"String\", \"LINEARID\": \"String\", \"MTFCC\": \"String\", \"RTTYP\": \"String\"} } ],\"tilestats\": {\"layerCount\": 1,\"layers\": [{\"layer\": \"macarthur\",\"count\": 24,\"geometry\": \"LineString\",\"attributeCount\": 4,\"attributes\": [{\"attribute\": \"FULLNAME\",\"count\": 3,\"type\": \"string\",\"values\": [\"Macarthur\",\"Macarthur Fwy\",\"W Macarthur\"]},{\"attribute\": \"LINEARID\",\"count\": 4,\"type\": \"string\",\"values\": [\"1102954918511\",\"1104474748623\",\"1104486090991\",\"1104486392881\"]},{\"attribute\": \"MTFCC\",\"count\": 2,\"type\": \"string\",\"values\": [\"S1100\",\"S1400\"]},{\"attribute\": \"RTTYP\",\"count\": 1,\"type\": \"string\",\"values\": [\"M\"]}]}]}}",
"maxzoom": "0",
"minzoom": "0",
"name": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
"type": "overlay",
"version": "2"
}, "features": [
{ "type": "FeatureCollection", "properties": { "zoom": 0, "x": 0, "y": 0 }, "features": [
{ "type": "FeatureCollection", "properties": { "layer": "macarthur", "version": 2, "extent": 4096 }, "features": [
{ "type": "Feature", "properties": { "LINEARID": "1104486392881", "FULLNAME": "W Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.857507 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486090991", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.343750, 37.857507 ], [ -122.167969, 37.718590 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104474748623", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.167969, 37.718590 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1102954918511", "FULLNAME": "Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.788081 ], [ -122.167969, 37.788081 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486392881", "FULLNAME": "W Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.857507 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486090991", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.343750, 37.857507 ], [ -122.167969, 37.718590 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104474748623", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.167969, 37.718590 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1102954918511", "FULLNAME": "Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.788081 ], [ -122.167969, 37.788081 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486392881", "FULLNAME": "W Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.857507 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486090991", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.343750, 37.857507 ], [ -122.167969, 37.718590 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104474748623", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.167969, 37.718590 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1102954918511", "FULLNAME": "Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.788081 ], [ -122.167969, 37.788081 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486392881", "FULLNAME": "W Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.857507 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486090991", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.343750, 37.857507 ], [ -122.167969, 37.718590 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104474748623", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.167969, 37.718590 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1102954918511", "FULLNAME": "Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.788081 ], [ -122.167969, 37.788081 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486392881", "FULLNAME": "W Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.857507 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486090991", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.343750, 37.857507 ], [ -122.167969, 37.718590 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104474748623", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.167969, 37.718590 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1102954918511", "FULLNAME": "Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.788081 ], [ -122.167969, 37.788081 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486392881", "FULLNAME": "W Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.857507 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104486090991", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.343750, 37.857507 ], [ -122.167969, 37.718590 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1104474748623", "FULLNAME": "Macarthur Fwy", "RTTYP": "M", "MTFCC": "S1100" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.167969, 37.718590 ], [ -122.343750, 37.857507 ] ] } }
,
{ "type": "Feature", "properties": { "LINEARID": "1102954918511", "FULLNAME": "Macarthur", "RTTYP": "M", "MTFCC": "S1400" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.255859, 37.788081 ], [ -122.167969, 37.788081 ] ] } }
] }
] }
] }

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More