From 2143b16b935b220ad6306b4ca0c5171e5351245a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E4=B8=89?= <940119273@qq.com> Date: Thu, 23 May 2024 07:03:19 +0000 Subject: [PATCH] =?UTF-8?q?!2774=20=E4=BC=98=E5=8C=96:=E5=B0=81=E9=97=AD?= =?UTF-8?q?=E5=A4=9A=E6=AE=B5=E7=BA=BF=E5=88=86=E5=89=B2=E6=88=90=E7=9F=A9?= =?UTF-8?q?=E5=BD=A2,=E4=BD=BF=E7=94=A8=E8=BD=AE=E5=BB=93=E5=88=87?= =?UTF-8?q?=E5=89=B2api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CurveUtils/PolylineSpliteRect.test.ts | 11 +++ .../PolylineSpliteRect.test.ts.snap | 38 ++++---- src/Add-on/BoardCutting/SplitPolyline.ts | 9 +- src/Common/CurveUtils.ts | 96 ++++--------------- 4 files changed, 55 insertions(+), 99 deletions(-) diff --git a/__test__/CurveUtils/PolylineSpliteRect.test.ts b/__test__/CurveUtils/PolylineSpliteRect.test.ts index f7e154d27..933311ea8 100644 --- a/__test__/CurveUtils/PolylineSpliteRect.test.ts +++ b/__test__/CurveUtils/PolylineSpliteRect.test.ts @@ -91,7 +91,18 @@ describe("封闭多段线分割矩形测试", () => expect(c.Area).toMatchSnapshot(); }); + test("轮廓7", () => + { + let data = { "file": [1, "Polyline", 10, 2, 102, 0, 1, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, 2, 8, [163.99999999999997, 0], 0, [182, 0], 0, [181.99999999999997, 132], 0, [169.00000000000003, 132], 0, [169.00000000000003, 332], 0, [182, 332], 0, [182.00000000000009, 464], 0, [164, 464], 0, true], "basePt": { "x": 163.99999999999997, "y": 0, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + let pl = LoadCurvesFromFileData(data) as Polyline[]; + let cons = PolylineSpliteRect(pl[0]); + + expect(cons.length).toBe(3); + + for (let c of cons) + expect(c.Area).toMatchSnapshot(); + }); test('交点参数为负数?', () => { let d = diff --git a/__test__/CurveUtils/__snapshots__/PolylineSpliteRect.test.ts.snap b/__test__/CurveUtils/__snapshots__/PolylineSpliteRect.test.ts.snap index b0e28d3b5..1e1bfdb1e 100644 --- a/__test__/CurveUtils/__snapshots__/PolylineSpliteRect.test.ts.snap +++ b/__test__/CurveUtils/__snapshots__/PolylineSpliteRect.test.ts.snap @@ -8,38 +8,44 @@ exports[`封闭多段线分割矩形测试 轮廓1 2`] = `595357.6812453549`; exports[`封闭多段线分割矩形测试 轮廓1 3`] = `251503.5221472336`; -exports[`封闭多段线分割矩形测试 轮廓2 1`] = `1855875.3072621506`; +exports[`封闭多段线分割矩形测试 轮廓2 1`] = `1855875.3072621487`; -exports[`封闭多段线分割矩形测试 轮廓2 2`] = `868579.4324262962`; +exports[`封闭多段线分割矩形测试 轮廓2 2`] = `857299.1800571308`; -exports[`封闭多段线分割矩形测试 轮廓2 3`] = `2003832.7922209054`; +exports[`封闭多段线分割矩形测试 轮廓2 3`] = `429306.6921083182`; -exports[`封闭多段线分割矩形测试 轮廓2 4`] = `1150366.7076290324`; +exports[`封闭多段线分割矩形测试 轮廓2 4`] = `2003832.7922209073`; -exports[`封闭多段线分割矩形测试 轮廓2 5`] = `857299.1800571308`; +exports[`封闭多段线分割矩形测试 轮廓2 5`] = `1963968.5993822813`; -exports[`封闭多段线分割矩形测试 轮廓2 6`] = `429306.6921083182`; +exports[`封闭多段线分割矩形测试 轮廓2 6`] = `1150366.7076290324`; -exports[`封闭多段线分割矩形测试 轮廓2 7`] = `1963968.5993822813`; +exports[`封闭多段线分割矩形测试 轮廓2 7`] = `868579.4324262962`; exports[`封闭多段线分割矩形测试 轮廓3 1`] = `447800.4779338776`; exports[`封闭多段线分割矩形测试 轮廓3 2`] = `145204.1154134143`; -exports[`封闭多段线分割矩形测试 轮廓3 3`] = `341919.1493761451`; +exports[`封闭多段线分割矩形测试 轮廓3 3`] = `103826.90503283963`; -exports[`封闭多段线分割矩形测试 轮廓3 4`] = `103826.90503283963`; +exports[`封闭多段线分割矩形测试 轮廓3 4`] = `466962.1139759575`; -exports[`封闭多段线分割矩形测试 轮廓3 5`] = `466962.1139759575`; +exports[`封闭多段线分割矩形测试 轮廓3 5`] = `341919.1493761451`; -exports[`封闭多段线分割矩形测试 轮廓4 1`] = `1492707.6629829132`; +exports[`封闭多段线分割矩形测试 轮廓4 1`] = `1492707.6629829137`; -exports[`封闭多段线分割矩形测试 轮廓4 2`] = `603373.0545650794`; +exports[`封闭多段线分割矩形测试 轮廓4 2`] = `603373.0545650786`; -exports[`封闭多段线分割矩形测试 轮廓5 1`] = `10638`; +exports[`封闭多段线分割矩形测试 轮廓5 1`] = `10637.999999999884`; -exports[`封闭多段线分割矩形测试 轮廓5 2`] = `3494.5113962781616`; +exports[`封闭多段线分割矩形测试 轮廓5 2`] = `3494.5113962782198`; -exports[`封闭多段线分割矩形测试 轮廓6 1`] = `5238`; +exports[`封闭多段线分割矩形测试 轮廓6 1`] = `5238.000000000931`; -exports[`封闭多段线分割矩形测试 轮廓6 2`] = `1733.4165836796165`; +exports[`封闭多段线分割矩形测试 轮廓6 2`] = `1733.4165836516768`; + +exports[`封闭多段线分割矩形测试 轮廓7 1`] = `2320.0000000000146`; + +exports[`封闭多段线分割矩形测试 轮廓7 2`] = `1715.9999999999945`; + +exports[`封闭多段线分割矩形测试 轮廓7 3`] = `1716`; diff --git a/src/Add-on/BoardCutting/SplitPolyline.ts b/src/Add-on/BoardCutting/SplitPolyline.ts index ea76d17df..484af34c0 100644 --- a/src/Add-on/BoardCutting/SplitPolyline.ts +++ b/src/Add-on/BoardCutting/SplitPolyline.ts @@ -7,13 +7,10 @@ import { IntersectOption } from "../../GraphicsSystem/IntersectWith"; /** * 线性切割多线段 - * - * @export * @param {Polyline} meatPl 被切割的曲线 * @param {Polyline[]} knifePls 刀曲线 - * @return {*} + * @return */ - export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[] { let allSplitPls: Polyline[] = []; @@ -30,8 +27,6 @@ export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[ pl.StartPoint = ipts[0]; pl.EndPoint = ipts[1]; } - - else { ipts.sort(ComparePointFnGenerate("xy")); @@ -39,8 +34,6 @@ export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[ pl.EndPoint = arrayLast(ipts); } } - - else { let iptsNotExt = ipts.filter(p => pl.PtOnCurve(p)); diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index ea07b6a75..e33d4ef92 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -1,4 +1,5 @@ import { Box2, Box3, Line3, Matrix3, Matrix4, Vec2, Vector2, Vector3 } from 'three'; +import { SplitPolyline } from '../Add-on/BoardCutting/SplitPolyline'; import { Arc } from '../DatabaseServices/Entity/Arc'; import { Circle } from '../DatabaseServices/Entity/Circle'; import { Curve } from '../DatabaseServices/Entity/Curve'; @@ -9,7 +10,7 @@ import { IsPointInBowArc } from '../DatabaseServices/PointInPolyline'; import { Spline } from '../DatabaseServices/Spline'; import { Count } from '../Geometry/Count'; import { CurveMap, Vertice } from '../Geometry/CurveMap'; -import { AsVector2, AsVector3, XAxis, YAxis, ZAxis, ZeroVec, equaln, equalv2, equalv3, isIntersect, isParallelTo } from '../Geometry/GeUtils'; +import { AsVector2, AsVector3, XAxis, YAxis, ZAxis, ZeroVec, equaln, equalv2, equalv3, isParallelTo } from '../Geometry/GeUtils'; import { Vec3 } from '../Geometry/IVec3'; import { Matrix2 } from '../Geometry/Matrix2'; import { Orbit } from '../Geometry/Orbit'; @@ -790,94 +791,39 @@ export function Pts2Polyline(pts: (Vec3 | Vec2)[], isClose: boolean): Polyline return pl; } -const PolylineSpliteRectFuzz = 1e-3; -/**封闭多段线 分割成矩形 */ -export function PolylineSpliteRect(outline: Polyline): Polyline[] +/** + * 将封闭的多段线,通过和y轴平行的线,分割成多个矩形 + * @param outline 这个多边形是横平竖直的,否则返回自身 + * @param polylineParalleXYFuzz 平行x或y的容差 + * @returns 裁剪后的矩形集 + */ +export function PolylineSpliteRect(outline: Polyline, polylineParalleXYFuzz = 1e-3): Polyline[] { if (!outline.IsClose || IsRect(outline)) return [outline]; - let firstDerv = outline.GetFirstDeriv(0).normalize(); - if (!isParallelTo(firstDerv, XAxis, PolylineSpliteRectFuzz) && !isParallelTo(firstDerv, YAxis, PolylineSpliteRectFuzz)) - return [outline]; - let cus = outline.Explode(); - let yCus: Curve[] = []; + let xSet: Set = new Set(); for (let c of cus) { if (c instanceof Arc) return [outline]; let derv = c.GetFirstDeriv(0).normalize(); - if (isParallelTo(derv, YAxis, PolylineSpliteRectFuzz)) - yCus.push(c); - else - if (!isParallelTo(derv, XAxis, PolylineSpliteRectFuzz)) - { - return [outline]; - } + if (isParallelTo(derv, YAxis, polylineParalleXYFuzz)) + xSet.add(c.StartPoint.x); + else if (!isParallelTo(derv, XAxis, polylineParalleXYFuzz)) + return [outline]; } - yCus.sort((c1, c2) => c1.StartPoint.x - c2.StartPoint.x); - - let rects: Polyline[] = []; - let endParam = outline.EndParam; - - for (let i = 0; i < yCus.length - 1; i++) - { - let c1 = yCus[i]; - let c2 = yCus[i + 1]; - - let x1 = c1.StartPoint.x; - let x2 = c2.StartPoint.x; - if (equaln(x1, x2)) - continue; - - let y1: number; - let y2: number; - - let res = c1.IntersectWith2(outline, IntersectOption.ExtendThis); - let res2 = c2.IntersectWith2(outline, IntersectOption.ExtendThis); - let pars: number[] = []; - for (let i of res) pars.push(i.argParam); - for (let i of res2) pars.push(i.argParam); - for (let i = 0; i < pars.length; i++) - { - let p = pars[i]; - if (p < 0) p = 0;//请参照测试用例 - else if (p > endParam) p = endParam;//请参照测试用例 - else p = Math.floor(p); - - pars[i] = p; - } - pars.sort((a, b) => a - b); - arrayRemoveDuplicateBySort(pars); + //轮廓的每条线段都平行于X或Y轴 可直接按端点切割 + const knifePls: Polyline[] = []; + const xList = Array.from(xSet).sort((a, b) => a - b); - let ys: number[] = []; - for (let par of pars) - { - let c = outline.GetCurveAtParam(par); - let derv = c.GetFirstDeriv(0).normalize(); - if (isParallelTo(derv, XAxis, PolylineSpliteRectFuzz)) - { - let x3 = c.StartPoint.x; - let x4 = c.EndPoint.x; - if (x3 > x4) - [x3, x4] = [x4, x3]; - if (isIntersect(x1, x2, x3, x4, -PolylineSpliteRectFuzz)) - ys.push(c.StartPoint.y); - } - } + for (let x of xList) + knifePls.push(new Polyline([{ pt: AsVector2({ x, y: 0 }), bul: 0 }, { pt: AsVector2({ x, y: 1 }), bul: 0 }])); - if (ys.length < 2) return [outline]; - - ys.sort((a, b) => a - b); - - y1 = ys[0]; - y2 = arrayLast(ys); - - rects.push(new Polyline().RectangleFrom2Pt(new Vector3(x1, y1), new Vector3(x2, y2))); - } + //裁剪结果 + let rects = SplitPolyline(outline, knifePls).filter(pl => pl.IsClose); return rects; - }