From 67f3845014e0c73750264afb9ba61aeae0ee215f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=91=EC=A1=B0?= Date: Thu, 29 Oct 2026 12:13:25 +0900 Subject: [PATCH] Add DXF verification: update src/dxf.js --- src/dxf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dxf.js b/src/dxf.js index e76a9ce..ff4ef07 100644 --- a/src/dxf.js +++ b/src/dxf.js @@ -1,5 +1,5 @@ // DXF parsing and plan geometry helpers. -function parseDxf(text){const entities=[],dimensionTexts=[];const raw=text.replace(/^\ufeff/,'').split(/\r?\n/),pairs=[];for(let i=0;i+1p[0]===8)?.[1]||'0',entity={type,layer};layers.add(layer);if(type==='LINE'){entity.pts=[{x:num(rec,10),y:num(rec,20)},{x:num(rec,11),y:num(rec,21)}]}else if(type==='LWPOLYLINE'){const pts=[];let point=null;for(const [code,value] of rec){if(code===10){if(point)pts.push(point);point={x:Number(value),y:0}}else if(code===20&&point)point.y=Number(value)}if(point)pts.push(point);entity.pts=pts;entity.closed=!!(Number(rec.find(p=>p[0]===70)?.[1]||0)&1)}else if(type==='POLYLINE'){let pts=[];while(ip[0]===70)?.[1]||0)&1);if(pairs[i]?.[0]===0&&pairs[i][1]==='SEQEND')i++}else if(type==='TEXT'||type==='MTEXT'){entity.text=rec.filter(p=>p[0]===1||p[0]===3).map(p=>p[1]).join('').replace(/\\P/g,' ').replace(/[{}]/g,'').trim();entity.pos={x:num(rec,10),y:num(rec,20)};entity.rotation=num(rec,50);if(entity.text&&layer==='DIM')dimensionTexts.push(entity)}if(entity.pts)entities.push(entity)}if(!entities.length)throw Error('도면의 ENTITIES 섹션에서 지원되는 선 도형을 찾지 못했습니다. ASCII DXF인지 확인해 주세요.');return {entities,dimensionTexts,layers:[...layers].sort((a,b)=>a.localeCompare(b,undefined,{numeric:true))}}} +function parseDxf(text){const entities=[],dimensionTexts=[];const raw=text.replace(/^\ufeff/,'').split(/\r?\n/),pairs=[];for(let i=0;i+1p[0]===8)?.[1]||'0',entity={type,layer};layers.add(layer);if(type==='LINE'){entity.pts=[{x:num(rec,10),y:num(rec,20)},{x:num(rec,11),y:num(rec,21)}]}else if(type==='LWPOLYLINE'){const pts=[];let point=null;for(const [code,value] of rec){if(code===10){if(point)pts.push(point);point={x:Number(value),y:0}}else if(code===20&&point)point.y=Number(value)}if(point)pts.push(point);entity.pts=pts;entity.closed=!!(Number(rec.find(p=>p[0]===70)?.[1]||0)&1)}else if(type==='POLYLINE'){let pts=[];while(ip[0]===70)?.[1]||0)&1);if(pairs[i]?.[0]===0&&pairs[i][1]==='SEQEND')i++}else if(type==='TEXT'||type==='MTEXT'){entity.text=rec.filter(p=>p[0]===1||p[0]===3).map(p=>p[1]).join('').replace(/\\P/g,' ').replace(/[{}]/g,'').trim();entity.pos={x:num(rec,10),y:num(rec,20)};entity.rotation=num(rec,50);if(entity.text&&layer==='DIM')dimensionTexts.push(entity)}if(entity.pts)entities.push(entity)}if(!entities.length)throw Error('도면의 ENTITIES 섹션에서 지원되는 선 도형을 찾지 못했습니다. ASCII DXF인지 확인해 주세요.');return {entities,dimensionTexts,layers:[...layers].sort((a,b)=>a.localeCompare(b,undefined,{numeric:true}))}} function num(rec,code){return Number(rec.find(p=>p[0]===code)?.[1]||0)} function eq(a,b){return Math.hypot(a.x-b.x,a.y-b.y)<1e-5}function closedLoops(entities,layer){const found=[];let lines=[];for(const e of entities.filter(x=>x.layer===layer)){if(e.pts?.length<2)continue;if(e.type==='LINE'||!e.closed){for(let i=0;i2)lines.push([e.pts.at(-1),e.pts[0]]);continue}if(e.pts.length>=3)found.push(e.pts.slice())}while(lines.length){let chain=lines.pop().map(p=>({...p})),changed=true;while(changed){changed=false;for(let i=0;i=4&&eq(chain[0],chain.at(-1)))found.push(chain.slice(0,-1))}return found}