make-cad-bim-unfitted-fallback.mjs 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. // Convert buildings rejected only by library asset-fit into exact-outline massing fallback.
  2. // This preserves the surveyed footprint instead of stretching an incompatible asset.
  3. import { readFileSync, writeFileSync } from 'node:fs'
  4. const root = 'tools/city-massing/city/cad-bim/'
  5. const batches = [
  6. 'lod-pilot', 'lod-batch-urban8000', 'lod-batch-urban8000b', 'lod-batch-urban8000c',
  7. 'lod-batch-urban-final', 'lod-batch-urban-tail', 'lod-batch-rural1', 'lod-batch-rural2', 'lod-batch-rural3',
  8. ]
  9. const ids = new Set()
  10. const placed = new Set()
  11. for (const batch of batches) {
  12. const manifest = JSON.parse(readFileSync(`${root}${batch}/manifest.json`, 'utf8'))
  13. for (const cell of manifest.cells || []) for (const id of cell.buildingIds || []) placed.add(id)
  14. for (const id of manifest.excludedUnfittedIds || []) ids.add(id)
  15. }
  16. for (const id of placed) ids.delete(id)
  17. const seated = JSON.parse(readFileSync(`${root}seated-plan.json`, 'utf8'))
  18. const byId = new Map(seated.buildings.map((b) => [b.id, b]))
  19. const buildings = []
  20. const missing = []
  21. for (const id of ids) {
  22. const source = byId.get(id)
  23. if (!source) {
  24. missing.push(id)
  25. continue
  26. }
  27. buildings.push({
  28. ...source,
  29. kind: 'massing',
  30. archetype: null,
  31. preferredAssets: null,
  32. massingFallbackFrom: source.kind,
  33. })
  34. }
  35. const plan = {
  36. ...seated,
  37. buildings,
  38. batch: {
  39. name: 'cad-bim-unfitted-exact-outline-fallback',
  40. sourceBatches: batches,
  41. selected: buildings.length,
  42. missing,
  43. note: 'Buildings rejected only by asset-fit are preserved as exact surveyed-outline massing.',
  44. },
  45. }
  46. writeFileSync(`${root}seated-unfitted-fallback.json`, JSON.stringify(plan, null, 2))
  47. console.log(JSON.stringify({ rejectedIds: ids.size, selected: buildings.length, missing: missing.length }))