| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- // Split long source blocks into stepped facade modules without changing street orientation.
- import { readFileSync, writeFileSync } from 'node:fs'
- import { Cartesian3, Cartographic, Matrix4, Math as CM } from 'cesium'
- const file = 'tools/city-massing/district/plan.json',
- p = JSON.parse(readFileSync(file))
- const transform = Matrix4.fromArray(p.transform)
- const toGeo = (q) => {
- const c = Cartographic.fromCartesian(Matrix4.multiplyByPoint(transform, new Cartesian3(...q), new Cartesian3()))
- return { lon: CM.toDegrees(c.longitude), lat: CM.toDegrees(c.latitude) }
- }
- const modules = [],
- samples = []
- for (const b of p.buildings) {
- const n = b.archetype === 'midrise' ? 1 : Math.max(1, Math.ceil(b.width / (b.archetype === 'house' ? 16 : 28)))
- for (let part = 0; part < n; part++) {
- const width = b.width / n,
- depth = b.depth,
- localOffset = -b.width / 2 + width * (part + 0.5),
- u = [Math.cos(b.heading), Math.sin(b.heading)],
- v = [-u[1], u[0]]
- const center = [b.centerENU[0] + u[0] * localOffset, b.centerENU[1] + u[1] * localOffset, 0]
- const footprint = [
- [-width / 2, -depth / 2],
- [width / 2, -depth / 2],
- [width / 2, depth / 2],
- [-width / 2, depth / 2],
- ].map(([x, y]) => [center[0] + u[0] * x + v[0] * y, center[1] + u[1] * x + v[1] * y, 0])
- const id = b.id + '-part' + part
- const points = []
- const cols = Math.ceil(width / 5),
- rows = Math.ceil(depth / 5)
- for (let y = 0; y <= rows; y++)
- for (let x = 0; x <= cols; x++) {
- let dx = -width / 2 + (width * x) / cols,
- dy = -depth / 2 + (depth * y) / rows
- points.push(toGeo([center[0] + u[0] * dx + v[0] * dy, center[1] + u[1] * dx + v[1] * dy, 0]))
- }
- const sampleIndices = points.map((a) => {
- samples.push({ ...a, building: id })
- return samples.length - 1
- })
- modules.push({
- id,
- sourceId: b.id,
- source: b.source,
- width,
- depth,
- heading: b.heading,
- centerENU: center,
- footprintENU: footprint,
- center: toGeo(center),
- archetype: b.archetype,
- floors: b.floors,
- part,
- sampleIndices,
- })
- }
- }
- p.modules = modules
- p.samples = samples
- writeFileSync(file, JSON.stringify(p, null, 2))
- console.log({ sourceBuildings: p.buildings.length, modules: modules.length, samples: samples.length })
|