!2774 优化:封闭多段线分割成矩形,使用轮廓切割api

other_split_method
林三 4 months ago committed by ChenX
parent b09df3ffd9
commit 2143b16b93

@ -91,7 +91,18 @@ describe("封闭多段线分割矩形测试", () =>
expect(c.Area).toMatchSnapshot(); 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('交点参数为负数?', () => test('交点参数为负数?', () =>
{ {
let d = let d =

@ -8,38 +8,44 @@ exports[`封闭多段线分割矩形测试 轮廓1 2`] = `595357.6812453549`;
exports[`封闭多段线分割矩形测试 轮廓1 3`] = `251503.5221472336`; 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 1`] = `447800.4779338776`;
exports[`封闭多段线分割矩形测试 轮廓3 2`] = `145204.1154134143`; 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`;

@ -7,13 +7,10 @@ import { IntersectOption } from "../../GraphicsSystem/IntersectWith";
/** /**
* 线线 * 线线
*
* @export
* @param {Polyline} meatPl 线 * @param {Polyline} meatPl 线
* @param {Polyline[]} knifePls 线 * @param {Polyline[]} knifePls 线
* @return {*} * @return
*/ */
export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[] export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[]
{ {
let allSplitPls: Polyline[] = []; let allSplitPls: Polyline[] = [];
@ -30,8 +27,6 @@ export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[
pl.StartPoint = ipts[0]; pl.StartPoint = ipts[0];
pl.EndPoint = ipts[1]; pl.EndPoint = ipts[1];
} }
else else
{ {
ipts.sort(ComparePointFnGenerate("xy")); ipts.sort(ComparePointFnGenerate("xy"));
@ -39,8 +34,6 @@ export function SplitPolyline(meatPl: Polyline, knifePls: Polyline[]): Polyline[
pl.EndPoint = arrayLast(ipts); pl.EndPoint = arrayLast(ipts);
} }
} }
else else
{ {
let iptsNotExt = ipts.filter(p => pl.PtOnCurve(p)); let iptsNotExt = ipts.filter(p => pl.PtOnCurve(p));

@ -1,4 +1,5 @@
import { Box2, Box3, Line3, Matrix3, Matrix4, Vec2, Vector2, Vector3 } from 'three'; 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 { Arc } from '../DatabaseServices/Entity/Arc';
import { Circle } from '../DatabaseServices/Entity/Circle'; import { Circle } from '../DatabaseServices/Entity/Circle';
import { Curve } from '../DatabaseServices/Entity/Curve'; import { Curve } from '../DatabaseServices/Entity/Curve';
@ -9,7 +10,7 @@ import { IsPointInBowArc } from '../DatabaseServices/PointInPolyline';
import { Spline } from '../DatabaseServices/Spline'; import { Spline } from '../DatabaseServices/Spline';
import { Count } from '../Geometry/Count'; import { Count } from '../Geometry/Count';
import { CurveMap, Vertice } from '../Geometry/CurveMap'; 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 { Vec3 } from '../Geometry/IVec3';
import { Matrix2 } from '../Geometry/Matrix2'; import { Matrix2 } from '../Geometry/Matrix2';
import { Orbit } from '../Geometry/Orbit'; import { Orbit } from '../Geometry/Orbit';
@ -790,94 +791,39 @@ export function Pts2Polyline(pts: (Vec3 | Vec2)[], isClose: boolean): Polyline
return pl; return pl;
} }
const PolylineSpliteRectFuzz = 1e-3; /**
/**封闭多段线 分割成矩形 */ * 线,y线,
export function PolylineSpliteRect(outline: Polyline): Polyline[] * @param outline ,
* @param polylineParalleXYFuzz xy
* @returns
*/
export function PolylineSpliteRect(outline: Polyline, polylineParalleXYFuzz = 1e-3): Polyline[]
{ {
if (!outline.IsClose || IsRect(outline)) if (!outline.IsClose || IsRect(outline))
return [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 cus = outline.Explode();
let yCus: Curve[] = [];
let xSet: Set<number> = new Set();
for (let c of cus) for (let c of cus)
{ {
if (c instanceof Arc) return [outline]; if (c instanceof Arc) return [outline];
let derv = c.GetFirstDeriv(0).normalize(); let derv = c.GetFirstDeriv(0).normalize();
if (isParallelTo(derv, YAxis, PolylineSpliteRectFuzz)) if (isParallelTo(derv, YAxis, polylineParalleXYFuzz))
yCus.push(c); xSet.add(c.StartPoint.x);
else else if (!isParallelTo(derv, XAxis, polylineParalleXYFuzz))
if (!isParallelTo(derv, XAxis, PolylineSpliteRectFuzz)) return [outline];
{
return [outline];
}
} }
yCus.sort((c1, c2) => c1.StartPoint.x - c2.StartPoint.x); //轮廓的每条线段都平行于X或Y轴 可直接按端点切割
const knifePls: Polyline[] = [];
let rects: Polyline[] = []; const xList = Array.from(xSet).sort((a, b) => a - b);
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);
let ys: number[] = []; for (let x of xList)
for (let par of pars) knifePls.push(new Polyline([{ pt: AsVector2({ x, y: 0 }), bul: 0 }, { pt: AsVector2({ x, y: 1 }), bul: 0 }]));
{
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);
}
}
if (ys.length < 2) return [outline]; //裁剪结果
let rects = SplitPolyline(outline, knifePls).filter(pl => pl.IsClose);
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)));
}
return rects; return rects;
} }

Loading…
Cancel
Save