improve scad rendering
This commit is contained in:
parent
3c9013220e
commit
5a2bb0fe3d
2 changed files with 36 additions and 22 deletions
|
@ -13,7 +13,7 @@ from shapely.ops import cascaded_union
|
|||
|
||||
from c3nav.mapdata.models.locations import SpecificLocation
|
||||
from c3nav.mapdata.utils.geometry import assert_multipolygon
|
||||
from c3nav.mapdata.utils.scad import polygon_scad
|
||||
from c3nav.mapdata.utils.scad import add_indent, polygon_scad
|
||||
from c3nav.mapdata.utils.svg import SVGImage
|
||||
|
||||
|
||||
|
@ -203,19 +203,19 @@ class Level(SpecificLocation, models.Model):
|
|||
geometry = geometry.difference(intersection)
|
||||
|
||||
low_height = max(altitude - low_altitude, 0)
|
||||
total_heght = low_height+height
|
||||
if total_heght:
|
||||
total_height = low_height+height
|
||||
if total_height:
|
||||
f.write(' ')
|
||||
f.write('translate([0, 0, %.2f]) ' % (altitude - low_height))
|
||||
f.write('linear_extrude(height=%.2f, center=false, convexity=20) ' % total_heght)
|
||||
f.write(polygon_scad(intersection) + ';\n')
|
||||
f.write(add_indent(polygon_scad(intersection, total_height))[4:])
|
||||
if not geometry.is_empty:
|
||||
f.write(' ')
|
||||
f.write('translate([0, 0, %.2f]) ' % (altitude - Decimal('0.5')))
|
||||
f.write('linear_extrude(height=%.2f, center=false, convexity=20) ' % (height+Decimal('0.5')))
|
||||
f.write(polygon_scad(geometry) + ';\n')
|
||||
f.write(add_indent(polygon_scad(geometry, height+Decimal('0.5')))[4:])
|
||||
|
||||
def _render_scad(self, f, low_clip=(), spaces=None, request=None):
|
||||
f.write(' // '+self.title+'\n')
|
||||
|
||||
if spaces is None:
|
||||
from c3nav.mapdata.models import Area, Space
|
||||
spaces = self.spaces.filter(Space.q_for_request(request, allow_none=True)).prefetch_related(
|
||||
|
@ -224,6 +224,8 @@ class Level(SpecificLocation, models.Model):
|
|||
'stairs', 'obstacles', 'lineobstacles'
|
||||
)
|
||||
|
||||
f.write('')
|
||||
|
||||
for area in self.altitudeareas.all():
|
||||
area.geometry = area.geometry.buffer(0)
|
||||
self._render_scad_polygon(f, area.geometry, area.altitude, low_clip=low_clip)
|
||||
|
|
|
@ -1,29 +1,41 @@
|
|||
import json
|
||||
from itertools import chain
|
||||
from decimal import Decimal
|
||||
|
||||
from shapely.geometry import mapping
|
||||
|
||||
from c3nav.mapdata.utils.geometry import assert_multipolygon
|
||||
|
||||
|
||||
def polygon_scad(polygon):
|
||||
results = [_polygon_scad(polygon) for polygon in assert_multipolygon(polygon)]
|
||||
def polygon_scad(polygon, height):
|
||||
results = [_polygon_scad(polygon, height=height) for polygon in assert_multipolygon(polygon)]
|
||||
if not results:
|
||||
raise ValueError
|
||||
if len(results) == 1:
|
||||
return results[0]
|
||||
return '{ '+'; '.join(results)+'; }'
|
||||
return 'union() {\n'+add_indent(''.join(results))+'}\n'
|
||||
|
||||
|
||||
def _polygon_scad(polygon):
|
||||
coords = mapping(polygon)['coordinates']
|
||||
result = 'polygon(points='+json.dumps(tuple(chain(*coords)), separators=(',', ':'))
|
||||
if len(coords) > 1:
|
||||
paths = []
|
||||
start = 0
|
||||
for subcoords in coords:
|
||||
paths.append(tuple(range(start, len(subcoords))))
|
||||
start += len(subcoords)
|
||||
result += ', paths='+json.dumps(paths, separators=(',', ':'))
|
||||
result += ', convexity=20)'
|
||||
def _polygon_scad(polygon, height):
|
||||
coords = mapping(polygon.simplify(0.001))['coordinates']
|
||||
|
||||
interior = coords[0]
|
||||
exteriors = coords[1:]
|
||||
result = 'linear_extrude(height=%.2f, center=false, convexity=20) ' % height
|
||||
result += _ring_scad(interior)
|
||||
if exteriors:
|
||||
result = 'difference() {\n'+add_indent(result)
|
||||
result += ' translate([0, 0, -0.01]) {\n'
|
||||
for ring in exteriors:
|
||||
result += ' linear_extrude(height=%.2f, center=false, convexity=20) ' % (height+Decimal('0.02'))
|
||||
result += _ring_scad(ring)
|
||||
result += ' }\n'
|
||||
result += '}\n'
|
||||
return result
|
||||
|
||||
|
||||
def _ring_scad(coords):
|
||||
return 'polygon(points='+json.dumps(coords[:-1], separators=(',', ':'))+', convexity=20);\n'
|
||||
|
||||
|
||||
def add_indent(text):
|
||||
return ' '+text.replace('\n', '\n ')[:(-4 if text.endswith('\n') else None)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue