verify-export-triangle-reference.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. """Regression at the exporter's pure triangle-reference seam; no bpy or scene startup."""
  2. import ast, math
  3. from pathlib import Path
  4. source = Path('tools/city-massing/assemble-cad-bim.py').read_text(encoding='utf8')
  5. functions = {'facade_profile_flags', 'prism_triangles', 'facade_window_count', 'facade_entrance_edge', 'facade_panel_halfwidth', 'facade_window_positions', 'massing_triangles'}
  6. module = ast.Module(body=[n for n in ast.parse(source).body if isinstance(n, ast.FunctionDef) and n.name in functions], type_ignores=[])
  7. scope = {'math': math, 'ARCHITECTURE': True, 'FULL_REVEALS': True, 'FACADE_PROFILE': 'off', 'BANDS': False}
  8. exec(compile(module, 'triangle-reference-seam', 'exec'), scope)
  9. assert scope['facade_profile_flags']('off', False, False) == {
  10. 'profile': 'off', 'architecture': False, 'fullReveals': False, 'bands': False}
  11. assert scope['facade_profile_flags']('compact', False, False) == {
  12. 'profile': 'compact', 'architecture': True, 'fullReveals': False, 'bands': False}
  13. assert scope['facade_profile_flags']('full', True, False)['fullReveals'] is True
  14. try:
  15. scope['facade_profile_flags']('full', False, False)
  16. except RuntimeError:
  17. pass
  18. else:
  19. raise AssertionError('full profile must require near architecture')
  20. # A notch-sized edge must remain in the solid but cannot fit the 0.35m facade panel.
  21. ring = [(0,0),(.2,0),(.2,5),(0,5)]
  22. # 4*n-4 shell + 12 door + 2 long-wall windows * 2 triangles * 4 floors.
  23. assert scope['massing_triangles'](ring,4,'lod1') == 12+12+16
  24. scope['ARCHITECTURE'] = False
  25. scope['FACADE_PROFILE'] = 'off'
  26. # Original large rectangular case retains one window on every edge.
  27. assert scope['massing_triangles']([(0,0),(12,0),(12,9),(0,9)],3,'lod1') == 12+12+24
  28. scope['ARCHITECTURE'] = True
  29. scope['FULL_REVEALS'] = False
  30. scope['FACADE_PROFILE'] = 'compact'
  31. scope['BANDS'] = False
  32. # 12x9m: 30 windows across 3 floors, except one centered ground window
  33. # reserved for the entrance: 12 shell + 12 door + 58 glass + 16 bands = 98.
  34. assert scope['massing_triangles']([(0,0),(12,0),(12,9),(0,9)],3,'lod0') == 98
  35. scope['FULL_REVEALS'] = True
  36. # Optional reveals add 58*4 triangles, roof edges add 8; the cap remains unchanged.
  37. assert scope['massing_triangles']([(0,0),(12,0),(12,9),(0,9)],3,'lod0') == 338
  38. print({'passed':True,'scope':'short surveyed edges plus compact massing facade profile reference','blenderStarted':False})