From 2376956cb431c13b776449385c6648b732836232 Mon Sep 17 00:00:00 2001 From: ChenX Date: Mon, 17 Jul 2023 03:00:52 +0000 Subject: [PATCH] =?UTF-8?q?!2285=20=E5=8A=9F=E8=83=BD:=E4=B8=89=E7=BB=B4?= =?UTF-8?q?=E6=94=BE=E6=A0=B7(Sweep)(=E7=BA=BF=E6=9D=A1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __test__/Sweep/SweepGripAndStrench.test.ts | 68 ++ __test__/Sweep/SweepSegs.test.ts | 12 +- .../SweepGripAndStrench.test.ts.snap | 705 ++++++++++++++++++ .../__snapshots__/SweepSegs.test.ts.snap | 118 +-- src/Add-on/BoardCutting/CuttingByFace.ts | 5 +- src/Add-on/BoardCutting/LinearCutting.ts | 3 +- src/Add-on/CostumUCS.ts | 24 +- src/Add-on/DrawArc.ts | 7 +- src/Add-on/DrawCircle.ts | 16 +- src/Add-on/DrawLight/DrawRectAreaLight.ts | 35 +- src/Add-on/DrawLine.ts | 15 +- src/Add-on/DrawPolyline.ts | 31 +- src/Add-on/DrawRect.ts | 4 +- src/Add-on/DrawTopline.ts | 16 +- src/Add-on/DrawViewport.ts | 19 +- src/Add-on/ExportData.tsx | 2 +- src/Add-on/KJL/KjlExport.ts | 32 +- src/Add-on/Room/DrawRectWall.ts | 11 +- src/Add-on/Viewport/OneKeyLayout.ts | 6 +- src/Add-on/testEntity/TestSweepMaxLength.ts | 33 +- src/DatabaseServices/3DSolid/SweepSolid.ts | 533 ++++++++++--- src/DatabaseServices/Entity/Line.ts | 6 +- src/DatabaseServices/Entity/Polyline.ts | 8 +- .../Hardware/HardwareTopline.ts | 244 ++---- src/Editor/CommandMachine.ts | 2 + src/Editor/GetRectServices.ts | 35 +- src/Editor/GripDragServices.ts | 23 +- src/Editor/PromptOptions.ts | 4 +- src/Editor/PromptResult.ts | 4 +- src/Editor/SnapServices.ts | 49 +- src/Editor/UCSRAII.ts | 68 ++ src/Geometry/SpaceParse/Point2SpaceParse.ts | 2 +- src/Geometry/SweepGeometry.ts | 111 ++- src/UI/Components/Panel.tsx | 15 +- src/UI/Store/DownPanelStore.ts | 3 + 35 files changed, 1810 insertions(+), 459 deletions(-) create mode 100644 __test__/Sweep/SweepGripAndStrench.test.ts create mode 100644 __test__/Sweep/__snapshots__/SweepGripAndStrench.test.ts.snap create mode 100644 src/Editor/UCSRAII.ts diff --git a/__test__/Sweep/SweepGripAndStrench.test.ts b/__test__/Sweep/SweepGripAndStrench.test.ts new file mode 100644 index 000000000..3a7cc212f --- /dev/null +++ b/__test__/Sweep/SweepGripAndStrench.test.ts @@ -0,0 +1,68 @@ +import { Vector3 } from "three"; +import { HardwareTopline } from "../../src/DatabaseServices/Hardware/HardwareTopline"; +import { LoadEntityFromFileData } from "../Utils/LoadEntity.util"; + + +describe("三维扫掠夹点拉伸及拖拽", () => +{ + test("连接点拖拽", () => + { + let data = { "file": [1, "HardwareTopline", 10, 2, 289, 0, 1, 7, 71, [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, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 2, "Polyline", 10, 2, 0, 0, 1, 7, 71, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, 2, 4, [0, -1759.3364756864237], 0, [2540.6486638849437, -1754.5919838318846], 0, [2646.5114137277756, 2782.5795590546654], 0, [0, 2676.716809211834], 0, false, "Polyline", 10, 2, 0, 0, 1, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, 2, 4, [1756.7709279402495, 2676.716809211834], 0, [-1452.394394942868, 2676.716809211834], 0, [-1452.394394942868, -1759.3364756864237], 0, [1756.7709279402495, -1759.3364756864237], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": -1558.2571447857001, "y": -2754.976206098365, "z": -1865.1992255292557 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + en.MoveGripPoints([6, 7], new Vector3(0, 3000, 3000)); + const pathGripPts = en.GetGripPoints(); + for (let pt of pathGripPts) + expect(pt).toMatchSnapshot(); + }); + test("中间点拖拽", () => + { + let data = { "file": [1, "HardwareTopline", 10, 2, 289, 0, 1, 7, 71, [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, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 2, "Polyline", 10, 2, 0, 0, 1, 7, 71, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, 2, 4, [0, -1759.3364756864237], 0, [2540.6486638849437, -1754.5919838318846], 0, [2646.5114137277756, 2782.5795590546654], 0, [0, 2676.716809211834], 0, false, "Polyline", 10, 2, 0, 0, 1, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, 2, 4, [1756.7709279402495, 2676.716809211834], 0, [-1452.394394942868, 2676.716809211834], 0, [-1452.394394942868, -1759.3364756864237], 0, [1756.7709279402495, -1759.3364756864237], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": -1558.2571447857001, "y": -2754.976206098365, "z": -1865.1992255292557 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + en.MoveGripPoints([5], new Vector3(0, 0, 2500)); + const pathGripPts = en.GetGripPoints(); + for (let pt of pathGripPts) + expect(pt).toMatchSnapshot(); + }); + test("三线段连接点拖拽", () => + { + let data = { "file": [1, "HardwareTopline", 10, 2, 290, 0, 1, 7, 71, [0.08710264982404563, -0.995587843197948, -0.03489949670250097, 0, 0.9961946980917455, 0.08715574274765814, 0, 0, 0.003041691556625918, -0.03476669358110182, 0.9993908270190958, 0, 4585.502577142352, -3723.710151480106, 2182.6332735674614, 1], 0, 0, 1, [0.08710264982404563, -0.995587843197948, -0.03489949670250097, 0, 0.9961946980917455, 0.08715574274765814, 0, 0, 0.003041691556625918, -0.03476669358110182, 0.9993908270190958, 0, 4585.502577142352, -3723.710151480106, 2182.6332735674614, 1], 0, 0, 1, 2, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 4, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 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, 4, [2079.4342344794095, 1585.0706627478594], 0, [5161.537758750944, 1369.5366844918453], 0, [5161.537758750944, -1871.4511341125599], 0, [2317.886631016043, -1896.850481283555], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, 2, 2, [1830.4094117647062, -3266.3871657754003], 0, [0, -3266.3871657754003], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [0, -1, 0, 0, 1.2246467991473532e-16, 0, -1, 0, 1, 0, 1.2246467991473532e-16, 0, 487.47721925133686, 0, -1896.850481283555, 1], 0, 0, 1, [0, -1, 0, 0, 1.2246467991473532e-16, 0, -1, 0, 1, 0, 1.2246467991473532e-16, 0, 487.47721925133686, 0, -1896.850481283555, 1], 0, 0, 1, 2, 4, [0, 0], 0, [2374.4326701394516, 0], 0, [2374.4326701394516, -3259.051966436142], 0, [0, -3740.6774573715625], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, 2, 2, [-5.808380874699053e-14, 474.29029159616266], 0, [1591.957015228073, 215.53397825601405], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": 2147.057632809272, "y": -9249.31319428957, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + en.MoveGripPoints([9, 10], new Vector3(70, -800, 2000)); + const pathGripPts = en.GetGripPoints(); + for (let pt of pathGripPts) + expect(pt).toMatchSnapshot(); + }); + test("三线段中间点拖拽", () => + { + let data = { "file": [1, "HardwareTopline", 10, 2, 290, 0, 1, 7, 71, [0.08710264982404563, -0.995587843197948, -0.03489949670250097, 0, 0.9961946980917455, 0.08715574274765814, 0, 0, 0.003041691556625918, -0.03476669358110182, 0.9993908270190958, 0, 4585.502577142352, -3723.710151480106, 2182.6332735674614, 1], 0, 0, 1, [0.08710264982404563, -0.995587843197948, -0.03489949670250097, 0, 0.9961946980917455, 0.08715574274765814, 0, 0, 0.003041691556625918, -0.03476669358110182, 0.9993908270190958, 0, 4585.502577142352, -3723.710151480106, 2182.6332735674614, 1], 0, 0, 1, 2, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 4, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 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, 4, [2079.4342344794095, 1585.0706627478594], 0, [5161.537758750944, 1369.5366844918453], 0, [5161.537758750944, -1871.4511341125599], 0, [2317.886631016043, -1896.850481283555], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, 2, 2, [1830.4094117647062, -3266.3871657754003], 0, [0, -3266.3871657754003], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [0, -1, 0, 0, 1.2246467991473532e-16, 0, -1, 0, 1, 0, 1.2246467991473532e-16, 0, 487.47721925133686, 0, -1896.850481283555, 1], 0, 0, 1, [0, -1, 0, 0, 1.2246467991473532e-16, 0, -1, 0, 1, 0, 1.2246467991473532e-16, 0, 487.47721925133686, 0, -1896.850481283555, 1], 0, 0, 1, 2, 4, [0, 0], 0, [2374.4326701394516, 0], 0, [2374.4326701394516, -3259.051966436142], 0, [0, -3740.6774573715625], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, 2, 2, [-5.808380874699053e-14, 474.29029159616266], 0, [1591.957015228073, 215.53397825601405], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": 2147.057632809272, "y": -9249.31319428957, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + en.MoveGripPoints([18], new Vector3(10, -1000, 2500)); + const pathGripPts = en.GetGripPoints(); + for (let pt of pathGripPts) + expect(pt).toMatchSnapshot(); + }); + + test("二线段拉伸", () => + { + let data = { "file": [1, "HardwareTopline", 10, 2, 289, 0, 1, 7, 71, [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, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 2, "Polyline", 10, 2, 0, 0, 1, 7, 71, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, 2, 4, [0, -1759.3364756864237], 0, [2540.6486638849437, -1754.5919838318846], 0, [2646.5114137277756, 2782.5795590546654], 0, [0, 2676.716809211834], 0, false, "Polyline", 10, 2, 0, 0, 1, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, 2, 4, [1756.7709279402495, 2676.716809211834], 0, [-1452.394394942868, 2676.716809211834], 0, [-1452.394394942868, -1759.3364756864237], 0, [1756.7709279402495, -1759.3364756864237], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": -1558.2571447857001, "y": -2754.976206098365, "z": -1865.1992255292557 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + en.MoveStretchPoints([6, 5], new Vector3(-2500, 0, 0)); + const pathGripPts = en.GetStretchPoints(); + for (let pt of pathGripPts) + expect(pt).toMatchSnapshot(); + }); + + test("三线段拉伸", () => + { + let data = { "file": [1, "HardwareTopline", 10, 2, 290, 0, 1, 7, 71, [0.08710264982404563, -0.995587843197948, -0.03489949670250097, 0, 0.9961946980917455, 0.08715574274765814, 0, 0, 0.003041691556625918, -0.03476669358110182, 0.9993908270190958, 0, 4585.502577142352, -3723.710151480106, 2182.6332735674614, 1], 0, 0, 1, [0.08710264982404563, -0.995587843197948, -0.03489949670250097, 0, 0.9961946980917455, 0.08715574274765814, 0, 0, 0.003041691556625918, -0.03476669358110182, 0.9993908270190958, 0, 4585.502577142352, -3723.710151480106, 2182.6332735674614, 1], 0, 0, 1, 2, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 4, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 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, 4, [2079.4342344794095, 1585.0706627478594], 0, [5161.537758750944, 1369.5366844918453], 0, [5161.537758750944, -1871.4511341125599], 0, [2317.886631016043, -1896.850481283555], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, 2, 2, [1830.4094117647062, -3266.3871657754003], 0, [0, -3266.3871657754003], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [0, -1, 0, 0, 1.2246467991473532e-16, 0, -1, 0, 1, 0, 1.2246467991473532e-16, 0, 487.47721925133686, 0, -1896.850481283555, 1], 0, 0, 1, [0, -1, 0, 0, 1.2246467991473532e-16, 0, -1, 0, 1, 0, 1.2246467991473532e-16, 0, 487.47721925133686, 0, -1896.850481283555, 1], 0, 0, 1, 2, 4, [0, 0], 0, [2374.4326701394516, 0], 0, [2374.4326701394516, -3259.051966436142], 0, [0, -3740.6774573715625], 0, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 487.4772192513367, 0, 1369.5366844918453, 1], 0, 0, 1, 2, 2, [-5.808380874699053e-14, 474.29029159616266], 0, [1591.957015228073, 215.53397825601405], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": 2147.057632809272, "y": -9249.31319428957, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + en.MoveStretchPoints([11, 10, 9, 8, 1, 0], new Vector3(0, 0, 2000)); + const pathGripPts = en.GetStretchPoints(); + for (let pt of pathGripPts) + expect(pt).toMatchSnapshot(); + }); +}); diff --git a/__test__/Sweep/SweepSegs.test.ts b/__test__/Sweep/SweepSegs.test.ts index 463d7445f..287a9cb26 100644 --- a/__test__/Sweep/SweepSegs.test.ts +++ b/__test__/Sweep/SweepSegs.test.ts @@ -59,11 +59,21 @@ describe("顶线分段测试", () => }); test("不闭合多补圆弧", () => { - let data = { "file": [1, "HardwareTopline", 8, 2, 461, false, 1, 7, 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, 1, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -287.8749030927833, -1610.1774753266122, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -259.0799031476998, 7.263922518159916, 0, 1], 0, 2, 12, [327.8749030927833, 1710.1774753266122], 0, [305.5142233177854, 1710.1774753266122], 0, [265.5142233177854, 1630.1774753266122], 0, [227.8749030927833, 1630.1774753266122], 0, [227.8749030927833, 1610.1774753266122], 0, [287.8749030927833, 1610.1774753266122], 0, [287.8749030927833, 1630.1774753266122], 0, [293.72274470531937, 1641.8731585516844], -0.4817330338808767, [307.8749030927833, 1670.1774753266122], 0, [315.06369878080005, 1684.5550667026457], -1.000000000000003, [322.30959178698555, 1699.0468527150167], 0, [327.8749030927833, 1710.1774753266122], 0, false, "Polyline", 8, 2, 0, false, 0, 7, 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, 9, [45751.96592203299, 3086.036062563707], 0.22239155538431857, [52423.0828344913, 5938.5569393828955], 1.1461811427928006, [56463.47934476306, 3849.018445843789], 1.043480940008842, [62001.088374224215, 3387.691765452039], 0.8769933217842865, [68693.87601580269, 3758.4758746386747], 0.798237664392203, [75267.09679427171, 4091.702169937928], -0.8843311793277688, [80944.03676807143, 3824.3355122590892], -1.0886924073122075, [88681.92945847644, 2000.566713469759], -0.803057870546459, [94187.65216324253, -492.2642729771228], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": 45750.62233582299, "y": -504.6289351196049, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + let data = + { "file": [1, "HardwareTopline", 8, 2, 461, false, 1, 7, 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, 1, "Polyline", 8, 2, 0, false, 0, 7, 0, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -287.8749030927833, -1610.1774753266122, 0, 1], 0, 0, true, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -259.0799031476998, 7.263922518159916, 0, 1], 0, 2, 12, [327.8749030927833, 1710.1774753266122], 0, [305.5142233177854, 1710.1774753266122], 0, [265.5142233177854, 1630.1774753266122], 0, [227.8749030927833, 1630.1774753266122], 0, [227.8749030927833, 1610.1774753266122], 0, [287.8749030927833, 1610.1774753266122], 0, [287.8749030927833, 1630.1774753266122], 0, [293.72274470531937, 1641.8731585516844], -0.4817330338808767, [307.8749030927833, 1670.1774753266122], 0, [315.06369878080005, 1684.5550667026457], -1.000000000000003, [322.30959178698555, 1699.0468527150167], 0, [327.8749030927833, 1710.1774753266122], 0, false, "Polyline", 8, 2, 0, false, 0, 7, 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, 9, [45751.96592203299, 3086.036062563707], 0.22239155538431857, [52423.0828344913, 5938.5569393828955], 1.1461811427928006, [56463.47934476306, 3849.018445843789], 1.043480940008842, [62001.088374224215, 3387.691765452039], 0.8769933217842865, [68693.87601580269, 3758.4758746386747], 0.798237664392203, [75267.09679427171, 4091.702169937928], -0.8843311793277688, [80944.03676807143, 3824.3355122590892], -1.0886924073122075, [88681.92945847644, 2000.566713469759], -0.803057870546459, [94187.65216324253, -492.2642729771228], 0, false, 1, 0, "0", "2", "", "", "", "", "", "", "", "", "", 0], "basePt": { "x": 45750.62233582299, "y": -504.6289351196049, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; let en = LoadEntityFromFileData(data)[0] as HardwareTopline; let sgs = en.Segmentations; for (let sg of sgs) expect(sg.Length).toMatchSnapshot(); }); + test("三维顶线", () => + { + let data = + { "file": [1, "HardwareTopline", 10, 2, 289, 0, 1, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4796.814917280106, -649.6766791599803, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4796.814917280106, -649.6766791599803, 0, 1], 0, 0, 1, 2, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1794.6800494579688, -752.3551866479207, 0, 1], 0, 0, 1, 2, 12, [1691.4177159478995, 702.8822712717154], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1714.7698425753852, 679.5301446442261], 0, [1746.210156625953, 710.970458694799], 0, [1775.6109646391687, 681.5696506815787], 0, [1811.5243923180442, 717.4830783604598], 0, [1851.9100343613813, 677.0974363171161], 0, [1851.9100343613813, 677.0974363171161], 0, [1900.5427993008007, 725.7302012565432], 0, [1799.7364779468508, 826.5365226105092], 0, [1691.4177159478995, 702.8822712717154], 0, false, 2, "Polyline", 10, 2, 239, 1, 1, 7, 71, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, [0, -1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 1756.7709279402495, 0, 0, 1], 0, 0, 1, 2, 4, [0, -1759.3364756864237], 0, [2540.6486638849437, -1754.5919838318846], 0, [2540.6486638849437, 2676.716809211834], 0, [0, 2676.716809211834], 0, false, "Polyline", 10, 2, 242, 1, 1, 7, 71, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1], 0, 0, 1, 2, 4, [1756.7709279402495, 2676.716809211834], 0, [-1452.394394942868, 2676.716809211834], 0, [-1452.394394942868, -1759.3364756864237], 0, [1756.7709279402495, -1759.3364756864237], 0, false, 1, 0, "0", "2", "", "", "", "23", "", "", "", "", "", 0], "basePt": { "x": 3238.557772494406, "y": -3296.1880928879395, "z": -1865.1992255292557 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }; + let en = LoadEntityFromFileData(data)[0] as HardwareTopline; + let sgs = en.Segmentations; + for (let sg of sgs) + expect(sg.Length).toMatchSnapshot(); + }); }); diff --git a/__test__/Sweep/__snapshots__/SweepGripAndStrench.test.ts.snap b/__test__/Sweep/__snapshots__/SweepGripAndStrench.test.ts.snap new file mode 100644 index 000000000..3806f94f8 --- /dev/null +++ b/__test__/Sweep/__snapshots__/SweepGripAndStrench.test.ts.snap @@ -0,0 +1,705 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 1`] = ` +Vector3 { + "x": 4779.153543829856, + "y": -5937.150829198574, + "z": 6225.898121747388, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 2`] = ` +Vector3 { + "x": 4909.202722547994, + "y": -7423.619743878054, + "z": 4798.549362535392, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 3`] = ` +Vector3 { + "x": 5039.251901266132, + "y": -8910.088658557535, + "z": 3371.2006033233943, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 4`] = ` +Vector3 { + "x": 5034.322858624644, + "y": -8853.749443362783, + "z": 1751.6938551264584, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 5`] = ` +Vector3 { + "x": 5029.393815983156, + "y": -8797.410228168032, + "z": 132.187106929523, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 6`] = ` +Vector3 { + "x": 4905.510413292816, + "y": -7381.416455973404, + "z": 169.1161662197635, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 7`] = ` +Vector3 { + "x": 4781.627010602477, + "y": -5965.4226837787755, + "z": 206.045225510004, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 8`] = ` +Vector3 { + "x": 4781.627010602477, + "y": -5965.4226837787755, + "z": 206.045225510004, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 9`] = ` +Vector3 { + "x": 4701.9102555886875, + "y": -5054.2560045647515, + "z": 237.9854091250586, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 10`] = ` +Vector3 { + "x": 4622.193500574898, + "y": -4143.0893253507265, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 11`] = ` +Vector3 { + "x": 4622.193500574898, + "y": -4143.0893253507265, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 12`] = ` +Vector3 { + "x": 3439.4948820905242, + "y": -4246.562046835881, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 13`] = ` +Vector3 { + "x": 2256.79626360615, + "y": -4350.034768321036, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 14`] = ` +Vector3 { + "x": 2261.752779030607, + "y": -4406.687998862022, + "z": 1898.4589127575264, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 15`] = ` +Vector3 { + "x": 2266.709294455064, + "y": -4463.341229403009, + "z": 3526.992232774939, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 16`] = ` +Vector3 { + "x": 3453.9931103730432, + "y": -4412.277554402447, + "z": 5033.523769555613, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 17`] = ` +Vector3 { + "x": 4641.276926291022, + "y": -4361.213879401886, + "z": 6540.055306336288, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 18`] = ` +Vector3 { + "x": 4641.276926291022, + "y": -4361.2138794018865, + "z": 6540.055306336288, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 19`] = ` +Vector3 { + "x": 4710.215235060439, + "y": -5149.18235430023, + "z": 6382.976714041839, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段中间点拖拽 20`] = ` +Vector3 { + "x": 4779.153543829856, + "y": -5937.150829198574, + "z": 6225.898121747388, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 1`] = ` +Vector3 { + "x": 4777.527782432507, + "y": -5918.5682913950595, + "z": 5691.731196145292, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 2`] = ` +Vector3 { + "x": 5045.331578546759, + "y": -8979.579687859008, + "z": 5368.764653583218, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 3`] = ` +Vector3 { + "x": 5029.393815983156, + "y": -8797.410228168032, + "z": 132.187106929523, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 4`] = ` +Vector3 { + "x": 4781.627010602477, + "y": -5965.4226837787755, + "z": 206.045225510004, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 5`] = ` +Vector3 { + "x": 4781.627010602477, + "y": -5965.4226837787755, + "z": 206.045225510004, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 6`] = ` +Vector3 { + "x": 4622.193500574898, + "y": -4143.0893253507265, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 7`] = ` +Vector3 { + "x": 4622.193500574898, + "y": -4143.0893253507265, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 8`] = ` +Vector3 { + "x": 2256.79626360615, + "y": -4350.034768321036, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 9`] = ` +Vector3 { + "x": 2272.7889717356907, + "y": -4532.832258704482, + "z": 5524.556283034763, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 10`] = ` +Vector3 { + "x": 4639.651164893673, + "y": -4342.631341598372, + "z": 6005.888380734192, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 11`] = ` +Vector3 { + "x": 4639.651164893673, + "y": -4342.631341598372, + "z": 6005.888380734192, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段拉伸 12`] = ` +Vector3 { + "x": 4777.527782432507, + "y": -5918.56829139506, + "z": 5691.731196145292, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 1`] = ` +Vector3 { + "x": 4771.44810515188, + "y": -5849.077262093586, + "z": 3694.167145885469, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 2`] = ` +Vector3 { + "x": 4905.350003209006, + "y": -7379.582960325561, + "z": 3532.6838746044314, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 3`] = ` +Vector3 { + "x": 5039.251901266132, + "y": -8910.088658557535, + "z": 3371.2006033233943, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 4`] = ` +Vector3 { + "x": 5034.322858624644, + "y": -8853.749443362783, + "z": 1751.6938551264584, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 5`] = ` +Vector3 { + "x": 5029.393815983156, + "y": -8797.410228168032, + "z": 132.187106929523, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 6`] = ` +Vector3 { + "x": 4905.510413292816, + "y": -7381.416455973404, + "z": 169.1161662197635, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 7`] = ` +Vector3 { + "x": 4781.627010602477, + "y": -5965.4226837787755, + "z": 206.045225510004, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 8`] = ` +Vector3 { + "x": 4781.627010602477, + "y": -5965.4226837787755, + "z": 206.045225510004, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 9`] = ` +Vector3 { + "x": 4704.992717868391, + "y": -5089.488709643054, + "z": 1250.7720344676763, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 10`] = ` +Vector3 { + "x": 4628.358425134305, + "y": -4213.554735507332, + "z": 2295.4988434253487, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 11`] = ` +Vector3 { + "x": 4628.358425134305, + "y": -4213.554735507332, + "z": 2295.4988434253487, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 12`] = ` +Vector3 { + "x": 3442.5773443702283, + "y": -4281.794751914184, + "z": 1282.712218082731, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 13`] = ` +Vector3 { + "x": 2256.79626360615, + "y": -4350.034768321036, + "z": 269.9255927401132, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 14`] = ` +Vector3 { + "x": 2261.752779030607, + "y": -4406.687998862022, + "z": 1898.4589127575264, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 15`] = ` +Vector3 { + "x": 2266.709294455064, + "y": -4463.341229403009, + "z": 3526.992232774939, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 16`] = ` +Vector3 { + "x": 3450.140391034055, + "y": -4368.240770849953, + "z": 3767.6582816246537, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 17`] = ` +Vector3 { + "x": 4633.571487613046, + "y": -4273.140312296899, + "z": 4008.3243304743673, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 18`] = ` +Vector3 { + "x": 4633.571487613046, + "y": -4273.140312296899, + "z": 4008.324330474368, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 19`] = ` +Vector3 { + "x": 4702.509796382463, + "y": -5061.108787195242, + "z": 3851.2457381799186, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 三线段连接点拖拽 20`] = ` +Vector3 { + "x": 4771.44810515188, + "y": -5849.077262093586, + "z": 3694.167145885469, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 1`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 2`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -1270.3243319424719, + "z": -1756.964229759154, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 3`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2540.6486638849437, + "z": -1754.5919838318846, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 4`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2593.58003880636, + "z": 1763.9937876113904, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 5`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2646.5114137277756, + "z": 5282.579559054666, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 6`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -1323.2557068638878, + "z": 5229.64818413325, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 7`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": 5176.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 8`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": 5176.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 9`] = ` +Vector3 { + "x": 152.18826649869084, + "y": 0, + "z": 3926.7168092118336, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 10`] = ` +Vector3 { + "x": -1452.394394942868, + "y": 0, + "z": 2676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 11`] = ` +Vector3 { + "x": -1452.394394942868, + "y": 0, + "z": 458.6901667627053, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 12`] = ` +Vector3 { + "x": -1452.394394942868, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 13`] = ` +Vector3 { + "x": 152.1882664986906, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 中间点拖拽 14`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 1`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 2`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2540.6486638849437, + "z": -1754.5919838318846, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 3`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2646.5114137277756, + "z": 2782.5795590546654, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 4`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": 2676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 5`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": 2676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 6`] = ` +Vector3 { + "x": -3952.394394942868, + "y": 0, + "z": 2676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 7`] = ` +Vector3 { + "x": -3952.394394942868, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 二线段拉伸 8`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 1`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 2`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -1270.3243319424719, + "z": -1756.964229759154, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 3`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2540.6486638849437, + "z": -1754.5919838318846, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 4`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2593.58003880636, + "z": 513.9937876113904, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 5`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -2646.5114137277756, + "z": 2782.5795590546654, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 6`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": -1323.2557068638878, + "z": 4229.64818413325, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 7`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": 5676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 8`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": 5676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 9`] = ` +Vector3 { + "x": 152.18826649869084, + "y": 0, + "z": 4176.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 10`] = ` +Vector3 { + "x": -1452.394394942868, + "y": 0, + "z": 2676.716809211834, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 11`] = ` +Vector3 { + "x": -1452.394394942868, + "y": 0, + "z": 458.6901667627053, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 12`] = ` +Vector3 { + "x": -1452.394394942868, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 13`] = ` +Vector3 { + "x": 152.1882664986906, + "y": 0, + "z": -1759.3364756864237, +} +`; + +exports[`三维扫掠夹点拉伸及拖拽 连接点拖拽 14`] = ` +Vector3 { + "x": 1756.7709279402495, + "y": 0, + "z": -1759.3364756864237, +} +`; diff --git a/__test__/Sweep/__snapshots__/SweepSegs.test.ts.snap b/__test__/Sweep/__snapshots__/SweepSegs.test.ts.snap index d20a5fa48..ea9ce3d28 100644 --- a/__test__/Sweep/__snapshots__/SweepSegs.test.ts.snap +++ b/__test__/Sweep/__snapshots__/SweepSegs.test.ts.snap @@ -1,123 +1,123 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`顶线分段测试 不闭合多补圆弧 1`] = `7527.309534097063`; +exports[`顶线分段测试 三维顶线 1`] = `2721.682828800552`; -exports[`顶线分段测试 不闭合多补圆弧 2`] = `181.54910804222436`; +exports[`顶线分段测试 三维顶线 2`] = `4642.836785695566`; -exports[`顶线分段测试 不闭合多补圆弧 3`] = `7972.744263135363`; +exports[`顶线分段测试 三维顶线 3`] = `2721.76916405858`; -exports[`顶线分段测试 不闭合多补圆弧 4`] = `175.5593866359881`; +exports[`顶线分段测试 三维顶线 4`] = `3390.2858230567535`; -exports[`顶线分段测试 不闭合多补圆弧 5`] = `9102.21522360141`; +exports[`顶线分段测试 三维顶线 5`] = `4647.778784583921`; -exports[`顶线分段测试 不闭合多补圆弧 6`] = `174.8880833875153`; +exports[`顶线分段测试 三维顶线 6`] = `3390.392564825428`; -exports[`顶线分段测试 不闭合多补圆弧 7`] = `9850.281806459629`; +exports[`顶线分段测试 不闭合多补圆弧 1`] = `8332.345474217764`; -exports[`顶线分段测试 不闭合多补圆弧 8`] = `167.5163609665956`; +exports[`顶线分段测试 不闭合多补圆弧 2`] = `9260.51515812123`; -exports[`顶线分段测试 不闭合多补圆弧 9`] = `9201.576517258296`; +exports[`顶线分段测试 不闭合多补圆弧 3`] = `10060.210786043295`; -exports[`顶线分段测试 不闭合多补圆弧 10`] = `8466.391158009821`; +exports[`顶线分段测试 不闭合多补圆弧 4`] = `10635.124906803252`; -exports[`顶线分段测试 不闭合多补圆弧 11`] = `13771.549281343903`; +exports[`顶线分段测试 不闭合多补圆弧 5`] = `9520.046158289355`; -exports[`顶线分段测试 不闭合多补圆弧 12`] = `8903.394215503084`; +exports[`顶线分段测试 不闭合多补圆弧 6`] = `8786.945272592342`; + +exports[`顶线分段测试 不闭合多补圆弧 7`] = `13951.062223956982`; + +exports[`顶线分段测试 不闭合多补圆弧 8`] = `8598.01492440969`; exports[`顶线分段测试 不闭合直线 1`] = `1107.864406779661`; exports[`顶线分段测试 不闭合直线 2`] = `1703.186440677966`; -exports[`顶线分段测试 不闭合直线 3`] = `877.3559322033899`; +exports[`顶线分段测试 不闭合直线 3`] = `877.35593220339`; exports[`顶线分段测试 不闭合直线 4`] = `1204.7457627118647`; -exports[`顶线分段测试 不闭合直线 5`] = `760.6101694915253`; +exports[`顶线分段测试 不闭合直线 5`] = `760.6101694915254`; exports[`顶线分段测试 不闭合直线 6`] = `1341.5593220338988`; -exports[`顶线分段测试 不闭合直线 7`] = `1127.7966101694917`; - -exports[`顶线分段测试 不闭合直线圆弧 1`] = `2149.542819791226`; - -exports[`顶线分段测试 不闭合直线圆弧 2`] = `3886.6189286714807`; +exports[`顶线分段测试 不闭合直线 7`] = `1127.7966101694915`; -exports[`顶线分段测试 不闭合直线圆弧 3`] = `4288.29067911474`; +exports[`顶线分段测试 不闭合直线圆弧 1`] = `2149.0765416496856`; -exports[`顶线分段测试 不闭合直线圆弧 4`] = `2721.960193789361`; +exports[`顶线分段测试 不闭合直线圆弧 2`] = `3885.0721054475634`; -exports[`顶线分段测试 不闭合直线圆弧 5`] = `2351.778679840207`; +exports[`顶线分段测试 不闭合直线圆弧 3`] = `4290.352436993804`; -exports[`顶线分段测试 不闭合直线圆弧 6`] = `4128.24578371541`; +exports[`顶线分段测试 不闭合直线圆弧 4`] = `2720.5813805765733`; -exports[`顶线分段测试 不闭合直线圆弧2 1`] = `4393.076886867966`; +exports[`顶线分段测试 不闭合直线圆弧 5`] = `2351.778679840056`; -exports[`顶线分段测试 不闭合直线圆弧2 2`] = `6.566024064602179`; +exports[`顶线分段测试 不闭合直线圆弧 6`] = `4128.245783715364`; -exports[`顶线分段测试 不闭合直线圆弧2 3`] = `8562.229412244687`; +exports[`顶线分段测试 不闭合直线圆弧2 1`] = `4396.01934675645`; -exports[`顶线分段测试 不闭合直线圆弧2 4`] = `7775.24228697155`; +exports[`顶线分段测试 不闭合直线圆弧2 2`] = `8566.964954296875`; -exports[`顶线分段测试 不闭合直线圆弧2 5`] = `7158.345287787588`; +exports[`顶线分段测试 不闭合直线圆弧2 3`] = `7771.3839398258315`; -exports[`顶线分段测试 不闭合直线圆弧2 6`] = `11250.987271676096`; +exports[`顶线分段测试 不闭合直线圆弧2 4`] = `7152.883616395713`; -exports[`顶线分段测试 闭合圆弧 1`] = `183.06306067444856`; +exports[`顶线分段测试 不闭合直线圆弧2 5`] = `11117.77639252228`; -exports[`顶线分段测试 闭合圆弧 2`] = `5822.513453880229`; +exports[`顶线分段测试 闭合圆弧 1`] = `6933.9381077667895`; -exports[`顶线分段测试 闭合圆弧 3`] = `6427.174944008036`; +exports[`顶线分段测试 闭合圆弧 2`] = `6428.240330201794`; -exports[`顶线分段测试 闭合圆弧 4`] = `9954.439545178504`; +exports[`顶线分段测试 闭合圆弧 3`] = `9956.600010830436`; -exports[`顶线分段测试 闭合圆弧 5`] = `5190.973862843558`; +exports[`顶线分段测试 闭合圆弧 4`] = `5191.714511479803`; -exports[`顶线分段测试 闭合圆弧 6`] = `7730.577675302795`; +exports[`顶线分段测试 闭合圆弧 5`] = `7730.598935634274`; -exports[`顶线分段测试 闭合圆弧 7`] = `14243.520190228797`; +exports[`顶线分段测试 闭合圆弧 6`] = `14243.548735716871`; -exports[`顶线分段测试 闭合圆弧 8`] = `11360.440190078047`; +exports[`顶线分段测试 闭合圆弧 7`] = `11361.148377723342`; -exports[`顶线分段测试 闭合圆弧 9`] = `4713.85413305274`; +exports[`顶线分段测试 闭合圆弧 8`] = `5816.095365378227`; -exports[`顶线分段测试 闭合直线 1`] = `1411.8807330899142`; +exports[`顶线分段测试 闭合直线 1`] = `2152.655017660517`; -exports[`顶线分段测试 闭合直线 2`] = `2152.655017660556`; +exports[`顶线分段测试 闭合直线 2`] = `1157.9339062625752`; -exports[`顶线分段测试 闭合直线 3`] = `1157.9339062625943`; +exports[`顶线分段测试 闭合直线 3`] = `1049.3737454027569`; -exports[`顶线分段测试 闭合直线 4`] = `1049.373745402737`; +exports[`顶线分段测试 闭合直线 4`] = `1007.793343552591`; -exports[`顶线分段测试 闭合直线 5`] = `1007.7933435525692`; +exports[`顶线分段测试 闭合直线 5`] = `1867.3971281882955`; -exports[`顶线分段测试 闭合直线 6`] = `1867.3971281882991`; +exports[`顶线分段测试 闭合直线 6`] = `711.6950394345738`; -exports[`顶线分段测试 闭合直线 7`] = `711.6950394345639`; +exports[`顶线分段测试 闭合直线 7`] = `1109.709597624015`; -exports[`顶线分段测试 闭合直线 8`] = `1109.7095976240196`; +exports[`顶线分段测试 闭合直线 8`] = `1099.4488714706827`; -exports[`顶线分段测试 闭合直线 9`] = `1099.4488714706863`; +exports[`顶线分段测试 闭合直线 9`] = `1411.880733089909`; -exports[`顶线分段测试 闭合直线2 1`] = `2378.824808973823`; +exports[`顶线分段测试 闭合直线2 1`] = `1773.6483926638061`; -exports[`顶线分段测试 闭合直线2 2`] = `1773.6483926638098`; +exports[`顶线分段测试 闭合直线2 2`] = `1327.031499455764`; -exports[`顶线分段测试 闭合直线2 3`] = `1327.0314994557618`; +exports[`顶线分段测试 闭合直线2 3`] = `1593.058941817248`; -exports[`顶线分段测试 闭合直线2 4`] = `1593.058941817248`; +exports[`顶线分段测试 闭合直线2 4`] = `1234.7942063629357`; -exports[`顶线分段测试 闭合直线2 5`] = `1234.7942063629366`; +exports[`顶线分段测试 闭合直线2 5`] = `1657.0432133817048`; -exports[`顶线分段测试 闭合直线2 6`] = `1657.0432133817048`; +exports[`顶线分段测试 闭合直线2 6`] = `1812.9802996395224`; -exports[`顶线分段测试 闭合直线2 7`] = `1812.9802996395224`; +exports[`顶线分段测试 闭合直线2 7`] = `1366.7470210563024`; -exports[`顶线分段测试 闭合直线2 8`] = `1366.7470210563024`; +exports[`顶线分段测试 闭合直线2 8`] = `2149.6670549035985`; -exports[`顶线分段测试 闭合直线2 9`] = `2149.6670549035985`; +exports[`顶线分段测试 闭合直线2 9`] = `1980.1205315844518`; -exports[`顶线分段测试 闭合直线2 10`] = `1980.1205315844518`; +exports[`顶线分段测试 闭合直线2 10`] = `1613.0589418172476`; -exports[`顶线分段测试 闭合直线2 11`] = `1613.0589418172485`; +exports[`顶线分段测试 闭合直线2 11`] = `1665.8400676945942`; -exports[`顶线分段测试 闭合直线2 12`] = `1665.8400676945942`; +exports[`顶线分段测试 闭合直线2 12`] = `2378.8248089738245`; diff --git a/src/Add-on/BoardCutting/CuttingByFace.ts b/src/Add-on/BoardCutting/CuttingByFace.ts index e450b27dd..8fe23296b 100644 --- a/src/Add-on/BoardCutting/CuttingByFace.ts +++ b/src/Add-on/BoardCutting/CuttingByFace.ts @@ -8,7 +8,7 @@ import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Command } from "../../Editor/CommandMachine"; import { JigUtils } from "../../Editor/JigUtils"; import { PromptStatus } from "../../Editor/PromptResult"; -import { isParallelTo, YAxis } from "../../Geometry/GeUtils"; +import { YAxis, isParallelTo } from "../../Geometry/GeUtils"; import { PlaneExt } from "../../Geometry/Plane"; import { ExtrudeApplyContour, SelectExtrudeContours } from "../DrawBoard/DrawSpecialShapeBoardTool"; @@ -187,8 +187,7 @@ export class CuttingByRectFace extends CuttingByFace { let rec = new Polyline(); rec.RectangleFrom2Pt(rectRes.Point1UCS, rectRes.Point2UCS); - rec.Position = new Vector3(0, 0, rectRes.Point1UCS.z); - rec.ApplyMatrix(app.Editor.UCSMatrix); + rec.ApplyMatrix(rectRes.UCS); let map = new Map(); map.set(rec, []); diff --git a/src/Add-on/BoardCutting/LinearCutting.ts b/src/Add-on/BoardCutting/LinearCutting.ts index 7816382fa..9e04ef9ed 100644 --- a/src/Add-on/BoardCutting/LinearCutting.ts +++ b/src/Add-on/BoardCutting/LinearCutting.ts @@ -271,8 +271,7 @@ export class RectLinearCutting extends LinearCutting { let rec = new Polyline(); rec.RectangleFrom2Pt(rectRes.Point1UCS, rectRes.Point2UCS); - rec.Position = new Vector3(0, 0, rectRes.Point1UCS.z); - rec.ApplyMatrix(app.Editor.UCSMatrix); + rec.ApplyMatrix(rectRes.UCS); let pts = rec.GetStretchPoints(); pts.push(pts[0]); diff --git a/src/Add-on/CostumUCS.ts b/src/Add-on/CostumUCS.ts index cf2747254..76db1df01 100644 --- a/src/Add-on/CostumUCS.ts +++ b/src/Add-on/CostumUCS.ts @@ -3,6 +3,7 @@ import { app } from "../ApplicationServices/Application"; import { LogType } from "../Common/Log"; import { Command } from "../Editor/CommandMachine"; import { PromptPointResult, PromptStatus } from "../Editor/PromptResult"; +import { GetPointUCS } from "../Editor/UCSRAII"; import { UCSPsotion } from "../Editor/UCSServices"; import { equalv3 } from "../Geometry/GeUtils"; @@ -13,6 +14,7 @@ export class CustomUcs implements Command let p1Res = await app.Editor.GetPoint( { Msg: "请点击坐标原点或", + Raycast: true, KeyWordList: [ { key: "W", msg: "世界" }, { key: "O", msg: "图标显示在原点" }, @@ -44,15 +46,17 @@ export class CustomUcs implements Command } if (p1Res.Status !== PromptStatus.OK) return; - let mat = app.Editor.UCSMatrix; - let oldMat = mat.clone(); - mat.setPosition(p1Res.Point); - app.Editor.UCSMatrix = mat; + let oldUcs = app.Editor.UCSMatrix; + let ucsMtx = GetPointUCS(p1Res); + if (!ucsMtx) + ucsMtx = app.Editor.UCSMatrix.setPosition(p1Res.Point); + + app.Editor.UCSMatrix = ucsMtx; let xv: Vector3, yv: Vector3, zv: Vector3; while (true) { - let xRes = await app.Editor.GetPoint({ Msg: "请点击X轴方向(空格仅修改基点):", BasePoint: p1Res.Point, AllowDrawRubberBand: true, AllowNone: true }); + let xRes = await app.Editor.GetPoint({ Msg: "请点击X轴方向(空格接受当前UCS):", BasePoint: p1Res.Point, AllowDrawRubberBand: true, AllowNone: true }); if (xRes.Status === PromptStatus.None) { @@ -60,7 +64,7 @@ export class CustomUcs implements Command } else if (xRes.Status !== PromptStatus.OK) { - app.Editor.UCSMatrix = oldMat; + app.Editor.UCSMatrix = oldUcs; return; } else @@ -72,10 +76,10 @@ export class CustomUcs implements Command else { xv = xRes.Point.sub(p1Res.Point).normalize(); - zv = new Vector3().setFromMatrixColumn(mat, 2); + zv = new Vector3().setFromMatrixColumn(ucsMtx, 2); yv = zv.clone().cross(xv); - this.UpdateUCS(mat, xv, yv, zv, p1Res); + this.UpdateUCS(ucsMtx, xv, yv, zv, p1Res); break; } } @@ -100,13 +104,13 @@ export class CustomUcs implements Command yv = yRes.Point.sub(p1Res.Point).normalize(); zv = xv.clone().cross(yv); yv = zv.clone().cross(xv); - this.UpdateUCS(mat, xv, yv, zv, p1Res); + this.UpdateUCS(ucsMtx, xv, yv, zv, p1Res); break; } } else { - app.Editor.UCSMatrix = oldMat; + app.Editor.UCSMatrix = oldUcs; return; } } diff --git a/src/Add-on/DrawArc.ts b/src/Add-on/DrawArc.ts index 7ea02773b..f5f69b750 100644 --- a/src/Add-on/DrawArc.ts +++ b/src/Add-on/DrawArc.ts @@ -3,15 +3,19 @@ import { Arc } from '../DatabaseServices/Entity/Arc'; import { Command } from '../Editor/CommandMachine'; import { JigUtils } from '../Editor/JigUtils'; import { PromptStatus } from '../Editor/PromptResult'; +import { UCSUtils } from '../Editor/UCSRAII'; import { equalv3 } from '../Geometry/GeUtils'; export class DrawArc implements Command { async exec() { - let ptRes = await app.Editor.GetPoint({ Msg: "请输入第一个点:" }); + let ptRes = await app.Editor.GetPoint({ Msg: "请输入第一个点:", Raycast: true }); if (ptRes.Status != PromptStatus.OK) return; + + UCSUtils.SetUCSFromPointRes(ptRes); + let pt1 = ptRes.Point; let ptRes2 = await app.Editor.GetPoint({ Msg: "请输入第二个点:", BasePoint: pt1, AllowDrawRubberBand: true }); if (ptRes2.Status != PromptStatus.OK) @@ -41,6 +45,5 @@ export class DrawArc implements Command updateArc(ptRes3.Point); app.LayoutTool.AppendDatabaseSpace(arc); } - JigUtils.End(); } } diff --git a/src/Add-on/DrawCircle.ts b/src/Add-on/DrawCircle.ts index 117f29744..30152b8a3 100644 --- a/src/Add-on/DrawCircle.ts +++ b/src/Add-on/DrawCircle.ts @@ -12,6 +12,7 @@ import { Polyline } from '../DatabaseServices/Entity/Polyline'; import { Command } from '../Editor/CommandMachine'; import { JigUtils } from '../Editor/JigUtils'; import { PromptStatus } from '../Editor/PromptResult'; +import { UCSUtils } from '../Editor/UCSRAII'; import { angle, midPoint, polar } from '../Geometry/GeUtils'; import { IntersectOption } from '../GraphicsSystem/IntersectWith'; export class DrawCircle implements Command @@ -20,8 +21,10 @@ export class DrawCircle implements Command { let ptRes = await app.Editor.GetPoint({ Msg: "指定圆的圆心", - KeyWordList: [{ key: "3P", msg: "三点" }, { key: "2P", msg: "二点" }, { key: "T", msg: "切点、切点、半径" }, { key: "3T", msg: "三角形内切圆" }] + KeyWordList: [{ key: "3P", msg: "三点" }, { key: "2P", msg: "二点" }, { key: "T", msg: "切点、切点、半径" }, { key: "3T", msg: "三角形内切圆" }], + Raycast: true, }); + switch (ptRes.Status) { case PromptStatus.Cancel: @@ -47,7 +50,11 @@ export class DrawCircle implements Command } break; case PromptStatus.OK: - await this.DrawCircleUseRadious(ptRes.Point); //圆心半径画圆 + { + UCSUtils.SetUCSFromPointRes(ptRes); + + await this.DrawCircleUseRadious(ptRes.Point); //圆心半径画圆 + } break; default: break; @@ -99,9 +106,12 @@ export class DrawCircle implements Command } async DrawCicleUseThreePoint() { - let ptRes1 = await app.Editor.GetPoint({ Msg: "指定圆上第一个点:" }); + let ptRes1 = await app.Editor.GetPoint({ Msg: "指定圆上第一个点:", Raycast: true }); if (ptRes1.Status != PromptStatus.OK) return; + + UCSUtils.SetUCSFromPointRes(ptRes1); + let cir = new Circle(); cir.ApplyMatrix(app.Editor.UCSMatrix); let ar = new Arc(); diff --git a/src/Add-on/DrawLight/DrawRectAreaLight.ts b/src/Add-on/DrawLight/DrawRectAreaLight.ts index 011a1e346..72baf20be 100644 --- a/src/Add-on/DrawLight/DrawRectAreaLight.ts +++ b/src/Add-on/DrawLight/DrawRectAreaLight.ts @@ -1,4 +1,3 @@ -import { Matrix4, Vector3 } from "three"; import { app } from "../../ApplicationServices/Application"; import { EntityUpdateWrap } from "../../Common/EntityUpdateWrap"; import { RectAreaLight } from "../../DatabaseServices/Lights/RectAreaLight"; @@ -7,7 +6,6 @@ import { JigUtils } from "../../Editor/JigUtils"; import { PromptStatus } from "../../Editor/PromptResult"; import { userConfig } from "../../Editor/UserConfig"; import { midPoint } from "../../Geometry/GeUtils"; -import { Orbit } from "../../Geometry/Orbit"; import { BoardModalType } from "../../UI/Components/Board/BoardModalType"; import { ModalState } from "../../UI/Components/Modal/ModalInterface"; import { LightConfigModel } from "../../UI/Store/RightPanelStore/LightConfigModel"; @@ -17,36 +15,7 @@ export class DrawRectAreaLight implements Command { async exec() { - let ptRes = await app.Editor.GetPoint({ - Msg: "选择矩形光范围:", - Raycast: true - }); - if (ptRes.Status !== PromptStatus.OK) return; - - let ucsMtx: Matrix4; - let bakMtx: Matrix4; - - if (ptRes.intersection?.face?.normal) - { - let i = ptRes.intersection; - let normal = i.face.normal.clone().transformDirection(i.object.matrix).negate(); - - let x = new Vector3; - let y = new Vector3; - Orbit.ComputUpDirection(normal, y, x); - - let p = ptRes.Point; - p.sub(normal.clone().multiplyScalar(5)); - ptRes.Point = p; - - let mtx = new Matrix4().makeBasis(x, y, normal).setPosition(p); - bakMtx = app.Editor.UCSMatrix; - ucsMtx = mtx; - app.Editor.UCSMatrix = mtx; - } - - let rectRes = await app.Editor.GetRectPoint({ BasePoint: ptRes.Point, Msg: "选择矩形光范围:" }); - if (bakMtx) app.Editor.UCSMatrix = bakMtx; + let rectRes = await app.Editor.GetRectPoint({ Msg: "选择矩形光范围:" }); if (rectRes.Status !== PromptStatus.OK) return; let light = JigUtils.Draw(new RectAreaLight()); @@ -55,7 +24,7 @@ export class DrawRectAreaLight implements Command { light.Width = Math.abs(rectRes.Width); light.Height = Math.abs(rectRes.Height); - light.ApplyMatrix(ucsMtx ?? app.Editor.UCSMatrix); + light.ApplyMatrix(rectRes.UCS); light.Position = midPoint(rectRes.Point1WCS, rectRes.Point2WCS); }); diff --git a/src/Add-on/DrawLine.ts b/src/Add-on/DrawLine.ts index 818fab5eb..8406cc247 100644 --- a/src/Add-on/DrawLine.ts +++ b/src/Add-on/DrawLine.ts @@ -9,16 +9,19 @@ import { JigUtils } from '../Editor/JigUtils'; import { ObjectSnapMode } from '../Editor/ObjectSnapMode'; import { PromptStatus } from '../Editor/PromptResult'; import { SelectPick } from '../Editor/SelectPick'; +import { UCSUtils } from '../Editor/UCSRAII'; import { equalv3, ZeroVec } from '../Geometry/GeUtils'; export class DrawLine implements Command { async exec() { - let ptRes = await app.Editor.GetPoint({ Msg: "请输入第一个点:" }); + let ptRes = await app.Editor.GetPoint({ Msg: "请输入第一个点:", Raycast: true }); if (ptRes.Status !== PromptStatus.OK) return; + UCSUtils.SetUCSFromPointRes(ptRes); + let ptLast = ptRes.Point; let isTan = ptRes.SnaoMode === ObjectSnapMode.Tan; let cir: Circle | Arc; @@ -76,6 +79,7 @@ export class DrawLine implements Command AllowDrawRubberBand: true, AllowNone: true, SupportSnapPoints: pts, + Raycast: true, KeyWordList: [ { msg: "放弃", key: "U" }, { msg: "闭合", key: "C" }, @@ -129,7 +133,10 @@ export class Command_DrawXLine implements Command { async exec() { - let ptRes = await app.Editor.GetPoint({ Msg: "请输入第一个点:" }); + let ptRes = await app.Editor.GetPoint({ + Msg: "请输入第一个点:", + Raycast: true, + }); if (ptRes.Status !== PromptStatus.OK) return; @@ -151,7 +158,9 @@ export class Command_DrawXLine implements Command let pt2Res = await app.Editor.GetPoint({ BasePoint: p1, - Msg: "点击构造线的方向:", Callback: UpdateLine + Msg: "点击构造线的方向:", + Raycast: true, + Callback: UpdateLine }); if (pt2Res.Status !== PromptStatus.OK) return; diff --git a/src/Add-on/DrawPolyline.ts b/src/Add-on/DrawPolyline.ts index 821f842e7..738336b9b 100644 --- a/src/Add-on/DrawPolyline.ts +++ b/src/Add-on/DrawPolyline.ts @@ -2,11 +2,13 @@ import hotkeys from 'hotkeys-js-ext'; import { Vector2, Vector3 } from 'three'; import { app } from '../ApplicationServices/Application'; import { getCirAngleByChordAndTangent } from '../Common/CurveUtils'; +import { UpdateDraw } from '../Common/Status'; import { Polyline } from '../DatabaseServices/Entity/Polyline'; import { JigUtils } from '../Editor/JigUtils'; import { GetPointPrompt } from "../Editor/PromptOptions"; import { PromptStatus } from '../Editor/PromptResult'; -import { AsVector2, AsVector3, equalv3, isParallelTo, XAxis, ZeroVec } from '../Geometry/GeUtils'; +import { UCSUtils } from '../Editor/UCSRAII'; +import { AsVector2, AsVector3, XAxis, ZeroVec, equalv3, isParallelTo } from '../Geometry/GeUtils'; enum PolylineModel { @@ -22,7 +24,6 @@ export class DrawPolyline this.model = PolylineModel.Line; let pl = new Polyline(); - pl.ApplyMatrix(app.Editor.UCSMatrix); app.LayoutTool.AppendDatabaseSpace(pl); let plJig = JigUtils.Draw(pl); @@ -30,11 +31,20 @@ export class DrawPolyline let Callback = (p: Vector3) => this.UpdatePoint(plJig, p); - let firstOps: GetPointPrompt = { Msg: "请输入第一个点:", Callback, AllowNone: true }; + let firstOps: GetPointPrompt = { + Msg: "请输入第一个点:", + Callback, + AllowNone: true, + NotSnapZ: true, + }; let keywords = [{ msg: "圆弧", key: "A" }, { msg: "直线", key: "L" }, { msg: "放弃", key: "U" }]; let keywords2 = keywords.concat([{ msg: "闭合", key: "C" }]); - let nextOps: GetPointPrompt = { Msg: "请点击下一个点或", Callback, AllowNone: true }; - + let nextOps: GetPointPrompt = { + Msg: "请点击下一个点或", + Callback, + AllowNone: true, + NotSnapZ: true, + }; const TempUndo = () => { @@ -59,11 +69,22 @@ export class DrawPolyline nextOps.KeyWordList = keywords; } + ops.Raycast = true; + plJig.AddVertexAt(plJig.NumberOfVertices, new Vector2()); let p = await app.Editor.GetPoint(ops); if (p.Status === PromptStatus.OK) { + if (ops === firstOps) + { + let ucs = UCSUtils.SetUCSFromPointRes(p) ?? app.Editor.UCSMatrix; + pl.OCS = ucs; + plJig.OCS = ucs; + pl.Update(UpdateDraw.Matrix); + plJig.Update(UpdateDraw.Matrix); + } + //避免直接画出0长度的多段线段 if (ops === firstOps || !equalv3(p.Point, pl.EndPoint)) { diff --git a/src/Add-on/DrawRect.ts b/src/Add-on/DrawRect.ts index 2638171c0..78ea8619f 100644 --- a/src/Add-on/DrawRect.ts +++ b/src/Add-on/DrawRect.ts @@ -8,14 +8,14 @@ export class DrawRect implements Command async exec() { - let rectRes = await app.Editor.GetRectPoint(); + let rectRes = await app.Editor.GetRectPoint({}); if (rectRes.Status === PromptStatus.OK) { let rec = new Polyline(); rec.RectangleFrom2Pt(rectRes.Point1UCS, rectRes.Point2UCS); rec.Position = new Vector3(0, 0, rectRes.Point1UCS.z); - rec.ApplyMatrix(app.Editor.UCSMatrix); + rec.ApplyMatrix(rectRes.UCS); app.LayoutTool.AppendDatabaseSpace(rec); } } diff --git a/src/Add-on/DrawTopline.ts b/src/Add-on/DrawTopline.ts index d772bf28f..11e68dc8f 100644 --- a/src/Add-on/DrawTopline.ts +++ b/src/Add-on/DrawTopline.ts @@ -1,16 +1,17 @@ +import { Scene } from "three"; import { app } from "../ApplicationServices/Application"; import { curveLinkGroup } from "../Common/CurveUtils"; +import { DisposeThreeObj } from "../Common/Dispose"; import { Arc } from "../DatabaseServices/Entity/Arc"; import { Board } from "../DatabaseServices/Entity/Board"; import { Curve } from "../DatabaseServices/Entity/Curve"; import { Line } from "../DatabaseServices/Entity/Line"; import { Polyline } from "../DatabaseServices/Entity/Polyline"; +import { HardwareTopline } from "../DatabaseServices/Hardware/HardwareTopline"; import { JigUtils } from "../Editor/JigUtils"; import { PromptStatus } from "../Editor/PromptResult"; +import { equalv3 } from "../Geometry/GeUtils"; import { SurroundOutlineParse } from "../Geometry/SpaceParse/SurroundOutlineParse"; -import { HardwareTopline } from "../DatabaseServices/Hardware/HardwareTopline"; -import { Scene } from "three"; -import { DisposeThreeObj } from "../Common/Dispose"; /**构建顶线 */ export async function buildTopline(outline: Polyline, name: string) @@ -81,8 +82,13 @@ async function draw(outline: Polyline, cus: Curve[]) let group = curveLinkGroup(cus); for (let cus of group) { - let path = Polyline.Combine(cus); - let sweepSolid = new HardwareTopline(outline, path); + let curves: Curve | Curve[]; + if (cus.find((v) => cus.some(c => !equalv3(v.Normal, c.Normal)))) + curves = cus.map((v) => v.Clone()); + else + curves = Polyline.Combine(cus); + + let sweepSolid = new HardwareTopline(outline, curves); JigUtils.Draw(sweepSolid); result.push(sweepSolid); } diff --git a/src/Add-on/DrawViewport.ts b/src/Add-on/DrawViewport.ts index d2e6b7086..57d523f19 100644 --- a/src/Add-on/DrawViewport.ts +++ b/src/Add-on/DrawViewport.ts @@ -1,5 +1,5 @@ import { Intent } from "@blueprintjs/core"; -import { Vector3 } from "three"; +import { Matrix4, Vector3 } from "three"; import { app } from "../ApplicationServices/Application"; import { Sleep } from "../Common/Sleep"; import { Hole } from "../DatabaseServices/3DSolid/Hole"; @@ -23,7 +23,7 @@ import { Viewport4ConfigModal, Viewport4ConfigStore } from "./ViewortConfig/View import { ViewportConfigModal, ViewportConfigStore } from "./ViewortConfig/ViewportConfig"; import { HideEntityText } from "./Viewport/OneKeyLayout"; -async function GetViewportInfo(): Promise<{ p1: Vector3; p2: Vector3; ens: Entity[]; }> +async function GetViewportInfo(): Promise<{ p1: Vector3; p2: Vector3; ens: Entity[]; UCS: Matrix4; }> { const downStore = DownPanelStore.GetInstance(); let bak = downStore.isLayout; @@ -65,7 +65,7 @@ async function GetViewportInfo(): Promise<{ p1: Vector3; p2: Vector3; ens: Entit let p2 = rectRes.Point2UCS; let retEntitys = ens.length === 0 ? app.Database.ModelSpace.Entitys.filter(e => !e.IsErase) : ens; return { - p1, p2, ens: retEntitys + p1, p2, ens: retEntitys, UCS: rectRes.UCS }; } else if (rectRes.Status === PromptStatus.Keyword) @@ -103,7 +103,7 @@ export class DrawViewport implements Command if (data) { - const { p1, p2, ens } = data; + const { p1, p2, ens, UCS } = data; let vp = new ViewportEntity(); vp.UpdateByPts(p1, p2); @@ -116,6 +116,7 @@ export class DrawViewport implements Command vp.AppendShowObjects(ids); vp.camera.LookAt(GetViewDirection(store.m_Option.view)); vp.RenderType = store.m_Option.renderType; + vp.ApplyMatrix(UCS); app.Database.LayoutSpace.Append(vp); vp.ZoomAll(); } @@ -134,7 +135,7 @@ export class Draw4Viewport implements Command if (data) { - const { p1, p2, ens } = data; + const { p1, p2, ens, UCS } = data; AppToaster.show({ message: "正在生成布局,请稍后", timeout: 0, @@ -146,6 +147,7 @@ export class Draw4Viewport implements Command for (let v of vps) { await Sleep(0); + v.ApplyMatrix(UCS); app.Database.LayoutSpace.Append(v); v.ZoomAll(); } @@ -341,7 +343,7 @@ export class Draw2Viewport implements Command const data = await GetViewportInfo(); if (!data) return; - const { p1, p2, ens } = data; + const { p1, p2, ens, UCS } = data; let width = Math.abs(p1.x - p2.x); let height = Math.abs(p1.y - p2.y); @@ -376,6 +378,8 @@ export class Draw2Viewport implements Command vp2.camera.LookAt(GetViewDirection(store.m_Option.view2)); vp1.RenderType = store.m_Option.renderType[0]; vp2.RenderType = store.m_Option.renderType[1]; + vp1.ApplyMatrix(UCS); + vp2.ApplyMatrix(UCS); app.Database.LayoutSpace.Append(vp1); app.Database.LayoutSpace.Append(vp2); vp1.ZoomAll(); @@ -397,7 +401,7 @@ export class Draw3Viewport implements Command if (!data) return; - const { p1, p2, ens } = data; + const { p1, p2, ens, UCS } = data; let basePt = new Vector3(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y)); @@ -476,6 +480,7 @@ export class Draw3Viewport implements Command vp.AppendShowObjects(ids); vp.camera.LookAt(GetViewDirection(store.m_Option.view[i])); vp.RenderType = store.m_Option.renderType[i]; + vp.ApplyMatrix(UCS); app.Database.LayoutSpace.Append(vp); vp.ZoomAll(); await Sleep(0); diff --git a/src/Add-on/ExportData.tsx b/src/Add-on/ExportData.tsx index 10ad89099..0419f900c 100644 --- a/src/Add-on/ExportData.tsx +++ b/src/Add-on/ExportData.tsx @@ -356,7 +356,7 @@ function ConverSweep2Data(e: SweepSolid) ed.Type = "Sweep"; ed.OCS = e.OCSNoClone.toArray(); ed.Contour = Curve2Data(e.Contour); - ed.Path = Curve2Data(e.Path); + ed.Path = Array.isArray(e.Path) ? e.Path.map((v) => Curve2Data(v)) : Curve2Data(e.Path); ed.MaterialId = e.Material?.Object?.Id?.Index || 71; let roomName = e instanceof HardwareTopline ? e.HardwareOption.roomName : "未命名"; ed.RoomName = roomName; diff --git a/src/Add-on/KJL/KjlExport.ts b/src/Add-on/KJL/KjlExport.ts index 4dba45dd5..c77fd9fee 100644 --- a/src/Add-on/KJL/KjlExport.ts +++ b/src/Add-on/KJL/KjlExport.ts @@ -20,7 +20,7 @@ import { ObjectId } from "../../DatabaseServices/ObjectId"; import { PhysicalMaterialRecord } from '../../DatabaseServices/PhysicalMaterialRecord'; import { Command } from "../../Editor/CommandMachine"; import { PromptStatus } from "../../Editor/PromptResult"; -import { equalv3, GetEulerAngle } from "../../Geometry/GeUtils"; +import { GetEulerAngle, equalv3 } from "../../Geometry/GeUtils"; import { AppConfirm } from '../../UI/Components/Common/Confirm'; import { AppToaster } from "../../UI/Components/Toaster"; import { BoardType, LinesType } from "../../UI/Store/BoardInterface"; @@ -516,14 +516,32 @@ export class KjlExport implements Command let path = sw.Path; let size = sw.BoundingBoxInOCS.getSize(new Vector3); - let 轮廓 = { + //轮廓信息 + let contourData = { points: this.GetPtNumberList(contour), curves: this.GetCurveList(contour), }; - let 路径 = { - points: this.GetPtNumberList(path), - curves: this.GetCurveList(path), + let pathPoints: number[] = []; + let pathCurves: IKJLCurve[] = []; + if (Array.isArray(path)) + { + for (let subPath of path) + { + pathPoints.push(...this.GetPtNumberList(subPath)); + pathCurves.push(...this.GetCurveList(subPath)); + } + } + else + { + pathPoints = this.GetPtNumberList(path); + pathCurves = this.GetCurveList(path); + } + + //路径信息 + let pathData = { + points: pathPoints, + curves: pathCurves, }; const model: IReferenceSubModel = { @@ -557,7 +575,7 @@ export class KjlExport implements Command }, { name: "SLLJ", - value: JSON.stringify(路径) + value: JSON.stringify(pathData) }, { name: "CZ", @@ -565,7 +583,7 @@ export class KjlExport implements Command }, { name: "SLLK", - value: JSON.stringify(轮廓) + value: JSON.stringify(contourData) } ], }; diff --git a/src/Add-on/Room/DrawRectWall.ts b/src/Add-on/Room/DrawRectWall.ts index 23a31228c..7f05830fb 100644 --- a/src/Add-on/Room/DrawRectWall.ts +++ b/src/Add-on/Room/DrawRectWall.ts @@ -1,4 +1,4 @@ -import { Box3, Vector3 } from "three"; +import { Box3, Matrix4, Vector3 } from "three"; import { app } from "../../ApplicationServices/Application"; import { Draw } from "../../Common/Draw"; import { Log, LogType } from "../../Common/Log"; @@ -37,7 +37,7 @@ export class Command_DrawRectWall implements Command wall.AutoUpdate = false; }; - const UpdateDraw = (p1: Vector3, p3: Vector3, updateDraw = true) => + const UpdateDraw = (p1: Vector3, p3: Vector3, ucs: Matrix4, updateDraw = true) => { if (this._DrawDirMode !== WallDirMode.Center) { @@ -86,7 +86,6 @@ export class Command_DrawRectWall implements Command }; let p2 = new Vector3, p4 = new Vector3; - let ucs = app.Editor.UCSMatrix; while (true) { @@ -94,9 +93,9 @@ export class Command_DrawRectWall implements Command let rectRes = await app.Editor.GetRectPoint({ SupportSnapPoints: RoomWallParse._CacheWallNodePoints, - Callback: (p1, p3) => + Callback: (p1, p3, ucs) => { - UpdateDraw(p1, p3); + UpdateDraw(p1, p3, ucs); }, KeyWordList: [ ...WallModelKeyWords.filter((k, i) => i !== this._DrawDirMode), @@ -105,7 +104,7 @@ export class Command_DrawRectWall implements Command if (rectRes.Status === PromptStatus.OK) { - UpdateDraw(rectRes.Point1UCS, rectRes.Point2UCS, false); + UpdateDraw(rectRes.Point1UCS, rectRes.Point2UCS, rectRes.UCS, false); let rrd = new RoomWallRemoveDuplicate(walls, GetAllWalls());//删除重复 diff --git a/src/Add-on/Viewport/OneKeyLayout.ts b/src/Add-on/Viewport/OneKeyLayout.ts index 2be62c03f..71009c9a5 100644 --- a/src/Add-on/Viewport/OneKeyLayout.ts +++ b/src/Add-on/Viewport/OneKeyLayout.ts @@ -6,11 +6,11 @@ import { EBoardKeyList } from "../../Common/BoardKeyList"; import { IRectInfo, IsRect } from "../../Common/CurveUtils"; import { GroupEntitysByBox } from "../../Common/GroupEntitysByBox"; import { ToplineUrls } from "../../Common/HostUrl"; -import { inflateBase64 } from "../../Common/inflate"; import { KeyWord } from "../../Common/InputState"; import { PostJson, RequestStatus } from "../../Common/Request"; import { GroupFileIn } from "../../Common/SerializeMaterial"; import { Sleep } from "../../Common/Sleep"; +import { inflateBase64 } from "../../Common/inflate"; import { Hole } from "../../DatabaseServices/3DSolid/Hole"; import { SweepSolid } from "../../DatabaseServices/3DSolid/SweepSolid"; import { AlignedDimension } from "../../DatabaseServices/Dimension/AlignedDimension"; @@ -420,8 +420,8 @@ export class OneKeyLayout implements Command if (rRes.Status === PromptStatus.OK) { - p1 = rRes.Point1UCS; - p2 = rRes.Point2UCS; + p1 = rRes.Point1UCS.applyMatrix4(rRes.UCS); + p2 = rRes.Point2UCS.applyMatrix4(rRes.UCS); } else if (rRes.Status === PromptStatus.Cancel) { diff --git a/src/Add-on/testEntity/TestSweepMaxLength.ts b/src/Add-on/testEntity/TestSweepMaxLength.ts index 1c680aaca..b9e0da843 100644 --- a/src/Add-on/testEntity/TestSweepMaxLength.ts +++ b/src/Add-on/testEntity/TestSweepMaxLength.ts @@ -1,4 +1,5 @@ import { app } from "../../ApplicationServices/Application"; +import { Log } from "../../Common/Log"; import { HardwareTopline } from "../../DatabaseServices/Hardware/HardwareTopline"; import { Command } from "../../Editor/CommandMachine"; import { PromptStatus } from "../../Editor/PromptResult"; @@ -10,15 +11,29 @@ export class Command_TestSweepMaxLength implements Command { async exec() { - let enRes = await app.Editor.GetEntity({ Filter: { filterTypes: [HardwareTopline] }, Msg: "选肉" }); + let enRes = await app.Editor.GetEntity({ Filter: { filterTypes: [HardwareTopline] }, Msg: "选择一个顶线,测试它的拆单尺寸" }); if (enRes.Status !== PromptStatus.OK) return; - let br = enRes.Entity as HardwareTopline; - let b = br.Path.Clone(); - b.Erase(false); - TestDraw(b, 1); - //@ts-ignore - TestDraw(br.Contours.map(c => c.ApplyMatrix(br.OCS)), 2); - TestDraw(br.Segmentations.map(c => c.ApplyMatrix(br.OCS)), 3); - br.Erase(); + let topLine = enRes.Entity as HardwareTopline; + + Log("放样路径:红色, 轮廓:黄色, 拆单尺寸:绿色"); + + //1 绘制 path(放样路径) + if (Array.isArray(topLine.Path)) + for (let p of topLine.Path) + { + let path = p.Clone().ApplyMatrix(topLine.OCSNoClone); + path.Erase(false); + TestDraw(path, 1); + } + else + { + let path = topLine.Path.Clone().ApplyMatrix(topLine.OCSNoClone); + path.Erase(false); + TestDraw(path, 1); + } + + //2.绘制最大线段 + for (let seg of topLine.Segmentations) + TestDraw(seg.ApplyMatrix(topLine.OCSNoClone), 3); } } diff --git a/src/DatabaseServices/3DSolid/SweepSolid.ts b/src/DatabaseServices/3DSolid/SweepSolid.ts index 24b85b24d..2d9630736 100644 --- a/src/DatabaseServices/3DSolid/SweepSolid.ts +++ b/src/DatabaseServices/3DSolid/SweepSolid.ts @@ -1,14 +1,16 @@ -import { Box3, BoxBufferGeometry, BufferGeometry, Float32BufferAttribute, InstancedInterleavedBuffer, InterleavedBufferAttribute, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Line as TLine, Vector3 } from "three"; +import { Box3, BoxBufferGeometry, BufferGeometry, Float32BufferAttribute, InstancedInterleavedBuffer, InterleavedBufferAttribute, LineSegments, Matrix3, Matrix4, Mesh, Object3D, Shape, Line as TLine, Vector2, Vector3 } from "three"; import { Line2 } from "three/examples/jsm/lines/Line2"; import { LineGeometry } from "three/examples/jsm/lines/LineGeometry"; import { arrayRemoveDuplicateBySort } from "../../Common/ArrayExt"; import { ColorMaterial } from '../../Common/ColorPalette'; +import { curveLinkGroup } from "../../Common/CurveUtils"; import { DisposeThreeObj, Object3DRemoveAll } from '../../Common/Dispose'; import { Log, LogType } from "../../Common/Log"; import { tempMatrix1 } from "../../Common/Matrix4Utils"; import { UpdateDraw } from "../../Common/Status"; +import { FixIndex } from "../../Common/Utils"; import { ObjectSnapMode } from "../../Editor/ObjectSnapMode"; -import { AsVector3, MoveMatrix, equaln, equalv3, isParallelTo } from '../../Geometry/GeUtils'; +import { AsVector3, MoveMatrix, ZAxis, ZeroVec, equaln, equalv2, equalv3, isParallelTo } from '../../Geometry/GeUtils'; import { ProjectionToPlane, SweepGeometry } from '../../Geometry/SweepGeometry'; import { RenderType } from "../../GraphicsSystem/RenderType"; import { Factory } from "../CADFactory"; @@ -25,9 +27,9 @@ export class SweepSolid extends Entity { static UseRectFakerContour = false; - private _Contour: Polyline; - private _PathCurve: Curve; - constructor(contour?: Polyline, pathCurve?: Curve) + protected _Contour: Polyline; + protected _PathCurve: Curve | Curve[]; + constructor(contour?: Polyline, pathCurve?: Curve | Curve[]) { super(); this._Contour = contour; @@ -39,15 +41,32 @@ export class SweepSolid extends Entity if (this._Contour && this._PathCurve) { this.TransfromPathToWCS(); - this.OCS = this._PathCurve.OCS; - this._SpaceOCS.copy(this._PathCurve.OCS); - this._PathCurve.ApplyMatrix(this._PathCurve.OCSInv); + + //将OCS变换成第一个路径的OCS(合理一点) + let paths = this.Paths; + let path = paths[0]; + + this.OCS = path.OCSNoClone; + this._SpaceOCS.copy(path.OCSNoClone); + + let ocsInv = this.OCSInv; + for (let p of paths) + p.ApplyMatrix(ocsInv); } } Explode() { - return [this._Contour.Clone(), this._PathCurve.Clone()]; + if (Array.isArray(this._PathCurve)) + { + const explode: Curve[] = [this._Contour.Clone().ApplyMatrix(this._Matrix)]; + for (let path of this._PathCurve) + { + explode.push(path.Clone().ApplyMatrix(this._Matrix)); + } + return explode; + } + return [this._Contour.Clone().ApplyMatrix(this._Matrix), this._PathCurve.Clone().ApplyMatrix(this._Matrix)]; } get Contour() @@ -58,10 +77,23 @@ export class SweepSolid extends Entity { return this._PathCurve; } + + //单纯的返回数组 + get Paths() + { + return Array.isArray(this._PathCurve) ? this._PathCurve : [this._PathCurve]; + } + Reverse() { this.WriteAllObjectRecord(); - this._PathCurve.Reverse(); + if (Array.isArray(this._PathCurve)) + { + for (let path of this._PathCurve) + path.Reverse(); + this._PathCurve.reverse(); + } + else this._PathCurve.Reverse(); this.Update(); } @@ -70,7 +102,8 @@ export class SweepSolid extends Entity */ private TransfromPathToWCS() { - if (equalv3(this._Contour.Normal, new Vector3(0, 0, 1))) + if (Array.isArray(this._PathCurve)) return; + if (equalv3(this._Contour.Normal, ZAxis)) return; let fDir = this._PathCurve.GetFistDeriv(0); @@ -128,6 +161,7 @@ export class SweepSolid extends Entity } Log("错误:提供的轮廓没有和路径垂直!", LogType.Error); } + private _MeshGeometry: SweepGeometry; private _lineGeo: LineGeometry; get MeshGeometry() @@ -175,7 +209,21 @@ export class SweepSolid extends Entity InitDrawObject(renderType: RenderType): Object3D { if (renderType === RenderType.Wireframe || renderType === RenderType.Edge) - return new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + { + let line = new LineSegments(this.EdgeGeometry, ColorMaterial.GetLineMaterial(this.ColorIndex)); + + // for (let p of this.Paths) + // { + // p.IsEmbedEntity = true; + // let lineObj = p.GetDrawObjectFromRenderType(RenderType.Wireframe) as TLine; + // lineObj.material = ColorMaterial.GetWallLineMtl(1); + // lineObj.computeLineDistances(); + // lineObj.matrix.copy(p.OCSNoClone); + // line.add(lineObj); + // } + + return line; + } else if (renderType === RenderType.Conceptual) { return new Object3D().add( @@ -195,6 +243,13 @@ export class SweepSolid extends Entity } else if (renderType === RenderType.Jig) { + if (Array.isArray(this._PathCurve)) + { + const object3d = new Object3D(); + for (let path of this._PathCurve) + object3d.add(path.DrawObject); + return object3d; + } return new Object3D().add(this._PathCurve.DrawObject); } else if (renderType === RenderType.Physical2) @@ -220,6 +275,16 @@ export class SweepSolid extends Entity let l = obj as LineSegments; l.geometry = this.EdgeGeometry; l.material = ColorMaterial.GetLineMaterial(this.ColorIndex); + + // Object3DRemoveAll(l); + // for (let p of this.Paths) + // { + // p.IsEmbedEntity = true; + // let lineObj = p.GetDrawObjectFromRenderType(RenderType.Wireframe) as TLine; + // lineObj.material = ColorMaterial.GetWallLineMtl(1); + // lineObj.computeLineDistances(); + // l.add(lineObj); + // } } else if (renderType === RenderType.Conceptual) { @@ -238,7 +303,11 @@ export class SweepSolid extends Entity else if (renderType === RenderType.Jig) { Object3DRemoveAll(obj); - obj.add((this._PathCurve.DrawObject)); + if (Array.isArray(this._PathCurve)) + for (let path of this._PathCurve) + obj.add(path.DrawObject); + else + obj.add((this._PathCurve.DrawObject)); } else if (renderType === RenderType.Physical2) { @@ -311,12 +380,29 @@ export class SweepSolid extends Entity case ObjectSnapMode.Per: case ObjectSnapMode.Tan: { - let contour = this._PathCurve.Clone(); - contour.ApplyMatrix(this.OCS); - let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform); - if (snapMode === ObjectSnapMode.Mid) - return [...pts, ...this.GetMidPoints()]; - return pts; + if (Array.isArray(this._PathCurve)) + { + const points: Vector3[] = []; + for (let path of this._PathCurve) + { + let contour = path.Clone(); + contour.ApplyMatrix(this.OCS); + let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform); + if (snapMode === ObjectSnapMode.Mid) + points.push(...pts, ...this.GetMidPoints()); + else points.push(...pts); + } + return points; + } + else + { + let contour = this._PathCurve.Clone(); + contour.ApplyMatrix(this.OCS); + let pts = contour.GetObjectSnapPoints(snapMode, pickPoint, lastPoint, viewXform); + if (snapMode === ObjectSnapMode.Mid) + return [...pts, ...this.GetMidPoints()]; + return pts; + } } default: break; @@ -324,68 +410,154 @@ export class SweepSolid extends Entity return []; } - GetGripPoints() + //缓存夹点和子实体的索引 + private _GripSubIndexMap: Map; + /** 获取夹点与子实体的索引 */ + GetGripSubIndexMap() { - let pts = this._PathCurve.GetGripPoints(); - for (let p of pts) - p.applyMatrix4(this._Matrix); - return pts; + if (this._GripSubIndexMap) + return this._GripSubIndexMap; + + this.GetGripPoints(); + + return this._GripSubIndexMap; } - GetStretchPoints() + + GetGripPoints() { - let pts = this._PathCurve.GetStretchPoints(); - for (let p of pts) - p.applyMatrix4(this._Matrix); - return pts; + this._GripSubIndexMap = undefined; + + if (Array.isArray(this._PathCurve)) + { + this._GripSubIndexMap = new Map; + + const points: Vector3[] = []; + for (let path of this._PathCurve) + { + let pts = path.GetGripPoints(); + for (let p of pts) + { + this._GripSubIndexMap.set(points.length, path); + + p.applyMatrix4(this._Matrix); + points.push(p); + } + } + return points; + } + else + { + let pts = this._PathCurve.GetGripPoints(); + for (let p of pts) + p.applyMatrix4(this._Matrix); + return pts; + } } - private UpdateEndMtx(dir: Vector3, pos: Vector3) + + GetStretchPoints() { - let y = this.Normal; - let roMat = new Matrix4().extractRotation(this.OCS); - let z = dir.applyMatrix4(roMat); - let x = z.clone().cross(y); - tempMatrix1.makeBasis(x, y, z); - tempMatrix1.setPosition(pos.applyMatrix4(this.OCS)); + if (Array.isArray(this._PathCurve)) + { + const points: Vector3[] = []; + for (let path of this._PathCurve) + { + let pts = path.GetStretchPoints(); + for (let p of pts) + { + p.applyMatrix4(this._Matrix); + points.push(p); + } + } + return points; + } + else + { + let pts = this._PathCurve.GetStretchPoints(); + for (let p of pts) + p.applyMatrix4(this._Matrix); + return pts; + } } //端点捕捉时提供端点 private GetEndPoint() { + let pathPts: Vector3[] = []; + let pathNormals: Vector3[] = []; //路径点表 - let pathPts2d = this._PathCurve.Shape.getPoints(4); - let pathPts = pathPts2d.map(AsVector3); - arrayRemoveDuplicateBySort(pathPts, equalv3); + if (Array.isArray(this._PathCurve)) + { + for (let path of this._PathCurve) + { + let pathPts2d = path.Shape.getPoints(4) as Vector2[]; + arrayRemoveDuplicateBySort(pathPts2d, (p1, p2) => + { + if (equalv2(p1, p2)) + { + p2["_mask_"] = p1["_mask_"]; + return true; + } + return false; + }); + + if (path !== this._PathCurve[0]) + pathPts2d.shift(); - for (let p of pathPts) - p.applyMatrix4(this._PathCurve.OCS); + let pNormal = path.Normal; + + for (let p of pathPts2d) + { + let p3 = AsVector3(p).applyMatrix4(path.OCSNoClone); + p3["_mask_"] = p["_mask_"]; + pathPts.push(p3); + pathNormals.push(pNormal); + } + } + } + else + { + const path = this._PathCurve; + //路径点表 + let pathPts2d = (path.Shape as Shape).getPoints(4); + pathPts = pathPts2d.map(AsVector3); + arrayRemoveDuplicateBySort(pathPts, equalv3); + let pNormal = path.Normal; + for (let p of pathPts) + { + p.applyMatrix4(path.OCSNoClone); + pathNormals.push(pNormal); + } + } let shapePts2d = this.Contour.Shape.getPoints(4); - // if (!ShapeUtils.isClockWise(shapePts2d)) shapePts2d.reverse(); //轮廓点表 let shapePts3d = shapePts2d.map(AsVector3); - + let isClosePath = equalv3(pathPts[0], pathPts[pathPts.length - 1], 1e-3); for (let p of shapePts3d) p.applyMatrix4(this.Contour.OCSNoClone); let pts: Vector3[] = [];//端点 - //遍历路径节点 + // arrayPushArray(pts, pathPts); + + //遍历所有的路径节点进行顶点投射 for (let i = 1; i < pathPts.length; i++) { if (i === pathPts.length - 1) { - if (this._PathCurve.IsClose) - pts.push(...ProjectionToPlane(shapePts3d, this._PathCurve.Normal, pathPts[i], pathPts[i - 1], pathPts[1])); + if (isClosePath) + pts.push(...ProjectionToPlane(shapePts3d, pathNormals[i], pathPts[i], pathPts[i - 1], pathPts[1])); else - pts.push(...ProjectionToPlane(shapePts3d, this._PathCurve.Normal, pathPts[i], pathPts[i - 1])); + pts.push(...ProjectionToPlane(shapePts3d, pathNormals[i], pathPts[i], pathPts[i - 1])); } else - pts.push(...ProjectionToPlane(shapePts3d, this._PathCurve.Normal, pathPts[i], pathPts[i - 1], pathPts[i + 1])); + { + pts.push(...ProjectionToPlane(shapePts3d, pathNormals[i], pathPts[i], pathPts[i - 1], pathPts[i + 1])); + } } - for (let p of pts) p.applyMatrix4(this.OCSNoClone); - + for (let pt of pts) pt.applyMatrix4(this.OCSNoClone); return pts; } @@ -393,49 +565,204 @@ export class SweepSolid extends Entity { let conPts = this._Contour.GetStretchPoints(); const pts: Vector3[] = []; - - for (let i = 0.5; i < this._PathCurve.EndParam; i++) + const UpdateEndMtx = (path: Curve) => { - let p = this._PathCurve.GetPointAtParam(i); - let d1 = this._PathCurve.GetFistDeriv(i).normalize(); - this.UpdateEndMtx(d1, p); - pts.push(...conPts.map(p => p.clone().applyMatrix4(tempMatrix1))); - } + for (let i = 0.5; i < path.EndParam; i++) + { + let pos = path.GetPointAtParam(i); + let dir = path.GetFistDeriv(i).normalize(); + let y = path.Normal; + let roMat = new Matrix4().extractRotation(this.OCS); + let z = dir.applyMatrix4(roMat); + let x = z.clone().cross(y); + tempMatrix1.makeBasis(x, y, z); + tempMatrix1.setPosition(pos.applyMatrix4(this.OCS)); + pts.push(...conPts.map(p => p.clone().applyMatrix4(tempMatrix1))); + } + }; + if (Array.isArray(this._PathCurve)) + for (let path of this._PathCurve) + UpdateEndMtx(path); + else + UpdateEndMtx(this._PathCurve); return pts; - } + MoveGripPoints(indexList: number[], vec: Vector3) { + if (equalv3(vec, ZeroVec)) return; + this.WriteAllObjectRecord(); - this.IfPathIsLineThenZ0Vector(vec); + vec = vec.clone().applyMatrix4(this.OCSInv.setPosition(0, 0, 0)); - this._PathCurve.MoveGripPoints(indexList, - vec.clone().applyMatrix4(new Matrix4().extractRotation(this.OCSInv))); - this.Update(); - } + if (Array.isArray(this._PathCurve)) + { + let ptsLengths = 0; + for (let i = 0; i < this._PathCurve.length; i += 1) + { + const path = this._PathCurve[i]; + const pathGripPts = path.GetGripPoints(); + const idxList = indexList.filter(v => v >= ptsLengths && v < (ptsLengths + pathGripPts.length)).map((v) => v - ptsLengths); - //如果路径是直线,我们在这里避免vec传递z轴信息 - private IfPathIsLineThenZ0Vector(vec: Vector3) - { - if (this._PathCurve instanceof Line) + ptsLengths += pathGripPts.length; + + if (idxList.length === 0) continue; + + let isMoveLine = (path instanceof Line && idxList.length === 1 && idxList[0] === 1); + let isMovePolylineStart = (path instanceof Polyline) && idxList.length === 1 && idxList.includes(1); + let isMovePolylineEnd = (path instanceof Polyline) && idxList.length === 1 && idxList.includes(pathGripPts.length - 2); + + //如果不是整体移动,那么vec被限制在CURVE OCS Z0 + let isMove = isMoveLine || idxList.length === pathGripPts.length; + if (!isMove) + { + vec = vec.clone() + .applyMatrix4(path.OCSInv.setPosition(0, 0, 0)) + .setZ(0) + .applyMatrix4(path.OCS.setPosition(0, 0, 0)); + } + + //我们校验它的前后曲线支不支持它移动这个点 + let prePath = this._PathCurve[FixIndex(i - 1, this._PathCurve)]; + let nextPath = this._PathCurve[FixIndex(i + 1, this._PathCurve)]; + + if ((isMoveLine || idxList.includes(0) || isMovePolylineStart)//(move line ) or (move start) or(move pl start) + && (i || equalv3(prePath.EndPoint, path.StartPoint, 1e-3)))//连接到下一段 + { + //vec限制在上一段的坐标系内 无z + vec = vec.clone() + .applyMatrix4(prePath.OCSInv.setPosition(0, 0, 0)) + .setZ(0) + .applyMatrix4(prePath.OCS.setPosition(0, 0, 0)); + + if (isMoveLine || isMovePolylineStart)//顺带移动上一段 + prePath.MoveGripPoints([prePath.GetGripPoints().length - 1], vec); + + } + if ((isMoveLine || idxList.includes(pathGripPts.length - 1) || isMovePolylineEnd)//(move line ) or (move end) or(move pl end) + && (i < this._PathCurve.length - 2 || equalv3(path.EndPoint, nextPath.StartPoint, 1e-3)))//连接到上一段 + { + //vec限制在下一段的坐标系内 无z + vec = vec.clone() + .applyMatrix4(nextPath.OCSInv.setPosition(0, 0, 0)) + .setZ(0) + .applyMatrix4(nextPath.OCS.setPosition(0, 0, 0)); + + if (isMoveLine || isMovePolylineEnd)//顺带移动下一段 + nextPath.MoveGripPoints([0], vec); + } + + if (isMove) + path.Move(vec); + else + path.MoveGripPoints(idxList, vec); + } + } + else { - let ocsinv = this._PathCurve.OCSInv.setPosition(0, 0, 0); - vec.applyMatrix4(ocsinv).setZ(0); - vec.applyMatrix4(this._PathCurve.OCSNoClone); + this._PathCurve.MoveGripPoints(indexList, vec); } + this.Update(); } MoveStretchPoints(indexList: number[], vec: Vector3) { + if (equalv3(vec, ZeroVec)) return; + this.WriteAllObjectRecord(); - this.IfPathIsLineThenZ0Vector(vec); + vec = vec.clone().applyMatrix4(this.OCSInv.setPosition(0, 0, 0)); + + if (Array.isArray(this._PathCurve)) + { + let ptsLengths = 0; + let pathIndexMap = new Map(); + + //1.parse + for (let i = 0; i < this._PathCurve.length; i++) + { + let path = this._PathCurve[i]; + const pts = path.GetStretchPoints(); + const idxList = indexList.filter(v => v >= ptsLengths && v < (ptsLengths + pts.length)).map((v) => v - ptsLengths); + + ptsLengths += pts.length; + + pathIndexMap.set(path, { + idx: idxList, + count: pts.length, + isMove: pts.length === idxList.length, + }); + } + + //2.change vec + for (let i = 0; i < this._PathCurve.length; i++) + { + let path = this._PathCurve[i]; + let { idx: idxList, count: ptsCount, isMove } = pathIndexMap.get(path); + + if (idxList.length === 0) continue; + + let isMoveStart = idxList.includes(0); + let isMoveEnd = idxList.includes(ptsCount - 1); + + if (!isMove)//如果不是移动 限制在本OCS内 NO Z + { + vec.applyMatrix4(path.OCSInv.setPosition(0, 0, 0)) + .setZ(0) + .applyMatrix4(path.OCS.setPosition(0, 0, 0)); + } + + //我们校验它的前后曲线支不支持它移动这个点 + let prePath = this._PathCurve[FixIndex(i - 1, this._PathCurve)]; + let nextPath = this._PathCurve[FixIndex(i + 1, this._PathCurve)]; + + //如果pre是move 则不需要过滤z + if ((isMove || isMoveStart)//(move line ) or (move start) or(move pl start) + && (i || equalv3(prePath.EndPoint, path.StartPoint, 1e-3))//连接到下一段 + && (!pathIndexMap.get(prePath).isMove)//非移动 + ) + { + //vec限制在上一段的坐标系内 无z + vec.applyMatrix4(prePath.OCSInv.setPosition(0, 0, 0)) + .setZ(0) + .applyMatrix4(prePath.OCS.setPosition(0, 0, 0)); + } + if ( + isMove || isMoveEnd + && (i < this._PathCurve.length - 2 || equalv3(path.EndPoint, nextPath.StartPoint, 1e-3))//连接到上一段 + && (!pathIndexMap.get(nextPath).isMove)//非移动 + ) + { + //vec限制在下一段的坐标系内 无z + vec.applyMatrix4(nextPath.OCSInv.setPosition(0, 0, 0)) + .setZ(0) + .applyMatrix4(nextPath.OCS.setPosition(0, 0, 0)); + } + } - this._PathCurve.MoveStretchPoints(indexList, - vec.clone().applyMatrix4(new Matrix4().extractRotation(this.OCSInv))); + //3 move + for (let i = 0; i < this._PathCurve.length; i++) + { + let path = this._PathCurve[i]; + let { idx: idxList, isMove } = pathIndexMap.get(path); + if (isMove) + path.Move(vec); + else + path.MoveStretchPoints(idxList, vec); + } + } + else + { + this._PathCurve.MoveStretchPoints(indexList, vec); + } this.Update(); } + ApplyMatrix(m: Matrix4) { this.WriteAllObjectRecord(); @@ -467,37 +794,67 @@ export class SweepSolid extends Entity this._Matrix.multiplyMatrices(m, this._Matrix); return this; } + let ocsInv = this.OCSInv; - this._PathCurve.ApplyMatrix(this.OCS).ApplyMatrix(m).ApplyMatrix(ocsInv); + if (Array.isArray(this._PathCurve)) + { + for (let p of this._PathCurve) + p.ApplyMatrix(this.OCSNoClone).ApplyMatrix(m).ApplyMatrix(ocsInv); - let mtx = this._PathCurve.OCS; - let mtxInv = new Matrix4().getInverse(mtx); - this._PathCurve.ApplyMatrix(mtxInv); - this._SpaceOCS.copy(this._Matrix); - this._Matrix.multiplyMatrices(this._Matrix, mtx); + let group = curveLinkGroup(this._PathCurve); + this._PathCurve = group[0]; + } + else + this._PathCurve.ApplyMatrix(this.OCSNoClone).ApplyMatrix(m).ApplyMatrix(ocsInv); this.Update(UpdateDraw.Geometry); return this; } + protected _ReadFile(file: CADFiler) { super._ReadFile(file); - let ver = file.Read();//1 + let ver = file.Read();//ver this._Contour = file.ReadObject() as Polyline; - this._PathCurve = file.ReadObject() as Curve; - - if (this._Contour instanceof Spline || this._PathCurve instanceof Spline) + if (ver === 1) { - this._isErase = true; - Log("放样实体是样条线生成的,自动删除它!", LogType.Info); + this._PathCurve = file.ReadObject() as Curve; + if (this._Contour instanceof Spline || this._PathCurve instanceof Spline) + { + this._isErase = true; + Log("放样实体是样条线生成的,自动删除它!", LogType.Info); + } + } + else if (ver > 1) + { + const pathCurveCount = file.Read(); + if (pathCurveCount === 1) + this._PathCurve = file.ReadObject() as Curve; + else + { + this._PathCurve = []; + for (let i = 0; i < pathCurveCount; i++) + { + this._PathCurve.push(file.ReadObject()); + } + } } - } WriteFile(file: CADFiler) { super.WriteFile(file); - file.Write(1);//ver + file.Write(2);//ver file.WriteObject(this._Contour); - file.WriteObject(this._PathCurve); + if (Array.isArray(this._PathCurve)) + { + file.Write(this._PathCurve.length); + for (let c of this._PathCurve) + file.WriteObject(c); + } + else + { + file.Write(1); + file.WriteObject(this._PathCurve); + } } } diff --git a/src/DatabaseServices/Entity/Line.ts b/src/DatabaseServices/Entity/Line.ts index fd1fed368..e7101cbcd 100644 --- a/src/DatabaseServices/Entity/Line.ts +++ b/src/DatabaseServices/Entity/Line.ts @@ -1,4 +1,4 @@ -import { Box3, BufferGeometry, Line as TLine, Line3, Matrix3, Matrix4, Object3D, Shape, Vector3 } from 'three'; +import { Box3, BufferGeometry, Line3, Matrix3, Matrix4, Object3D, Shape, Line as TLine, Vector3 } from 'three'; import { Line2 } from 'three/examples/jsm/lines/Line2'; import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'; import { ColorMaterial } from '../../Common/ColorPalette'; @@ -7,7 +7,7 @@ import { Status } from '../../Common/Status'; import { ObjectSnapMode } from '../../Editor/ObjectSnapMode'; import { Box3Ext } from '../../Geometry/Box'; import { BufferGeometryUtils } from '../../Geometry/BufferGeometryUtils'; -import { AsVector2, equaln, equalv3, isParallelTo, MoveMatrix, updateGeometry } from '../../Geometry/GeUtils'; +import { AsVector2, MoveMatrix, equaln, equalv3, isParallelTo, updateGeometry } from '../../Geometry/GeUtils'; import { PlaneExt } from '../../Geometry/Plane'; import { ROTATE_MTX2 } from '../../Geometry/RotateUV'; import { IntersectEllipseAndLine, IntersectLineAndArc, IntersectLineAndCircle, IntersectLineAndLine, IntersectOption, IntersectPolylineAndCurve, IntersectResult, reverseIntersectOption } from '../../GraphicsSystem/IntersectWith'; @@ -402,7 +402,7 @@ export class Line extends Curve return this; } - GetOffsetCurves(offsetDist: number): Array + GetOffsetCurves(offsetDist: number): Array { let offset = this._EndPoint.clone().sub(this._StartPoint).normalize().multiplyScalar(offsetDist); ROTATE_MTX2.applyVector(offset); diff --git a/src/DatabaseServices/Entity/Polyline.ts b/src/DatabaseServices/Entity/Polyline.ts index d12ab1aa8..78b0cea8a 100644 --- a/src/DatabaseServices/Entity/Polyline.ts +++ b/src/DatabaseServices/Entity/Polyline.ts @@ -1207,9 +1207,9 @@ export class Polyline extends Curve /** * 分解 */ - Explode(): Curve[] + Explode(): (Line | Arc)[] { - let exportCus: Curve[] = []; + let exportCus: (Line | Arc)[] = []; for (let i = 0; i < this.EndParam; i++) { exportCus.push(this.GetCurveAtIndex(i)); @@ -1257,7 +1257,7 @@ export class Polyline extends Curve * 获得曲线,来自索引位置. * @param {number} i 索引位置 整数 */ - GetCurveAtIndex(i: number): Curve + GetCurveAtIndex(i: number): Line | Arc { if (i >= this._LineData.length) return undefined; @@ -1268,7 +1268,7 @@ export class Polyline extends Curve let d1 = this._LineData[i]; let d2 = this._LineData[FixIndex(i + 1, this._LineData)]; - let curve: Curve; + let curve: Line | Arc; if (equaln(d1.bul, 0, BUL_IS_LINE_FUZZ)) curve = new Line(AsVector3(d1.pt), AsVector3(d2.pt)).ApplyMatrix(this.OCSNoClone); else diff --git a/src/DatabaseServices/Hardware/HardwareTopline.ts b/src/DatabaseServices/Hardware/HardwareTopline.ts index 07bf10b73..9495f17f8 100644 --- a/src/DatabaseServices/Hardware/HardwareTopline.ts +++ b/src/DatabaseServices/Hardware/HardwareTopline.ts @@ -1,15 +1,15 @@ -import { Matrix4 } from "three"; -import { arrayRemoveIf } from "../../Common/ArrayExt"; -import { GetPointAtCurveDir } from "../../Common/CurveUtils"; +import { Matrix4, Vector3 } from "three"; +import { FixIndex } from "../../Common/Utils"; import { DefaultToplineMetalsOption } from "../../Editor/DefaultConfig"; -import { equaln, isPerpendicularityTo, rotatePoint, ZAxis } from "../../Geometry/GeUtils"; -import { IntersectOption } from "../../GraphicsSystem/IntersectWith"; -import { FixIndex } from "../../Nest/Common/Util"; +import { AsVector3, ZeroVec, equalv3 } from "../../Geometry/GeUtils"; +import { ProjectionToPlane } from "../../Geometry/SweepGeometry"; +import { Max } from "../../Nest/Common/Util"; import { IToplineOption } from "../../UI/Components/RightPanel/RightPanelInterface"; -import { SweepSolid } from '../3DSolid/SweepSolid'; +import { SweepSolid } from "../3DSolid/SweepSolid"; import { AutoRecord, AutoRecordObject } from "../AutoRecord"; import { Factory } from "../CADFactory"; import { CADFiler } from "../CADFiler"; +import { Arc } from "../Entity/Arc"; import { Curve } from "../Entity/Curve"; import { Line } from "../Entity/Line"; import { Polyline } from "../Entity/Polyline"; @@ -24,193 +24,112 @@ export class HardwareTopline extends SweepSolid { return this._contourRotation; } - private _ContourWidth: number; - private get Contours(): Curve[] - { - let c = this.Path; - let conBox = this.Contour.BoundingBox; - let cMin = conBox.min; - let cMax = conBox.max; - let y = ZAxis; - let z = c.GetFistDeriv(0).normalize(); - let x = z.clone().cross(y); - let mat = new Matrix4().makeBasis(x, y, z); - mat.setPosition(c.StartPoint); - [cMin, cMax].forEach(p => p.applyMatrix4(mat).setZ(0)); - - let firstCurve: Curve; - if (c instanceof Polyline) - firstCurve = c.GetCurveAtParam(0); - else - firstCurve = c; - - let closePt = firstCurve.GetClosestPointTo(cMin, false); - let offset = cMin.distanceTo(closePt); - let dir = GetPointAtCurveDir(firstCurve, cMin); - let cus = this.Path.GetOffsetCurves(offset * dir); - let l1 = cus[0] ?? this.Path.Clone(); - closePt = firstCurve.GetClosestPointTo(cMax, false); - let offset2 = cMax.distanceTo(closePt); - dir = GetPointAtCurveDir(firstCurve, cMax); - cus = this.Path.GetOffsetCurves(offset2 * dir); - let l2 = cus[0] ?? this.Path.Clone(); - - this._ContourWidth = offset + offset2; - return [l1, l2]; - } /** *延伸取最大最小轮廓每段首尾到前面线段,取最长线段作为分段长 - * */ get Segmentations(): Curve[] { - const [l1, l2] = this.Contours; - if (!(l1 instanceof Polyline)) - return [l1]; - - let cus1 = l1.Explode() as Curve[]; - let cus2 = l2.Explode() as Curve[]; - - [cus1, cus2] = cus1.length < cus2.length ? [cus2, cus1] : [cus1, cus2]; - - let sgs: Curve[] = []; - - const AddSgs = (c1: Curve, c2: Curve) => + //轮廓点表 + let contourPts = this._Contour.Shape.getPoints(4).map(AsVector3); + for (let p of contourPts) + p.applyMatrix4(this._Contour.OCSNoClone); + + //收集所有的点 + let pathCurves: (Line | Arc)[] = []; + if (Array.isArray(this._PathCurve)) { - sgs.push(c1.Length > c2.Length ? c1 : c2); - }; - - const ExtendCurve = (c: Curve, refC: Curve, isPre) => - { - let pts = c.IntersectWith2(refC, IntersectOption.ExtendBoth).filter(r => + for (let p of this._PathCurve) { - if (isPre) - return r.thisParam < 0; + if (p instanceof Polyline) + pathCurves.push(...p.Explode() as Line[]); else - return r.thisParam > 1; - }); - if (isPre) - { - pts.sort((r1, r2) => r2.thisParam - r1.thisParam); - if (pts.length > 0 && pts[0].thisParam < 0) - c.Extend(pts[0].thisParam); + pathCurves.push(p.Clone() as Line); } + } + else + if (this._PathCurve instanceof Polyline) + pathCurves.push(...this._PathCurve.Explode() as Line[]); else - { - pts.sort((r1, r2) => r1.thisParam - r2.thisParam); - if (pts.length > 0 && pts[0].thisParam > 1) - c.Extend(pts[0].thisParam); - } - }; - const IsNoRelativeCurve = (c1: Curve, c2: Curve) => - { - if ((c1 instanceof Line) !== (c2 instanceof Line)) - return true; + pathCurves.push(this._PathCurve.Clone() as Line); - let midPt = c1.GetPointAtParam(0.5); - let closePt = c2.GetClosestPointTo(midPt, false); - return !closePt || !equaln(midPt.distanceTo(closePt), this._ContourWidth, 1e-3); - }; - const HasRelativeCurveAndChange = (target: Curve, cs: Curve[], isChange = false) => - { - let index = cs.findIndex(c => !IsNoRelativeCurve(c, target)); - if (index !== -1) - { - if (isChange && l1.IsClose) - cs.unshift(...cs.splice(index)); - return true; - } - return false; - }; + let isClosePath = equalv3(pathCurves[0].StartPoint, pathCurves[pathCurves.length - 1].EndPoint, 1e-3); - if (cus1.length !== cus2.length) - arrayRemoveIf(cus2, c => !HasRelativeCurveAndChange(c, cus1)); + let radiusMap = new Map(); - for (let i = 0; i < cus1.length; i++) + function ExtendsCurve(path: Curve, pts: Vector3[]) { - let c1 = cus1[i]; - let c2 = cus2[i]; + let params = pts.map(p => path.GetParamAtPoint2(path.GetClosestPointTo(p, true))); - if (cus1.length !== cus2.length) - { - if (IsNoRelativeCurve(c1, c2)) - { - sgs.push(c1); - cus1.splice(i, 1); - i--; - continue; - } - } - else - { - //第一段验证是否是关联段,不关联重置数组顺序 - if (i === 0) - { - if (IsNoRelativeCurve(c1, c2)) - { - if (!HasRelativeCurveAndChange(c1, cus2, true)) - { - console.error("错误"); - return cus1; - } - i--; - continue; - } - } - } + let min = Math.min(0, params[Max(params, (p1, p2) => p1 > p2)]); + let max = Math.max(1, params[Max(params, (p1, p2) => p1 < p2)]); - let nextC1: Curve; + let sp = path.GetPointAtParam(min); + let ep = path.GetPointAtParam(max); - if (l1.IsClose) - { - nextC1 = cus1[FixIndex(i + 1, cus1.length)]; - } - else + path.StartPoint = sp; + path.EndPoint = ep; + } + + //遍历所有的路径节点进行顶点投射 + for (let i = 0; i < pathCurves.length; i++) + { + let path = pathCurves[i]; + if (isClosePath || i !== pathCurves.length - 1)//与下一段 { - if (i < cus1.length - 1) + let ep = path.EndPoint; + let nextPath = pathCurves[FixIndex(i + 1, pathCurves)]; + let preP: Vector3; + if (path instanceof Line) + preP = ep.clone().sub(path.GetFistDeriv(1).normalize()); + else { - nextC1 = cus1[i + 1]; + let pts = path.Shape.getPoints(4); + preP = AsVector3(pts[pts.length - 2]).applyMatrix4(path.OCSNoClone); } - } - - if (nextC1) - { - let derv = c1.GetFistDeriv(0).normalize(); - let derv2 = nextC1.GetFistDeriv(0).normalize(); - - if (isPerpendicularityTo(derv, derv2) && isPerpendicularityTo(derv, c1.StartPoint.sub(c2.StartPoint).normalize())) + let nextP: Vector3; + if (nextPath instanceof Line) + nextP = ep.clone().add(nextPath.GetFistDeriv(0).normalize()); + else { - AddSgs(c1, c2); - continue; + let pts = nextPath.Shape.getPoints(4); + nextP = AsVector3(pts[1]).applyMatrix4(nextPath.OCSNoClone); } - } - let nextDerv1 = c1.GetFistDeriv(1).normalize(); - let nextDerv2 = c2.GetFistDeriv(1).normalize(); - let preDerv1 = c1.GetFistDeriv(0).normalize(); - let preDerv2 = c2.GetFistDeriv(0).normalize(); - [nextDerv1, nextDerv2, preDerv1, preDerv2].forEach(d => rotatePoint(d, Math.PI / 2)); + //投射的点表 + let pts = ProjectionToPlane(contourPts, path.Normal, ep, preP, nextP); - let preRefLine1 = new Line(c1.StartPoint, c1.StartPoint.add(preDerv1)); - let preRefLine2 = new Line(c2.StartPoint, c2.StartPoint.add(preDerv2)); + // for (let j = 0; j < pts.length - 1; j++) + // TestDraw(new Line(pts[j].clone(), pts[j + 1].clone()).ApplyMatrix(this.OCSNoClone), i + 1); - let nextRefLine1 = new Line(c1.EndPoint, c1.EndPoint.add(nextDerv1)); - let nextRefLine2 = new Line(c2.EndPoint, c2.EndPoint.add(nextDerv2)); - - ExtendCurve(c1, nextRefLine2, false); - ExtendCurve(c2, nextRefLine1, false); + //针对圆弧 修改它的半径 + if (path instanceof Arc) + { + let mp = path.GetPointAtParam(0.5); + let arcPts = ProjectionToPlane(contourPts, path.Normal, mp, mp.clone().sub(path.GetFistDeriv(0.5).normalize())); + + let r = radiusMap.get(path); + let ocsInv = path.OCSInv; + let radius = arcPts.map(p => p.applyMatrix4(ocsInv).setZ(0).distanceTo(ZeroVec)); + if (r) radius.push(r); + let maxRadius = radius[Max(radius, (r1, r2) => r1 < r2)]; + radiusMap.set(path, maxRadius); + } - ExtendCurve(c1, preRefLine2, true); - ExtendCurve(c2, preRefLine1, true); - AddSgs(c1, c2); + ExtendsCurve(path, pts); + ExtendsCurve(nextPath, pts); + } } - return sgs; + for (let [arc, rad] of radiusMap) + arc.Radius = rad; + + return pathCurves; } + get MaxLength() { return this.Segmentations.reduce((len, c) => len + c.Length, 0); @@ -226,11 +145,11 @@ export class HardwareTopline extends SweepSolid this.Contour.ApplyMatrix(mat); this.Update(); } + protected _ReadFile(file: CADFiler) { super._ReadFile(file); let ver = file.Read();//1 - this._contourRotation = file.Read(); this.HardwareOption.addLen = file.Read(); @@ -254,7 +173,6 @@ export class HardwareTopline extends SweepSolid d[1] = file.Read(); this.DataList.push(d); } - } WriteFile(file: CADFiler) { diff --git a/src/Editor/CommandMachine.ts b/src/Editor/CommandMachine.ts index dd0731298..e573f40e0 100644 --- a/src/Editor/CommandMachine.ts +++ b/src/Editor/CommandMachine.ts @@ -10,6 +10,7 @@ import { ConfigTagCommand } from '../UI/Components/Board/ConfigTagCommand'; import { AppToaster } from '../UI/Components/Toaster'; import { CommandState } from './CommandState'; import { JigUtils } from './JigUtils'; +import { UCSUtils } from './UCSRAII'; import { userConfig } from './UserConfig'; export interface Command { @@ -139,6 +140,7 @@ class CommandMachine { //先把Jig实体清除了,避免残影 JigUtils.End(); + UCSUtils.End(); let hasHistory = !noHistory && app.Database.hm.CurrentHasHistory(); //先执行反应器 diff --git a/src/Editor/GetRectServices.ts b/src/Editor/GetRectServices.ts index c117834fc..9a1ebf2f1 100644 --- a/src/Editor/GetRectServices.ts +++ b/src/Editor/GetRectServices.ts @@ -12,6 +12,7 @@ import { GetRectPointPromptBlock } from "../UI/DynamicPrompt/GetRectPointPromptB import { IsKeyword } from "./InitKeyword"; import { PromptRectPointOptions } from "./PromptOptions"; import { PromptRectResult, PromptStatus } from "./PromptResult"; +import { GetPointUCS } from "./UCSRAII"; export class GetRectPointServices { @@ -26,7 +27,8 @@ export class GetRectPointServices private dynPrompt: GetRectPointPromptBlock; private destroyCalls = []; - private _UCSMatrix: Matrix4; + private _UCSMatrixBak: Matrix4;//备份UCS矩阵 + private _CurUCSMtx: Matrix4; async Start(prompt: PromptRectPointOptions = {}): Promise { @@ -36,15 +38,23 @@ export class GetRectPointServices this.promisResolve = resolve; let basePoint = prompt.BasePoint; + this._UCSMatrixBak = app.Editor.UCSMatrix; + if (!basePoint) { let ptRes = await app.Editor.GetPoint({ Msg: prompt.Msg || "请输入或者点取第一个角点:", KeyWordList: prompt.KeyWordList, SupportSnapPoints: prompt.SupportSnapPoints, + Raycast: true, }); if (ptRes.Status === PromptStatus.OK) + { basePoint = ptRes.Point; + + //设置合理的UCS + app.Editor.UCSMatrix = GetPointUCS(ptRes) ?? this._UCSMatrixBak.clone().setPosition(basePoint); + } else if (ptRes.Status === PromptStatus.Keyword) { let res = new PromptRectResult(); @@ -59,14 +69,15 @@ export class GetRectPointServices return; } } + else//设置合理的UCS + app.Editor.UCSMatrix = this._UCSMatrixBak.clone().setPosition(basePoint); + + this._CurUCSMtx = app.Editor.UCSMatrix; this.dynPrompt = new GetRectPointPromptBlock(); let ucsInv = app.Editor.UCSMatrixInv; let basePointUCS = basePoint.clone().applyMatrix4(ucsInv); - //备份坐标系,结束时还原它,(当捕获的点不在当前的UCS平面时) - this._UCSMatrix = app.Editor.UCSMatrix; - app.Editor.UCSMatrix = this._UCSMatrix.clone().setPosition(basePoint); let signX = 1; let signY = 1; @@ -147,7 +158,7 @@ export class GetRectPointServices this.UpdateDynPrompt(basePointUCS, p2UCS); if (prompt.Callback) - prompt.Callback(basePointUCS, p2UCS); + prompt.Callback(basePointUCS, p2UCS, this._CurUCSMtx); } }); if (ptRes.Status === PromptStatus.OK) @@ -155,6 +166,8 @@ export class GetRectPointServices let res = new PromptRectResult(); res.Status = PromptStatus.OK; + res.UCS = this._CurUCSMtx; + res.Point1UCS = basePointUCS; res.Point2UCS = ptRes.Point.applyMatrix4(ucsInv); @@ -167,7 +180,7 @@ export class GetRectPointServices res.Point2UCS.y = basePointUCS.y + this.dynPrompt.Height * signY; if (this.dynPrompt.xDynIpt.IsLock || this.dynPrompt.yDynIpt.IsLock) - res.Point2WCS.copy(res.Point2UCS).applyMatrix4(this._UCSMatrix); + res.Point2WCS.copy(res.Point2UCS).applyMatrix4(this._CurUCSMtx); this.ReturnResult(res); } @@ -201,7 +214,7 @@ export class GetRectPointServices ]; for (let p of pts) { - p.applyMatrix4(this._UCSMatrix); + p.applyMatrix4(this._CurUCSMtx); app.Viewer.PreViewer.WorldToViewPoint(p); } BufferGeometryUtils.UpdatePts(this.rubberBandLine.geometry as BufferGeometry, pts, true); @@ -246,12 +259,14 @@ export class GetRectPointServices this.dynPrompt = undefined; } - if (this._UCSMatrix) + if (this._UCSMatrixBak) { - app.Editor.UCSMatrix = this._UCSMatrix; - this._UCSMatrix = undefined; + app.Editor.UCSMatrix = this._UCSMatrixBak; + this._UCSMatrixBak = undefined; } + this._CurUCSMtx = undefined;//clear + this.destroyCalls.forEach(f => f()); } Cancel() diff --git a/src/Editor/GripDragServices.ts b/src/Editor/GripDragServices.ts index 6a070d9da..4ca84d915 100644 --- a/src/Editor/GripDragServices.ts +++ b/src/Editor/GripDragServices.ts @@ -1,4 +1,4 @@ -import { BufferGeometry, Line as TLine, Points, Vector3 } from 'three'; +import { BufferGeometry, Points, Line as TLine, Vector3 } from 'three'; import { end } from 'xaop'; import { app } from '../ApplicationServices/Application'; import { ColorMaterial } from '../Common/ColorPalette'; @@ -6,6 +6,7 @@ import { CommandNames } from '../Common/CommandNames'; import { InputState } from '../Common/InputState'; import { MouseKey } from '../Common/KeyEnum'; import { GetEntity } from '../Common/Utils'; +import { SweepSolid } from '../DatabaseServices/3DSolid/SweepSolid'; import { Entity } from '../DatabaseServices/Entity/Entity'; import { Line } from '../DatabaseServices/Entity/Line'; import { RectAreaLight } from '../DatabaseServices/Lights/RectAreaLight'; @@ -14,7 +15,7 @@ import { RoomWallBase } from '../DatabaseServices/Room/Entity/Wall/RoomWallBase' import { WallSnapMode } from '../DatabaseServices/Room/Entity/Wall/WallSnapMode'; import { RoomWallParse } from '../DatabaseServices/Room/ParseService/RoomWallParse'; import { BufferGeometryUtils } from '../Geometry/BufferGeometryUtils'; -import { isParallelTo, isPerpendicularityTo, SnapPoint } from '../Geometry/GeUtils'; +import { SnapPoint, isParallelTo, isPerpendicularityTo } from '../Geometry/GeUtils'; import { PointShapeUtils } from '../Geometry/PointShapeUtils'; import { DrawMode } from '../GraphicsSystem/PreViewer'; import { CommandWrap } from './CommandMachine'; @@ -176,9 +177,19 @@ export class GripDragServices implements EditorService //修改UCS let oldUcs = app.Editor.UCSMatrix; - if (snapIndexMap[0] && !(snapIndexMap[0].ent instanceof Line)) + let ent = snapIndexMap[0]?.ent; + if (ent && ent instanceof SweepSolid && Array.isArray(ent.Path)) { - let ocs = snapIndexMap[0].ent.OCS; + let map = ent.GetGripSubIndexMap(); + ent = map.get(snapIndexMap[0].indexArr[0]);//我们以第一个点作为我们的拉伸坐标系 + } + + if (ent && !(ent instanceof Line)) + { + let ocs = ent.OCS; + if (snapIndexMap[0].ent !== ent) + ocs.multiplyMatrices(snapIndexMap[0].ent.OCSNoClone, ocs); + let viewDir = app.Viewer.CameraCtrl.Direction; let z = new Vector3(); //如果对象坐标系和视图坐标系垂直,则修正坐标系 @@ -191,9 +202,9 @@ export class GripDragServices implements EditorService ocs.makeBasis(xv, yv, viewDir).setPosition(p); } - if (snapIndexMap[0].ent instanceof SpotLight && snapIndexMap[0].indexArr[0] > 2) + if (ent instanceof SpotLight && snapIndexMap[0].indexArr[0] > 2) ocs.setPosition(snapIndexMap[0].snapP); - else if (snapIndexMap[0].ent instanceof RoomWallBase) + else if (ent instanceof RoomWallBase) { SupportSnapPoints = RoomWallParse._CacheWallNodePoints; RoomWallBase.SnapMode = WallSnapMode.Center; diff --git a/src/Editor/PromptOptions.ts b/src/Editor/PromptOptions.ts index b457047eb..c6647d95f 100644 --- a/src/Editor/PromptOptions.ts +++ b/src/Editor/PromptOptions.ts @@ -1,4 +1,4 @@ -import { Intersection, Vector3 } from 'three'; +import { Intersection, Matrix4, Vector3 } from 'three'; import { KeyWord } from '../Common/InputState'; import { PromptEntityResult, PromptSsgetResult } from './PromptResult'; import { SelectType } from './SelectBox'; @@ -64,7 +64,7 @@ export interface GetDistendPrompt extends PromptOptions export interface PromptRectPointOptions extends PromptOptions { BasePoint?: Vector3; - Callback?: (p1UCS: Vector3, p2UCS: Vector3) => void; + Callback?: (p1UCS: Vector3, p2UCS: Vector3, UCS: Matrix4) => void; // AllowDrawRubberBand?: Boolean; SupportSnapPoints?: Vector3[]; } diff --git a/src/Editor/PromptResult.ts b/src/Editor/PromptResult.ts index 12a0fe65e..37949a355 100644 --- a/src/Editor/PromptResult.ts +++ b/src/Editor/PromptResult.ts @@ -1,4 +1,4 @@ -import { Intersection, Object3D, Vector3 } from 'three'; +import { Intersection, Matrix4, Object3D, Vector3 } from 'three'; import { Entity } from '../DatabaseServices/Entity/Entity'; import { ObjectSnapMode } from './ObjectSnapMode'; import { SelectSet } from './SelectSet'; @@ -79,6 +79,8 @@ export class PromptDistendResult extends PromptResult export class PromptRectResult extends PromptResult { + UCS: Matrix4; + Point1UCS: Vector3; Point2UCS: Vector3; diff --git a/src/Editor/SnapServices.ts b/src/Editor/SnapServices.ts index ca6a78ac3..49d5cda65 100644 --- a/src/Editor/SnapServices.ts +++ b/src/Editor/SnapServices.ts @@ -1,4 +1,4 @@ -import { BufferGeometry, Line, Matrix3, Matrix4, Object3D, PerspectiveCamera, Vector3 } from 'three'; +import { BufferGeometry, Line, Matrix3, Matrix4, Mesh, Object3D, PerspectiveCamera, Vector3 } from 'three'; import { app } from '../ApplicationServices/Application'; import { ColorMaterial } from '../Common/ColorPalette'; import { GetEntity } from '../Common/Utils'; @@ -11,7 +11,7 @@ import { Polyline } from '../DatabaseServices/Entity/Polyline'; import { RoomWallBase } from '../DatabaseServices/Room/Entity/Wall/RoomWallBase'; import { BufferGeometryUtils } from '../Geometry/BufferGeometryUtils'; import { CurveIntersection } from '../Geometry/CurveIntersection'; -import { equaln, equalv3, midPoint, SnapPoint, XAxis, YAxis, ZAxis } from '../Geometry/GeUtils'; +import { SnapPoint, XAxis, YAxis, ZAxis, equaln, equalv3, midPoint } from '../Geometry/GeUtils'; import { PointShapeUtils } from '../Geometry/PointShapeUtils'; import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { DrawMode } from '../GraphicsSystem/PreViewer'; @@ -19,6 +19,7 @@ import { Max } from '../Nest/Common/Util'; import { DynamicInputManage } from '../UI/DynamicPrompt/DynamicInputManage'; import { PromptBlock } from '../UI/DynamicPrompt/PromptBlock'; import { ObjectSnapMode } from './ObjectSnapMode'; +import { GenerateRaycaster, Raycast } from './PointPick'; import { GetPointPrompt } from "./PromptOptions"; import { SelectPick } from './SelectPick'; @@ -87,12 +88,14 @@ export class SnapServices private _SupportSnapPoints: SupportSnapPoint[] = [];//辅助捕捉点WCS private _LockSuppotPointIndex = -1;//只允许删除这个后面的辅助捕捉点 private _UCS: Matrix4; + private _Prompt: GetPointPrompt; /** 切线捕捉时使用的基点 */ TanBasePoint: Vector3; //开始捕捉 Start(prompt: GetPointPrompt) { + this._Prompt = prompt; this._UCS = app.Editor.UCSMatrix; this.InitDynPrompt(); @@ -305,6 +308,12 @@ export class SnapServices let selectEns = sel.SelectEntityList; + //收集Mesh(以便我们过滤点击穿透) + let selectMeshs: Mesh[] = []; + for (let obj of sel._SelectList) + if (obj instanceof Mesh) + selectMeshs.push(obj); + let viewXform = new Matrix3().setFromMatrix4(app.Viewer.Camera.matrix); //如果只有切线捕捉 @@ -345,7 +354,7 @@ export class SnapServices bp = this.TanBasePoint; let ens = mode === ObjectSnapMode.Cen ? circles : selectEns; - let snapData = this.CalcClosestSnapPoint(ens, mode, wcsP, vcsP, bp, viewXform); + let snapData = this.CalcClosestSnapPoint(ens, selectMeshs, mode, wcsP, vcsP, bp, viewXform); if (snapData.Point) { @@ -393,6 +402,20 @@ export class SnapServices for (let p of pts) { let pv = app.Viewer.WorldToScreen(p.clone()); + + //避免捕捉穿透 + if (selectMeshs.length) + { + let ray = GenerateRaycaster(pv, app.Viewer); + let i = Raycast(ray, selectMeshs); + if (i) + { + let d = i.point.subVectors(p, i.point).dot(ray.ray.direction); + if (d > 0.1) + continue; + } + } + if (SnapPoint(vcsP, pv, this.SnapSize)) { this.SnapType = ObjectSnapMode.Int; @@ -407,7 +430,7 @@ export class SnapServices //#region 最近点捕捉 if (this.SnapModeEnable & ObjectSnapMode.Nea) { - let snapData = this.CalcClosestSnapPoint(selectEns, ObjectSnapMode.Nea, wcsP, vcsP, baseP, viewXform); + let snapData = this.CalcClosestSnapPoint(selectEns, selectMeshs, ObjectSnapMode.Nea, wcsP, vcsP, baseP, viewXform); if (snapData.Point) { this.SnapType = ObjectSnapMode.Nea; @@ -418,7 +441,9 @@ export class SnapServices } //计算最近的捕捉点 - private CalcClosestSnapPoint(selectEns: Entity[], + private CalcClosestSnapPoint( + selectEns: Entity[], + selectMeshs: Mesh[], mode: ObjectSnapMode, wcsP: Vector3, vcsP: Vector3, @@ -445,6 +470,20 @@ export class SnapServices let pv = app.Viewer.WorldToScreen(p.clone()); let z = pv.z; pv.z = 0; + + //避免捕捉穿透 + if (selectMeshs.length) + { + let ray = GenerateRaycaster(pv, app.Viewer); + let i = Raycast(ray, selectMeshs); + if (i) + { + let d = i.point.subVectors(p, i.point).dot(ray.ray.direction); + if (d > 0.1) + continue; + } + } + let dist = vcsP.distanceToSquared(pv); if (equaln(dist, minDistance) && z < minZ) { diff --git a/src/Editor/UCSRAII.ts b/src/Editor/UCSRAII.ts new file mode 100644 index 000000000..102223042 --- /dev/null +++ b/src/Editor/UCSRAII.ts @@ -0,0 +1,68 @@ +import { Matrix4, Vector3 } from "three"; +import { app } from "../ApplicationServices/Application"; +import { Singleton } from "../Common/Singleton"; +import { equalv3 } from "../Geometry/GeUtils"; +import { Orbit } from "../Geometry/Orbit"; +import { DownPanelStore } from "../UI/Store/DownPanelStore"; +import { PromptPointResult } from "./PromptResult"; + +//通过拾取的点智能的给一个UCS +export function GetPointUCS(ptRes: PromptPointResult): Matrix4 | undefined +{ + const downPanelStore = DownPanelStore.GetInstance(); + if (downPanelStore.EnableSmartUCS && ptRes.intersection) + { + let ucs = app.Editor.UCSMatrix; + let ucsN = new Vector3().setFromMatrixColumn(ucs, 2); + + let n = ptRes.intersection.face.normal.clone().transformDirection(ptRes.intersection.object.matrixWorld); + + if (equalv3(n, ucsN))//如果相同 + return ucs.setPosition(ptRes.Point); + + let x = new Vector3; + let y = new Vector3; + Orbit.ComputUpDirection(n, y, x); + return new Matrix4().makeBasis(x, y, n).setPosition(ptRes.Point); + } +} + + +class UCSRAII extends Singleton +{ + private _UCSBak: Matrix4; + + private SaveUCS() + { + if (!this._UCSBak) + this._UCSBak = app.Editor.UCSMatrix; + } + + set UCSMtx(mtx: Matrix4) + { + this.SaveUCS(); + app.Editor.UCSMatrix = mtx; + } + + SetUCSFromPointRes(ptRes: PromptPointResult): Matrix4 | undefined + { + let ucs = GetPointUCS(ptRes); + if (ucs) + { + this.SaveUCS(); + app.Editor.UCSMatrix = ucs; + return ucs; + } + } + + End() + { + if (this._UCSBak) + { + app.Editor.UCSMatrix = this._UCSBak; + this._UCSBak = undefined; + } + } +} + +export const UCSUtils = UCSRAII.GetInstance(); diff --git a/src/Geometry/SpaceParse/Point2SpaceParse.ts b/src/Geometry/SpaceParse/Point2SpaceParse.ts index 9eafa457b..e03b79f47 100644 --- a/src/Geometry/SpaceParse/Point2SpaceParse.ts +++ b/src/Geometry/SpaceParse/Point2SpaceParse.ts @@ -27,7 +27,7 @@ export class Point2SpaceParse extends ISpaceParse if (rectRes.Status !== PromptStatus.OK) return; - let depth = await GetSpaceDepth(rectRes.Point1UCS, rectRes.Point2UCS, app.Editor.UCSMatrix, lastDepth); + let depth = await GetSpaceDepth(rectRes.Point1UCS, rectRes.Point2UCS, rectRes.UCS, lastDepth); if (!depth) return; lastDepth = depth; diff --git a/src/Geometry/SweepGeometry.ts b/src/Geometry/SweepGeometry.ts index de0baa187..eca2665f0 100644 --- a/src/Geometry/SweepGeometry.ts +++ b/src/Geometry/SweepGeometry.ts @@ -1,9 +1,9 @@ -import { Face3, Geometry, Line3, Matrix4, ShapeUtils, Vector2, Vector3 } from "three"; +import { Face3, Geometry, Line3, Matrix4, Shape, ShapeUtils, Vector2, Vector3 } from "three"; import { arrayRemoveDuplicateBySort } from "../Common/ArrayExt"; import { Curve } from "../DatabaseServices/Entity/Curve"; import { Polyline } from "../DatabaseServices/Entity/Polyline"; import { FixIndex } from "../Nest/Common/Util"; -import { AsVector3, equalv3 } from "./GeUtils"; +import { AsVector3, equalv2, equalv3 } from "./GeUtils"; import { PlaneExt } from "./Plane"; /** @@ -13,11 +13,15 @@ import { PlaneExt } from "./Plane"; export class SweepGeometry extends Geometry { edgePts: number[] = []; - constructor(contour: Polyline, path: Curve) + constructor(contour: Polyline, path: Curve[] | Curve) { super(); - this.AddShape(contour, path); + if (Array.isArray(path)) + this.AddShape2(contour, path); + else + this.AddShape(contour, path); + this.computeVertexNormals(); this.computeFaceNormals(); } @@ -25,11 +29,11 @@ export class SweepGeometry extends Geometry AddShape(contour: Polyline, path: Curve) { //路径点表 - let pathPts2d = path.Shape.getPoints(4); + let pathPts2d = (path.Shape as Shape).getPoints(4); let pathPts = pathPts2d.map(AsVector3); arrayRemoveDuplicateBySort(pathPts, equalv3); for (let p of pathPts) - p.applyMatrix4(path.OCS); + p.applyMatrix4(path.OCSNoClone); let shapePts2d = contour.Shape.getPoints(4); if (!ShapeUtils.isClockWise(shapePts2d)) shapePts2d.reverse(); @@ -38,36 +42,115 @@ export class SweepGeometry extends Geometry let shapePts3d = shapePts2d.map(AsVector3); for (let p of shapePts3d) - p.applyMatrix4(contour.OCS); + p.applyMatrix4(contour.OCSNoClone); let isClosePath = path.IsClose; let verts: Vector3[][] = [];//所有路径上的轮廓点 + + let pathNormal = path.Normal; + //计算所有需要的几何点,本质是不断的投影 - if (isClosePath) - verts.push(ProjectionToPlane(shapePts3d, path.Normal, pathPts[0], pathPts[pathPts.length - 2], pathPts[1])); - else - verts.push(ProjectionToPlane(shapePts3d, path.Normal, pathPts[0], undefined, pathPts[1])); + if (!isClosePath) + verts.push(ProjectionToPlane(shapePts3d, pathNormal, pathPts[0], undefined, pathPts[1])); + + //遍历所有的路径节点进行顶点投射 for (let i = 1; i < pathPts.length; i++) { if (i === pathPts.length - 1) { if (isClosePath) - verts.push(ProjectionToPlane(shapePts3d, path.Normal, pathPts[i], pathPts[i - 1], pathPts[1])); + verts.push(ProjectionToPlane(shapePts3d, pathNormal, pathPts[i], pathPts[i - 1], pathPts[1])); else - verts.push(ProjectionToPlane(shapePts3d, path.Normal, pathPts[i], pathPts[i - 1])); + verts.push(ProjectionToPlane(shapePts3d, pathNormal, pathPts[i], pathPts[i - 1])); } else { - verts.push(ProjectionToPlane(shapePts3d, path.Normal, pathPts[i], pathPts[i - 1], pathPts[i + 1])); + verts.push(ProjectionToPlane(shapePts3d, pathNormal, pathPts[i], pathPts[i - 1], pathPts[i + 1])); } } + if (isClosePath) + verts.unshift(verts[verts.length - 1]); + this.BuildSideFaces(shapePts2d, pathPts2d, pathPts, verts); if (!isClosePath) this.BuildLid(shapePts2d, verts); } + AddShape2(contour: Polyline, paths: Curve[]) + { + let pathPts: Vector3[] = []; + let pathNormals: Vector3[] = []; + + //路径点表 + for (let path of paths) + { + let pathPts2d = path.Shape.getPoints(4) as Vector2[]; + arrayRemoveDuplicateBySort(pathPts2d, (p1, p2) => + { + if (equalv2(p1, p2)) + { + p2["_mask_"] = p1["_mask_"]; + return true; + } + return false; + }); + + if (path !== paths[0]) + pathPts2d.shift(); + + let pNormal = path.Normal; + + for (let p of pathPts2d) + { + let p3 = AsVector3(p).applyMatrix4(path.OCSNoClone); + p3["_mask_"] = p["_mask_"]; + pathPts.push(p3); + + pathNormals.push(pNormal); + } + } + + let shapePts2d = contour.Shape.getPoints(4); + if (!ShapeUtils.isClockWise(shapePts2d)) shapePts2d.reverse(); + + //轮廓点表 + let shapePts3d = shapePts2d.map(AsVector3); + + for (let p of shapePts3d) + p.applyMatrix4(contour.OCSNoClone); + + let isClosePath = equalv3(pathPts[0], pathPts[pathPts.length - 1], 1e-3); + + let verts: Vector3[][] = [];//所有路径上的轮廓点 + //计算所有需要的几何点,本质是不断的投影 + if (!isClosePath) + verts.push(ProjectionToPlane(shapePts3d, pathNormals[0], pathPts[0], undefined, pathPts[1])); + + //遍历所有的路径节点进行顶点投射 + for (let i = 1; i < pathPts.length; i++) + { + if (i === pathPts.length - 1) + { + if (isClosePath) + verts.push(ProjectionToPlane(shapePts3d, pathNormals[i], pathPts[i], pathPts[i - 1], pathPts[1])); + else + verts.push(ProjectionToPlane(shapePts3d, pathNormals[i], pathPts[i], pathPts[i - 1])); + } + else + { + verts.push(ProjectionToPlane(shapePts3d, pathNormals[i], pathPts[i], pathPts[i - 1], pathPts[i + 1])); + } + } + + if (isClosePath) + verts.unshift(verts[verts.length - 1]); + + this.BuildSideFaces(shapePts2d, pathPts as unknown as Vector2[], pathPts, verts); + if (!isClosePath) this.BuildLid(shapePts2d, verts); + } + private BuildSideFaces(shapePts2d: Vector2[], pathPts2d: Vector2[], pathPts: Vector3[], verts: Vector3[][]) { let addCount = 0; //补充个数 diff --git a/src/UI/Components/Panel.tsx b/src/UI/Components/Panel.tsx index 1b1478558..b15a1e7c0 100644 --- a/src/UI/Components/Panel.tsx +++ b/src/UI/Components/Panel.tsx @@ -15,7 +15,7 @@ import { Light } from '../../DatabaseServices/Lights/Light'; import { PointLight } from '../../DatabaseServices/Lights/PointLight'; import { RectAreaLight } from '../../DatabaseServices/Lights/RectAreaLight'; import { SpotLight } from '../../DatabaseServices/Lights/SpotLight'; -import { commandMachine, CommandWrap } from '../../Editor/CommandMachine'; +import { CommandWrap, commandMachine } from '../../Editor/CommandMachine'; import { CommandState } from '../../Editor/CommandState'; import { LightsMenu } from '../../Editor/LightsMenu'; import { SnapMenuFixed } from '../../Editor/SnapMenuFixed'; @@ -575,6 +575,19 @@ export class DownPanel extends React.Component<{ store: DownPanelStore; }, {}> /> } + + + ); diff --git a/src/UI/Store/DownPanelStore.ts b/src/UI/Store/DownPanelStore.ts index 2499872b3..abfb92f47 100644 --- a/src/UI/Store/DownPanelStore.ts +++ b/src/UI/Store/DownPanelStore.ts @@ -163,6 +163,7 @@ export class DownPanelStore @observable isTopToolBarShowMin: boolean = false; @observable isBottomToolBarShowMin: boolean = false; @observable showHideSync: boolean = false; //显隐同步 + @observable EnableSmartUCS: boolean = false; //智能UCS private timeId; private constructor() { @@ -233,6 +234,7 @@ export class DownPanelStore fontName: this.fontName, lightsData: this.lightsData.map(l => l.enable), showHideSync: this.showHideSync, + smartUCS: this.EnableSmartUCS, }; } async Upload() @@ -314,6 +316,7 @@ export class DownPanelStore this.SetSnapMode(); this.showType = (this.isSmallScreen ? !this.isLeftToolBarShowMin : !this.isLeftToolBarShow) ? this.showType ^ ToolBarType.lefttoolbar : this.showType | ToolBarType.lefttoolbar; this.showHideSync = config.showHideSync ?? false; + this.EnableSmartUCS = config.smartUCS ?? false; } toggleLeftToolBarShow()