From 1f897ccec9b7139f8d8374917332f8f324833cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Sat, 13 May 2017 19:19:28 +0200 Subject: [PATCH] improve shadow rendering --- src/c3nav/mapdata/models/section.py | 8 ++-- src/c3nav/mapdata/render/svg.py | 66 +++++++++-------------------- 2 files changed, 24 insertions(+), 50 deletions(-) diff --git a/src/c3nav/mapdata/models/section.py b/src/c3nav/mapdata/models/section.py index c7dd34d3..66619f06 100644 --- a/src/c3nav/mapdata/models/section.py +++ b/src/c3nav/mapdata/models/section.py @@ -73,8 +73,9 @@ class Section(SpecificLocation, EditorFormMixin, models.Model): # draw space background door_geometries = cascaded_union(tuple(d.geometry for d in self.doors.all())) section_geometry = cascaded_union((space_geometries[''], building_geometries, door_geometries)) - section_svg = svg.add_geometry(section_geometry, defid='section') - svg.use_geometry(section_svg, fill_color='#d1d1d1', mask=hole_mask) + section_geometry = section_geometry.difference(hole_geometries) + section_clip = svg.add_geometry(section_geometry, defid='section', as_clip_path=True) + svg.use_geometry(fill_color='#d1d1d1', clip_path=section_clip) # color in spaces spaces_by_color = {} @@ -89,12 +90,11 @@ class Section(SpecificLocation, EditorFormMixin, models.Model): # calculate walls wall_geometry = building_geometries.difference(space_geometries['']).difference(door_geometries) wall_svg = svg.add_geometry(wall_geometry, 'walls') - accessible_mask = svg.add_mask(section_svg, wall_svg, hole_svg, subtract=True, defid='accessible') # draw wall shadow wall_dilated_geometry = wall_geometry.buffer(0.7, join_style=JOIN_STYLE.mitre) wall_dilated_svg = svg.add_geometry(wall_dilated_geometry, 'wall-shadows') - svg.use_geometry(wall_dilated_svg, fill_color='rgba(0, 0, 0, 0.1)', mask=accessible_mask, filter='wallblur') + svg.use_geometry(wall_dilated_svg, fill_color='#000000', opacity=0.1, filter='wallblur', clip_path=section_clip) # draw walls svg.use_geometry(wall_svg, fill_color='#929292') diff --git a/src/c3nav/mapdata/render/svg.py b/src/c3nav/mapdata/render/svg.py index cd8c0b9b..6f302eac 100644 --- a/src/c3nav/mapdata/render/svg.py +++ b/src/c3nav/mapdata/render/svg.py @@ -40,11 +40,10 @@ class SVGImage(SVGGroup): # blur_filter.append(ET.Element('feBlend', {'in': 'SourceGraphic', 'in2': 'inner', 'mode': 'multiply'})) blur_filter = ET.Element('filter', {'id': 'wallblur'}) - blur_filter.append(ET.Element('feGaussianBlur', {'stdDeviation': str(0.7 * self.scale)})) + blur_filter.append(ET.Element('feGaussianBlur', + {'in': 'SourceGraphic', + 'stdDeviation': str(int(0.7 * self.scale))})) self.defs.append(blur_filter) - # blur_filter = ET.Element('filter', {'id': 'wallblur'}) - # blur_filter.append(ET.Element('feGaussianBlur', {'in': 'SourceGraphic', 'stdDeviation': str(5*self.scale)})) - # self.defs.append(blur_filter) def get_element(self): root = ET.Element('svg', { @@ -63,7 +62,7 @@ class SVGImage(SVGGroup): self.def_i += 1 return defid - def add_geometry(self, geometry, defid=None, comment=None): + def add_geometry(self, geometry, defid=None, as_clip_path=False, comment=None): if defid is None: defid = self.new_defid() @@ -74,6 +73,8 @@ class SVGImage(SVGGroup): new_element = ET.Element('g') new_element.append(element) element = new_element + if as_clip_path: + element.tag = 'clipPath' paths = element.findall('polyline') if len(paths) == 0: @@ -108,50 +109,21 @@ class SVGImage(SVGGroup): self.defs.append(mask) return defid - def add_union(self, *geometries, wall_shadow=False, defid=None): + def add_clip_path(self, *geometries, inverted=False, subtract=False, defid=None): if defid is None: defid = self.new_defid() - element = ET.Element('g', {'id': defid}) - for geometry in geometries: - newelem = ET.Element('use', {'xlink:href': '#'+geometry}) - if wall_shadow: - newelem.set('filter', 'url(#wallshadow)') - element.append(newelem) - self.defs.append(element) + clippath = ET.Element('clipPath', {'id': defid}) + clippath.append(ET.Element('use', {'xlink:href': '#' + geometries[0]})) + self.defs.append(clippath) return defid - def add_intersection(self, geometry1, geometry2, defid=None): - if defid is None: - defid = self.new_defid() - - mask = ET.Element('mask', {'id': defid+'-mask'}) - mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'black'})) - mask.append(ET.Element('use', {'xlink:href': '#'+geometry2, 'fill': 'white'})) - self.defs.append(mask) - - element = ET.Element('g', {'id': defid, 'mask': 'url(#'+defid+'-mask)'}) - element.append(ET.Element('use', {'xlink:href': '#'+geometry1})) - self.defs.append(element) - return defid - - def add_difference(self, geometry1, geometry2, defid=None): - if defid is None: - defid = self.new_defid() - - mask = ET.Element('mask', {'id': defid+'-mask'}) - mask.append(ET.Element('rect', {'width': '100%', 'height': '100%', 'fill': 'white'})) - mask.append(ET.Element('use', {'xlink:href': '#'+geometry2, 'fill': 'black'})) - self.defs.append(mask) - - element = ET.Element('g', {'id': defid, 'mask': 'url(#'+defid+'-mask)'}) - element.append(ET.Element('use', {'xlink:href': '#' + geometry1})) - self.defs.append(element) - return defid - - def use_geometry(self, geometry, fill_color=None, fill_opacity=None, opacity=None, mask=None, filter=None, - stroke_width=0.0, stroke_color=None, stroke_opacity=None, stroke_linejoin=None): - element = ET.Element('use', {'xlink:href': '#'+geometry}) + def use_geometry(self, geometry=None, fill_color=None, fill_opacity=None, opacity=None, mask=None, filter=None, + stroke_width=0.0, stroke_color=None, stroke_opacity=None, stroke_linejoin=None, clip_path=None): + if geometry: + element = ET.Element('use', {'xlink:href': '#'+geometry}) + else: + element = ET.Element('rect', {'width': '100%', 'height': '100%'}) element.set('fill', fill_color or 'none') if fill_opacity: element.set('fill-opacity', str(fill_opacity)) @@ -165,10 +137,12 @@ class SVGImage(SVGGroup): element.set('stroke-linejoin', str(stroke_linejoin)) if opacity: element.set('opacity', str(opacity)) - if mask: - element.set('mask', 'url(#'+mask+')') if filter: element.set('filter', 'url(#'+filter+')') + if mask: + element.set('mask', 'url(#'+mask+')') + if clip_path: + element.set('clip-path', 'url(#'+clip_path+')') self.g.append(element) return element