From cd466e63a4584386a87365c806d866418da6c718 Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Mon, 9 Sep 2024 21:49:07 -0700 Subject: [PATCH] Copy antimeridian-crossing geometries to the other side too --- read_json.cpp | 45 +++++++++++++++++++++----- tests/pbf/0-0-0-pop-0-0-0.pbf.out.json | 2 +- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/read_json.cpp b/read_json.cpp index c38d3240..7ccf70ff 100644 --- a/read_json.cpp +++ b/read_json.cpp @@ -290,17 +290,45 @@ std::vector parse_layers(FILE *fp, int z, unsigned x, unsigned y, int // so move it to the other side. if (fix_longitudes) { + const long long quarter_world = 1LL << 30; + const long long world = 1LL << 32; + + bool copy_to_left = false; + bool copy_to_right = false; + for (size_t i = 0; i < dv.size(); i++) { + // is this vertex on a different side of the world + // than the first vertex? then shift this one to match if (i > 0) { - if ((dv[0].x < (1LL << 30)) && - (dv[i].x > 3 * (1LL << 30))) { - dv[i].x -= 1LL << 32; + if ((dv[0].x < quarter_world) && (dv[i].x > 3 * quarter_world)) { + dv[i].x -= world; } - if ((dv[0].x > 3 * (1LL << 30)) && - (dv[i].x < (1LL << 30))) { - dv[i].x += 1LL << 32; + if ((dv[0].x > 3 * quarter_world) && (dv[i].x < quarter_world)) { + dv[i].x += world; } } + + // does it stick off the edge of the world? + // then we need another copy on the other side of the world + if (dv[i].x < 0) { + copy_to_right = true; + } + if (dv[i].x > world) { + copy_to_left = true; + } + } + + if (copy_to_left) { + size_t n = dv.size(); + for (size_t i = 0; i < n; i++) { + dv.emplace_back(dv[i].op, dv[i].x - world, (long long) dv[i].y); + } + } + if (copy_to_right) { + size_t n = dv.size(); + for (size_t i = 0; i < n; i++) { + dv.emplace_back(dv[i].op, dv[i].x + world, (long long) dv[i].y); + } } } @@ -319,8 +347,9 @@ std::vector parse_layers(FILE *fp, int z, unsigned x, unsigned y, int } if (mb_geometry[t] == VT_POLYGON) { - // we can try scaling up because these are tile coordinates - dv = clean_or_clip_poly(dv, 0, 0, false, true); + // don't try scaling up because we may have coordinates + // on the other side of the world + dv = clean_or_clip_poly(dv, z, 256, true, false); if (dv.size() < 3) { dv.clear(); } diff --git a/tests/pbf/0-0-0-pop-0-0-0.pbf.out.json b/tests/pbf/0-0-0-pop-0-0-0.pbf.out.json index f8ecc2c6..4e49551f 100644 --- a/tests/pbf/0-0-0-pop-0-0-0.pbf.out.json +++ b/tests/pbf/0-0-0-pop-0-0-0.pbf.out.json @@ -74,7 +74,7 @@ , { "type": "Feature", "properties": { "bin": "8075fffffffffff", "felt:h3_level": 0, "tippecanoe:count": 1, "tippecanoe:sum:ABBREV_LEN": 4, "tippecanoe:count:ABBREV_LEN": 1, "tippecanoe:mean:ABBREV_LEN": 4, "tippecanoe:min:ABBREV_LEN": 4, "tippecanoe:max:ABBREV_LEN": 4, "tippecanoe:sum:ADM0_A3_UN": -99, "tippecanoe:count:ADM0_A3_UN": 1, "tippecanoe:mean:ADM0_A3_UN": -99, "tippecanoe:min:ADM0_A3_UN": -99, "tippecanoe:max:ADM0_A3_UN": -99, "tippecanoe:sum:ADM0_A3_WB": -99, "tippecanoe:count:ADM0_A3_WB": 1, "tippecanoe:mean:ADM0_A3_WB": -99, "tippecanoe:min:ADM0_A3_WB": -99, "tippecanoe:max:ADM0_A3_WB": -99, "tippecanoe:sum:ADM0_DIF": 0, "tippecanoe:count:ADM0_DIF": 1, "tippecanoe:mean:ADM0_DIF": 0, "tippecanoe:min:ADM0_DIF": 0, "tippecanoe:max:ADM0_DIF": 0, "tippecanoe:sum:BRK_DIFF": 0, "tippecanoe:count:BRK_DIFF": 1, "tippecanoe:mean:BRK_DIFF": 0, "tippecanoe:min:BRK_DIFF": 0, "tippecanoe:max:BRK_DIFF": 0, "tippecanoe:sum:GDP_MD": 58539, "tippecanoe:count:GDP_MD": 1, "tippecanoe:mean:GDP_MD": 58539, "tippecanoe:min:GDP_MD": 58539, "tippecanoe:max:GDP_MD": 58539, "tippecanoe:sum:GDP_YEAR": 2019, "tippecanoe:count:GDP_YEAR": 1, "tippecanoe:mean:GDP_YEAR": 2019, "tippecanoe:min:GDP_YEAR": 2019, "tippecanoe:max:GDP_YEAR": 2019, "tippecanoe:sum:GEOU_DIF": 0, "tippecanoe:count:GEOU_DIF": 1, "tippecanoe:mean:GEOU_DIF": 0, "tippecanoe:min:GEOU_DIF": 0, "tippecanoe:max:GEOU_DIF": 0, "tippecanoe:sum:HOMEPART": 1, "tippecanoe:count:HOMEPART": 1, "tippecanoe:mean:HOMEPART": 1, "tippecanoe:min:HOMEPART": 1, "tippecanoe:max:HOMEPART": 1, "tippecanoe:sum:LABELRANK": 3, "tippecanoe:count:LABELRANK": 1, "tippecanoe:mean:LABELRANK": 3, "tippecanoe:min:LABELRANK": 3, "tippecanoe:max:LABELRANK": 3, "tippecanoe:sum:LABEL_X": -5.568618, "tippecanoe:count:LABEL_X": 1, "tippecanoe:mean:LABEL_X": -5.568618, "tippecanoe:min:LABEL_X": -5.568618, "tippecanoe:max:LABEL_X": -5.568618, "tippecanoe:sum:LABEL_Y": 7.49139, "tippecanoe:count:LABEL_Y": 1, "tippecanoe:mean:LABEL_Y": 7.49139, "tippecanoe:min:LABEL_Y": 7.49139, "tippecanoe:max:LABEL_Y": 7.49139, "tippecanoe:sum:LEVEL": 2, "tippecanoe:count:LEVEL": 1, "tippecanoe:mean:LEVEL": 2, "tippecanoe:min:LEVEL": 2, "tippecanoe:max:LEVEL": 2, "tippecanoe:sum:LONG_LEN": 13, "tippecanoe:count:LONG_LEN": 1, "tippecanoe:mean:LONG_LEN": 13, "tippecanoe:min:LONG_LEN": 13, "tippecanoe:max:LONG_LEN": 13, "tippecanoe:sum:MAPCOLOR13": 3, "tippecanoe:count:MAPCOLOR13": 1, "tippecanoe:mean:MAPCOLOR13": 3, "tippecanoe:min:MAPCOLOR13": 3, "tippecanoe:max:MAPCOLOR13": 3, "tippecanoe:sum:MAPCOLOR7": 4, "tippecanoe:count:MAPCOLOR7": 1, "tippecanoe:mean:MAPCOLOR7": 4, "tippecanoe:min:MAPCOLOR7": 4, "tippecanoe:max:MAPCOLOR7": 4, "tippecanoe:sum:MAPCOLOR8": 6, "tippecanoe:count:MAPCOLOR8": 1, "tippecanoe:mean:MAPCOLOR8": 6, "tippecanoe:min:MAPCOLOR8": 6, "tippecanoe:max:MAPCOLOR8": 6, "tippecanoe:sum:MAPCOLOR9": 3, "tippecanoe:count:MAPCOLOR9": 1, "tippecanoe:mean:MAPCOLOR9": 3, "tippecanoe:min:MAPCOLOR9": 3, "tippecanoe:max:MAPCOLOR9": 3, "tippecanoe:sum:MAX_LABEL": 8, "tippecanoe:count:MAX_LABEL": 1, "tippecanoe:mean:MAX_LABEL": 8, "tippecanoe:min:MAX_LABEL": 8, "tippecanoe:max:MAX_LABEL": 8, "tippecanoe:sum:MIN_LABEL": 2.5, "tippecanoe:count:MIN_LABEL": 1, "tippecanoe:mean:MIN_LABEL": 2.5, "tippecanoe:min:MIN_LABEL": 2.5, "tippecanoe:max:MIN_LABEL": 2.5, "tippecanoe:sum:MIN_ZOOM": 0, "tippecanoe:count:MIN_ZOOM": 1, "tippecanoe:mean:MIN_ZOOM": 0, "tippecanoe:min:MIN_ZOOM": 0, "tippecanoe:max:MIN_ZOOM": 0, "tippecanoe:sum:NAME_LEN": 13, "tippecanoe:count:NAME_LEN": 1, "tippecanoe:mean:NAME_LEN": 13, "tippecanoe:min:NAME_LEN": 13, "tippecanoe:max:NAME_LEN": 13, "tippecanoe:sum:NE_ID": 1159320507, "tippecanoe:count:NE_ID": 1, "tippecanoe:mean:NE_ID": 1159320507, "tippecanoe:min:NE_ID": 1159320507, "tippecanoe:max:NE_ID": 1159320507, "tippecanoe:sum:POP_EST": 25716544, "tippecanoe:count:POP_EST": 1, "tippecanoe:mean:POP_EST": 25716544, "tippecanoe:min:POP_EST": 25716544, "tippecanoe:max:POP_EST": 25716544, "tippecanoe:sum:POP_RANK": 15, "tippecanoe:count:POP_RANK": 1, "tippecanoe:mean:POP_RANK": 15, "tippecanoe:min:POP_RANK": 15, "tippecanoe:max:POP_RANK": 15, "tippecanoe:sum:POP_YEAR": 2019, "tippecanoe:count:POP_YEAR": 1, "tippecanoe:mean:POP_YEAR": 2019, "tippecanoe:min:POP_YEAR": 2019, "tippecanoe:max:POP_YEAR": 2019, "tippecanoe:sum:SU_DIF": 0, "tippecanoe:count:SU_DIF": 1, "tippecanoe:mean:SU_DIF": 0, "tippecanoe:min:SU_DIF": 0, "tippecanoe:max:SU_DIF": 0, "tippecanoe:sum:TINY": -99, "tippecanoe:count:TINY": 1, "tippecanoe:mean:TINY": -99, "tippecanoe:min:TINY": -99, "tippecanoe:max:TINY": -99, "tippecanoe:sum:WOE_ID": 23424854, "tippecanoe:count:WOE_ID": 1, "tippecanoe:mean:WOE_ID": 23424854, "tippecanoe:min:WOE_ID": 23424854, "tippecanoe:max:WOE_ID": 23424854, "tippecanoe:sum:WOE_ID_EH": 23424854, "tippecanoe:count:WOE_ID_EH": 1, "tippecanoe:mean:WOE_ID_EH": 23424854, "tippecanoe:min:WOE_ID_EH": 23424854, "tippecanoe:max:WOE_ID_EH": 23424854, "tippecanoe:sum:scalerank": 0, "tippecanoe:count:scalerank": 1, "tippecanoe:mean:scalerank": 0, "tippecanoe:min:scalerank": 0, "tippecanoe:max:scalerank": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -4.042969, 11.523088 ], [ 3.955078, 3.951941 ], [ -0.791016, -5.878332 ], [ -11.689453, -4.477856 ], [ -13.710938, 6.227934 ], [ -4.042969, 11.523088 ] ] ] } } , -{ "type": "Feature", "properties": { "bin": "8003fffffffffff", "felt:h3_level": 0, "tippecanoe:count": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -214.453125, 87.364326 ], [ -34.716797, 81.268385 ], [ -66.884766, 72.208678 ], [ -100.810547, 67.542167 ], [ -131.748047, 69.380313 ], [ -163.476562, 76.142958 ], [ -214.453125, 87.364326 ] ] ] } } +{ "type": "Feature", "properties": { "bin": "8003fffffffffff", "felt:h3_level": 0, "tippecanoe:count": 0 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -214.453125, 87.364326 ], [ -34.716797, 81.268385 ], [ -66.884766, 72.208678 ], [ -100.810547, 67.542167 ], [ -131.748047, 69.380313 ], [ -163.476562, 76.142958 ], [ -214.453125, 87.364326 ] ] ], [ [ [ 145.546875, 87.364326 ], [ 325.283203, 81.268385 ], [ 293.115234, 72.208678 ], [ 259.189453, 67.542167 ], [ 228.251953, 69.380313 ], [ 196.523438, 76.142958 ], [ 145.546875, 87.364326 ] ] ] ] } } , { "type": "Feature", "properties": { "bin": "80c1fffffffffff", "felt:h3_level": 0, "tippecanoe:count": 0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -15.556641, -22.998852 ], [ -2.109375, -24.766785 ], [ 4.394531, -35.746512 ], [ -4.394531, -46.195042 ], [ -21.621094, -43.897892 ], [ -25.224609, -31.877558 ], [ -15.556641, -22.998852 ] ] ] } } ,