Skip to content

Commit 935a6ee

Browse files
authored
Merge pull request #1704 from tilezen/zerebubuth/fix-buffer-topology-problem
Fix buffer topology problem with building merging
2 parents d4f15bf + abb1b68 commit 935a6ee

2 files changed

Lines changed: 30 additions & 2 deletions

File tree

test/test_transform.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,3 +943,25 @@ def test_half_left(self):
943943

944944
def test_half_top(self):
945945
self._intersects((0, 0, 2, 5), (1, 1, 3, 4))
946+
947+
948+
class MergeBuildingTest(unittest.TestCase):
949+
950+
def test_merge_buildings(self):
951+
from shapely.wkb import loads
952+
from vectordatasource.transform import _merge_buildings
953+
954+
mp = loads(
955+
'01060000000200000001030000000100000005000000295C8FC2F57A9040'
956+
'E17A140E126B59410000000000A3904085EB51D8126B594148E17A14AEB9'
957+
'9040C3F5285C0E6B5941666666666692904085EB51A80D6B5941295C8FC2'
958+
'F57A9040E17A140E126B5941010300000001000000050000005C8FC2F528'
959+
'439040713D0A070C6B5941666666666692904085EB51A80D6B5941333333'
960+
'3333B99040EC51B84E066B594100000000006A9040B81E85AB046B59415C'
961+
'8FC2F528439040713D0A070C6B5941'.decode('hex')
962+
)
963+
tolerance = 1.9109257071294063
964+
result = _merge_buildings(mp, tolerance)
965+
966+
self.assertEquals(len(result), 1)
967+
self.assertTrue(result[0].is_valid)

vectordatasource/transform.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3190,6 +3190,11 @@ def _merge_buildings(polygon_shapes, tolerance):
31903190
from shapely.geometry import JOIN_STYLE
31913191

31923192
area_tolerance = tolerance * tolerance
3193+
# small factor, relative to tolerance. this is used so that we don't buffer
3194+
# polygons out by exactly the same amount as we buffer them inwards. using
3195+
# the exact same value ends up causing topology problems when two points on
3196+
# opposing sides of the polygon meet eachother exactly.
3197+
epsilon = tolerance * 1.0e-6
31933198

31943199
result = _merge_polygons(polygon_shapes)
31953200
if not result:
@@ -3202,14 +3207,15 @@ def _merge_buildings(polygon_shapes, tolerance):
32023207
# keeps angles the same. to avoid spikes, we limit the mitre to a little
32033208
# under 90 degrees.
32043209
result = result.buffer(
3205-
tolerance, join_style=JOIN_STYLE.mitre, mitre_limit=1.5)
3210+
tolerance - epsilon, join_style=JOIN_STYLE.mitre, mitre_limit=1.5)
32063211
result = result.simplify(tolerance)
32073212
result = _drop_small_inners_multi(result, area_tolerance)
32083213
result = result.buffer(
32093214
-tolerance, join_style=JOIN_STYLE.mitre, mitre_limit=1.5)
32103215
result = _drop_small_outers_multi(result, area_tolerance)
32113216

3212-
if result.is_empty:
3217+
# don't return invalid results!
3218+
if result.is_empty or not result.is_valid:
32133219
return []
32143220

32153221
return [result]

0 commit comments

Comments
 (0)