From aa384a81c86b2b8387b50830b6b2041048707bc1 Mon Sep 17 00:00:00 2001 From: ZoeLeeFZ Date: Fri, 27 Nov 2020 11:06:00 +0800 Subject: [PATCH] =?UTF-8?q?!1310=20=E4=BC=98=E5=8C=96:=E7=9F=A9=E5=BD=A2?= =?UTF-8?q?=E6=A7=BD=E8=B5=B0=E5=88=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__snapshots__/rectOffset.test.ts.snap | 208 ++++++++++++++++++ __test__/Polyline/rectOffset.test.ts | 70 ++++++ src/Common/CurveUtils.ts | 10 +- .../ToolPath/FeedingToolPath.ts | 16 +- .../ToolPath/OptimizeToolPath.ts | 51 ++++- 5 files changed, 344 insertions(+), 11 deletions(-) create mode 100644 __test__/Polyline/__snapshots__/rectOffset.test.ts.snap create mode 100644 __test__/Polyline/rectOffset.test.ts diff --git a/__test__/Polyline/__snapshots__/rectOffset.test.ts.snap b/__test__/Polyline/__snapshots__/rectOffset.test.ts.snap new file mode 100644 index 000000000..1b1a737a7 --- /dev/null +++ b/__test__/Polyline/__snapshots__/rectOffset.test.ts.snap @@ -0,0 +1,208 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`矩形偏移 其他视图旋转矩形 1`] = `50`; + +exports[`矩形偏移 其他视图旋转矩形 2`] = ` +Array [ + 0.7789093282833537, + 0, + 0.6271365547575544, + 0, + -0.6271365547575544, + 0, + 0.7789093282833537, + 0, + 0, + -1, + 0, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 其他视图旋转矩形 3`] = `89.99993930803612`; + +exports[`矩形偏移 其他视图旋转矩形 4`] = ` +Array [ + 0.7789093282833537, + 0, + 0.6271365547575544, + 0, + -0.6271365547575544, + 0, + 0.7789093282833537, + 0, + 0, + -1, + 0, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 其他视图旋转矩形 5`] = `15.00001517299097`; + +exports[`矩形偏移 其他视图旋转矩形 6`] = ` +Array [ + 0.7789093282833537, + 0, + 0.6271365547575544, + 0, + -0.6271365547575544, + 0, + 0.7789093282833537, + 0, + 0, + -1, + 0, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 常规矩形 1`] = `50`; + +exports[`矩形偏移 常规矩形 2`] = ` +Array [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 常规矩形 3`] = `89.99993930803612`; + +exports[`矩形偏移 常规矩形 4`] = ` +Array [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 常规矩形 5`] = `15.00001517299097`; + +exports[`矩形偏移 常规矩形 6`] = ` +Array [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 旋转矩形 1`] = `50`; + +exports[`矩形偏移 旋转矩形 2`] = ` +Array [ + 0.7789093282833537, + 0.6271365547575543, + 0, + 0, + -0.6271365547575543, + 0.7789093282833537, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 旋转矩形 3`] = `89.99993930803612`; + +exports[`矩形偏移 旋转矩形 4`] = ` +Array [ + 0.7789093282833537, + 0.6271365547575543, + 0, + 0, + -0.6271365547575543, + 0.7789093282833537, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, +] +`; + +exports[`矩形偏移 旋转矩形 5`] = `15.00001517299097`; + +exports[`矩形偏移 旋转矩形 6`] = ` +Array [ + 0.7789093282833537, + 0.6271365547575543, + 0, + 0, + -0.6271365547575543, + 0.7789093282833537, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, +] +`; diff --git a/__test__/Polyline/rectOffset.test.ts b/__test__/Polyline/rectOffset.test.ts new file mode 100644 index 000000000..ab5f97132 --- /dev/null +++ b/__test__/Polyline/rectOffset.test.ts @@ -0,0 +1,70 @@ +import { IsRect, Polyline } from "../../src/api"; +import { RectOffset } from "../../src/GraphicsSystem/ToolPath/OptimizeToolPath"; +import { LoadEntityFromFileData } from "../Utils/LoadEntity.util"; + +describe("矩形偏移", () => +{ + test("常规矩形", () => + { + let d = { "file": [1, "Polyline", 8, 2, 102, false, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1327.419794987397, 40.97675544794174, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1875.419794987397, -2248.0232597250492, 0, 1], 0, 2, 5, [0, 0], 0, [25, 0], 0, [25, 9.99998482700903], 0, [0, 9.99998482700903], 0, [0, 0], 0, false], "basePt": { "x": -1327.419794987397, "y": 40.97675544794174, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let pl = LoadEntityFromFileData(d)[0] as Polyline; + + let rectInfo = IsRect(pl); + let maxDist = Math.min(rectInfo.size.x, rectInfo.size.y) / 2; + + for (let d of [maxDist / 2, -maxDist / 2, maxDist]) + { + let l = RectOffset(pl, rectInfo, d); + if (l) + { + expect(l.Length).toMatchSnapshot(); + expect(l.OCS.toArray()).toMatchSnapshot(); + } + else + expect(l).toBeUndefined(); + } + }); + test("旋转矩形", () => + { + let d = { "file": [1, "Polyline", 8, 2, 106, false, 1, 7, 0, [0.7789093282833541, 0.6271365547575537, 0, 0, -0.6271365547575537, 0.7789093282833541, 0, 0, 0, 0, 1, 0, -1281.8810060380358, 34.63108438909671, 0, 1], 0, 0, true, [0.7789093282833541, 0.6271365547575537, 0, 0, -0.6271365547575537, 0.7789093282833541, 0, 0, 0, 0, 1, 0, -273.2077345817363, -2091.963211877024, 0, 1], 0, 2, 5, [0, 0], 0, [25, 0], 0, [25, 9.99998482700903], 0, [0, 9.99998482700903], 0, [0, 0], 0, false], "basePt": { "x": -1288.152362070074, "y": 34.63108438909671, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let pl = LoadEntityFromFileData(d)[0] as Polyline; + + let rectInfo = IsRect(pl); + let maxDist = Math.min(rectInfo.size.x, rectInfo.size.y) / 2; + + for (let d of [maxDist / 2, -maxDist / 2, maxDist]) + { + let l = RectOffset(pl, rectInfo, d); + if (l) + { + expect(l.Length).toMatchSnapshot(); + expect(l.OCS.toArray()).toMatchSnapshot(); + } + else + expect(l).toBeUndefined(); + } + }); + test("其他视图旋转矩形", () => + { + let d = { "file": [1, "Polyline", 8, 2, 113, false, 1, 7, 0, [0.7789093282833541, 0, 0.6271365547575537, 0, -0.6271365547575537, 0, 0.7789093282833541, 0, 0, -1, 0, 0, -1062.1715399995587, 0, 0.21291538503150775, 1], 0, 0, true, [0.7789093282833541, 0, 0.6271365547575537, 0, -0.6271365547575537, 0, 0.7789093282833541, 0, 0, -1, 0, 0, -53.4982685432592, 0, -2126.381380881089, 1], 0, 2, 5, [0, 0], 0, [25, 0], 0, [25, 9.99998482700903], 0, [0, 9.99998482700903], 0, [0, 0], 0, false], "basePt": { "x": -1068.442896031597, "y": 0, "z": 0.21291538503150775 }, "ucs": [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1] }; + + let pl = LoadEntityFromFileData(d)[0] as Polyline; + + let rectInfo = IsRect(pl); + let maxDist = Math.min(rectInfo.size.x, rectInfo.size.y) / 2; + + for (let d of [maxDist / 2, -maxDist / 2, maxDist]) + { + let l = RectOffset(pl, rectInfo, d); + if (l) + { + expect(l.Length).toMatchSnapshot(); + expect(l.OCS.toArray()).toMatchSnapshot(); + } + else + expect(l).toBeUndefined(); + } + }); +}); diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index bdcca3603..e7794f4a0 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -497,7 +497,15 @@ export function getTanPtsOnEllipse(cu: Ellipse, lastPoint: Vector3) return []; } -export function IsRect(cu: Curve): { isRect: boolean, size?: Vector3, box?: Box3, OCS?: Matrix4; } +export interface IRectInfo +{ + isRect: boolean; + size?: Vector3; + box?: Box3; + OCS?: Matrix4; +} + +export function IsRect(cu: Curve): IRectInfo { if (cu instanceof Polyline) { diff --git a/src/GraphicsSystem/ToolPath/FeedingToolPath.ts b/src/GraphicsSystem/ToolPath/FeedingToolPath.ts index 925e7bb8e..594f0cb6e 100644 --- a/src/GraphicsSystem/ToolPath/FeedingToolPath.ts +++ b/src/GraphicsSystem/ToolPath/FeedingToolPath.ts @@ -71,25 +71,25 @@ export class FeedingToolPath extends Singleton let offsetDist = 0; - let isRect = IsRect(outline).isRect; + let rectInfo = IsRect(outline); while (true) { - if ((!isOut || offsetDist >= knifRadius) && isRect) + if ((!isOut || offsetDist >= knifRadius) && rectInfo.isRect) offsetDist += knifRadius * 2; else offsetDist += knifRadius; let retCus: Curve[] = []; - let tempOffsetCus = GetOffsetCurves(outline, offsetDist * dir); + let tempOffsetCus = GetOffsetCurves(outline, offsetDist * dir, rectInfo); retCus.push(...tempOffsetCus); //最后一次内偏移如果是矩形,需在偏移一个刀半径避免没切到中心 - if (retCus.length === 0 && isRect) + if (retCus.length === 0 && rectInfo.isRect && offsetDist > knifRadius) { offsetDist -= knifRadius; - retCus.push(...GetOffsetCurves(outline, offsetDist * dir)); + retCus.push(...GetOffsetCurves(outline, offsetDist * dir, rectInfo)); } if (retCus.length === 0) break; @@ -405,12 +405,15 @@ export class FeedingToolPath extends Singleton let cus = outline.Explode(); MergeCurvelist(cus); let hasChange = false; + let curveBak: Curve; + for (let i = 0; i < cus.length; i++) { let c = cus[i]; if (c instanceof Line) { - let mp = c.Midpoint; + let mp = (curveBak ?? c).Midpoint; + curveBak = undefined; if (brCon.PtOnCurve(mp)) { hasChange = true; @@ -474,6 +477,7 @@ export class FeedingToolPath extends Singleton if (intPts[0].thisParam <= 1 && intPts[0].argParam >= 0) { + curveBak = backLine.Clone(); backLine.StartPoint = intPts[0].pt; cs[0].EndPoint = intPts[0].pt; } diff --git a/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts b/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts index a89c0ceb8..b1cfb02da 100644 --- a/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts +++ b/src/GraphicsSystem/ToolPath/OptimizeToolPath.ts @@ -1,12 +1,13 @@ +import { Vector3 } from "three"; import { arrayRemoveIf } from "../../Common/ArrayExt"; -import { ConverCircleToPolyline, curveLinkGroup, equalCurve } from "../../Common/CurveUtils"; +import { ConverCircleToPolyline, curveLinkGroup, equalCurve, IRectInfo, IsRect } from "../../Common/CurveUtils"; import { matrixAlignCoordSys } from "../../Common/Matrix4Utils"; import { Circle } from "../../DatabaseServices/Entity/Circle"; import { Curve } from "../../DatabaseServices/Entity/Curve"; import { Line } from "../../DatabaseServices/Entity/Line"; import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Shape } from "../../DatabaseServices/Shape"; -import { AsVector2, AsVector3, comparePoint, equalv3 } from "../../Geometry/GeUtils"; +import { AsVector2, AsVector3, comparePoint, equaln, equalv3 } from "../../Geometry/GeUtils"; /** * 优化走刀路径,连接偏移后的曲线数组 @@ -248,10 +249,18 @@ function RempveEqualCurves(cus: Curve[]) arrayRemoveIf(cus, (c) => needRemoveCurve.has(c)); } -export function GetOffsetCurves(cu: Curve, dist: number): Curve[] +/**获取内偏移的轮廓 */ +export function GetOffsetCurves(cu: Curve, dist: number, rectInfo?: IRectInfo): Curve[] { if (cu instanceof Polyline) - return cu.GetFeedingToolPath(dist); + { + if (rectInfo?.isRect) + { + let r = RectOffset(cu, rectInfo, Math.abs(dist)); + return r ? [r] : []; + } + return cu.GetFeedingToolPath(dist).filter(c => !equaln(c.Length, 0, 1e-5)); + } else return cu.GetOffsetCurves(dist); } @@ -261,3 +270,37 @@ export function GetCurveToInDir(cu: Curve): number { return cu.IsClockWise ? 1 : -1; } + +/**矩形偏移,正为内偏移 */ +export function RectOffset(rect: Polyline, res: IRectInfo, dist: number) +{ + if (!res.isRect || equaln(dist, 0)) return; + + let box = res.box; + let size = res.size; + let min = box.min.clone(); + let max = box.max.clone(); + + if (dist > Math.min(size.x, size.y) / 2 + 1e-2) return; + + if (equaln(size.x / 2, dist, 1e-5)) + { + let x = (box.min.x + box.max.x) * 0.5; + let sPt = new Vector3(x, box.min.y + dist); + let ePt = new Vector3(x, box.max.y - dist); + return new Polyline([{ pt: AsVector2(sPt), bul: 0 }, { pt: AsVector2(ePt), bul: 0 }]).ApplyMatrix(res.OCS); + } + else if (equaln(size.y / 2, dist, 1e-5)) + { + let y = (box.min.y + box.max.y) * 0.5; + let sPt = new Vector3(box.min.x + dist, y); + let ePt = new Vector3(box.max.x - dist, y); + return new Polyline([{ pt: AsVector2(sPt), bul: 0 }, { pt: AsVector2(ePt), bul: 0 }]).ApplyMatrix(res.OCS); + } + else + { + min.add(new Vector3(dist, dist)); + max.add(new Vector3(-dist, -dist)); + return new Polyline().RectangleFrom2Pt(min, max).ApplyMatrix(res.OCS); + } +}