From f0d9236efd3c3a5ffb6dc1aa3863ec12a962e2a5 Mon Sep 17 00:00:00 2001 From: ChenX Date: Thu, 27 May 2021 17:25:51 +0800 Subject: [PATCH] =?UTF-8?q?!1509=20=E4=BF=AE=E5=A4=8D:V=E5=9E=8B=E5=88=80?= =?UTF-8?q?=E8=B5=B0=E5=88=80=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VPath/__snapshots__/vpath.test.ts.snap | 110 ++++++++++++++++++ __test__/VPath/vpath.test.ts | 14 +++ src/Add-on/testEntity/TestVPath.ts | 20 +++- src/GraphicsSystem/ToolPath/VKnifToolPath.ts | 36 +++--- 4 files changed, 160 insertions(+), 20 deletions(-) create mode 100644 __test__/VPath/__snapshots__/vpath.test.ts.snap create mode 100644 __test__/VPath/vpath.test.ts diff --git a/__test__/VPath/__snapshots__/vpath.test.ts.snap b/__test__/VPath/__snapshots__/vpath.test.ts.snap new file mode 100644 index 000000000..72b257e69 --- /dev/null +++ b/__test__/VPath/__snapshots__/vpath.test.ts.snap @@ -0,0 +1,110 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`V型刀测试 1`] = ` +Array [ + Object { + "bul": 0, + "pt": Vector3 { + "x": 86.00039030917347, + "y": 325.00039030917355, + "z": 12, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 106.785, + "y": 345.7850000000001, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 193.21499999999997, + "y": 345.7850000000001, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 213.9996096908265, + "y": 325.00039030917355, + "z": 12, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 193.21499999999997, + "y": 345.7850000000001, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 193.21499999999997, + "y": 359.21500000000015, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 213.9996096908265, + "y": 379.99960969082656, + "z": 12, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 193.21499999999997, + "y": 359.21500000000015, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 106.785, + "y": 359.21500000000015, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 86.00039030917347, + "y": 379.99960969082656, + "z": 12, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 106.785, + "y": 359.21500000000015, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 106.785, + "y": 345.7850000000001, + "z": 0, + }, + }, + Object { + "bul": 0, + "pt": Vector3 { + "x": 86.00039030917347, + "y": 325.00039030917355, + "z": 12, + }, + }, +] +`; diff --git a/__test__/VPath/vpath.test.ts b/__test__/VPath/vpath.test.ts new file mode 100644 index 000000000..68a3f6675 --- /dev/null +++ b/__test__/VPath/vpath.test.ts @@ -0,0 +1,14 @@ +import { MathUtils } from "three"; +import { Polyline, VKnifToolPath } from "../../src/api"; +import { LoadEntityFromFileData } from "../Utils/LoadEntity.util"; + +test('V型刀测试', () => +{ + let d = { "file": [5, "Polyline", 8, 2, 209, false, 1, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 2, 4, [212.36464735516373, 1006.9161234266252], 0, [298.7946473551637, 1006.9161234266252], 0, [298.7946473551637, 1020.3461234266252], 0, [212.36464735516373, 1020.3461234266252], 0, true, "Polyline", 8, 2, 234, false, 1, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 2, 4, [212.36464735516373, 1006.9161234266252], 0, [298.7946473551637, 1006.9161234266252], 0, [298.7946473551637, 1020.3461234266252], 0, [212.36464735516373, 1020.3461234266252], 0, true, "Polyline", 8, 2, 235, false, 1, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 2, 4, [212.36464735516373, 1006.9161234266252], 0, [298.7946473551637, 1006.9161234266252], 0, [298.7946473551637, 1020.3461234266252], 0, [212.36464735516373, 1020.3461234266252], 0, true, "Polyline", 8, 2, 243, false, 1, 8, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 2, 2, [193.21499999999997, 359.21500000000015], 0, [106.785, 359.21500000000015], 0, false, "Polyline", 8, 2, 254, false, 1, 1, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -105.57964735516373, -661.1311234266251, 0, 1], 0, 2, 4, [212.36464735516373, 1006.9161234266252], 0, [298.7946473551637, 1006.9161234266252], 0, [298.7946473551637, 1020.3461234266252], 0, [212.36464735516373, 1020.3461234266252], 0, true], "basePt": { "x": 106.785, "y": 345.7850000000001, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let pl = LoadEntityFromFileData(d)[0] as Polyline; + + let vd = VKnifToolPath(pl, 12, MathUtils.DEG2RAD * 120 / 2); + + expect(vd).toMatchSnapshot(); +}); diff --git a/src/Add-on/testEntity/TestVPath.ts b/src/Add-on/testEntity/TestVPath.ts index 9fe28e65b..7e2c739f3 100644 --- a/src/Add-on/testEntity/TestVPath.ts +++ b/src/Add-on/testEntity/TestVPath.ts @@ -1,3 +1,4 @@ +import { MathUtils } from "three"; import { app } from "../../ApplicationServices/Application"; import { Line } from "../../DatabaseServices/Entity/Line"; import { Polyline } from "../../DatabaseServices/Entity/Polyline"; @@ -13,11 +14,26 @@ export class Command_TestVPath implements Command { async exec() { - let plRes = await app.Editor.GetEntity({ Filter: { filterTypes: [Polyline] } }); + let plRes = await app.Editor.GetEntity({ Msg: "请选择俯视图的二维刀路", Filter: { filterTypes: [Polyline] } }); if (plRes.Status !== PromptStatus.OK) return; + let anRes = await app.Editor.GetDistance({ Msg: "请输入刀具角度(完整的角度)", Default: 120 }); + if (anRes.Status !== PromptStatus.OK) return; + if (anRes.Distance <= 0 || anRes.Distance >= 180) + { + app.Editor.Prompt("角度不能小于0或者大于180!"); + return; + } + + let depthRes = await app.Editor.GetDistance({ Msg: "请输入吃刀深度:", Default: 12 }); + if (depthRes.Distance <= 0 || depthRes.Distance >= 50) + { + app.Editor.Prompt("深度不能小于0或者大于50!"); + return; + } + let pl = plRes.Entity as Polyline; - let pts = VKnifToolPath(pl, 10, Math.PI / 3); + let pts = VKnifToolPath(pl, depthRes.Distance, MathUtils.DEG2RAD * anRes.Distance / 2); console.log(pts); for (let i = 1; i < pts.length; i++) diff --git a/src/GraphicsSystem/ToolPath/VKnifToolPath.ts b/src/GraphicsSystem/ToolPath/VKnifToolPath.ts index 81ccb0ad7..e04ec0b06 100644 --- a/src/GraphicsSystem/ToolPath/VKnifToolPath.ts +++ b/src/GraphicsSystem/ToolPath/VKnifToolPath.ts @@ -17,12 +17,10 @@ import { IntersectOption } from "../IntersectWith"; */ export function VKnifToolPath(polyline: Polyline, feedingDepth: number, knifAngle: number): { pt: Vec3, bul: number; }[] { - let x = feedingDepth * Math.tan(knifAngle); + let x = Math.abs(feedingDepth * Math.tan(knifAngle)); let cus = polyline.Explode(); arrayRemoveIf(cus, c => c.Length < 0.01); - let offsetx = [x, -x]; - let ptsbul: { pt: Vec3, bul: number; }[] = []; let isClose = polyline.IsClose; @@ -40,10 +38,10 @@ export function VKnifToolPath(polyline: Polyline, feedingDepth: number, knifAngl if (c1 instanceof Arc) { d.bul = c1.Bul; - c1 = new Line(curP.clone().sub(c1.GetFistDeriv(1).multiplyScalar(100)), curP); + c1 = new Line(curP.clone().sub(c1.GetFistDeriv(1).multiplyScalar(100)), curP.clone()); } if (c2 instanceof Arc) - c2 = new Line(c2.StartPoint, c2.StartPoint.add(c2.GetFistDeriv(0).multiplyScalar(100))); + c2 = new Line(curP.clone(), curP.clone().add(c2.GetFistDeriv(0).multiplyScalar(100))); ptsbul.push(d); @@ -56,24 +54,26 @@ export function VKnifToolPath(polyline: Polyline, feedingDepth: number, knifAngl //圆弧与直线相切,此时不要提刀 if (isParallelTo(c1.GetFistDeriv(0), c2.GetFistDeriv(0))) continue; - //提刀 - for (let x of offsetx) - { - let co1 = c1.GetOffsetCurves(x)[0]; - let co2 = c2.GetOffsetCurves(x)[0]; + //计算提刀部分: + //向量与平分线,参照倒角代码 + let derv1 = c1.GetFistDeriv(0).normalize(); + let derv2 = c2.GetFistDeriv(0).normalize(); + let bisectorVec = derv1.clone().negate().add(derv2).multiplyScalar(0.5); - if (!co1 || !co2) continue; + let co1 = c1.GetOffsetCurves(x * Math.sign(derv1.cross(bisectorVec).z))[0]; + let co2 = c2.GetOffsetCurves(x * Math.sign(derv2.cross(bisectorVec).z))[0]; - let ipts = co1.IntersectWith(co2, IntersectOption.ExtendBoth); + if (!co1 || !co2) continue; - if (ipts.length === 0) continue; + let ipts = co1.IntersectWith(co2, IntersectOption.ExtendBoth); - if (co1.PtOnCurve(ipts[0])) continue; + if (ipts.length === 0) continue; - //抬刀路径 - ptsbul.push({ pt: curP, bul: 0 }); - ptsbul.push({ pt: ipts[0].setZ(feedingDepth), bul: 0 }); - } + if (co1.PtOnCurve(ipts[0])) continue; + + //抬刀路径 + ptsbul.push({ pt: curP, bul: 0 }); + ptsbul.push({ pt: ipts[0].setZ(feedingDepth), bul: 0 }); } if (isClose)