Files
Pier_v1/src/view/all-piers.ts
T

56 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import * as THREE from 'three';
import type { PierModel, Vec2 } from '../core/geometry';
import type { TerrainGrid } from '../core/ground-model';
import { buildPierScene, type PierScene } from './scene';
import { terrainGeometry } from './terrain';
/**
* Scene offset of a pier's group inside the shared frame of the reference pier. Each pier's scene is centred on its own
* pivot, so moving it by the pivot difference puts it at its national-grid place (x = E, z = −N, as in stretchMatrix).
*/
export function pierOffset(pivot: Vec2, reference: Vec2): { x: number; z: number } {
return { x: pivot.e - reference.e, z: reference.n - pivot.n };
}
export interface AllPiers {
/** Holds every pier's group, placed by pierOffset. Used for the camera fit and picking. */
piers: THREE.Group;
/** Shared terrain grid in the reference frame, or null without a terrain model. */
terrain: THREE.Mesh | null;
/** Scene of each pier, keyed by the pier name. Parts are shown per pier. */
scenes: Map<string, PierScene>;
/** Scene with the same shape the single-pier view expects (root = pier group, size = whole span). */
view: PierScene;
}
/**
* Builds the concrete members of several piers in one frame (전체 보기, 콘크리트만: no rebar). The first entry is the
* reference. With a terrain grid it is drawn once and the per-pier ground lines are hidden.
*/
export function buildAllPiers(entries: { name: string; model: PierModel; groundEl?: number | null }[], terrain?: TerrainGrid): AllPiers {
const piers = new THREE.Group();
const scenes = new Map<string, PierScene>();
const reference = entries[0].model.pivot;
const terrainSurface = terrain ? terrainGeometry(terrain, reference) : undefined;
const hasTerrainSurface = Boolean(terrainSurface && (terrainSurface.getIndex()?.count ?? 0) > 0);
for (const { name, model, groundEl } of entries) {
const scene = buildPierScene(model, undefined, groundEl);
// Without terrain each pier keeps its own 지반고 line; with terrain the shared grid replaces them.
scene.parts.ground.visible = !hasTerrainSurface;
const { x, z } = pierOffset(model.pivot, reference);
scene.root.position.set(x, 0, z);
scene.root.userData.pier = name;
piers.add(scene.root);
scenes.set(name, scene);
}
let terrainMesh: THREE.Mesh | null = null;
if (terrainSurface && hasTerrainSurface) {
const material = new THREE.MeshStandardMaterial({ color: 0xb8c7b0, roughness: 0.9, metalness: 0, transparent: true, opacity: 0.35, depthWrite: false, side: THREE.DoubleSide });
terrainMesh = new THREE.Mesh(terrainSurface, material);
}
const box = new THREE.Box3().setFromObject(piers);
const size = box.getSize(new THREE.Vector3()).length();
const view: PierScene = { root: piers, parts: scenes.get(entries[0].name)!.parts, size };
return { piers, terrain: terrainMesh, scenes, view };
}