Files
Pier_v1/도면작성/iso-visibility.ts
T
2026-11-04 13:34:51 +09:00

32 lines
2.2 KiB
TypeScript

import { Vector3 } from 'three';
export type DepthFace<T>={vertices:Vector3[];edges:boolean[];data:T};
/** BSP painter for an orthographic camera at negative depth. Split crossing faces,
* preserving only original edges so partition boundaries never become CAD outlines. */
export function visibleOrder<T>(input:DepthFace<T>[]):DepthFace<T>[] {
const visit=(faces:DepthFace<T>[]):DepthFace<T>[]=>{
if(!faces.length)return [];
const seed=faces[0],a=seed.vertices[0];let normal=new Vector3();
for(let i=1;i<seed.vertices.length-1&&normal.lengthSq()<1e-16;i++)normal=seed.vertices[i].clone().sub(a).cross(seed.vertices[i+1].clone().sub(a));
if(normal.lengthSq()<1e-16)return visit(faces.slice(1));
normal.normalize();const offset=normal.dot(a),front:DepthFace<T>[]=[],back:DepthFace<T>[]=[],same:DepthFace<T>[]=[seed];
for(const face of faces.slice(1)){
const ds=face.vertices.map(p=>normal.dot(p)-offset),positive=ds.some(d=>d>1e-5),negative=ds.some(d=>d< -1e-5);
if(!positive&&!negative){same.push(face);continue;}
if(!negative){front.push(face);continue;}if(!positive){back.push(face);continue;}
for(const [sign,list] of [[1,front],[-1,back]] as const){
const vertices:Vector3[]=[],incoming:boolean[]=[];
for(let i=0;i<face.vertices.length;i++){
const j=(i+1)%face.vertices.length,p=face.vertices[i],q=face.vertices[j],inside=ds[i]*sign>=-1e-5,next=ds[j]*sign>=-1e-5;
if(inside&&next){vertices.push(q);incoming.push(face.edges[i]);}
else if(inside&&!next){vertices.push(p.clone().lerp(q,ds[i]/(ds[i]-ds[j])));incoming.push(face.edges[i]);}
else if(!inside&&next){vertices.push(p.clone().lerp(q,ds[i]/(ds[i]-ds[j])),q);incoming.push(false,face.edges[i]);}
}
if(vertices.length>=3)list.push({vertices,edges:incoming.map((_,i)=>incoming[(i+1)%incoming.length]),data:face.data});
}
}
return normal.z<0?[...visit(back),...same,...visit(front)]:[...visit(front),...same,...visit(back)];
};
return visit(input.flatMap(face=>Array.from({length:face.vertices.length-2},(_,j)=>{const i=j+1;return {vertices:[face.vertices[0],face.vertices[i],face.vertices[i+1]],edges:[i===1&&face.edges[0],face.edges[i],i===face.vertices.length-2&&face.edges[i+1]],data:face.data};})));
}