t53-manhole.mjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import assert from 'node:assert/strict'
  2. import * as THREE from 'three'
  3. import { planPipeEnhancement } from '../../../src/modules/cockpit/domain/pipeEnhancement.js'
  4. import { mountPipeEnhancement } from '../../../src/modules/cockpit/services/threePipeEnhancement.js'
  5. const manhole = { code: 'MH-1', sourceId: 'source-manhole', networkId: 'unknown-ref', industry: 'MANHOLE', kind: 'other', position: [110, 28], name: '真实窨井' }
  6. const nearby = { code: 'P', industry: 'DRAINAGE', networkLevel: 0, positions: [[109.9999, 28], [110.0001, 28]] }
  7. const plan = planPipeEnhancement({ selected: { kind: 'component', code: 'MH-1' }, visiblePipes: [nearby], visibleComponents: [manhole] })
  8. assert.equal(plan.object.renderKind, 'manhole')
  9. assert.equal(plan.object.title, '真实窨井')
  10. assert.match(plan.connectionNote, /接管关系未提供/)
  11. assert.equal(plan.objects.length, 2)
  12. assert.equal(plan.object.stateText, '状态未提供')
  13. let scene
  14. const canvas = new EventTarget()
  15. const host = { clientWidth: 900, clientHeight: 500, appendChild(n) { n.parentNode = this }, removeChild(n) { n.parentNode = null } }
  16. const viewer = mountPipeEnhancement(host, plan, { rendererFactory: () => ({ domElement: canvas, setSize() {}, dispose() {}, render(s) { scene = s } }) })
  17. assert.ok(scene.getObjectByName('manhole-shaft'))
  18. assert.ok(scene.getObjectByName('manhole-cover'))
  19. assert.ok(!scene.getObjectByName('invented-connection'))
  20. assert.ok(scene.getObjectByName('pipe-enhancement:P'))
  21. viewer.destroy()
  22. const isolated = planPipeEnhancement({ selected: { kind: 'component', code: 'MH-1' }, visibleComponents: [manhole] })
  23. for (const position of [[110.0002, 28], [110, 28]]) {
  24. isolated.devices = [{ code: 'standalone', industry: 'WATER_SUPPLY', colorKey: 'WATER_SUPPLY', depthM: 4, slot: 0, position }]
  25. let isolatedCamera
  26. const next = mountPipeEnhancement(host, isolated, { rendererFactory: () => ({ domElement: canvas, setSize() {}, dispose() {}, render(s, c) { scene = s; isolatedCamera = c } }) })
  27. const device = scene.getObjectByName('device:standalone')
  28. scene.updateMatrixWorld(true); isolatedCamera.updateMatrixWorld()
  29. const screen = device.getWorldPosition(new THREE.Vector3()).project(isolatedCamera)
  30. assert.ok(Math.abs(screen.x) < 1 && Math.abs(screen.y) < 1 && screen.z < 1, '井边独立设备须纳入相机可见范围')
  31. next.destroy()
  32. }
  33. console.log('PASS 无管线源时独立设备坐标及深度参与取景,设备模型不会落到远裁面外')
  34. const deep = planPipeEnhancement({ selected: { kind: 'pipe', code: 'deep' }, visiblePipes: [
  35. { code: 'deep', industry: 'DRAINAGE', networkLevel: 1, positions: [[110, 28], [110.00001, 28]] },
  36. ] })
  37. deep.devices = [{ code: 'shallow', industry: 'GAS', colorKey: 'GAS', depthM: 1.5, slot: 0, position: [110, 28] }]
  38. let view
  39. const deepViewer = mountPipeEnhancement(host, deep, { rendererFactory: () => ({ domElement: canvas, setSize() {}, dispose() {}, render(s, camera) { scene = s; view = camera } }) })
  40. scene.updateMatrixWorld(true); view.updateMatrixWorld()
  41. const projected = scene.getObjectByName('device:shallow').getWorldPosition(new THREE.Vector3()).project(view)
  42. assert.ok(Math.abs(projected.x) < 1 && Math.abs(projected.y) < 1 && projected.z > -1 && projected.z < 1, '浅层设备必须在初始视锥内')
  43. deepViewer.destroy()
  44. console.log('PASS 深层雨水管与浅层独立燃气设备三维居中,设备初始投影在视锥内')
  45. console.log('PASS 窨井身份计划 → 剖切井筒和井盖+邻近管道,不造接管/状态')