unwrap geometries were necessary to comply with the new shapely api

This commit is contained in:
Gwendolyn 2023-11-07 20:26:18 +01:00
parent d27b408acb
commit 1ae1274c2c
6 changed files with 36 additions and 35 deletions

View file

@ -229,13 +229,13 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
if space.outside: if space.outside:
space.geometry = space.geometry.difference(buildings_geom) space.geometry = space.geometry.difference(buildings_geom)
space_accessible = space.geometry.difference( space_accessible = space.geometry.difference(
unary_union(tuple(c.geometry for c in space.columns.all() if c.access_restriction_id is None) + unary_union(tuple(unwrap_geom(c.geometry) for c in space.columns.all() if c.access_restriction_id is None) +
tuple(o.geometry for o in space.obstacles.all() if o.altitude == 0) + tuple(unwrap_geom(o.geometry) for o in space.obstacles.all() if o.altitude == 0) +
tuple(o.buffered_geometry for o in space.lineobstacles.all() if o.altitude == 0) + tuple(o.buffered_geometry for o in space.lineobstacles.all() if o.altitude == 0) +
tuple(h.geometry for h in space.holes.all())) tuple(unwrap_geom(h.geometry) for h in space.holes.all()))
) )
space_ramps = unary_union(tuple(r.geometry for r in space.ramps.all())) space_ramps = unary_union(tuple(unwrap_geom(r.geometry) for r in space.ramps.all()))
areas.append(space_accessible.difference(space_ramps)) areas.append(space_accessible.difference(space_ramps))
for geometry in assert_multipolygon(space_accessible.intersection(space_ramps)): for geometry in assert_multipolygon(space_accessible.intersection(space_ramps)):
ramp = AltitudeArea(geometry=geometry, level=level) ramp = AltitudeArea(geometry=geometry, level=level)
@ -244,7 +244,7 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
ramps.append(ramp) ramps.append(ramp)
areas = tuple(orient(polygon) for polygon in assert_multipolygon( areas = tuple(orient(polygon) for polygon in assert_multipolygon(
unary_union(areas+list(door.geometry for door in level.doors.all())) unary_union(areas+list(unwrap_geom(door.geometry) for door in level.doors.all()))
)) ))
# collect all stairs on this level # collect all stairs on this level
@ -281,7 +281,7 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
for space in level.spaces.all(): for space in level.spaces.all():
for altitudemarker in space.altitudemarkers.all(): for altitudemarker in space.altitudemarkers.all():
for area in space_areas[space.pk]: for area in space_areas[space.pk]:
if area.geometry_prep.contains(altitudemarker.geometry): if area.geometry_prep.contains(unwrap_geom(altitudemarker.geometry)):
area.altitude = altitudemarker.altitude area.altitude = altitudemarker.altitude
break break
else: else:
@ -471,7 +471,7 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
space.geometry = space.orig_geometry space.geometry = space.orig_geometry
buildings_geom = unary_union(tuple(unwrap_geom(b.geometry) for b in level.buildings.all())) buildings_geom = unary_union(tuple(unwrap_geom(b.geometry) for b in level.buildings.all()))
doors_geom = unary_union(tuple(d.geometry for d in level.doors.all())) doors_geom = unary_union(tuple(unwrap_geom(d.geometry) for d in level.doors.all()))
space_geom = unary_union(tuple((unwrap_geom(s.geometry) space_geom = unary_union(tuple((unwrap_geom(s.geometry)
if not s.outside if not s.outside
else s.geometry.difference(buildings_geom)) else s.geometry.difference(buildings_geom))
@ -481,7 +481,7 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
accessible_area = unary_union((doors_geom, space_geom)) accessible_area = unary_union((doors_geom, space_geom))
for space in level.spaces.all(): for space in level.spaces.all():
accessible_area = accessible_area.difference(space.geometry.intersection( accessible_area = accessible_area.difference(space.geometry.intersection(
unary_union(tuple(h.geometry for h in space.holes.all())) unary_union(tuple(unwrap_geom(h.geometry) for h in space.holes.all()))
)) ))
# areas mean altitude areas (including ramps) here # areas mean altitude areas (including ramps) here
@ -497,17 +497,17 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
if space.outside: if space.outside:
space_geom = space_geom.difference(buildings_geom) space_geom = space_geom.difference(buildings_geom)
space_geom_prep = prepared.prep(unwrap_geom(space_geom)) space_geom_prep = prepared.prep(unwrap_geom(space_geom))
holes_geom = unary_union(tuple(h.geometry for h in space.holes.all())) holes_geom = unary_union(tuple(unwrap_geom(h.geometry) for h in space.holes.all()))
# remaining_space means remaining space (=obstacles) that still needs to be added to altitude areas # remaining_space means remaining space (=obstacles) that still needs to be added to altitude areas
remaining_space = ( remaining_space = (
tuple(o.geometry for o in space.obstacles.all()) + tuple(unwrap_geom(o.geometry) for o in space.obstacles.all()) +
tuple(o.buffered_geometry for o in space.lineobstacles.all()) tuple(o.buffered_geometry for o in space.lineobstacles.all())
) )
# make sure to remove everything outside the space the obstacles are in as well as holes # make sure to remove everything outside the space the obstacles are in as well as holes
remaining_space = tuple(g.intersection(space_geom).difference(holes_geom) remaining_space = tuple(g.intersection(unwrap_geom(space_geom)).difference(holes_geom)
for g in remaining_space for g in remaining_space
if space_geom_prep.intersects(g)) if space_geom_prep.intersects(unwrap_geom(g)))
# we need this to be a list of simple normal polygons # we need this to be a list of simple normal polygons
remaining_space = tuple(chain(*( remaining_space = tuple(chain(*(
assert_multipolygon(g) for g in remaining_space if not g.is_empty assert_multipolygon(g) for g in remaining_space if not g.is_empty
@ -597,9 +597,9 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
potential_areas = [area for area in potential_areas potential_areas = [area for area in potential_areas
if (candidate.altitude, candidate.altitude2) in ((area.altitude, area.altitude2), if (candidate.altitude, candidate.altitude2) in ((area.altitude, area.altitude2),
(area.altitude2, area.altitude))] (area.altitude2, area.altitude))]
potential_areas = [(area, area.geometry.intersection(candidate.geometry).area) potential_areas = [(area, area.geometry.intersection(unwrap_geom(candidate.geometry)).area)
for area in potential_areas for area in potential_areas
if candidate.geometry_prep.intersects(area.geometry)] if candidate.geometry_prep.intersects(unwrap_geom(area.geometry))]
if potential_areas: if potential_areas:
new_area = max(potential_areas, key=itemgetter(1))[0] new_area = max(potential_areas, key=itemgetter(1))[0]

View file

@ -78,11 +78,11 @@ class LevelGeometries:
if columns: if columns:
subtract.extend(columns) subtract.extend(columns)
if subtract: if subtract:
space.geometry = space.geometry.difference(unary_union(subtract)) space.geometry = space.geometry.difference(unary_union([unwrap_geom(geom) for geom in subtract]))
holes = tuple(h.geometry for h in space.holes.all()) holes = tuple(h.geometry for h in space.holes.all())
if holes: if holes:
space.holes_geom = unary_union([h.geometry for h in space.holes.all()]) space.holes_geom = unary_union([unwrap_geom(h.geometry) for h in space.holes.all()])
space.walkable_geom = space.geometry.difference(space.holes_geom) space.walkable_geom = space.geometry.difference(space.holes_geom)
space.holes_geom = space.geometry.intersection(space.holes_geom) space.holes_geom = space.geometry.intersection(space.holes_geom)
else: else:
@ -110,7 +110,7 @@ class LevelGeometries:
heightareas = {} heightareas = {}
for space in level.spaces.all(): for space in level.spaces.all():
buffered = space.geometry.buffer(0.01).union(unary_union( buffered = space.geometry.buffer(0.01).union(unary_union(
tuple(door.geometry for door in level.doors.all() if door.geometry.intersects(space.geometry)) tuple(unwrap_geom(door.geometry) for door in level.doors.all() if door.geometry.intersects(unwrap_geom(space.geometry)))
).difference(walkable_spaces_geom)) ).difference(walkable_spaces_geom))
intersects = buildings_geom_prep.intersects(buffered) intersects = buildings_geom_prep.intersects(buffered)
@ -133,7 +133,7 @@ class LevelGeometries:
for area in space.areas.all(): for area in space.areas.all():
access_restriction = area.access_restriction_id or space.access_restriction_id access_restriction = area.access_restriction_id or space.access_restriction_id
area.geometry = area.geometry.intersection(space.walkable_geom) area.geometry = area.geometry.intersection(unwrap_geom(space.walkable_geom))
if access_restriction is not None: if access_restriction is not None:
access_restriction_affected.setdefault(access_restriction, []).append(area.geometry) access_restriction_affected.setdefault(access_restriction, []).append(area.geometry)
colors.setdefault(area.get_color_sorted(), {}).setdefault(access_restriction, []).append(area.geometry) colors.setdefault(area.get_color_sorted(), {}).setdefault(access_restriction, []).append(area.geometry)
@ -142,7 +142,7 @@ class LevelGeometries:
access_restriction = column.access_restriction_id access_restriction = column.access_restriction_id
if access_restriction is None: if access_restriction is None:
continue continue
column.geometry = column.geometry.intersection(space.walkable_geom) column.geometry = column.geometry.intersection(unwrap_geom(space.walkable_geom))
buffered_column = column.geometry.buffer(0.01) buffered_column = column.geometry.buffer(0.01)
if intersects: if intersects:
restricted_spaces_indoors.setdefault(access_restriction, []).append(buffered_column) restricted_spaces_indoors.setdefault(access_restriction, []).append(buffered_column)
@ -156,14 +156,14 @@ class LevelGeometries:
obstacles.setdefault( obstacles.setdefault(
int((obstacle.height+obstacle.altitude)*1000), {} int((obstacle.height+obstacle.altitude)*1000), {}
).setdefault(obstacle.color, []).append( ).setdefault(obstacle.color, []).append(
obstacle.geometry.intersection(space.walkable_geom) obstacle.geometry.intersection(unwrap_geom(space.walkable_geom))
) )
for lineobstacle in space.lineobstacles.all(): for lineobstacle in space.lineobstacles.all():
if not lineobstacle.height: if not lineobstacle.height:
continue continue
obstacles.setdefault(int(lineobstacle.height*1000), {}).setdefault(lineobstacle.color, []).append( obstacles.setdefault(int(lineobstacle.height*1000), {}).setdefault(lineobstacle.color, []).append(
lineobstacle.buffered_geometry.intersection(space.walkable_geom) lineobstacle.buffered_geometry.intersection(unwrap_geom(space.walkable_geom))
) )
geoms.ramps.extend(ramp.geometry for ramp in space.ramps.all()) geoms.ramps.extend(ramp.geometry for ramp in space.ramps.all())
@ -196,7 +196,7 @@ class LevelGeometries:
new_color_obstacles = [] new_color_obstacles = []
for obstacle in color_obstacles: for obstacle in color_obstacles:
if altitudearea_prep.intersects(obstacle): if altitudearea_prep.intersects(obstacle):
new_color_obstacles.append(obstacle.intersection(altitudearea.geometry)) new_color_obstacles.append(obstacle.intersection(unwrap_geom(altitudearea.geometry)))
if new_color_obstacles: if new_color_obstacles:
new_height_obstacles[color] = new_color_obstacles new_height_obstacles[color] = new_color_obstacles
if new_height_obstacles: if new_height_obstacles:
@ -211,7 +211,7 @@ class LevelGeometries:
for height, geoms in sorted(heightareas.items(), key=operator.itemgetter(0))) for height, geoms in sorted(heightareas.items(), key=operator.itemgetter(0)))
# merge access restrictions # merge access restrictions
geoms.access_restriction_affected = {access_restriction: unary_union(areas) geoms.access_restriction_affected = {access_restriction: unary_union([unwrap_geom(geom) for geom in areas])
for access_restriction, areas in access_restriction_affected.items()} for access_restriction, areas in access_restriction_affected.items()}
geoms.restricted_spaces_indoors = {access_restriction: unary_union(spaces) geoms.restricted_spaces_indoors = {access_restriction: unary_union(spaces)
for access_restriction, spaces in restricted_spaces_indoors.items()} for access_restriction, spaces in restricted_spaces_indoors.items()}
@ -228,11 +228,11 @@ class LevelGeometries:
intersection = altitudearea.geometry.intersection(remaining).buffer(0) intersection = altitudearea.geometry.intersection(remaining).buffer(0)
if intersection.is_empty: if intersection.is_empty:
continue continue
remaining = remaining.difference(altitudearea.geometry) remaining = remaining.difference(unwrap_geom(altitudearea.geometry))
geoms.short_walls.append((altitudearea, intersection)) geoms.short_walls.append((altitudearea, intersection))
geoms.all_walls = geoms.walls geoms.all_walls = geoms.walls
geoms.walls = geoms.walls.difference( geoms.walls = geoms.walls.difference(
unary_union(tuple(altitudearea.geometry for altitudearea in altitudeareas_above)) unary_union(tuple(unwrap_geom(altitudearea.geometry) for altitudearea in altitudeareas_above))
) )
# general level infos # general level infos

View file

@ -211,7 +211,7 @@ class LevelRenderData:
new_color_obstacles = [] new_color_obstacles = []
for obstacle in color_obstacles: for obstacle in color_obstacles:
if new_geometry_prep.intersects(obstacle): if new_geometry_prep.intersects(obstacle):
new_color_obstacles.append(obstacle.intersection(altitudearea.geometry)) new_color_obstacles.append(obstacle.intersection(unwrap_geom(altitudearea.geometry)))
if new_color_obstacles: if new_color_obstacles:
new_height_obstacles[color] = new_color_obstacles new_height_obstacles[color] = new_color_obstacles
if new_height_obstacles: if new_height_obstacles:
@ -224,12 +224,12 @@ class LevelRenderData:
continue continue
new_geoms.ramps = tuple( new_geoms.ramps = tuple(
ramp for ramp in (crop_to.intersection(ramp) for ramp in old_geoms.ramps) ramp for ramp in (crop_to.intersection(unwrap_geom(ramp)) for ramp in old_geoms.ramps)
if not ramp.is_empty if not ramp.is_empty
) )
new_geoms.heightareas = tuple( new_geoms.heightareas = tuple(
(area, height) for area, height in ((crop_to.intersection(area), height) (area, height) for area, height in ((crop_to.intersection(unwrap_geom(area)), height)
for area, height in old_geoms.heightareas) for area, height in old_geoms.heightareas)
if not area.is_empty if not area.is_empty
) )

View file

@ -131,8 +131,8 @@ def good_representative_point(geometry):
if Polygon(polygon.exterior.coords).contains(c): if Polygon(polygon.exterior.coords).contains(c):
return c return c
x1, y1, x2, y2 = geometry.bounds x1, y1, x2, y2 = geometry.bounds
lines = (tuple(assert_multilinestring(LineString(((x1, c.y), (x2, c.y))).intersection(geometry))) + lines = (tuple(assert_multilinestring(LineString(((x1, c.y), (x2, c.y))).intersection(unwrap_geom(geometry)))) +
tuple(assert_multilinestring(LineString(((c.x, y1), (c.x, y2))).intersection(geometry)))) tuple(assert_multilinestring(LineString(((c.x, y1), (c.x, y2))).intersection(unwrap_geom(geometry)))))
return min(lines, key=lambda line: (line.distance(c), line.length), return min(lines, key=lambda line: (line.distance(c), line.length),
default=geometry.representative_point()).centroid default=geometry.representative_point()).centroid

View file

@ -20,6 +20,7 @@ from c3nav.mapdata.models.geometry.level import LevelGeometryMixin, Space
from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
from c3nav.mapdata.models.locations import LocationRedirect, LocationSlug, Position, SpecificLocation from c3nav.mapdata.models.locations import LocationRedirect, LocationSlug, Position, SpecificLocation
from c3nav.mapdata.utils.cache.local import LocalCacheProxy from c3nav.mapdata.utils.cache.local import LocalCacheProxy
from c3nav.mapdata.utils.geometry import unwrap_geom
from c3nav.mapdata.utils.models import get_submodels from c3nav.mapdata.utils.models import get_submodels
proxied_cache = LocalCacheProxy(maxsize=128) proxied_cache = LocalCacheProxy(maxsize=128)
@ -137,7 +138,7 @@ def get_better_space_geometries():
result = {} result = {}
for space in Space.objects.prefetch_related('columns', 'holes'): for space in Space.objects.prefetch_related('columns', 'holes'):
geometry = space.geometry.difference( geometry = space.geometry.difference(
unary_union(tuple(obj.geometry for obj in chain(space.columns.all(), space.holes.all()))) unary_union(tuple(unwrap_geom(obj.geometry) for obj in chain(space.columns.all(), space.holes.all())))
) )
if not geometry.is_empty: if not geometry.is_empty:
result[space.pk] = geometry result[space.pk] = geometry

View file

@ -78,13 +78,13 @@ class Router:
for space in level.spaces.all(): for space in level.spaces.all():
# create space geometries # create space geometries
accessible_geom = space.geometry.difference(unary_union( accessible_geom = space.geometry.difference(unary_union(
tuple(column.geometry for column in space.columns.all() if column.access_restriction_id is None) + tuple(unwrap_geom(column.geometry) for column in space.columns.all() if column.access_restriction_id is None) +
tuple(hole.geometry for hole in space.holes.all()) + tuple(unwrap_geom(hole.geometry) for hole in space.holes.all()) +
((buildings_geom, ) if space.outside else ()) ((buildings_geom, ) if space.outside else ())
)) ))
obstacles_geom = unary_union( obstacles_geom = unary_union(
tuple(obstacle.geometry for obstacle in space.obstacles.all()) + tuple(unwrap_geom(obstacle.geometry) for obstacle in space.obstacles.all()) +
tuple(lineobstacle.buffered_geometry for lineobstacle in space.lineobstacles.all()) tuple(unwrap_geom(lineobstacle.buffered_geometry) for lineobstacle in space.lineobstacles.all())
) )
clear_geom = unary_union(tuple(get_rings(accessible_geom.difference(obstacles_geom)))) clear_geom = unary_union(tuple(get_rings(accessible_geom.difference(obstacles_geom))))
clear_geom_prep = prepared.prep(clear_geom) clear_geom_prep = prepared.prep(clear_geom)