Skip to content

Commit a0c567a

Browse files
authored
Merge pull request #101 from mapbox/polygon-clipping-fix
Polygon clipping fix
2 parents 02d352b + fce6a9c commit a0c567a

File tree

4 files changed

+69
-54
lines changed

4 files changed

+69
-54
lines changed

.travis.yml

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,10 @@ matrix:
3535

3636
## ** Builds that are published **
3737

38-
# linux cfi build node v6/release
38+
# linux cfi build node v10/release
3939
- os: linux
4040
env: BUILDTYPE=release TOOLSET=cfi CXXFLAGS="-flto -fsanitize=cfi -fvisibility=hidden" LDFLAGS="-flto -fsanitize=cfi"
41-
node_js: 6
42-
# linux publishable node v6/release
43-
- os: linux
44-
env: BUILDTYPE=release
45-
node_js: 6
46-
# linux publishable node v6/debug
47-
- os: linux
48-
env: BUILDTYPE=debug
49-
node_js: 6
41+
node_js: 10
5042
# linux publishable node v8/release
5143
- os: linux
5244
env: BUILDTYPE=release
@@ -63,16 +55,6 @@ matrix:
6355
- os: linux
6456
env: BUILDTYPE=debug
6557
node_js: 10
66-
# osx publishable node v6/release
67-
- os: osx
68-
osx_image: xcode9.2
69-
env: BUILDTYPE=release
70-
node_js: 6
71-
# osx publishable node v6/debug
72-
- os: osx
73-
osx_image: xcode9.2
74-
env: BUILDTYPE=debug
75-
node_js: 6
7658
# osx publishable node v8/release
7759
- os: osx
7860
osx_image: xcode9.2
@@ -85,7 +67,7 @@ matrix:
8567
node_js: 10
8668
- os: linux
8769
env: BUILDTYPE=debug TOOLSET=asan
88-
node_js: 6
70+
node_js: 10
8971
sudo: required
9072
# Overrides `install` to set up custom asan flags
9173
install:
@@ -107,8 +89,8 @@ matrix:
10789

10890
# g++ build (default builds all use clang++)
10991
- os: linux
110-
env: BUILDTYPE=debug CXX="g++-6" CC="gcc-6" LINK="g++-6" AR="ar" NM="nm"
111-
node_js: 6
92+
env: BUILDTYPE=debug CXX="g++-6" CC="gcc-6" LINK="g++-6" AR="ar" NM="nm" CXXFLAGS="-fext-numeric-literals"
93+
node_js: 10
11294
addons:
11395
apt:
11496
sources:
@@ -124,7 +106,7 @@ matrix:
124106
# Coverage build
125107
- os: linux
126108
env: BUILDTYPE=debug CXXFLAGS="--coverage" LDFLAGS="--coverage"
127-
node_js: 6
109+
node_js: 10
128110
# Overrides `script` to publish coverage data to codecov
129111
script:
130112
- export PATH=$(pwd)/mason_packages/.link/bin/:${PATH}
@@ -151,7 +133,7 @@ matrix:
151133
# Clang tidy build
152134
- os: linux
153135
env: CLANG_TIDY
154-
node_js: 6
136+
node_js: 10
155137
# Overrides `install` to avoid initializing clang toolchain
156138
install:
157139
# First run the clang-tidy target

