import { describe, expect, it } from 'vitest' import * as THREE from 'three' import { getWalkableSurfaceHits, projectRoutePositionToSurface, resolveDominantRouteSurfaceY } from '@/components/map/routeSurfaceProjection' const createDeck = ( y: number, width = 40, depth = 40, x = 0, z = 0 ) => { const deck = new THREE.Mesh( new THREE.BoxGeometry(width, 0.2, depth), new THREE.MeshBasicMaterial() ) deck.position.set(x, y - 0.1, z) return deck } const boundsOf = (object: THREE.Object3D) => { object.updateWorldMatrix(true, true) return new THREE.Box3().setFromObject(object) } describe('route surface projection', () => { it('将5楼遗留的非零路线Y投射到真实楼面', () => { const floor = new THREE.Group() floor.add(createDeck(26.964)) const fixture = new THREE.Mesh( new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial() ) fixture.position.set(0, 28, 0) floor.add(fixture) const bounds = boundsOf(floor) const hits = getWalkableSurfaceHits(floor, bounds, [0, 0.33, 0]) const projected = projectRoutePositionToSurface( floor, bounds, [0, 0.33, 0], 26.964, 0.24 ) expect(hits[0]).toBeCloseTo(26.964, 3) expect(projected?.y).toBeCloseTo(27.204, 3) }) it('以多数路线点命中的楼面为当前楼层高度', () => { const floor = new THREE.Group() floor.add(createDeck(26.964, 20, 20)) floor.add(createDeck(29.5, 4, 4, 20, 0)) const bounds = boundsOf(floor) const surfaceY = resolveDominantRouteSurfaceY(floor, bounds, [ [-5, 0.197, 0], [0, 0.33, 0], [5, 0.254, 0], [20, 0.33, 0] ]) expect(surfaceY).toBeCloseTo(26.964, 3) }) it('不把当前楼层已隐藏的模型表面作为路线高度', () => { const floor = new THREE.Group() const hiddenDeck = createDeck(2) hiddenDeck.visible = false floor.add(hiddenDeck) floor.add(createDeck(10)) const bounds = boundsOf(floor) const surfaceY = resolveDominantRouteSurfaceY(floor, bounds, [[0, 0, 0]]) expect(surfaceY).toBeCloseTo(10, 3) }) it('返回包含楼层布局位移的世界高度,避免重复叠加偏移', () => { const floor = new THREE.Group() floor.add(createDeck(5)) floor.position.y = 68 const bounds = boundsOf(floor) const projected = projectRoutePositionToSurface( floor, bounds, [0, 5.074, 0], undefined, 0.24 ) expect(projected?.y).toBeCloseTo(73.24, 3) }) })