diff --git a/__test__/EdgeSealing/OneEdgeSealing.test.ts b/__test__/EdgeSealing/OneEdgeSealing.test.ts index 0ac9c24a3..311aae389 100644 --- a/__test__/EdgeSealing/OneEdgeSealing.test.ts +++ b/__test__/EdgeSealing/OneEdgeSealing.test.ts @@ -1,6 +1,7 @@ +import { Polyline } from "../../src/DatabaseServices/Entity/Polyline"; import { GetSealedBoardContour } from "../../src/GraphicsSystem/CalcEdgeSealing"; import "../Utils/jest.util"; -import { LoadBoardsFromFileData } from "../Utils/LoadEntity.util"; +import { LoadBoardsFromFileData, LoadEntityFromFileData } from "../Utils/LoadEntity.util"; test('只有一个封边,并且失败的案例', () => { @@ -57,9 +58,32 @@ test('偏移后曲线不闭合的问题', () => for (let br of brs) { + let cus = br.ContourCurve.GetOffsetCurves(-1); + for (let c of cus) + { + expect(c.Length).toMatchNumberSnapshot(); + expect(c.IsClose).toBeTruthy(); + } + let con = GetSealedBoardContour(br, false); expect(con.IsClose).toBeTruthy(); expect(con.Area2).toMatchNumberSnapshot(); expect(con.Length).toMatchNumberSnapshot(); } }); + +test('偏移后曲线不闭合的问题2', () => +{ + let d = + { "file": [1, "Polyline", 10, 2, 209, 0, 1, 7, 71, [2.220446049250313e-16, 1, -1.8369701987210297e-16, 0, -1, 2.220446049250313e-16, -1.232595164407831e-32, 0, 1.232595164407831e-32, 1.8369701987210297e-16, 1, 0, 2800.6273980057904, -327.6194030341822, 154.3982712660218, 1], 0, 0, 1, [0, 1, -1.8369701987210297e-16, 0, -1, 0, 0, 0, 0, 1.8369701987210297e-16, 1, 0, 2800.6273980057904, -327.6194030341822, 154.3982712660218, 1], 0, 0, 1, 2, 37, [203.75274236917448, 0.6657821176631771], -0.12647817046362458, [216.58249214357465, 3.9639078952714044], 0, [216.70369214357606, 3.9639078952714044], 0, [216.70349214357384, 3.9670232852913614], 0, [216.7026921436518, 3.970172431976607], 0.005962190972429685, [216.04074477292943, 6.451513648837135], -0.002176672718212006, [215.35998088513043, 8.927953781329961], -0.00044376333274056043, [213.84759951148862, 14.544604951137444], -0.0003667819041204022, [212.34429214357397, 20.16382417328441], -0.001544194315380855, [206.4925267933031, 42.376867817670245], -0.0015310584877568476, [200.7774921435739, 64.62548417628375], -0.009890393483378371, [165.09260900743266, 218.00339530303336], -0.006193200118673486, [134.3552921435803, 372.4679898662846], -0.003954883402352878, [109.80113359540337, 510.43208818801577], -0.0012080368562184874, [86.67219214350916, 648.6462885313813], -0.00011581093482110962, [53.09282355173491, 852.6265914568794], 0.00002500101529673068, [19.906391149862884, 1054.4486651826255], 0, [21.720227807596984, 1087.039396742547], -0.00521091907627027, [26.7729988737874, 1161.6355313137447], -0.006073474799553129, [35.294008103393935, 1255.8468454906397], -0.0050452671458160485, [45.90799214357321, 1349.8476338032733], -0.009637488483441259, [73.09402035463063, 1540.2785908202159], -0.0021345969443920146, [83.22271449620018, 1600.9769090419366], 0, [62.8446583269706, 1600.9769090419366], 0.0036001887197470227, [48.08769214356744, 1510.076619646293], 0.009976279550128881, [20.351018578063304, 1303.993887760866], 0.01322079246633355, [2.2040921435805103, 1096.8779752522942], -0.0042031964376284, [0.3365602451176528, 1069.9961093543807], 0.06027708278844141, [1.4769921435768083, 1043.2679710122866], 0, [61.287392140351585, 679.720449795841], 0.00009084267787460379, [68.4354857399303, 636.314626773783], 0.0003367141025187746, [75.62069214250369, 592.9149412077645], 0.0017524780389864619, [96.762927535794, 468.4425780357958], 0.003912932302896014, [119.31359214358599, 344.2207988532739], 0.007554149456815115, [154.3982712660013, 173.3497428441044], 0.011551705859636422, [195.9783921435751, 3.9698256912733987], 0.3388891824181241, [201.16284145136657, -5.506706202140776e-13], 0.12647815605716622, true], "basePt": { "x": 1199.6504889638538, "y": -327.6194030341818, "z": 154.39827126602174 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3117.2750559817937, 228.82635435795817, 154.39827126600176, 1] }; + + let pl = LoadEntityFromFileData(d)[0] as Polyline; + + let cus = pl.GetOffsetCurves(-1); + for (let c of cus) + { + expect(c.EndParam).toMatchNumberSnapshot(0); + expect(c.Length).toMatchNumberSnapshot(); + expect(c.IsClose).toBeTruthy(); + } +}); diff --git a/__test__/EdgeSealing/__snapshots__/OneEdgeSealing.test.ts.snap b/__test__/EdgeSealing/__snapshots__/OneEdgeSealing.test.ts.snap index 65cb3dd75..b2dbd904d 100644 --- a/__test__/EdgeSealing/__snapshots__/OneEdgeSealing.test.ts.snap +++ b/__test__/EdgeSealing/__snapshots__/OneEdgeSealing.test.ts.snap @@ -1,8 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`偏移后曲线不闭合的问题 1`] = `"14601.05210"`; +exports[`偏移后曲线不闭合的问题 1`] = `"1271.45306"`; -exports[`偏移后曲线不闭合的问题 2`] = `"1271.45304"`; +exports[`偏移后曲线不闭合的问题 2`] = `"14601.00364"`; + +exports[`偏移后曲线不闭合的问题 3`] = `"1271.45306"`; + +exports[`偏移后曲线不闭合的问题2 1`] = `"33"`; + +exports[`偏移后曲线不闭合的问题2 2`] = `"3274.96050"`; exports[`只有一个封边,并且失败的案例 1`] = `"77140.00000"`; diff --git a/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap b/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap index e9d591161..9ea823535 100644 --- a/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap +++ b/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap @@ -184,7 +184,7 @@ exports[`精度不一致导致的错误 4`] = `"55.04455"`; exports[`精度不一致导致的错误: 走刀数量 1`] = `4`; -exports[`超级复杂造型01 1`] = `"23338.03271"`; +exports[`超级复杂造型01 1`] = `"23338.03272"`; exports[`超级复杂造型01 2`] = `"11855.39981"`; diff --git a/__test__/Polyline/__snapshots__/offset.test.ts.snap b/__test__/Polyline/__snapshots__/offset.test.ts.snap index 943009655..bddda90f9 100644 --- a/__test__/Polyline/__snapshots__/offset.test.ts.snap +++ b/__test__/Polyline/__snapshots__/offset.test.ts.snap @@ -184,7 +184,7 @@ exports[`简单图形因为点在线内算法错误导致的丢失 3`] = `7.1494 exports[`简单图形因为点在线内算法错误导致的丢失 4`] = `6.693604273021893`; -exports[`精度过高导致无法连接 1`] = `"6723.54642"`; +exports[`精度过高导致无法连接 1`] = `"6723.54643"`; exports[`精度过高导致的曲线丢失 1`] = `1`; @@ -200,15 +200,15 @@ exports[`精度过高导致直连失败 2`] = `"32040.01390"`; exports[`精度过高导致直连失败 3`] = `1`; -exports[`精度过高导致直连失败 4`] = `"32045.24858"`; +exports[`精度过高导致直连失败 4`] = `"32045.24859"`; exports[`精度过高导致连接失败 1`] = `1`; -exports[`精度过高导致连接失败 2`] = `"75154.17787"`; +exports[`精度过高导致连接失败 2`] = `"75154.17860"`; exports[`精度过高导致连接失败 3`] = `1`; -exports[`精度过高导致连接失败 4`] = `"91209.36321"`; +exports[`精度过高导致连接失败 4`] = `"91209.36322"`; exports[`精度问题导致的连接错误 1`] = `2`; diff --git a/__test__/Polyline/__snapshots__/offset4.test.ts.snap b/__test__/Polyline/__snapshots__/offset4.test.ts.snap index f83b0dd83..ece61ecb3 100644 --- a/__test__/Polyline/__snapshots__/offset4.test.ts.snap +++ b/__test__/Polyline/__snapshots__/offset4.test.ts.snap @@ -4,8 +4,8 @@ exports[`因为错误的点在多段线内部导致的偏移错误 1`] = `"2029. exports[`圆裁剪精度 1`] = `1`; -exports[`圆裁剪精度 2`] = `"8360.62214"`; +exports[`圆裁剪精度 2`] = `"8360.63312"`; exports[`圆裁剪精度 3`] = `1`; -exports[`圆裁剪精度 4`] = `"8385.98689"`; +exports[`圆裁剪精度 4`] = `"8385.98861"`; diff --git a/src/GraphicsSystem/OffsetPolyline.ts b/src/GraphicsSystem/OffsetPolyline.ts index 43de149d2..6500b0e8f 100644 --- a/src/GraphicsSystem/OffsetPolyline.ts +++ b/src/GraphicsSystem/OffsetPolyline.ts @@ -1,5 +1,5 @@ import { Box3, Matrix4, Vector3 } from "three"; -import { arrayLast } from "../Common/ArrayExt"; +import { arrayLast, arrayRemoveDuplicateBySort } from "../Common/ArrayExt"; import { ConverCircleToPolyline } from "../Common/CurveUtils"; import { Status } from "../Common/Status"; import { FixIndex } from "../Common/Utils"; @@ -61,8 +61,36 @@ export class CurveTreeNode } //交点参数列表 - let iParams = this.curve.IntersectWith(contour.Curve, IntersectOption.ExtendNone) - .map(p => this.curve.GetParamAtPoint2(p)); + let iParams = this.curve.IntersectWith2(contour.Curve, IntersectOption.ExtendNone) + .map(p => p.thisParam); + + //#region 交点参数优化,避免出现无意义长度的曲线被移除 CurveIsFine + let length = this.curve.Length; + if (!(this.curve instanceof Circle)) + iParams.push(0, 1); + iParams.sort((e1, e2) => e1 - e2); + if (this.curve instanceof Arc || this.curve instanceof Circle) + { + let allAngle = this.curve instanceof Circle ? Math.PI * 2 : this.curve.AllAngle; + arrayRemoveDuplicateBySort(iParams, (p1, p2) => + { + return allAngle * (p2 - p1) < ARC_MIN_ALLANGLE || length * (p2 - p1) < CURVE_MIN_LENGTH; + }); + } + else + { + arrayRemoveDuplicateBySort(iParams, (p1, p2) => + { + return length * (p2 - p1) < CURVE_MIN_LENGTH; + }); + } + + if (!(this.curve instanceof Circle)) + { + iParams.shift();//remove 0 + iParams.pop(); //remove 1 or 0.9999 + } + //#endregion let cus = this.curve.GetSplitCurves(iParams); if (cus.length === 0) @@ -161,6 +189,19 @@ export class OffsetPolyline } else this.GeneralTrimContours(); + + // for (let c of this._SubOffsetedCurves) + // { + // TestDraw(c.curve.Clone(), 1); + // if (c.paddingCurve) + // for (let cc of c.paddingCurve) + // TestDraw(cc.Clone(), 2); + // } + // for (let c of this._TrimPolylineContours) + // { + // TestDraw(c.Curve.Clone(), 3); + // } + this.TrimByContours(); this.FilterInvalidCurve(); this.JoinCollinear(); @@ -174,7 +215,7 @@ export class OffsetPolyline this._CacheOCS = this._Polyline.OCS; this._IsClose = this._Polyline.IsClose; this._Polyline.OCS = IdentityMtx4; - this._SubCurves = this._Polyline.Explode().filter(c => c.Length > 1e-4); + this._SubCurves = this._Polyline.Explode().filter(c => c.Length > 1e-4);//TODO: 简化这个 并且生成圆 顶点 圆 this._Polyline.OCS = this._CacheOCS; return this; } @@ -836,9 +877,12 @@ export function EntityEncode2(c1: Curve, c2: Curve) return EntityEncode(c1) & EntityEncode(c2); } + +const CURVE_MIN_LENGTH = 5e-5; +const ARC_MIN_ALLANGLE = 2e-6; //表示这个是一个正常的曲线,不是0长度的线,也不是0长度的圆弧 export function CurveIsFine(curve: Curve) { - if (curve instanceof Arc && curve.AllAngle < 2e-6) return false; - return curve.Length > 5e-5; + if (curve instanceof Arc && curve.AllAngle < ARC_MIN_ALLANGLE) return false; + return curve.Length > CURVE_MIN_LENGTH; } diff --git a/src/UI/Components/EntityModal/EntityModal.tsx b/src/UI/Components/EntityModal/EntityModal.tsx index e910834a2..9f14fe613 100644 --- a/src/UI/Components/EntityModal/EntityModal.tsx +++ b/src/UI/Components/EntityModal/EntityModal.tsx @@ -82,6 +82,9 @@ export class EntityModal extends React.Component<{}, {}> {
  • 时针: {ents[0].IsClockWise ? "顺时针" : "逆时针"}
  • +
  • + 闭合: {ents[0].IsClose ? "闭合" : "不闭合"} +
  • } diff --git a/src/UI/Components/ToolBar/PropertiesPanel.tsx b/src/UI/Components/ToolBar/PropertiesPanel.tsx index 3df12e2c9..9f24d2122 100644 --- a/src/UI/Components/ToolBar/PropertiesPanel.tsx +++ b/src/UI/Components/ToolBar/PropertiesPanel.tsx @@ -154,6 +154,9 @@ export class PropertiesPanel extends React.Component<{}, {}>
  • 时针: {(ents[0] as Curve).IsClockWise ? "顺时针" : "逆时针"}
  • +
  • + 闭合: {ents[0].IsClose ? "闭合" : "不闭合"} +
  • } {