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

36 lines
2.3 KiB
TypeScript

import type { Entity, Point, ViewBreak } from './types';
const id=(p:Point)=>`${Math.round(p[0]*1000)},${Math.round(p[1]*1000)}`;
export function hatchGeometry(entities:Entity[],scale:number):Entity[] {
const out:Entity[]=[],groups=new Map<string,Extract<Entity,{kind:'line'}>[]>();
for(const e of entities){
if(!['STRUCTURE','BEARING'].includes(e.layer))continue;
if(e.kind==='polyline'&&e.closed)out.push({kind:'hatch',points:e.points,pattern:e.source.member==='pile'?'ANSI31':'SOLID',angle:45,spacing:2*scale,color:e.source.member==='blinding'?'#e7e9ec':'#cccccc',source:e.source,layer:'HATCH'});
if(e.kind==='circle'&&e.source.member==='column')out.push({kind:'hatch',points:Array.from({length:48},(_,i)=>[e.center[0]+e.radius*Math.cos(i*Math.PI/24),e.center[1]+e.radius*Math.sin(i*Math.PI/24)] as Point),pattern:'SOLID',angle:45,spacing:2*scale,color:'#cccccc',source:e.source,layer:'HATCH'});
if(e.kind==='line'){const key=`${e.source.member}:${e.source.index}`;if(!groups.has(key))groups.set(key,[]);groups.get(key)!.push(e);}
}
for(const group of groups.values()){
const unused=new Set(group);
while(unused.size){const first=unused.values().next().value!;unused.delete(first);const points=[first.a,first.b];
while(id(points[points.length-1])!==id(points[0])){
const last=id(points[points.length-1]),next=[...unused].find(e=>id(e.a)===last||id(e.b)===last);
if(!next)break;unused.delete(next);points.push(id(next.a)===last?next.b:next.a);
}
if(points.length>3&&id(points[0])===id(points[points.length-1]))out.push({kind:'hatch',points:points.slice(0,-1),pattern:first.source.member==='blinding'?'ANSI31':'SOLID',spacing:2*scale,angle:45,color:'#cccccc',layer:'HATCH',source:first.source});
}
}
return out;
}
const clipY=(points:Point[],y:number,above:boolean):Point[]=>{
const out:Point[]=[];
for(let i=0;i<points.length;i++){
const a=points[i],b=points[(i+1)%points.length],da=(a[1]-y)*(above?1:-1),db=(b[1]-y)*(above?1:-1);
if(da>=0)out.push(a);
if((da>=0)!==(db>=0)){const t=(y-a[1])/(b[1]-a[1]);out.push([a[0]+(b[0]-a[0])*t,y]);}
}return out;
};
export function cutHatch(points:Point[],cuts:readonly ViewBreak[]):Point[][] {
let polygons=[points];
for(const cut of cuts)polygons=polygons.flatMap(p=>[clipY(p,cut.from,false),clipY(p,cut.to,true)]).filter(p=>p.length>2);
return polygons;
}