Files
Pier_v1/src/view/all-piers.ts
T
ypshimandClaude Haiku 5.5 e5d8002c79 fix(view): 지형 모델이 없을 때 60 m 사각판 대신 교각별 지반고 선 표시
- 지형 격자가 없으면 교각 지반고 위치에 얇은 선(코핑 길이 + 여유 2 m)만 그림
- 전체 보기에서도 지형이 없으면 교각별 지반고 선을 표시, 지형이 있으면 공유 격자만 표시
- 부재 표시 '지반' 체크박스는 두 경우 모두 동작
- 테스트: 얇은 선 위치와 길이, 지형 있을 때 선 미표시

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-27 15:16:49 +09:00

54 lines
2.6 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 }[], terrain?: TerrainGrid): AllPiers {
const piers = new THREE.Group();
const scenes = new Map<string, PierScene>();
const reference = entries[0].model.pivot;
for (const { name, model } of entries) {
const scene = buildPierScene(model);
// Without terrain each pier keeps its own 지반고 line; with terrain the shared grid replaces them.
scene.parts.ground.visible = terrain === undefined;
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 (terrain) {
const material = new THREE.MeshStandardMaterial({ color: 0xb8c7b0, roughness: 0.9, metalness: 0, transparent: true, opacity: 0.35, side: THREE.DoubleSide });
terrainMesh = new THREE.Mesh(terrainGeometry(terrain, reference), 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 };
}