diff --git a/__test__/FeedingToolPath/FeedingToolPath.test.ts b/__test__/FeedingToolPath/FeedingToolPath.test.ts index bb5e3613b..ca27112f0 100644 --- a/__test__/FeedingToolPath/FeedingToolPath.test.ts +++ b/__test__/FeedingToolPath/FeedingToolPath.test.ts @@ -125,3 +125,11 @@ test("#IYX1P", () => let brs = LoadBoardsFromFileData(data); testPathCount(brs[0], 5); }) + +test("极限刀半径#I11UDE", () => +{ + let data = + [1, "Board", 5, 2, 101, false, 1, 2, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, -2274.8106081003034, 1049.489754699042, 0, 1], 0, 0, 2, 1500, 996.4248716877983, 18, true, "Polyline", 5, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 396.42487168779826, 0, 0, 1], 0, 0, 2, 4, [-396.42487168779826, 0], 0, [600, 0], 0, [600, 1500], 0, [-396.42487168779826, 1500], 0, true, 1, 2, 613.5945382529881, 504.5731587306118, 12, false, "Polyline", 5, 2, 0, false, 0, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -286.0137526959925, -382.0303425189268, 0, 1], 0, 0, 2, 12, [656.1445063338533, 607.3988458450913], 0, [763.0711684959024, 607.3988458450913], 0, [763.0711684959024, 995.6248807719148], 0, [476.8367190159561, 995.6248807719148], 0, [476.8367190159561, 794.9317610216076], 0, [286.0137526959925, 794.9317610216076], 0, [286.0137526959925, 382.0303425189268], 0, [656.1445063338533, 382.0303425189268], 0, [656.1445063338533, 519.394335722528], 0, [790.5869114266043, 519.394335722528], 0, [790.5869114266043, 525.394335722528], 0, [656.1445063338533, 525.394335722528], 0, true, 1, 2, 601.5945382529881, 465.0574157999099, 12, false, "Polyline", 5, 2, 0, false, 0, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -292.0137526959925, -388.0303425189268, 0, 1], 0, 0, 2, 12, [650.1445063338533, 525.394335722528], 0, [650.1445063338533, 613.3988458450913], 0, [757.0711684959024, 613.3988458450913], 0, [757.0711684959024, 989.6248807719148], 0, [482.8367190159561, 989.6248807719148], 0, [482.8367190159561, 788.9317610216076], 0, [292.0137526959925, 788.9317610216076], 0, [292.0137526959925, 388.0303425189268], 0, [650.1445063338533, 388.0303425189268], 0, [650.1445063338533, 519.394335722528], 0, [507.05781142660453, 519.394335722528], 0, [507.05781142660453, 525.394335722528], 0, true, 0, 3, 0, 0, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, -2662.84095061923, 1341.5035073950344, 6, 1], 3, 0, 0, 0, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, -2656.84095061923, 1335.5035073950344, 6, 1], 3, 0, 0, 0, 5, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -2274.8106081003034, 1049.489754699042, 0, 1], 0, "底板", "主卧", "下柜", "", "", "", 0, 1, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0] + let brs = LoadBoardsFromFileData(data); + testPathCount(brs[0], 4); +}) diff --git a/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap b/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap index 7b890a51b..12bb78940 100644 --- a/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap +++ b/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap @@ -152,6 +152,16 @@ exports[`带孔造型板件: 走刀数量 1`] = `2`; exports[`带孔造型板件: 走刀数量 2`] = `2`; +exports[`极限刀半径#I11UDE: 曲线长度 1`] = `2434.8330081057957`; + +exports[`极限刀半径#I11UDE: 曲线长度 2`] = `4992.8497433755965`; + +exports[`极限刀半径#I11UDE: 曲线长度 3`] = `2450.188718291298`; + +exports[`极限刀半径#I11UDE: 曲线长度 4`] = `2419.4772979202935`; + +exports[`极限刀半径#I11UDE: 走刀数量 1`] = `1`; + exports[`极限刀半径: 曲线长度 1`] = `999.9999999999999`; exports[`极限刀半径: 曲线长度 2`] = `3600`; diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index bc47eb585..32ffc7fc2 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -252,6 +252,12 @@ export function equalCurve(cu1: Curve, cu2: Curve, tolerance = 1e-4) && equaln(cu1.RadY, cu2.RadY) && equalv3(cu1.StartPoint, cu2.StartPoint); } + else if (cu1 instanceof Line && cu2 instanceof Line) + { + let ps1 = [cu1.StartPoint, cu1.EndPoint]; + let ps2 = [cu2.StartPoint, cu2.EndPoint]; + return ps1.every(p => ps2.some(p1 => equalv3(p1, p))); + } return false; } diff --git a/src/GraphicsSystem/ToolPath/FeedingToolPath.ts b/src/GraphicsSystem/ToolPath/FeedingToolPath.ts index e1d47c55e..0fed8b730 100644 --- a/src/GraphicsSystem/ToolPath/FeedingToolPath.ts +++ b/src/GraphicsSystem/ToolPath/FeedingToolPath.ts @@ -10,6 +10,7 @@ import { BoolOpeartionType } from "../BoolOperateUtils"; import { OptimizeToolPath } from "./OptimizeToolPath"; import { equalCurve, IsRect } from "../../Common/CurveUtils"; import { Vector3 } from "three"; +import { RegionParse } from "../../Geometry/RegionParse"; /** *计算走刀工具类 @@ -29,17 +30,39 @@ export class FeedingToolPath extends Singleton let dir = this.GetCurveToInDir(outline); let offsetCus: Curve[] = [outline]; + //偏移后不闭合的走刀路径 + let uncloseCurves: Curve[] = []; //获得形状外孔轮廓 - let holes = shape.Holes.map(h => + let holes: Contour[] = [] + for (let h of shape.Holes) { if (!isOut) - return h.Clone(); - - let dir = -this.GetCurveToInDir(h.Curve); - let tmpCus = h.Curve.GetOffsetCurves(knifRadius * dir); - return Contour.CreateContour(tmpCus); - }); + holes.push(h.Clone()); + else + { + let dir = -this.GetCurveToInDir(h.Curve); + let tmpCus: Curve[]; + if (h.Curve instanceof Polyline) + { + tmpCus = h.Curve.GetFeedingToolPath(knifRadius * dir); + if (tmpCus[0] instanceof Polyline && !tmpCus[0].IsClose) + { + uncloseCurves.push(tmpCus[0]); + let reg = new RegionParse(tmpCus[0].Explode() as Curve[], 3); + tmpCus.length = 0 + for (let routes of reg.RegionsOutline) + for (let r of routes) + tmpCus.push(r.curve); + } + } + else + tmpCus = h.Curve.GetOffsetCurves(knifRadius * dir); + let con = Contour.CreateContour(tmpCus); + if (con) + holes.push(con); + } + } let offsetDist = 0; @@ -59,7 +82,7 @@ export class FeedingToolPath extends Singleton let isInt = false; for (let c of retCus) { - if (holes.length > 0) + if (holes.length > 0 && c.IsClose) { isInt = holes.some(h => h.Curve.IntersectWith(c, 0).length > 0 || h.CuInOutline(c)); if (isInt) break; @@ -118,6 +141,8 @@ export class FeedingToolPath extends Singleton offsetCus.push(h.Curve); } + offsetCus.push(...uncloseCurves); + return offsetCus; } /** diff --git a/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts b/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts index e1c451825..7661c32f1 100644 --- a/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts +++ b/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts @@ -1,12 +1,12 @@ import { Curve } from "../../DatabaseServices/Entity/Curve"; import { Shape } from "../../DatabaseServices/Shape"; import { matrixAlignCoordSys } from "../../Common/Matrix4Utils"; -import { curveLinkGroup, ConverCircleToPolyline } from "../../Common/CurveUtils"; +import { curveLinkGroup, ConverCircleToPolyline, equalCurve } from "../../Common/CurveUtils"; import { Line } from "../../DatabaseServices/Entity/Line"; import { Circle } from "../../DatabaseServices/Entity/Circle"; import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { comparePoint, AsVector3, AsVector2 } from "../../Geometry/GeUtils"; -import { arrayLast } from "../../Common/ArrayExt"; +import { arrayLast, arrayRemoveIf } from "../../Common/ArrayExt"; /** * 优化走刀路径,连接偏移后的曲线数组 @@ -46,7 +46,9 @@ export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: nu if (noCloseCus.length > 0) { let culist: Curve[] = []; - noCloseCus.forEach(c => culist.push(...c.Explode() as Curve[])) + noCloseCus.forEach(c => culist.push(...c.Explode() as Curve[])); + //移除相等的曲线避免重复走刀 + RempveEqualCurves(culist); let groups = curveLinkGroup(culist); for (let g of groups) { @@ -206,3 +208,23 @@ function SortPlByStartPt(plList: Polyline[]) plList.length = 0; plList.push(...result); } + +function RempveEqualCurves(cus: Curve[]) +{ + let needRemoveCurve: Set = new Set(); + for (let i = 0; i < cus.length; i++) + { + let cu1 = cus[i]; + if (needRemoveCurve.has(cu1)) continue; + for (let j = i + 1; j < cus.length; j++) + { + let cu2 = cus[j]; + if (needRemoveCurve.has(cu2)) continue; + if (equalCurve(cu1, cu2)) + { + needRemoveCurve.add(cu2); + } + } + } + arrayRemoveIf(cus, (c) => needRemoveCurve.has(c)); +}