sample-district.mjs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. // Direct local DEM sampling at each actual rotated footprint edge/interior. Missing data fails.
  2. import { readFileSync, writeFileSync } from 'node:fs'
  3. const BASE = process.env.COCKPIT_BASE || 'http://localhost:8000'
  4. const path = 'tools/city-massing/district/plan.json'
  5. const plan = JSON.parse(readFileSync(path))
  6. const puppeteer = (
  7. await import(
  8. 'file:///C:/Users/ASUS/.dsh/profiles/desktop/node_modules/puppeteer-core/lib/puppeteer/puppeteer-core.js'
  9. )
  10. ).default
  11. const browser = await puppeteer.launch({
  12. executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe',
  13. headless: true,
  14. args: ['--no-sandbox'],
  15. })
  16. try {
  17. const page = await browser.newPage()
  18. await page.goto(BASE, { waitUntil: 'domcontentloaded' })
  19. await page.setContent('<p>本地 DEM 逐栋采样</p>')
  20. const heights = await page.evaluate(async (points) => {
  21. window.CESIUM_BASE_URL = '/cesium/'
  22. const text = await (await fetch('/src/modules/cockpit/services/cesiumEngine.js')).text()
  23. const url = text.match(/from\s*["']([^"']*\/cesium\.js[^"']*)["']/)?.[1]
  24. if (!url) throw new Error('Cesium URL missing')
  25. const C = await import(url)
  26. const provider = await C.CesiumTerrainProvider.fromUrl('/gis/dem', { requestVertexNormals: false })
  27. const result = []
  28. for (let i = 0; i < points.length; i += 256) {
  29. const chunk = points.slice(i, i + 256).map((p) => C.Cartographic.fromDegrees(p.lon, p.lat))
  30. const sampled = await C.sampleTerrainMostDetailed(provider, chunk, true)
  31. result.push(...sampled.map((p) => p.height))
  32. }
  33. if (result.some((h) => !Number.isFinite(h))) throw new Error('Missing terrain: reject rather than fallback')
  34. return result
  35. }, plan.samples)
  36. writeFileSync(
  37. 'tools/city-massing/district/terrain-samples.json',
  38. JSON.stringify(
  39. {
  40. provider: '/gis/dem',
  41. sampling:
  42. 'sampleTerrainMostDetailed original provider, true on tile failure; actual rotated footprints edges and interiors',
  43. planPoints: plan.samples,
  44. heights,
  45. },
  46. null,
  47. 2
  48. )
  49. )
  50. console.log({ directSamples: heights.length, min: Math.min(...heights), max: Math.max(...heights) })
  51. } finally {
  52. await browser.close()
  53. }