check-roof-triangulation.py 1.3 KB

1234567891011121314151617181920212223242526
  1. """Compare Blender's cap triangulation to active GIS outlines without exporting assets."""
  2. import json
  3. from pathlib import Path
  4. from mathutils import Vector
  5. from mathutils.geometry import tessellate_polygon
  6. root = Path(__file__).parent / 'city/cad-bim'
  7. area = lambda ring: 0.5 * sum(p[0] * ring[(i + 1) % len(ring)][1] - ring[(i + 1) % len(ring)][0] * p[1]
  8. for i, p in enumerate(ring))
  9. plan = json.loads((root / 'seated-batch-urban8000c.json').read_text(encoding='utf-8'))
  10. manifest = json.loads((root / 'lod-batch-urban8000c-aligned/manifest.json').read_text(encoding='utf-8'))
  11. ids = {id for cell in manifest['cells'] for id in cell['buildingIds']}
  12. for building in plan['buildings']:
  13. if building['id'] not in ids:
  14. continue
  15. ring = building['footprintENU']
  16. if area(ring) < 0:
  17. ring = list(reversed(ring))
  18. ax, ay, _ = building['positionENU']
  19. points = [Vector((x - ax, y - ay, 0)) for x, y in ring]
  20. triangles = tessellate_polygon([points])
  21. actual = sum(abs(area([ring[i] for i in triangle])) for triangle in triangles)
  22. wanted = area(ring)
  23. if abs(actual - wanted) > max(0.001, actual * 1e-6):
  24. print(json.dumps({'id': building['id'], 'actual': actual, 'wanted': wanted,
  25. 'difference': actual - wanted, 'ring': ring, 'triangles': triangles}), flush=True)