diff --git a/__test__/Geometry/arc.test.ts b/__test__/Geometry/arc.test.ts index 70478781f..36f04d79d 100644 --- a/__test__/Geometry/arc.test.ts +++ b/__test__/Geometry/arc.test.ts @@ -1,6 +1,6 @@ import { Vector3 } from 'three'; import { Arc } from '../../src/DatabaseServices/Arc'; -import { equal, equaln } from '../../src/Geometry/GeUtils'; +import { equaln, equalv3 } from '../../src/Geometry/GeUtils'; test("三点共线", () => { @@ -124,7 +124,7 @@ test("由距离得到对应点", () => { let arc = new Arc(new Vector3(5, 0, 0), 5, Math.PI, 0); - expect(equal(arc.GetPointAtDistance(0.5 * Math.PI * 5), new Vector3(5, 5, 0))).toBeTruthy(); + expect(equalv3(arc.GetPointAtDistance(0.5 * Math.PI * 5), new Vector3(5, 5, 0))).toBeTruthy(); } ); diff --git a/__test__/Geometry/circle.test.ts b/__test__/Geometry/circle.test.ts index 11595867d..534a2c1ea 100644 --- a/__test__/Geometry/circle.test.ts +++ b/__test__/Geometry/circle.test.ts @@ -1,10 +1,6 @@ +import { Vector3 } from 'three'; import { Circle } from '../../src/DatabaseServices/Circle'; -import { Vector3, Vector2 } from 'three'; -import { app } from '../../src/ApplicationServices/Application'; -import { Command } from '../../src/Editor/CommandMachine'; -import { PromptStatus } from '../../src/Editor/PromptResult'; -import { RenderType } from '../../src/GraphicsSystem/Enum'; -import { equal, equaln } from '../../src/Geometry/GeUtils'; +import { equaln, equalv3 } from '../../src/Geometry/GeUtils'; test('圆参数', () => { @@ -62,7 +58,7 @@ test("由距离得到圆参数", () => test("由距离得到对应点", () => { let circle = new Circle(new Vector3(5, 0, 0), 5); - expect(equal(circle.GetPointAtDistance(0.5 * Math.PI * 5), new Vector3(5, 5, 0))).toBeTruthy(); + expect(equalv3(circle.GetPointAtDistance(0.5 * Math.PI * 5), new Vector3(5, 5, 0))).toBeTruthy(); } ); diff --git a/__test__/Geometry/orbit.test.ts b/__test__/Geometry/orbit.test.ts index bfe4efee9..7273a3757 100644 --- a/__test__/Geometry/orbit.test.ts +++ b/__test__/Geometry/orbit.test.ts @@ -1,6 +1,5 @@ import * as THREE from 'three'; - -import { equaln ,equal} from '../../src/Geometry/GeUtils'; +import { equaln, equalv3 } from '../../src/Geometry/GeUtils'; import { Orbit } from '../../src/Geometry/Orbit'; test("", () => @@ -17,7 +16,7 @@ test("", () => //试着还原 orb.UpdateDirection(dir); - expect(equal(dir, new THREE.Vector3(0, 1, 0))).toBe(true); + expect(equalv3(dir, new THREE.Vector3(0, 1, 0))).toBe(true); //试试新的 dir.set(1, 0, 0); @@ -27,7 +26,7 @@ test("", () => //试着还原 orb.UpdateDirection(dir); - expect(equal(dir, new THREE.Vector3(1, 0, 0))).toBe(true); + expect(equalv3(dir, new THREE.Vector3(1, 0, 0))).toBe(true); //试试新的 dir.set(0.5, 0.5, 0).normalize(); @@ -38,7 +37,7 @@ test("", () => //试着还原 orb.UpdateDirection(dir); console.log('dir: ', dir); - expect(equal(dir, dirc)).toBe(true); + expect(equalv3(dir, dirc)).toBe(true); //试试新的 dir.set(0.5, 0.5, 1).normalize(); @@ -48,7 +47,7 @@ test("", () => //试着还原 orb.UpdateDirection(dir); console.log('dir: ', dir); - expect(equal(dir, dirc)).toBe(true); + expect(equalv3(dir, dirc)).toBe(true); dir.set(0, 0, -1); dirc = dir.clone(); @@ -60,7 +59,7 @@ test("", () => //试着还原 orb.UpdateDirection(dir); console.log('dir: ', dir); - expect(equal(dir, dirc)).toBe(true); + expect(equalv3(dir, dirc)).toBe(true); let newDir = orb.UpdateDirection(); @@ -68,7 +67,7 @@ test("", () => let up = Orbit.ComputUpDirection(new THREE.Vector3(0, 0, 1)); - expect(equal(up, new THREE.Vector3(0, -1, 0))).toBe(true); + expect(equalv3(up, new THREE.Vector3(0, -1, 0))).toBe(true); Orbit.ComputUpDirection(new THREE.Vector3(0, 0, -1), up); console.log(up); @@ -80,7 +79,7 @@ test("", () => let newD = orb.UpdateDirection(); console.log(newD); - expect(equal(newD, new THREE.Vector3(0, 0, -1))).toBe(true); + expect(equalv3(newD, new THREE.Vector3(0, 0, -1))).toBe(true); }) @@ -108,4 +107,4 @@ test("测试求向量", () => Orbit.ComputUpDirection(dir, up); console.log('up: ', up); expect(up).toMatchSnapshot(); -}) \ No newline at end of file +}) diff --git a/__test__/Line/__snapshots__/line.test.ts.snap b/__test__/Line/__snapshots__/line.test.ts.snap index 892a51696..584b4cba8 100644 --- a/__test__/Line/__snapshots__/line.test.ts.snap +++ b/__test__/Line/__snapshots__/line.test.ts.snap @@ -34,8 +34,8 @@ Vector3 { exports[`最近点 1`] = ` Vector3 { - "x": -2.499999999999999, - "y": -2.499999999999999, + "x": -2.4999999999999996, + "y": -2.4999999999999996, "z": 0, } `; @@ -127,3 +127,7 @@ Vector3 { "z": 0, } `; + +exports[`直线参数 1`] = `-0.9999999999999999`; + +exports[`直线参数 2`] = `1.9999999999999998`; diff --git a/__test__/Line/line.test.ts b/__test__/Line/line.test.ts index d6041f4c0..c62a080b8 100644 --- a/__test__/Line/line.test.ts +++ b/__test__/Line/line.test.ts @@ -12,9 +12,9 @@ test('直线参数', () => expect(l.GetParamAtPoint(new Vector3(5, 5, 0))).toBe(1); - expect(l.GetParamAtPoint(new Vector3(-5, -5, 0))).toBe(-1); + expect(l.GetParamAtPoint(new Vector3(-5, -5, 0))).toMatchSnapshot(); - expect(l.GetParamAtPoint(new Vector3(10, 10, 0))).toBe(2); + expect(l.GetParamAtPoint(new Vector3(10, 10, 0))).toMatchSnapshot(); expect(l.GetParamAtPoint(new Vector3(11, 10, 0))).toBe(NaN); diff --git a/__test__/Polyline/__snapshots__/offset.test.ts.snap b/__test__/Polyline/__snapshots__/offset.test.ts.snap index 46a71b6dc..a3f63f481 100644 --- a/__test__/Polyline/__snapshots__/offset.test.ts.snap +++ b/__test__/Polyline/__snapshots__/offset.test.ts.snap @@ -12,10 +12,48 @@ exports[`IKKGK圆与直线补圆弧 5`] = `1`; exports[`IKKGK圆与直线补圆弧 6`] = `52.52605376818707`; +exports[`IKKGK圆与直线补圆弧 7`] = `2`; + +exports[`IKKGK圆与直线补圆弧 8`] = `15.234528310991957`; + +exports[`IKKGK圆与直线补圆弧 9`] = `37.292463663372004`; + +exports[`IKKGK圆与直线补圆弧 10`] = `6.283185307179586`; + +exports[`IKKGK圆与直线补圆弧 11`] = `39.37762788501941`; + +exports[`IKKGK圆与直线补圆弧 12`] = `58.582296960642424`; + +exports[`IKKGK圆与直线补圆弧 13`] = `5`; + +exports[`IKKGK圆与直线补圆弧 14`] = `52.52605376818707`; + +exports[`IKKGK圆与直线补圆弧 15`] = `12.10385896662238`; + +exports[`IKKGK圆与直线补圆弧 16`] = `12.10385896662238`; + +exports[`IKKGK圆与直线补圆弧 17`] = `37.51446423182355`; + +exports[`IKKGK圆与直线补圆弧 18`] = `71.87112445902166`; + exports[`中间区域需要圆裁剪 1`] = `1`; exports[`中间区域需要圆裁剪 2`] = `24.711300177432392`; +exports[`中间区域需要圆裁剪 3`] = `223.68139693559328`; + +exports[`中间区域需要圆裁剪 4`] = `223.68139693559328`; + +exports[`中间区域需要圆裁剪 5`] = `150.4931383967326`; + +exports[`中间区域需要圆裁剪 6`] = `106.06313658304032`; + +exports[`中间区域需要圆裁剪 7`] = `223.68139693559328`; + +exports[`中间区域需要圆裁剪 8`] = `223.68139693559328`; + +exports[`中间区域需要圆裁剪 9`] = `223.68139693559328`; + exports[`圆求交错误导致的线丢失 1`] = `4148.643109243218`; exports[`圆求交错误导致的线丢失 2`] = `4425.268216257021`; @@ -40,6 +78,34 @@ exports[`多段线存在0长度线段导致偏移错误 3`] = `1`; exports[`多段线存在0长度线段导致偏移错误 4`] = `86143.95799639553`; +exports[`多段线存在0长度线段导致偏移错误 5`] = `12931.456758241411`; + +exports[`多段线存在0长度线段导致偏移错误 6`] = `10056.231029584353`; + +exports[`多段线存在0长度线段导致偏移错误 7`] = `17891.674969196265`; + +exports[`多段线存在0长度线段导致偏移错误 8`] = `9355.91677188456`; + +exports[`多段线存在0长度线段导致偏移错误 9`] = `2140.6181396506136`; + +exports[`多段线存在0长度线段导致偏移错误 10`] = `8`; + +exports[`多段线存在0长度线段导致偏移错误 11`] = `9773.1166496292`; + +exports[`多段线存在0长度线段导致偏移错误 12`] = `11370.157165896057`; + +exports[`多段线存在0长度线段导致偏移错误 13`] = `9341.707068201697`; + +exports[`多段线存在0长度线段导致偏移错误 14`] = `14993.848091308573`; + +exports[`多段线存在0长度线段导致偏移错误 15`] = `10038.32067141617`; + +exports[`多段线存在0长度线段导致偏移错误 16`] = `18161.102674842623`; + +exports[`多段线存在0长度线段导致偏移错误 17`] = `9582.108634127204`; + +exports[`多段线存在0长度线段导致偏移错误 18`] = `2883.804539574228`; + exports[`拱门偏移 1`] = `1`; exports[`拱门偏移 2`] = `4.314156035548454`; @@ -48,6 +114,26 @@ exports[`拱门偏移 3`] = `1`; exports[`拱门偏移 4`] = `6.827404319936081`; +exports[`拱门偏移 5`] = `3`; + +exports[`拱门偏移 6`] = `2`; + +exports[`拱门偏移 7`] = `2.827433388230814`; + +exports[`拱门偏移 8`] = `2`; + +exports[`拱门偏移 9`] = `6.827404319936081`; + +exports[`拱门偏移 10`] = `2.5132741228718345`; + +exports[`拱门偏移 11`] = `2.5132741228718345`; + +exports[`拱门偏移 12`] = `4.800000000000001`; + +exports[`拱门偏移 13`] = `5.198184497678349`; + +exports[`拱门偏移 14`] = `4.800000000000001`; + exports[`简单图形因为点在线内算法错误导致的丢失 1`] = `8.675026988029915`; exports[`简单图形因为点在线内算法错误导致的丢失 2`] = `8.252659494518674`; diff --git a/__test__/Polyline/__snapshots__/offsetbug.test.ts.snap b/__test__/Polyline/__snapshots__/offsetbug.test.ts.snap index 89cfbec09..3269b40c6 100644 --- a/__test__/Polyline/__snapshots__/offsetbug.test.ts.snap +++ b/__test__/Polyline/__snapshots__/offsetbug.test.ts.snap @@ -2,9 +2,9 @@ exports[`补充bug测试#IKWGF 1`] = `1.1376402440608806`; -exports[`补充bug测试#IKWGF 2`] = `0.44573816538516137`; +exports[`补充bug测试#IKWGF 2`] = `0.44573896329246554`; -exports[`补充bug测试#IKWGF 3`] = `10.733056812077686`; +exports[`补充bug测试#IKWGF 3`] = `10.73282822209507`; exports[`补充bug测试#IKWGF 4`] = `12.786755410504352`; @@ -14,9 +14,9 @@ exports[`补充bug测试#IKWGF 6`] = `10.586543051841131`; exports[`补充bug测试#IKWGF 7`] = `14.066950838248612`; -exports[`补充bug测试#IKWGF 8`] = `2.16930889523746`; +exports[`补充bug测试#IKWGF 8`] = `2.168984971098264`; -exports[`补充bug测试#IKWGF 9`] = `11.890848111457423`; +exports[`补充bug测试#IKWGF 9`] = `11.89085508498112`; exports[`补充bug测试#IKWGF 10`] = `1.0803373815793473`; diff --git a/__test__/Polyline/offsetbug.test.ts b/__test__/Polyline/offsetbug.test.ts index 48fe4a19d..41a254717 100644 --- a/__test__/Polyline/offsetbug.test.ts +++ b/__test__/Polyline/offsetbug.test.ts @@ -59,4 +59,4 @@ test('补充bug测试#IKWGF', () => expect(cus[1].Length).toMatchSnapshot(); expect(cus[2].Length).toMatchSnapshot(); -}) +}); diff --git a/__test__/Polyline/polyline.test.ts b/__test__/Polyline/polyline.test.ts index d08f53616..0f5244c09 100644 --- a/__test__/Polyline/polyline.test.ts +++ b/__test__/Polyline/polyline.test.ts @@ -1,8 +1,7 @@ import { Vector2, Vector3 } from 'three'; - -import { Polyline } from '../../src/DatabaseServices/Polyline'; -import { equal, equaln } from '../../src/Geometry/GeUtils'; import { CADFile } from '../../src/DatabaseServices/CADFile'; +import { Polyline } from '../../src/DatabaseServices/Polyline'; +import { equaln, equalv3 } from '../../src/Geometry/GeUtils'; test("多段线点获取参数", () => { @@ -88,12 +87,12 @@ describe('多段线', () => } ]) - expect(equal(pl.GetPointAtParam(1), new Vector3(5, 0, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtParam(0.5), new Vector3(2.5, 0, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtParam(-0.5), new Vector3(-2.5, 0, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtParam(4.5), new Vector3(0, 5, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtParam(5), new Vector3(0, 0, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtParam(5.5), new Vector3(0, -5, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtParam(1), new Vector3(5, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtParam(0.5), new Vector3(2.5, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtParam(-0.5), new Vector3(-2.5, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtParam(4.5), new Vector3(0, 5, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtParam(5), new Vector3(0, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtParam(5.5), new Vector3(0, -5, 0))).toBeTruthy(); }) test("多段线参数获取弧长", () => { @@ -158,11 +157,11 @@ describe('多段线', () => bul: 0 } ]) - expect(equal(pl.GetPointAtDistance(5), new Vector3(5, 0, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtDistance(2.5), new Vector3(2.5, 0, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtDistance(5 + Math.PI * 2.5), new Vector3(5, 5, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtDistance(5 + Math.PI * 2.5 * 2), new Vector3(5, 10, 0))).toBeTruthy(); - expect(equal(pl.GetPointAtDistance(0), new Vector3(0, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtDistance(5), new Vector3(5, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtDistance(2.5), new Vector3(2.5, 0, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtDistance(5 + Math.PI * 2.5), new Vector3(5, 5, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtDistance(5 + Math.PI * 2.5 * 2), new Vector3(5, 10, 0))).toBeTruthy(); + expect(equalv3(pl.GetPointAtDistance(0), new Vector3(0, 0, 0))).toBeTruthy(); }) test("多段线距离获取参数", () => { @@ -305,10 +304,10 @@ describe('多段线', () => } ]) pl3.Extend(1.5); - expect(equal(pl3.EndPoint, new Vector3(-2.5, 2.5, 0))).toBeTruthy(); + expect(equalv3(pl3.EndPoint, new Vector3(-2.5, 2.5, 0))).toBeTruthy(); pl3.Extend(1 + 1 / 3); // expect(pl3.EndPoint).toEqual(new Vector3(0, 0, 0)); - expect(equal(pl3.EndPoint /*?*/, new Vector3(0, 0, 0))).toBeTruthy(); + expect(equalv3(pl3.EndPoint /*?*/, new Vector3(0, 0, 0))).toBeTruthy(); }) test("多段线延伸,闭合", () => { @@ -408,8 +407,8 @@ describe('多段线', () => expect(pl.GetClosestPointTo(new Vector3(), true)).toEqual(new Vector3()); expect(pl.GetClosestPointTo(new Vector3(3.5, 2.5), true)).toEqual(new Vector3(3.5, 0, 0)); expect(pl.GetClosestPointTo(new Vector3(1.5, 3.5), true)).toEqual(new Vector3(0, 3.5, 0)); - expect(equal(pl.GetClosestPointTo(new Vector3(1.5, 3.5), true), new Vector3(0, 3.5, 0))).toBeTruthy(); - expect(equal(pl.GetClosestPointTo(new Vector3(-0.5, -1), true), new Vector3(0, -1, 0))).toBeTruthy(); + expect(equalv3(pl.GetClosestPointTo(new Vector3(1.5, 3.5), true), new Vector3(0, 3.5, 0))).toBeTruthy(); + expect(equalv3(pl.GetClosestPointTo(new Vector3(-0.5, -1), true), new Vector3(0, -1, 0))).toBeTruthy(); }) test("多段线包围盒", () => @@ -529,3 +528,30 @@ test('最近点参数刚好在端点上', () => expect(equaln(param, 1)).toBeTruthy(); }); + +function loadFile(data) +{ + let file = new CADFile(); + file.Data = data; + let cus: Polyline[] = []; + let count = file.Read(); + for (let i = 0; i < count; i++) + { + cus.push(file.ReadObject(undefined) as Polyline); + } + return cus; +} + +//https://gitee.com/BearCAD/WebThreeJs/issues/IKWGF#note_977523 +test('点在线上精度', () => +{ + let data = + [1, ["Polyline", 1, 1, 4, false, 2, -1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 6.283029954893735, -0.21450491241551983, 0, 1], 2, 5, [-6.290104635739899, 3.3748564511765324], -0.10216571300036131, [-6.136537456708874, 3.2958817075766764], 0, [-6.236783847999098, 3.0649817075766763], 0.44141445079284647, [-6.5210046357398985, 3.121255471298752], 0, [-6.290104635739899, 3.3748564511765324], 0, false]] + + let pl = loadFile(data)[0]; + + let pt = new Vector3().fromArray([-0.23760717950533072, 2.9070744830224284, 0]); + + + expect(pl.PtOnCurve(pt)).toBeFalsy(); +}); diff --git a/package.json b/package.json index 98063c743..c21b0c7d2 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build": "webpack", "i": "npm i && npm i -dev", "test": "jest", + "testu": "jest -u", "ser": "node ./utils/server.js", "type": "node ./utils/copy_type.js" }, diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index f394ef1c3..aceb20bcd 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -7,7 +7,7 @@ import { IsPointInBowArc } from '../DatabaseServices/PointInPolyline'; import { Polyline } from '../DatabaseServices/Polyline'; import { Count } from '../Geometry/Count'; import { CurveMap } from '../Geometry/CurveMap'; -import { equal, equaln } from '../Geometry/GeUtils'; +import { equaln, equalv2, equalv3 } from '../Geometry/GeUtils'; import { Stand } from '../Geometry/RegionParse'; import { FixIndex } from './Utils'; @@ -135,14 +135,14 @@ export function curveLinkGroup(cus: Curve[]): Array> if (isEndSeach) { //保证曲线总是从起点连接到终点 - if (!equal(cu.StartPoint, stand.position)) + if (!equalv3(cu.StartPoint, stand.position)) cu.Reverse(); cus.push(cu); } else { //保证曲线总是从起点连接到终点 - if (!equal(cu.EndPoint, stand.position)) + if (!equalv3(cu.EndPoint, stand.position)) cu.Reverse(); cus.unshift(cu); } @@ -198,17 +198,17 @@ export function equalCurveAndCurve(cu1: Curve, cu2: Curve) return ptsAndBuls1.pts.every((pt, i) => { - return equal(pt, pts2[i]); + return equalv2(pt, pts2[i]); }) } else if (cu1 instanceof Circle && cu2 instanceof Circle) { - return equal(cu1.Center, cu2.Center) && equaln(cu1.Radius, cu2.Radius, 1e-6) + return equalv3(cu1.Center, cu2.Center) && equaln(cu1.Radius, cu2.Radius, 1e-6) } else if (cu1 instanceof Arc && cu2 instanceof Arc) { - if (!equal(cu1.StartPoint, cu2.EndPoint)) cu1.Reverse(); - return equal(cu1.Center, cu2.Center) && equaln(cu1.Radius, cu2.Radius, 1e-6) && equaln(cu1.StartAngle, cu2.StartAngle) && equaln(cu1.EndAngle, cu2.EndAngle) + if (!equalv3(cu1.StartPoint, cu2.EndPoint)) cu1.Reverse(); + return equalv3(cu1.Center, cu2.Center) && equaln(cu1.Radius, cu2.Radius, 1e-6) && equaln(cu1.StartAngle, cu2.StartAngle) && equaln(cu1.EndAngle, cu2.EndAngle) } return false; } @@ -226,6 +226,13 @@ export function GetPointAtCurveDir(cu: Curve, pt: Vector3): boolean let cp = cu.GetClosestPointTo(pt, false); //最近点参数 let cparam = cu.GetParamAtPoint(cp); + if (isNaN(cparam)) + { + //最近点 + let cp = cu.GetClosestPointTo(pt, false); + //最近点参数 + let cparam = cu.GetParamAtPoint(cp); + } //归一化最近点参数 let floorParam = Math.floor(cparam + 0.5); @@ -244,7 +251,7 @@ export function GetPointAtCurveDir(cu: Curve, pt: Vector3): boolean ) { let plVerCount = cu.NumberOfVertices; - if (equal(cu.GetPoint2dAt(0), cu.GetPoint2dAt(plVerCount - 1))) + if (equalv2(cu.GetPoint2dAt(0), cu.GetPoint2dAt(plVerCount - 1))) plVerCount--; //分三点,本点,前一个点,后一个点 @@ -266,9 +273,9 @@ export function GetPointAtCurveDir(cu: Curve, pt: Vector3): boolean let cp1 = l1.GetClosestPointTo(pt, true); let cp2 = l2.GetClosestPointTo(pt, true); - if (equal(fDer, nDer.clone().negate())) + if (equalv3(fDer, nDer.clone().negate())) return true; - if (equal(fDer, nDer)) + if (equalv3(fDer, nDer)) return fDer.cross(pt.clone().sub(cp1)).z < 0; let adir = Math.sign(fDer.clone().cross(nDer).z); diff --git a/src/DatabaseServices/Arc.ts b/src/DatabaseServices/Arc.ts index f57a9f0ee..329803f86 100644 --- a/src/DatabaseServices/Arc.ts +++ b/src/DatabaseServices/Arc.ts @@ -3,7 +3,7 @@ import { Box3, Matrix4, Object3D, ShapeGeometry, Vector2, Vector3 } from 'three' import { ColorMaterial } from '../Common/ColorPalette'; import { Vec2DTo3D, getCircleCenter } from '../Common/CurveUtils'; import { matrixSetVector } from '../Common/Matrix4Utils'; -import { angle, angleTo2Pi, equal, equaln, midPoint, polar, MoveMatrix } from '../Geometry/GeUtils'; +import { angle, angleTo2Pi, equalv3, equaln, midPoint, polar, MoveMatrix } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectArcAndArc, IntersectCircleAndArc, IntersectLineAndArc, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; @@ -204,7 +204,7 @@ export class Arc extends Curve { if (this.m_Radius == 0 || this.AllAngle == 0 || - !equaln(pt.distanceToSquared(this.Center), this.m_Radius * this.m_Radius, 1e-4)) + !equaln(pt.distanceTo(this.Center), this.m_Radius, 1e-8)) return NaN; let ptTmp = pt.clone().applyMatrix4(this.OCSInv); @@ -290,7 +290,7 @@ export class Arc extends Curve if (cu instanceof Arc) { this.WriteAllObjectRecord(); - if (equal(cu.Center, this.Center) && equaln(cu.m_Radius, this.m_Radius)) + if (equalv3(cu.Center, this.Center) && equaln(cu.m_Radius, this.m_Radius)) { let [sa, ea] = [cu.StartAngle, cu.EndAngle]; if (cu.m_Clockwise != this.m_Clockwise) diff --git a/src/DatabaseServices/Circle.ts b/src/DatabaseServices/Circle.ts index f73875093..cc173f274 100644 --- a/src/DatabaseServices/Circle.ts +++ b/src/DatabaseServices/Circle.ts @@ -293,7 +293,8 @@ export class Circle extends Curve } GetClosestPointTo(pt: Vector3, extend: boolean): Vector3 { - if (pt.distanceToSquared(this.Center) == 0) return this.GetPointAtParam(0); + if (equaln(pt.distanceToSquared(this.Center), 0, 1e-10)) + return this.GetPointAtParam(0); let l = new Line(this.Center, pt); let pts = l.IntersectWith(this, IntersectOption.ExtendBoth); let ptIns = pt.distanceTo(pts[0]) < pt.distanceTo(pts[1]) ? pts[0] : pts[1]; diff --git a/src/DatabaseServices/Curve.ts b/src/DatabaseServices/Curve.ts index 65d326aa0..56a72ad9b 100644 --- a/src/DatabaseServices/Curve.ts +++ b/src/DatabaseServices/Curve.ts @@ -1,7 +1,7 @@ import { Mesh, Object3D, Vector3 } from 'three'; import { arrayRemoveDuplicateBySort, arraySortByNumber } from '../Common/ArrayExt'; import { ColorMaterial } from '../Common/ColorPalette'; -import { equal, equaln } from '../Geometry/GeUtils'; +import { equalv3, equaln } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { Factory } from './CADFactory'; @@ -121,7 +121,7 @@ export abstract class Curve extends Entity //点在曲线上 PtOnCurve(pt: Vector3): boolean { - return equal(this.StartPoint, pt, 1e-12) || equal(this.EndPoint, pt, 1e-12) || this.ParamOnCurve(this.GetParamAtPoint(pt)); + return equalv3(this.StartPoint, pt, 1e-12) || equalv3(this.EndPoint, pt, 1e-12) || this.ParamOnCurve(this.GetParamAtPoint(pt)); } //参数在曲线上 容差,1e-12 diff --git a/src/DatabaseServices/Line.ts b/src/DatabaseServices/Line.ts index e4f318688..dda67c434 100644 --- a/src/DatabaseServices/Line.ts +++ b/src/DatabaseServices/Line.ts @@ -2,7 +2,7 @@ import * as THREE from 'three'; import { Box3, Geometry, Object3D, Vector3 } from 'three'; import { arraySortByNumber } from '../Common/ArrayExt'; import { ColorMaterial } from '../Common/ColorPalette'; -import { MoveMatrix, equal, isParallelTo, polar, equaln } from '../Geometry/GeUtils'; +import { equalv3, isParallelTo, MoveMatrix, polar } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectLineAndArc, IntersectLineAndCircle, IntersectLineAndLine, IntersectOption, IntersectPolylineAndCurve, reverseIntersectOption } from '../GraphicsSystem/IntersectWith'; import { Arc } from './Arc'; @@ -114,28 +114,10 @@ export class Line extends Curve } GetParamAtPoint(pt: Vector3): number { - let len = this.Length; - if (len == 0) - { - if (equal(this.m_StartPoint, pt)) - return 0; - else - return NaN; - } - //得到一阶导数 - let v = this.GetFistDeriv(0); - let pV = pt.clone().sub(this.StartPoint);//得到指向p点的向量. - - v.multiplyScalar(pV.length() / len); - if (equal(v, pV)) - { - return pV.length() / len; - } - else if (equal(v.negate(), pV)) - { - return -pV.length() / len; - } - return NaN; + let { closestPt, param } = this.GetClosestAtPoint(pt, true); + if (!equalv3(closestPt, pt)) + return NaN; + return param; } GetParamAtDist(d: number): number { @@ -171,20 +153,56 @@ export class Line extends Curve return ret; } + GetClosestAtPoint(pt: Vector3, extend: boolean): { closestPt: Vector3, param: number } + { + let sp = this.StartPoint; + let ep = this.EndPoint; + if (equalv3(pt, sp, 1e-12)) + return { closestPt: sp, param: 0 }; + else if (equalv3(pt, ep, 1e-12)) + return { closestPt: ep, param: 1 }; + + let direction = this.GetFistDeriv(0); + let length = direction.length(); + + if (length === 0) + { + let param = NaN; + if (equalv3(pt, this.StartPoint, 1e-7)) + param = 0; + return { closestPt: sp, param: param }; + } + + direction.divideScalar(length); + + let diff = pt.clone().sub(sp); + let param = direction.dot(diff); + + let closestPt: Vector3; + if (extend) + closestPt = sp.add(direction.multiplyScalar(param)) + else + if (param < 0) + { + closestPt = sp; + param = 0; + } + else if (param > length) + { + closestPt = this.EndPoint; + param = 1; + } + else + closestPt = sp.add(direction.multiplyScalar(param)) + return { + closestPt: closestPt, + param: param / length + } + } + GetClosestPointTo(pt: Vector3, extend: boolean): Vector3 { - let an = this.GetFistDerivAngle(0) + Math.PI * 0.5; - let line = new Line(pt, polar(pt.clone(), an, 1) as Vector3); - //交点 - let pt_int = this.IntersectWith(line, IntersectOption.ExtendBoth)[0]; - if (!pt_int) return this.StartPoint; - if (extend) return pt_int; - //参数 - let param = this.GetParamAtPoint(pt_int); - if (param >= 0 && param <= 1) return pt_int; - if (param < 0) return this.StartPoint; - if (param > 0) return this.EndPoint; - return this.StartPoint; + return this.GetClosestAtPoint(pt, extend).closestPt; } Extend(newParam: number) diff --git a/src/DatabaseServices/PointInPolyline.ts b/src/DatabaseServices/PointInPolyline.ts index 5373ad19b..7b29e5d32 100644 --- a/src/DatabaseServices/PointInPolyline.ts +++ b/src/DatabaseServices/PointInPolyline.ts @@ -1,5 +1,5 @@ import { Vector2, Vector3 } from 'three'; -import { angle, equaln, equal } from '../Geometry/GeUtils'; +import { angle, equaln, equalv3 } from '../Geometry/GeUtils'; import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { Arc } from './Arc'; import { Line } from './Line'; @@ -144,7 +144,7 @@ export function IsPointInPolyLine(pl: Polyline, pt: Vector3): boolean for (let pti of arc.IntersectWith(insLine, IntersectOption.ExtendArg)) { - if (pti.y < pt.y || equal(sp, pti) || equal(ep, pti)) + if (pti.y < pt.y || equalv3(sp, pti) || equalv3(ep, pti)) continue; let der = arc.GetFistDeriv(pti); diff --git a/src/DatabaseServices/Polyline.ts b/src/DatabaseServices/Polyline.ts index 97f3409fa..110ebf5c4 100644 --- a/src/DatabaseServices/Polyline.ts +++ b/src/DatabaseServices/Polyline.ts @@ -6,7 +6,7 @@ import { ColorMaterial } from '../Common/ColorPalette'; import { getDeterminantFor2V, Vec2DTo3D, Vec3DTo2D } from '../Common/CurveUtils'; import { matrixAlignCoordSys } from '../Common/Matrix4Utils'; import { FixIndex } from '../Common/Utils'; -import { equal, equaln, updateGeometry } from '../Geometry/GeUtils'; +import { equalv3, equaln, updateGeometry } from '../Geometry/GeUtils'; import { RenderType } from '../GraphicsSystem/Enum'; import { IntersectOption, IntersectPolylineAndCurve } from '../GraphicsSystem/IntersectWith'; import { PolyOffsetUtil } from '../GraphicsSystem/OffsetPolyline'; @@ -243,7 +243,7 @@ export class Polyline extends Curve //曲线是否闭合 get IsClose(): boolean { - return this.CloseMark || (equal(this.StartPoint, this.EndPoint, 1e-5)) && this.EndParam > 1; + return this.CloseMark || (equalv3(this.StartPoint, this.EndPoint, 1e-4)) && this.EndParam > 1; } set CloseMark(v: boolean) { @@ -540,7 +540,7 @@ export class Polyline extends Curve this.Update(); } - Join(cu: Curve): boolean + Join(cu: Curve, fuzz = 1e-5): boolean { if (this.m_ClosedMark) return false; @@ -575,19 +575,19 @@ export class Polyline extends Curve { if (cu instanceof Line) { - if (equal(cuSp, sp)) + if (equalv3(cuSp, sp, fuzz)) { this.m_LineData.unshift({ pt: cuEp2, bul: 0 }); } - else if (equal(cuSp, ep)) + else if (equalv3(cuSp, ep, fuzz)) { this.m_LineData.push({ pt: cuEp2, bul: 0 }); } - else if (equal(cuEp, sp)) + else if (equalv3(cuEp, sp, fuzz)) { this.m_LineData.unshift({ pt: cuSp2, bul: 0 }); } - else if (equal(cuEp, ep)) + else if (equalv3(cuEp, ep, fuzz)) { this.m_LineData.push({ pt: cuSp2, bul: 0 }); } @@ -597,20 +597,20 @@ export class Polyline extends Curve else if (cu instanceof Arc) { let bul = Math.tan(cu.AllAngle * 0.25) * (cu.IsClockWise ? -1 : 1); - if (equal(cuSp, sp)) + if (equalv3(cuSp, sp, fuzz)) { this.m_LineData.unshift({ pt: cuEp2, bul: -bul }); } - else if (equal(cuSp, ep)) + else if (equalv3(cuSp, ep, fuzz)) { arrayLast(this.m_LineData).bul = bul; this.m_LineData.push({ pt: cuEp2, bul: 0 }); } - else if (equal(cuEp, sp)) + else if (equalv3(cuEp, sp, fuzz)) { this.m_LineData.unshift({ pt: cuSp2, bul: bul }); } - else if (equal(cuEp, ep)) + else if (equalv3(cuEp, ep, fuzz)) { arrayLast(this.m_LineData).bul = -bul; this.m_LineData.push({ pt: cuSp2, bul: 0 }); @@ -633,7 +633,7 @@ export class Polyline extends Curve p.copy(Vec3DTo2D(Vec2DTo3D(p).applyMatrix4(alMat))); } - if (equal(cuSp, sp)) + if (equalv3(cuSp, sp)) { cu.Reverse(); cuPtsBul.pts.pop(); @@ -641,7 +641,7 @@ export class Polyline extends Curve pts = cuPtsBul.pts.concat(pts); buls = cuPtsBul.buls.concat(buls); } - else if (equal(cuSp, ep)) + else if (equalv3(cuSp, ep)) { pts.pop(); buls.pop(); @@ -649,14 +649,14 @@ export class Polyline extends Curve pts = pts.concat(cuPtsBul.pts); buls = buls.concat(cuPtsBul.buls); } - else if (equal(cuEp, sp)) + else if (equalv3(cuEp, sp)) { cuPtsBul.pts.pop(); cuPtsBul.buls.pop(); pts = cuPtsBul.pts.concat(pts); buls = cuPtsBul.buls.concat(buls); } - else if (equal(cuEp, ep)) + else if (equalv3(cuEp, ep)) { pts.pop(); buls.pop(); @@ -705,9 +705,9 @@ export class Polyline extends Curve if (this.m_ClosedMark) extType = ExtendType.None; //最近点 - let ptC = this.StartPoint; - //最近点的距离\ - let ptCDist = ptC.distanceToSquared(pt); + let ptC = undefined; + //最近点的距离 + let ptCDist = Infinity; for (let i = 0; i < this.EndParam; i++) { diff --git a/src/Geometry/GeUtils.ts b/src/Geometry/GeUtils.ts index f8d01b62b..969ab6232 100644 --- a/src/Geometry/GeUtils.ts +++ b/src/Geometry/GeUtils.ts @@ -26,10 +26,15 @@ export function equaln(v1: number, v2: number, fuzz = 1e-5) { return Math.abs(v1 - v2) < fuzz; } -export function equal(v1: T, v2: T, fuzzSq = 1e-8) +export function equalv3(v1: Vector3, v2: Vector3, fuzz = 1e-8) { - return v1.distanceToSquared(v2) < fuzzSq; + return equaln(v1.x, v2.x, fuzz) && equaln(v1.y, v2.y, fuzz) && equaln(v1.z, v2.z, fuzz); } +export function equalv2(v1: Vector2, v2: Vector2, fuzz = 1e-8) +{ + return equaln(v1.x, v2.x, fuzz) && equaln(v1.y, v2.y, fuzz); +} + export function less(v1, v2, fuzz = 0) { return v1 - v2 < fuzz; diff --git a/src/Geometry/RegionParse.ts b/src/Geometry/RegionParse.ts index 6f6e22148..b4ce47a96 100644 --- a/src/Geometry/RegionParse.ts +++ b/src/Geometry/RegionParse.ts @@ -3,7 +3,7 @@ import { Arc } from '../DatabaseServices/Arc'; import { Curve } from '../DatabaseServices/Curve'; import { Count } from './Count'; import { CurveMap } from './CurveMap'; -import { angle, equal } from './GeUtils'; +import { angle, equalv3 } from './GeUtils'; //路线 export interface Route @@ -195,12 +195,12 @@ export class RegionParse s.routes.sort((r1, r2) => { let a1: number, a2: number; - if (equal(r1.curve.StartPoint, s.position)) + if (equalv3(r1.curve.StartPoint, s.position)) a1 = angle(r1.curve.GetFistDeriv(0)); else a1 = angle(r1.curve.GetFistDeriv(r1.curve.EndParam).negate()); - if (equal(r2.curve.StartPoint, s.position)) + if (equalv3(r2.curve.StartPoint, s.position)) a2 = angle(r2.curve.GetFistDeriv(0)); else a2 = angle(r2.curve.GetFistDeriv(r1.curve.EndParam).negate()); diff --git a/src/GraphicsSystem/IntersectWith.ts b/src/GraphicsSystem/IntersectWith.ts index 307f0b9db..0418a17d2 100644 --- a/src/GraphicsSystem/IntersectWith.ts +++ b/src/GraphicsSystem/IntersectWith.ts @@ -6,7 +6,7 @@ import { Circle } from '../DatabaseServices/Circle'; import { Curve } from '../DatabaseServices/Curve'; import { Line } from '../DatabaseServices/Line'; import { Polyline } from '../DatabaseServices/Polyline'; -import { comparePoint, equal, equaln, midPoint } from '../Geometry/GeUtils'; +import { comparePoint, equalv3, equaln, midPoint } from '../Geometry/GeUtils'; /** @@ -106,7 +106,7 @@ export function IntersectCircleAndCircle(cu1: Circle | Arc, cu2: Circle | Arc) p2.applyMatrix4(c1Ocs); pts.push(p1); - if (!equal(p1, p2))//防止点重复 + if (!equalv3(p1, p2))//防止点重复 pts.push(p2); return pts; @@ -235,7 +235,7 @@ export function IntersectLAndLFor3D(p1: Vector3, p2: Vector3, p3: Vector3, p4: V let v2 = p4.clone().sub(p3).normalize(); let w = p3.clone().sub(p1).normalize(); - if (equaln(Math.abs(v1.dot(v2)), 1, 1e-6) && (equal(w, new Vector3()) || equaln(Math.abs(v1.dot(w)), 1, 1e-6))) //平行共线 + if (equaln(Math.abs(v1.dot(v2)), 1, 1e-6) && (equalv3(w, new Vector3()) || equaln(Math.abs(v1.dot(w)), 1, 1e-6))) //平行共线 { let pts = [p1, p2, p3, p4]; pts.sort(comparePoint('xyz')); @@ -286,7 +286,7 @@ export function IntersectLAndLFor3D1(p1: Vector3, p2: Vector3, p3: Vector3, p4: { let tmpPts = [p1, p2, p3, p4]; tmpPts.sort(comparePoint('xyz')); - if (equal(tmpPts[1], p3) || equal(tmpPts[1], p4)) + if (equalv3(tmpPts[1], p3) || equalv3(tmpPts[1], p4)) { pts = [tmpPts[1], tmpPts[2]]; } @@ -358,7 +358,7 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte if ((cu instanceof Polyline && cu.CloseMark) || !(isStart2 || isEnd2)) ext = ext & ~IntersectOption.ExtendArg; - let ipts = cu1.IntersectWith(cu2, ext).filter(p1 => pts.every(p2 => !equal(p1, p2))); + let ipts = cu1.IntersectWith(cu2, ext).filter(p1 => pts.every(p2 => !equalv3(p1, p2))); //校验延伸 if (IntersectOption.ExtendThis & ext) @@ -396,6 +396,6 @@ export function IntersectPolylineAndCurve(pl: Polyline, cu: Curve, extType: Inte } } pts.sort(comparePoint("xyz")); - arrayRemoveDuplicateBySort(pts, equal); + arrayRemoveDuplicateBySort(pts, equalv3); return pts; } diff --git a/src/GraphicsSystem/LinkSelft.ts b/src/GraphicsSystem/LinkSelft.ts index 5b8ec26c7..0d5d86960 100644 --- a/src/GraphicsSystem/LinkSelft.ts +++ b/src/GraphicsSystem/LinkSelft.ts @@ -2,7 +2,7 @@ import { Vector3 } from "three"; import { Curve } from "../DatabaseServices/Curve"; import { CurveIntersection } from "../Geometry/CurveIntersection"; import { CurveMap } from "../Geometry/CurveMap"; -import { equal, equaln } from "../Geometry/GeUtils"; +import { equalv3, equaln } from "../Geometry/GeUtils"; import { Stand } from "../Geometry/RegionParse"; export class LinkSelf @@ -95,7 +95,7 @@ export class LinkSelf let ways: Stand[] = []; ways.push(cuMap.GetStand(cu.StartPoint)); - if (equal(route.curve.EndPoint, stand.position)) + if (equalv3(route.curve.EndPoint, stand.position)) continue; //如果方向相反,那么退出计算 (不符合) let routeIndex = this.GetCurveIndex(route.curve); @@ -167,7 +167,7 @@ export class LinkSelf if (this.GetCurveUse(cu2)) continue; //能够连接 - let isLink = isInv ? equal(cu2.EndPoint, originCu.StartPoint) : equal(cu2.StartPoint, originCu.EndPoint); + let isLink = isInv ? equalv3(cu2.EndPoint, originCu.StartPoint) : equalv3(cu2.StartPoint, originCu.EndPoint); if (isLink) { this.SetCurveUse(cu2); @@ -196,7 +196,7 @@ export class LinkSelf let cu = nowStand.routes[j].curve; let cuIndex = this.GetCurveIndex(cu); if (this.GetCurveUse(cu)) continue; - if (!equal(cu.StartPoint, nowStand.position)) continue; + if (!equalv3(cu.StartPoint, nowStand.position)) continue; if (nowIndex === cuIndex) { let routes2 = routes.concat();//复制数组保证函数有唯一结果 @@ -242,7 +242,7 @@ export class LinkSelf { for (let route of nowStand.routes) { - if (equal(route.curve.EndPoint, nowStand.position)) + if (equalv3(route.curve.EndPoint, nowStand.position)) continue; //如果方向相反,那么退出计算 (不符合) if (this.GetCurveUse(route.curve)) continue; diff --git a/src/GraphicsSystem/OffsetPolyline.ts b/src/GraphicsSystem/OffsetPolyline.ts index 762166a0d..cdd878a39 100644 --- a/src/GraphicsSystem/OffsetPolyline.ts +++ b/src/GraphicsSystem/OffsetPolyline.ts @@ -8,7 +8,7 @@ import { Contour } from '../DatabaseServices/Contour'; import { Curve } from "../DatabaseServices/Curve"; import { Line } from "../DatabaseServices/Line"; import { Polyline } from '../DatabaseServices/Polyline'; -import { equal, equaln } from "../Geometry/GeUtils"; +import { equaln, equalv2, equalv3 } from "../Geometry/GeUtils"; import { EBox, SortEntityByBox } from "../Geometry/SortEntityByBox"; import { IsPtsAllOutOrOnReg } from "./BoolOperateUtils"; import { IntersectOption } from "./IntersectWith"; @@ -75,7 +75,6 @@ export class PolyOffsetUtil // 如果源线段闭合只保留闭合的部分 if (this.m_Polyline.IsClose) return this.m_RetCurves.filter(c => c.IsClose); - return this.m_RetCurves; } private CheckPointDir(pt: Vector3) @@ -141,7 +140,7 @@ export class PolyOffsetUtil let c2EndPt = c2.EndPoint; //同心圆弧 - let equalArc = c1 instanceof Arc && c2 instanceof Arc && equal(c1.Center, c2.Center); + let equalArc = c1 instanceof Arc && c2 instanceof Arc && equalv3(c1.Center, c2.Center); //被包含的直线删掉 if ((c1 instanceof Line && c2 instanceof Line) || equalArc) @@ -163,7 +162,7 @@ export class PolyOffsetUtil } //如果线段端点相连,跳过 - let isLink = [c1StartPt, c1EndPt].some(p => equal(p, c2StartPt) || equal(p, c2EndPt)); + let isLink = [c1StartPt, c1EndPt].some(p => equalv3(p, c2StartPt) || equalv3(p, c2EndPt)); if (isLink) continue; if (equalArc || c1.IntersectWith(c2, IntersectOption.OnBothOperands).length > 0) @@ -316,7 +315,7 @@ export class PolyOffsetUtil //#region 1.中间丢失线段的情况下且循环到尾部,补圆弧. - let isFillArc = !equal( + let isFillArc = !equalv2( this.m_Polyline.GetPoint2dAt(FixIndex(startIndex + 1, this.m_PtCount)), this.m_Polyline.GetPoint2dAt(endIndex) ); @@ -343,7 +342,7 @@ export class PolyOffsetUtil let iPts: Vector3[]; //延伸交点 let tPts: Vector3[]; //都在两条线上的为真交点 - if (equal(frontLine.EndPoint, laterLine.StartPoint)) + if (equalv3(frontLine.EndPoint, laterLine.StartPoint)) tPts = [frontLine.EndPoint]; else { @@ -593,9 +592,9 @@ export class PolyOffsetUtil let lastCu = arrayLast(this.m_RetCurves); //让圆弧保持和最后一段首尾相连 - if (!equal(arc1.StartPoint, lastCu.EndPoint)) + if (!equalv3(arc1.StartPoint, lastCu.EndPoint)) arc1.Reverse(); - if (!equal(arc2.StartPoint, lastCu.EndPoint)) + if (!equalv3(arc2.StartPoint, lastCu.EndPoint)) arc2.Reverse(); //优先选择和源线段不想交的圆弧,如果都相交或者都不相交,选择和最后一段切线接近的圆弧 @@ -697,9 +696,7 @@ export class PolyOffsetUtil { let pl = new Polyline(); for (let cu of g) - { pl.Join(cu); - } resultPls.push(pl) } return resultPls;