From 677e6324e746f696b82f9af893ce3e94d1a75824 Mon Sep 17 00:00:00 2001 From: ChenX Date: Mon, 5 Apr 2021 15:52:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=E4=BD=99=E6=96=99=E5=88=86?= =?UTF-8?q?=E6=9E=90-=E9=87=8D=E5=8F=A0=E4=BD=99=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Nest/Core/ParseOddments.ts | 69 ++++++++++++++++--- src/Nest/Core/Path.ts | 10 +++ src/Nest/Test/TestPraseOddments.ts | 4 +- src/UI/Components/EntityModal/EntityModal.tsx | 3 + src/UI/Components/ToolBar/PropertiesPanel.tsx | 3 + 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/Nest/Core/ParseOddments.ts b/src/Nest/Core/ParseOddments.ts index 99540c488..2e5c4b436 100644 --- a/src/Nest/Core/ParseOddments.ts +++ b/src/Nest/Core/ParseOddments.ts @@ -3,7 +3,7 @@ import { Box2 } from "../Common/Box2"; import { clipperCpp } from "../Common/ClipperCpp"; import { Container } from "./Container"; import { NestCache } from "./NestCache"; -import { Path, PathScale, TranslatePath } from "./Path"; +import { Path, PathScale, TranslatePath, TranslatePath_Self } from "./Path"; const SquarePath = NestCache.CreatePath(60, 60, 0); const CanPutPaths = [ @@ -58,7 +58,8 @@ export function ParseOddments(container: Container, binPath: Path, knifeRadius: ]; } - let splitPolygons: Path[] = []; + let clipedPaths: Path[] = [];//已经减去网洞投影的余料轮廓列表 + //由于手动排版可能造成余料网洞,我们将网洞的盒子投影,然后裁剪余料,避免余料有网洞 for (let node of oddmentsPolygon.childs) { @@ -112,38 +113,84 @@ export function ParseOddments(container: Container, binPath: Path, knifeRadius: }); for (let p of splits) - splitPolygons.push(new Path(PathScale(p, 1e-4))); + clipedPaths.push(new Path(PathScale(p, 1e-4))); } else - splitPolygons.push(new Path(node.contour.map(p => { return { x: p.x * 1e-4, y: p.y * 1e-4 }; }),)); + clipedPaths.push(new Path(node.contour.map(p => { return { x: p.x * 1e-4, y: p.y * 1e-4 }; }),)); } let OddmentsPaths: Path[] = []; - for (let polygonPath of splitPolygons) + for (let polygonPath of clipedPaths) { //先获取内部的nfp let insideNFPS = polygonPath.GetInsideNFP(squarePath); if (!insideNFPS) continue; + let beferPolygons: ClipInput[] = []; + for (let nfp of insideNFPS) { let nfpPath = new Path(PathScale(nfp, 1e-4)); //通过内部nfp还原实际轮廓 - let sumPolygons = clipperCpp.lib.minkowskiSumPath(nfpPath.BigIntPoints, SquarePath.BigIntPoints, true); + let sumPolygons = clipperCpp.lib.minkowskiSumPath(nfpPath.BigIntPoints, squarePath.BigIntPoints, true); sumPolygons = clipperCpp.lib.simplifyPolygons(sumPolygons); for (let poly of sumPolygons) { if (clipperCpp.lib.area(poly) < 0) continue;//移除内部的,无意义的 - let tempPath = new Path(PathScale(poly, 1e-4)); + let tempPath = new Path(poly.map(p => { return { x: p.x * 1e-4, y: p.y * 1e-4 }; }));//这里new一个新的,下面就复用这个 if (canPutPaths.some(p => tempPath.GetInsideNFP(p)?.length))//能塞的下指定的轮廓才会被留下 { - //设置轮廓的位置 - tempPath.OrigionMinPoint.x += nfpPath.OrigionMinPoint.x + polygonPath.OrigionMinPoint.x; - tempPath.OrigionMinPoint.y += nfpPath.OrigionMinPoint.y + polygonPath.OrigionMinPoint.y; - OddmentsPaths.push(tempPath); + if (beferPolygons.length) + { + //移动到实际位置 + TranslatePath_Self(poly, (polygonPath.OrigionMinPoint.x + nfpPath.OrigionMinPoint.x) * 1e4, (polygonPath.OrigionMinPoint.y + nfpPath.OrigionMinPoint.y) * 1e4); + + //在这里裁剪之前的余料轮廓 + let tree = clipperCpp.lib.clipToPolyTree({ + subjectInputs: [{ data: poly, closed: true }], + clipInputs: beferPolygons, + clipType: ClipType.Difference, + subjectFillType: PolyFillType.NonZero + }); + + for (let node of tree.childs) + { + if (node.childs.length) continue; + + tempPath = new Path(node.contour.map(p => { return { x: p.x * 1e-4, y: p.y * 1e-4 }; })); + OddmentsPaths.push(tempPath); + + //偏移2把刀 + let offsetedPolygon = clipperCpp.lib.offsetToPaths({ + delta: knifeRadius * 2e4, + offsetInputs: [{ data: node.contour, joinType: JoinType.Miter, endType: EndType.ClosedPolygon }] + })[0]; + beferPolygons.push({ data: offsetedPolygon });//用于裁剪后续的余料 + } + } + else + { + //设置轮廓的位置 + tempPath.OrigionMinPoint.x += nfpPath.OrigionMinPoint.x + polygonPath.OrigionMinPoint.x; + tempPath.OrigionMinPoint.y += nfpPath.OrigionMinPoint.y + polygonPath.OrigionMinPoint.y; + OddmentsPaths.push(tempPath); + + //将余料轮廓加入到裁剪轮廓中,用于裁剪后续的余料 + if (insideNFPS.length) + { + //移动到实际位置 + TranslatePath_Self(poly, (polygonPath.OrigionMinPoint.x + nfpPath.OrigionMinPoint.x) * 1e4, (polygonPath.OrigionMinPoint.y + nfpPath.OrigionMinPoint.y) * 1e4); + //偏移2把刀 + let offsetedPolygon = clipperCpp.lib.offsetToPaths({ + delta: knifeRadius * 2e4, + offsetInputs: [{ data: poly, joinType: JoinType.Miter, endType: EndType.ClosedPolygon }] + })[0]; + beferPolygons.push({ data: offsetedPolygon });//用于裁剪后续的余料 + } + } } } } diff --git a/src/Nest/Core/Path.ts b/src/Nest/Core/Path.ts index a6d7baaf6..13f8a2a2c 100644 --- a/src/Nest/Core/Path.ts +++ b/src/Nest/Core/Path.ts @@ -348,6 +348,16 @@ export function TranslatePath(pts: Point[], p: Point): Point[] }); } +export function TranslatePath_Self(pts: Point[], mx: number, my: number): Point[] +{ + for (let pt of pts) + { + pt.x += mx; + pt.y += my; + } + return pts; +} + //缩放点表,返回原始点表 export function PathScale(pts: Point[], scale: number): Point[] { diff --git a/src/Nest/Test/TestPraseOddments.ts b/src/Nest/Test/TestPraseOddments.ts index 8ffd1a840..398e49d60 100644 --- a/src/Nest/Test/TestPraseOddments.ts +++ b/src/Nest/Test/TestPraseOddments.ts @@ -36,11 +36,13 @@ export class Command_TestParseOddments implements Command let binP = AsVector3(binPath.OrigionMinPoint).multiplyScalar(1e4); let odd = ParseOddments(container, binPath); + let i = 1; for (let p of odd) { let pl = Path2Polyline(p.Points); pl.Position = AsVector3(p.OrigionMinPoint).add(binP); - TestDraw(pl, 2); + TestDraw(pl, i); + i++; } } } diff --git a/src/UI/Components/EntityModal/EntityModal.tsx b/src/UI/Components/EntityModal/EntityModal.tsx index 4629566d3..3abcffc7c 100644 --- a/src/UI/Components/EntityModal/EntityModal.tsx +++ b/src/UI/Components/EntityModal/EntityModal.tsx @@ -76,6 +76,9 @@ export class EntityModal extends React.Component<{ store?: EntityStore; }, {}> {
  • 面积: {ents[0].Area.toFixed(2)}
  • +
  • + 时针: {ents[0].IsClockWise ? "顺时针" : "逆时针"} +
  • } diff --git a/src/UI/Components/ToolBar/PropertiesPanel.tsx b/src/UI/Components/ToolBar/PropertiesPanel.tsx index 878bc3697..42cf73d72 100644 --- a/src/UI/Components/ToolBar/PropertiesPanel.tsx +++ b/src/UI/Components/ToolBar/PropertiesPanel.tsx @@ -116,6 +116,9 @@ export class PropertiesPanel extends React.Component
  • 参数:{(ents[0] as Curve).EndParam}
  • +
  • + 时针: {ents[0].IsClockWise ? "顺时针" : "逆时针"} +
  • } {