From 651d6b79ebaa740250b7770da4528b4c1f61efff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 14 Nov 2017 18:18:22 +0100 Subject: [PATCH] avoid merging intersecting polygons too early --- src/c3nav/mapdata/render/engines/base.py | 8 ++++---- src/c3nav/mapdata/render/engines/base3d.py | 6 +++--- src/c3nav/mapdata/render/engines/openscad.py | 12 ++++++------ src/c3nav/mapdata/render/engines/svg.py | 2 +- src/c3nav/mapdata/render/renderer.py | 11 ++++++----- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/c3nav/mapdata/render/engines/base.py b/src/c3nav/mapdata/render/engines/base.py index 03d55ada..94b04181 100644 --- a/src/c3nav/mapdata/render/engines/base.py +++ b/src/c3nav/mapdata/render/engines/base.py @@ -69,7 +69,7 @@ class RenderEngine(ABC): pass def add_geometry(self, geometry, fill: Optional[FillAttribs] = None, stroke: Optional[StrokeAttribs] = None, - altitude=None, height=None, shape_cache_key=None, category=None): + altitude=None, height=None, shape_cache_key=None, category=None, item=None): # draw a shapely geometry with a given style # altitude is the absolute altitude of the upper bound of the element # height is the height of the element @@ -79,12 +79,12 @@ class RenderEngine(ABC): if geometry.is_empty: return - self._add_geometry(geometry=geometry, fill=fill, stroke=stroke, - altitude=altitude, height=height, shape_cache_key=shape_cache_key, category=category) + self._add_geometry(geometry=geometry, fill=fill, stroke=stroke, altitude=altitude, height=height, + shape_cache_key=shape_cache_key, category=category, item=item) @abstractmethod def _add_geometry(self, geometry, fill: Optional[FillAttribs], stroke: Optional[StrokeAttribs], - altitude=None, height=None, shape_cache_key=None): + altitude=None, height=None, shape_cache_key=None, item=None): pass def set_mesh_lookup_data(self, data): diff --git a/src/c3nav/mapdata/render/engines/base3d.py b/src/c3nav/mapdata/render/engines/base3d.py index 32c82cc0..e5f167e9 100644 --- a/src/c3nav/mapdata/render/engines/base3d.py +++ b/src/c3nav/mapdata/render/engines/base3d.py @@ -32,13 +32,13 @@ class Base3DEngine(RenderEngine): self._current_group = group self.groups.setdefault(group, []) - def _add_geometry(self, geometry, fill: Optional[FillAttribs], stroke: Optional[StrokeAttribs], category=None, - **kwargs): + def _add_geometry(self, geometry, fill: Optional[FillAttribs], stroke: Optional[StrokeAttribs], + category=None, item=None, **kwargs): if fill is not None: key = '%s_%s' % (self._current_group, category) if key not in self.vertices: self.groups[self._current_group].append(key) - self.vertices.setdefault(key, []).append(self._place_geometry(geometry)) + self.vertices.setdefault(key, OrderedDict()).setdefault(item, []).append(self._place_geometry(geometry)) self.colors.setdefault(key, self.color_to_rgb(fill.color)) @staticmethod diff --git a/src/c3nav/mapdata/render/engines/openscad.py b/src/c3nav/mapdata/render/engines/openscad.py index fab0134a..c2fd82b8 100644 --- a/src/c3nav/mapdata/render/engines/openscad.py +++ b/src/c3nav/mapdata/render/engines/openscad.py @@ -8,13 +8,12 @@ from c3nav.mapdata.render.engines.base3d import Base3DEngine class OpenSCADEngine(Base3DEngine): filetype = 'scad' - def _create_polyhedron(self, name, vertices): + def _create_polyhedron(self, vertices): facets = np.vstack(vertices) vertices = tuple(set(tuple(vertex) for vertex in facets.reshape((-1, 3)))) lookup = {vertex: i for i, vertex in enumerate(vertices)} - return (b'module ' + name.replace('-', 'minus').encode() + b'() {\n' + - b' polyhedron(\n' + + return (b' polyhedron(\n' + b' points = [\n' + b'\n'.join((b' [%.3f, %.3f, %.3f],' % tuple(vertex)) for vertex in vertices) + b'\n' + b' ],\n' + @@ -23,8 +22,7 @@ class OpenSCADEngine(Base3DEngine): for a, b, c in facets) + b'\n' + b' ],\n' + b' convexity = 10\n' + - b' );\n' - b'}\n') + b' );') def render(self) -> bytes: result = (b'c3nav_export();\n\n' + @@ -41,5 +39,7 @@ class OpenSCADEngine(Base3DEngine): b'}\n') result += b'\n' for group, vertices in self.vertices.items(): - result += self._create_polyhedron(group, vertices) + result += (b'module ' + group.replace('-', 'minus').encode() + b'() {\n' + + b'\n'.join(self._create_polyhedron(v) for v in vertices.values()) + + b'}\n') return result diff --git a/src/c3nav/mapdata/render/engines/svg.py b/src/c3nav/mapdata/render/engines/svg.py index 56d739fc..e387a400 100644 --- a/src/c3nav/mapdata/render/engines/svg.py +++ b/src/c3nav/mapdata/render/engines/svg.py @@ -215,7 +215,7 @@ class SVGEngine(RenderEngine): self.altitudes[new_altitude] = new_geometry def _add_geometry(self, geometry, fill: Optional[FillAttribs], stroke: Optional[StrokeAttribs], - altitude=None, height=None, shape_cache_key=None, category=None): + altitude=None, height=None, shape_cache_key=None, **kwargs): geometry = self.buffered_bbox.intersection(geometry.geom) if geometry.is_empty: diff --git a/src/c3nav/mapdata/render/renderer.py b/src/c3nav/mapdata/render/renderer.py index de4bf2d7..82d21195 100644 --- a/src/c3nav/mapdata/render/renderer.py +++ b/src/c3nav/mapdata/render/renderer.py @@ -107,21 +107,21 @@ class MapRenderer: engine.add_geometry(geoms.walls_bottom.fit(scale=geoms.min_altitude-min_altitude, offset=min_altitude-int(0.7*1000)), fill=FillAttribs('#aaaaaa'), category='walls') - for altitudearea in geoms.altitudeareas: + for i, altitudearea in enumerate(geoms.altitudeareas): scale = (altitudearea.altitude - min_altitude) / int(0.7 * 1000) offset = (min_altitude - int(0.7*1000)) - (altitudearea.altitude - int(0.7*1000)) * scale geometry = altitudearea.geometry.difference(crop_areas) engine.add_geometry(geometry.fit(scale=scale, offset=offset).filter(top=False), - fill=FillAttribs('#eeeeee'), category='ground') + fill=FillAttribs('#eeeeee'), category='ground', item=i) # render altitude areas in default ground color and add ground colors to each one afterwards # shadows are directly calculated and added by the engine - for altitudearea in geoms.altitudeareas: + for i, altitudearea in enumerate(geoms.altitudeareas): geometry = altitudearea.geometry.difference(crop_areas) if not_full_levels: geometry = geometry.filter(bottom=False) engine.add_geometry(geometry, altitude=altitudearea.altitude, fill=FillAttribs('#eeeeee'), - category='ground') + category='ground', item=i) i = 0 for color, areas in altitudearea.colors.items(): @@ -130,7 +130,8 @@ class MapRenderer: if access_restriction in unlocked_access_restrictions) if areas: i += 1 - engine.add_geometry(hybrid_union(areas), fill=FillAttribs(color), category='groundcolor%s' % i) + engine.add_geometry(hybrid_union(areas), fill=FillAttribs(color), + category='groundcolor%s' % i, item=i) # add walls, stroke_px makes sure that all walls are at least 1px thick on all zoom levels, walls = None