avoid merging intersecting polygons too early

This commit is contained in:
Laura Klünder 2017-11-14 18:18:22 +01:00
parent 54b21b12ce
commit 651d6b79eb
5 changed files with 20 additions and 19 deletions

View file

@ -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):

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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