diff --git a/__test__/EdgeSealing/__snapshots__/EdgeSealing.test.ts.snap b/__test__/EdgeSealing/__snapshots__/EdgeSealing.test.ts.snap index be49c1538..0182081f4 100644 --- a/__test__/EdgeSealing/__snapshots__/EdgeSealing.test.ts.snap +++ b/__test__/EdgeSealing/__snapshots__/EdgeSealing.test.ts.snap @@ -8,7 +8,7 @@ exports[`常规板件,常规坐标系 3`] = `712816`; exports[`异型板件,常规坐标系 1`] = `2709777.7883832143`; -exports[`异型板件,常规坐标系 2`] = `2682243.404899422`; +exports[`异型板件,常规坐标系 2`] = `2682243.4048994216`; exports[`异型板件,常规坐标系 3`] = `2660261.483308105`; @@ -20,4 +20,4 @@ exports[`异型板件,非常规坐标系 1`] = `75939516.39226122`; exports[`异型板件,非常规坐标系 2`] = `75852693.84266448`; -exports[`异型板件,非常规坐标系 3`] = `75675829.72975095`; +exports[`异型板件,非常规坐标系 3`] = `75675829.72975093`; diff --git a/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap b/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap index d43e8c61f..ceb16aa68 100644 --- a/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap +++ b/__test__/FeedingToolPath/__snapshots__/FeedingToolPath.test.ts.snap @@ -4,7 +4,7 @@ exports[`刀切到外轮廓情况: 曲线长度 1`] = `3600`; exports[`刀切到外轮廓情况: 曲线长度 2`] = `22596.75011038597`; -exports[`刀切到外轮廓情况: 曲线长度 3`] = `6355.243980782`; +exports[`刀切到外轮廓情况: 曲线长度 3`] = `6355.243980781998`; exports[`刀切到外轮廓情况: 曲线长度 4`] = `1478.9393851461323`; @@ -12,21 +12,21 @@ exports[`刀切到外轮廓情况: 曲线长度 5`] = `729.5688477133849`; exports[`刀切到外轮廓情况: 曲线长度 6`] = `3600`; -exports[`刀切到外轮廓情况: 曲线长度 7`] = `939.4039853849399`; +exports[`刀切到外轮廓情况: 曲线长度 7`] = `939.4039853849379`; -exports[`刀切到外轮廓情况: 曲线长度 8`] = `13736.355649626385`; +exports[`刀切到外轮廓情况: 曲线长度 8`] = `13736.355649626326`; -exports[`刀切到外轮廓情况: 曲线长度 9`] = `1216.9875775199403`; +exports[`刀切到外轮廓情况: 曲线长度 9`] = `1216.9875775199405`; -exports[`刀切到外轮廓情况: 曲线长度 10`] = `13428.231939084159`; +exports[`刀切到外轮廓情况: 曲线长度 10`] = `13428.231939084173`; exports[`刀切到外轮廓情况: 曲线长度 11`] = `939.4039853849375`; exports[`刀切到外轮廓情况: 曲线长度 12`] = `13736.35564962633`; -exports[`刀切到外轮廓情况: 曲线长度 13`] = `13428.231939084155`; +exports[`刀切到外轮廓情况: 曲线长度 13`] = `13428.23193908413`; -exports[`刀切到外轮廓情况: 曲线长度 14`] = `1216.9875775199403`; +exports[`刀切到外轮廓情况: 曲线长度 14`] = `1216.9875775199384`; exports[`刀切到外轮廓情况: 曲线长度 15`] = `2683.281572999748`; @@ -44,10 +44,12 @@ exports[`复杂极限刀半径: 曲线长度 3`] = `951.5402172137751`; exports[`复杂极限刀半径: 曲线长度 4`] = `35730.26757931215`; -exports[`复杂极限刀半径: 曲线长度 5`] = `2927.3167299028473`; +exports[`复杂极限刀半径: 曲线长度 5`] = `2927.3167299028455`; exports[`复杂极限刀半径: 曲线长度 6`] = `3278.917934988776`; +exports[`复杂极限刀半径: 曲线长度 7`] = `3278.917934988776`; + exports[`复杂极限刀半径: 走刀数量 1`] = `4`; exports[`复杂造型测试: 曲线长度 1`] = `2402.511185283596`; @@ -72,7 +74,7 @@ exports[`复杂造型测试: 曲线长度 10`] = `4096.105045378745`; exports[`复杂造型测试: 曲线长度 11`] = `476.0989607667294`; -exports[`复杂造型测试: 曲线长度 12`] = `910.1341511193465`; +exports[`复杂造型测试: 曲线长度 12`] = `910.1341511193467`; exports[`复杂造型测试: 曲线长度 13`] = `1167.5479341842504`; @@ -102,11 +104,11 @@ exports[`复杂造型测试: 曲线长度 25`] = `162.171881370416`; exports[`复杂造型测试: 曲线长度 26`] = `3600`; -exports[`复杂造型测试: 曲线长度 27`] = `103756.10963582453`; +exports[`复杂造型测试: 曲线长度 27`] = `103756.1096358091`; exports[`复杂造型测试: 曲线长度 28`] = `487.19933816470575`; -exports[`复杂造型测试: 曲线长度 29`] = `2152.7628031484855`; +exports[`复杂造型测试: 曲线长度 29`] = `2152.7628031484846`; exports[`复杂造型测试: 曲线长度 30`] = `2581.084814115112`; @@ -164,7 +166,7 @@ exports[`极限刀半径: 曲线长度 7`] = `3600`; exports[`极限刀半径: 曲线长度 8`] = `3517.9183450322453`; -exports[`极限刀半径: 曲线长度 9`] = `1638.9591725161226`; +exports[`极限刀半径: 曲线长度 9`] = `1638.9591725161224`; exports[`极限刀半径: 曲线长度 10`] = `3600`; diff --git a/__test__/Geometry/intersect.test.ts b/__test__/Geometry/intersect.test.ts index a4cbba101..d7ec12c93 100644 --- a/__test__/Geometry/intersect.test.ts +++ b/__test__/Geometry/intersect.test.ts @@ -5,8 +5,7 @@ import { CADFile } from '../../src/DatabaseServices/CADFile'; import { Circle } from '../../src/DatabaseServices/Circle'; import { Curve } from '../../src/DatabaseServices/Curve'; import { Line } from '../../src/DatabaseServices/Line'; -import { IntersectCircleAndCircle, IntersectLAndLFor3D, IntersectOption } from '../../src/GraphicsSystem/IntersectWith'; - +import { IntersectCircleAndCircle, IntersectLine3AndLine3, IntersectOption } from '../../src/GraphicsSystem/IntersectWith'; test('相交测试', () => { @@ -18,13 +17,13 @@ test('相交测试', () => let p5 = new THREE.Vector3(3, 0, 0); let p6 = new THREE.Vector3(6, 0, 0); - let res = IntersectLAndLFor3D(p1, p2, p3, p4);/*?*/ + let res = IntersectLine3AndLine3(p1, p2, p3, p4);/*?*/ expect(res).toMatchSnapshot(); - res = IntersectLAndLFor3D(p1, p2, p5, p6);/*?*/ + res = IntersectLine3AndLine3(p1, p2, p5, p6);/*?*/ expect(res).toMatchSnapshot(); - let ins = IntersectLAndLFor3D( + let ins = IntersectLine3AndLine3( new THREE.Vector3(0, 5), new THREE.Vector3(5, 5), new THREE.Vector3(0.5, 1), @@ -42,22 +41,22 @@ test('三维空间直线相交测试', () => let p5 = new THREE.Vector3(3, 3, 3); let p6 = new THREE.Vector3(6, 6, 6); - let res = IntersectLAndLFor3D(p1, p2, p3, p4);/*?*/ + let res = IntersectLine3AndLine3(p1, p2, p3, p4);/*?*/ expect(res).toMatchSnapshot(); - res = IntersectLAndLFor3D(p1, p2, p5, p6);/*?*/ + res = IntersectLine3AndLine3(p1, p2, p5, p6);/*?*/ expect(res).toMatchSnapshot(); - res = IntersectLAndLFor3D(p2, p6, p3, p4);/*?*/ + res = IntersectLine3AndLine3(p2, p6, p3, p4);/*?*/ expect(res).toMatchSnapshot(); - res = IntersectLAndLFor3D( + res = IntersectLine3AndLine3( new Vector3(1, 1, 1), new Vector3(1, 1, 4), new Vector3(2, 2, 2), new Vector3(2, 2, 10) ) expect(res).toBeUndefined(); - res = IntersectLAndLFor3D( + res = IntersectLine3AndLine3( new Vector3(1, 0, 1), new Vector3(1, 0, 4), new Vector3(0.5, 0, 3), diff --git a/src/Add-on/test/testIntersect.ts b/src/Add-on/test/testIntersect.ts index 6d96e9492..cbe639cdf 100644 --- a/src/Add-on/test/testIntersect.ts +++ b/src/Add-on/test/testIntersect.ts @@ -5,7 +5,7 @@ import { Circle } from "../../DatabaseServices/Circle"; import { Curve } from "../../DatabaseServices/Curve"; import { Command } from "../../Editor/CommandMachine"; import { PromptStatus } from "../../Editor/PromptResult"; -import { IntersectCircleAndCircle, IntersectLAndLFor3D, IntersectOption } from "../../GraphicsSystem/IntersectWith"; +import { IntersectCircleAndCircle, IntersectOption } from "../../GraphicsSystem/IntersectWith"; import { Point } from "../../DatabaseServices/Point"; export class TestIntersect implements Command @@ -44,27 +44,6 @@ export class TestIntersect implements Command } } } - - async testLineAndLine() - { - let exRefSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true }); - if (exRefSsRes.Status !== PromptStatus.OK) return; - let cus = exRefSsRes.SelectSet.SelectEntityList as Curve[]; - let pt = IntersectLAndLFor3D(cus[0].StartPoint, cus[0].EndPoint, cus[1].StartPoint, cus[1].EndPoint); - console.log('pt: ', pt); - if (pt) - { - cus[0].ColorIndex = 7; - cus[1].ColorIndex = 7; - let cir = new Circle(pt, 0.1); - cir.ColorIndex = 2; - app.m_Database.ModelSpace.Append(cir); - } else - { - cus[0].ColorIndex = 1; - cus[1].ColorIndex = 1; - } - } async testLineAndCirOrArc() { let exRefSsRes = await app.m_Editor.GetSelection({ Msg: "请选择对象<全部选择>:", UseSelect: true }); diff --git a/src/GraphicsSystem/IntersectWith.ts b/src/GraphicsSystem/IntersectWith.ts index f3d24019d..63314020c 100644 --- a/src/GraphicsSystem/IntersectWith.ts +++ b/src/GraphicsSystem/IntersectWith.ts @@ -1,12 +1,11 @@ import { Vector3 } from 'three'; import { arrayRemoveDuplicateBySort } from '../Common/ArrayExt'; -import { getDeterminantFor3V } from '../Common/CurveUtils'; import { Arc } from '../DatabaseServices/Arc'; import { Circle } from '../DatabaseServices/Circle'; import { Curve } from '../DatabaseServices/Curve'; import { Line } from '../DatabaseServices/Line'; import { Polyline } from '../DatabaseServices/Polyline'; -import { comparePoint, equalv3, equaln, midPoint } from '../Geometry/GeUtils'; +import { comparePoint, equaln, equalv3, midPoint } from '../Geometry/GeUtils'; /** @@ -217,101 +216,67 @@ export function IntersectLAndLFor2D(p1: Vector3, p2: Vector3, p3: Vector3, p4: V return pt; } -export function IntersectLAndLFor3D(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3) + +export function IntersectLine3AndLine3(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3, epsilon = 1e-6) { - let x12 = p1.x - p2.x; - let x43 = p4.x - p3.x; - let x42 = p4.x - p2.x; - let y12 = p1.y - p2.y; - let y43 = p4.y - p3.y; - let y42 = p4.y - p2.y; - let z12 = p1.z - p2.z; - let z43 = p4.z - p3.z; - let z42 = p4.z - p2.z; - - let v1 = p2.clone().sub(p1).normalize(); - let v2 = p4.clone().sub(p3).normalize(); - let w = p3.clone().sub(p1).normalize(); - - if (equaln(Math.abs(v1.dot(v2)), 1, 1e-6) && (equalv3(w, new Vector3()) || equaln(Math.abs(v1.dot(w)), 1, 1e-6))) //平行共线 - return undefined; - else if (equaln(Math.abs(v1.dot(v2)), 1, 1e-6)) //平行不共线 - return undefined; - else if (equaln(getDeterminantFor3V(v1, v2, w), 0, 0.01)) - { - let t: number; - if (x12 * y43 - y12 * x43) - { - t = (x42 * y43 - x43 * y42) / (x12 * y43 - y12 * x43); - } - else if (x12 * z43 - x43 * z12) - { - t = (x42 * z43 - x43 * z42) / (x12 * z43 - x43 * z12); - } - else - { - t = (y42 * z43 - y43 * z42) / (y12 * z43 - y43 * z12); - } - return new Vector3(x12 * t + p2.x, y12 * t + p2.y, z12 * t + p2.z); - } + let pts = ShortestLine3AndLine3(p1, p2, p3, p4); + if (pts) return pts[0]; } -export function IntersectLAndLFor3D1(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3) + +/** + * 三维中两行之间最短的直线 + * ref:https://stackoverflow.com/questions/2316490/the-algorithm-to-find-the-point-of-intersection-of-two-3d-line-segment + * ref:http://paulbourke.net/geometry/pointlineplane/ + * ref:http://paulbourke.net/geometry/pointlineplane/calclineline.cs + * + * @export + * @param {Vector3} p1 l1.start + * @param {Vector3} p2 l1.end + * @param {Vector3} p3 l2.start + * @param {Vector3} p4 l2.end + * @returns 交点集合 + */ +function ShortestLine3AndLine3(p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3, epsilon = 1e-6) { - let x12 = p1.x - p2.x; - let x43 = p4.x - p3.x; - let x42 = p4.x - p2.x; - let y12 = p1.y - p2.y; - let y43 = p4.y - p3.y; - let y42 = p4.y - p2.y; - let z12 = p1.z - p2.z; - let z43 = p4.z - p3.z; - let z42 = p4.z - p2.z; + let p43 = p4.clone().sub(p3); + if (p43.lengthSq() < epsilon) + return; + let p21 = p2.clone().sub(p1); + if (p21.lengthSq() < epsilon) + return; - let pts: Vector3[] = []; - let v1 = p2.clone().sub(p1).normalize(); - let v2 = p4.clone().sub(p3).normalize(); - let w = p3.clone().sub(p1).normalize(); + let p13 = p1.clone().sub(p3); - if (equaln(Math.abs(v1.dot(v2)), 1, 1e-6) && equaln(Math.abs(v1.dot(w)), 1, 1e-6)) //平行共线 - { - let tmpPts = [p1, p2, p3, p4]; - tmpPts.sort(comparePoint('xyz')); - if (equalv3(tmpPts[1], p3) || equalv3(tmpPts[1], p4)) - { - pts = [tmpPts[1], tmpPts[2]]; - } - else - { - pts = [midPoint(tmpPts[1], tmpPts[2])] - } - } - else if (equaln(Math.abs(v1.dot(v2)), 1, 1e-6)) //平行不共线 - { - return []; - } - else if (equaln(getDeterminantFor3V(v1, v2, w), 0, 0.01)) - { - let t: number; - if (x12 * y43 - y12 * x43) - { - t = (x42 * y43 - x43 * y42) / (x12 * y43 - y12 * x43); - } - else if (x12 * z43 - x43 * z12) - { - t = (x42 * z43 - x43 * z42) / (x12 * z43 - x43 * z12); - } - else - { - t = (y42 * z43 - y43 * z42) / (y12 * z43 - y43 * z12); - } - pts = [new Vector3(x12 * t + p2.x, y12 * t + p2.y, z12 * t + p2.z)] - } - return pts; + let d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z; + let d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z; + let d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z; + let d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z; + let d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z; + + let denom = d2121 * d4343 - d4321 * d4321; + if (Math.abs(denom) < epsilon) + return; + let numer = d1343 * d4321 - d1321 * d4343; + + let mua = numer / denom; + let mub = (d1343 + d4321 * (mua)) / d4343; + + let resultSegmentPoint1 = new Vector3(); + resultSegmentPoint1.x = p1.x + mua * p21.x; + resultSegmentPoint1.y = p1.y + mua * p21.y; + resultSegmentPoint1.z = p1.z + mua * p21.z; + let resultSegmentPoint2 = new Vector3(); + resultSegmentPoint2.x = p3.x + mub * p43.x; + resultSegmentPoint2.y = p3.y + mub * p43.y; + resultSegmentPoint2.z = p3.z + mub * p43.z; + + return [resultSegmentPoint1, resultSegmentPoint2]; } + //直线和直线 export function IntersectLineAndLine(l1: Line, l2: Line, extType: IntersectOption) { - let pt = IntersectLAndLFor3D(l1.StartPoint, l1.EndPoint, l2.StartPoint, l2.EndPoint); + let pt = IntersectLine3AndLine3(l1.StartPoint, l1.EndPoint, l2.StartPoint, l2.EndPoint); return pt ? CheckPointOnCurve([pt], l1, l2, extType) : []; }