src/feature_builder.hpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -220,43 +220,40 @@ struct overzoomed_feature_builder
220220
{
221221
std::vector<detail::annotated_ring<CoordinateType>> rings;
222222
vtzero::decode_polygon_geometry(feature.geometry(), detail::polygon_handler<CoordinateType>(rings, dx_, dy_, zoom_factor_));
223-
if (!rings.empty())
223+
std::vector<mapbox::geometry::polygon<CoordinateType>> polygons;
224+
bool process = false;
225+
for (auto const& r : rings)
226+
{
227+
if (r.second == vtzero::ring_type::outer)
228+
{
229+
auto extent = mapbox::geometry::envelope(r.first);
230+
process = boost::geometry::intersects(extent, bbox_);
231+
if (process) polygons.emplace_back(); // start new polygon
232+
}
233+
if (process && r.first.size() > 3)
234+
{
235+
polygons.back().push_back(std::move(r.first));
236+
}
237+
}
238+
if (!polygons.empty())
224239
{
225240
vtzero::polygon_feature_builder feature_builder{layer_builder_};
226241
feature_builder.copy_id(feature);
227242
bool valid = false;
228-
bool process = false;
229-
for (auto& r : rings)
243+
for (auto const& poly : polygons)
230244
{
231-
if (r.second == vtzero::ring_type::outer)
232-
{
233-
auto extent = mapbox::geometry::envelope(r.first);
234-
process = boost::geometry::intersects(extent, bbox_);
235-
}
236-
if (process)
245+
std::vector<mapbox::geometry::polygon<coordinate_type>> result;
246+
boost::geometry::intersection(poly, bbox_, result);
247+
for (auto const& p : result)
237248
{
238-
std::vector<mapbox::geometry::polygon<coordinate_type>> result;
239-
if (r.second == vtzero::ring_type::inner) boost::geometry::reverse(r.first);
240-
// ^^ reverse inner rings before clipping as we're dealing with a disassembled polygon
241-
boost::geometry::intersection(r.first, bbox_, result);
242-
for (auto const& p : result)
249+
for (auto const& ring : p)
243250
{
244-
for (auto const& ring : p)
251+
if (ring.size() > 3)
245252
{
246-
if (ring.size() > 3)
247-
{
248-
valid = true;
249-
feature_builder.add_ring(static_cast<unsigned>(ring.size()));
250-
if (r.second == vtzero::ring_type::outer)
251-
{
252-
std::for_each(ring.begin(), ring.end(), [&feature_builder](auto const& pt) { feature_builder.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y)); });
253-
}
254-
else
255-
{
256-
// apply points in reverse to preserve original winding order of inner rings
257-
std::for_each(ring.rbegin(), ring.rend(), [&feature_builder](auto const& pt) { feature_builder.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y)); });
258-
}
259-
}
253+
valid = true;
254+
feature_builder.add_ring(static_cast<unsigned>(ring.size()));
255+
std::for_each(ring.begin(), ring.end(),
256+
[&feature_builder](auto const& pt) { feature_builder.set_point(static_cast<int>(pt.x), static_cast<int>(pt.y)); });
260257
}
261258
}
262259
}
2.66 KB
Binary file not shown.

test/vtcomposite-polygons.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,39 @@ test('[composite] composite and overzooming success polygons - overzooming polyg
129129
assert.end();
130130
});
131131
});
132+
133+
test('[composite] composite and overzooming polygons with holes', function(assert) {
134+
const zxy = { z:8, x:221, y:99 };
135+
const parent = { z:4, x:13, y:6 };
136+
137+
const tiles = [
138+
{ buffer: fs.readFileSync('./test/fixtures/polygons-with-holes-4-13-6.mvt'), z: parent.z, x: parent.x, y: parent.y }
139+
];
140+
141+
composite(tiles, zxy, {buffer_size:4080}, (err, vtBuffer) => {
142+
assert.notOk(err);
143+
assert.equal(vtBuffer.length, 848);
144+
const outputInfo = vtinfo(vtBuffer);
145+
// one feature
146+
assert.equal(outputInfo.layers.polygons.feature.length, 1);
147+
var feature = outputInfo.layers.polygons.feature(0);
148+
var geojson = feature.toGeoJSON(zxy.x,zxy.y,zxy.z);
149+
var coords = geojson.geometry.coordinates;
150+
// two polygons
151+
assert.equal(coords.length,2);
152+
// first polygons 8 rings
153+
assert.equal(coords[0].length, 8);
154+
assert.equal(coords[0][0].length, 95);
155+
assert.equal(coords[0][1].length, 25);
156+
assert.equal(coords[0][2].length, 23);
157+
assert.equal(coords[0][3].length, 18);
158+
assert.equal(coords[0][4].length, 26);
159+
assert.equal(coords[0][5].length, 18);
160+
assert.equal(coords[0][6].length, 14);
161+
assert.equal(coords[0][7].length, 16);
162+
// second polygon 1 ring
163+
assert.equal(coords[1].length,1);
164+
assert.equal(coords[1][0].length, 6);
165+
assert.end();
166+
});
167+
});

0 commit comments

Comments
 (0)