!514 重构偏移算法,优化走刀结果

pull/514/MERGE
ChenX 5 years ago
parent 9a4b8205b2
commit 60f2491d04

@ -18,7 +18,7 @@ exports[`异型板件,常规坐标系 3`] = `2660261.483308105`;
exports[`异型板件,常规坐标系 4`] = `2628158.6443366623`; exports[`异型板件,常规坐标系 4`] = `2628158.6443366623`;
exports[`异型板件,常规坐标系 5`] = `2603082.551922608`; exports[`异型板件,常规坐标系 5`] = `2603082.551922609`;
exports[`异型板件,非常规坐标系 1`] = `75939516.39226122`; exports[`异型板件,非常规坐标系 1`] = `75939516.39226122`;

File diff suppressed because one or more lines are too long

@ -1,20 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`#IYX1P: 曲线长度 1`] = `1334.7992356906177`; exports[`#IYX1P: 曲线长度 1`] = `1346.3292345344717`;
exports[`#IYX1P: 曲线长度 2`] = `7092.317327216775`; exports[`#IYX1P: 曲线长度 2`] = `8468.604267178238`;
exports[`#IYX1P: 曲线长度 3`] = `3600`; exports[`#IYX1P: 曲线长度 3`] = `10.71238898038469`;
exports[`#IYX1P: 曲线长度 4`] = `1483.4533999999999`; exports[`#IYX1P: 曲线长度 4`] = `10.71238898038469`;
exports[`#IYX1P: 曲线长度 5`] = `1324.9044565737036`; exports[`#IYX1P: 曲线长度 5`] = `3600`;
exports[`#IYX1P: 走刀数量 1`] = `2`; exports[`#IYX1P: 曲线长度 6`] = `1483.4533999999999`;
exports[`刀切到外轮廓情况: 曲线长度 1`] = `22596.75011038597`; exports[`#IYX1P: 曲线长度 7`] = `1324.9044565737036`;
exports[`刀切到外轮廓情况: 曲线长度 2`] = `6355.243980781998`; exports[`#IYX1P: 走刀数量 1`] = `4`;
exports[`刀切到外轮廓情况: 曲线长度 1`] = `22596.75011038598`;
exports[`刀切到外轮廓情况: 曲线长度 2`] = `6355.243980782019`;
exports[`刀切到外轮廓情况: 曲线长度 3`] = `3600`; exports[`刀切到外轮廓情况: 曲线长度 3`] = `3600`;
@ -22,115 +26,155 @@ exports[`刀切到外轮廓情况: 曲线长度 4`] = `1478.9393851461323`;
exports[`刀切到外轮廓情况: 曲线长度 5`] = `729.5688477133849`; exports[`刀切到外轮廓情况: 曲线长度 5`] = `729.5688477133849`;
exports[`刀切到外轮廓情况: 曲线长度 6`] = `939.4039853849376`; exports[`刀切到外轮廓情况: 曲线长度 6`] = `14681.465974109033`;
exports[`刀切到外轮廓情况: 曲线长度 7`] = `13736.355649626326`; exports[`刀切到外轮廓情况: 曲线长度 7`] = `14658.277022001026`;
exports[`刀切到外轮廓情况: 曲线长度 8`] = `1216.987577519942`; exports[`刀切到外轮廓情况: 曲线长度 8`] = `14681.465974109033`;
exports[`刀切到外轮廓情况: 曲线长度 9`] = `13428.231939084195`; exports[`刀切到外轮廓情况: 曲线长度 9`] = `14658.277022000973`;
exports[`刀切到外轮廓情况: 曲线长度 10`] = `939.4039853849374`; exports[`刀切到外轮廓情况: 曲线长度 10`] = `3600`;
exports[`刀切到外轮廓情况: 曲线长度 11`] = `13736.355649626326`; exports[`刀切到外轮廓情况: 曲线长度 11`] = `2683.281572999748`;
exports[`刀切到外轮廓情况: 曲线长度 12`] = `13428.23193908413`; exports[`刀切到外轮廓情况: 曲线长度 12`] = `1800`;
exports[`刀切到外轮廓情况: 曲线长度 13`] = `1216.9875775199384`; exports[`刀切到外轮廓情况: 走刀数量 1`] = `2`;
exports[`刀切到外轮廓情况: 曲线长度 14`] = `3600`; exports[`刀切到外轮廓情况: 走刀数量 2`] = `4`;
exports[`刀切到外轮廓情况: 曲线长度 15`] = `2683.281572999748`; exports[`复杂极限刀半径: 曲线长度 1`] = `232.80420650475034`;
exports[`刀切到外轮廓情况: 曲线长度 16`] = `1800`; exports[`复杂极限刀半径: 曲线长度 2`] = `806.2513545258738`;
exports[`刀切到外轮廓情况: 走刀数量 1`] = `2`; exports[`复杂极限刀半径: 曲线长度 3`] = `31170.805670163638`;
exports[`复杂极限刀半径: 曲线长度 4`] = `2917.48021978714`;
exports[`复杂极限刀半径: 曲线长度 5`] = `4434.591784188829`;
exports[`复杂极限刀半径: 曲线长度 6`] = `4356.840832388074`;
exports[`复杂极限刀半径: 曲线长度 7`] = `951.5402172137751`;
exports[`复杂极限刀半径: 曲线长度 8`] = `3278.9179349887763`;
exports[`复杂极限刀半径: 走刀数量 1`] = `5`;
exports[`复杂造型01: 曲线长度 1`] = `59609.750635032455`;
exports[`复杂造型01: 曲线长度 2`] = `1482.4552077856665`;
exports[`复杂造型01: 曲线长度 3`] = `838.7907023816642`;
exports[`复杂造型01: 曲线长度 4`] = `119.2450237058813`;
exports[`复杂造型01: 曲线长度 5`] = `920.6205527518313`;
exports[`刀切到外轮廓情况: 走刀数量 2`] = `8`; exports[`复杂造型01: 曲线长度 6`] = `136.38881122495832`;
exports[`复杂极限刀半径: 曲线长度 1`] = `1068.3190582501113`; exports[`复杂造型01: 曲线长度 7`] = `40.76338989846492`;
exports[`复杂极限刀半径: 曲线长度 2`] = `35730.26757931215`; exports[`复杂造型01: 曲线长度 8`] = `3.2524680966497335`;
exports[`复杂极限刀半径: 曲线长度 3`] = `2927.3167299028455`; exports[`复杂造型01: 曲线长度 9`] = `301.66992978702626`;
exports[`复杂极限刀半径: 曲线长度 4`] = `4356.840832388074`; exports[`复杂造型01: 曲线长度 10`] = `1749.8631881230112`;
exports[`复杂极限刀半径: 曲线长度 5`] = `951.5402172137751`; exports[`复杂造型01: 曲线长度 11`] = `7.8285491298056655`;
exports[`复杂极限刀半径: 曲线长度 6`] = `3278.9179349887763`; exports[`复杂造型01: 曲线长度 12`] = `2.5692483033658107`;
exports[`复杂极限刀半径: 走刀数量 1`] = `3`; exports[`复杂造型01: 曲线长度 13`] = `3600`;
exports[`复杂造型01: 曲线长度 14`] = `4316.136010511218`;
exports[`复杂造型01: 曲线长度 15`] = `60.75516885168303`;
exports[`复杂造型01: 曲线长度 16`] = `270.97161059159566`;
exports[`复杂造型01: 曲线长度 17`] = `282.82481905047365`;
exports[`复杂造型01: 曲线长度 18`] = `819.9411466147131`;
exports[`复杂造型01: 曲线长度 19`] = `1463.6056529693449`;
exports[`复杂造型01: 走刀数量 1`] = `12`;
exports[`复杂造型测试: 曲线长度 1`] = `24373.250750763476`; exports[`复杂造型测试: 曲线长度 1`] = `24373.250750763476`;
exports[`复杂造型测试: 曲线长度 2`] = `4285.071854430757`; exports[`复杂造型测试: 曲线长度 2`] = `4285.071854430756`;
exports[`复杂造型测试: 曲线长度 3`] = `2418.1434517838106`; exports[`复杂造型测试: 曲线长度 3`] = `2418.1434517838115`;
exports[`复杂造型测试: 曲线长度 4`] = `2293.0762218537734`; exports[`复杂造型测试: 曲线长度 4`] = `2293.0762218537734`;
exports[`复杂造型测试: 曲线长度 5`] = `4096.105045378747`; exports[`复杂造型测试: 曲线长度 5`] = `4096.105045378748`;
exports[`复杂造型测试: 曲线长度 6`] = `910.1341511193466`; exports[`复杂造型测试: 曲线长度 6`] = `8.0486334855557`;
exports[`复杂造型测试: 曲线长度 7`] = `2841.1337227520216`; exports[`复杂造型测试: 曲线长度 7`] = `875.5142132396979`;
exports[`复杂造型测试: 曲线长度 8`] = `1079.2736477434973`; exports[`复杂造型测试: 曲线长度 8`] = `2841.1337227520225`;
exports[`复杂造型测试: 曲线长度 9`] = `227.8342135021163`; exports[`复杂造型测试: 曲线长度 9`] = `1079.273647743498`;
exports[`复杂造型测试: 曲线长度 10`] = `16.405200898113836`; exports[`复杂造型测试: 曲线长度 10`] = `227.8342135021163`;
exports[`复杂造型测试: 曲线长度 11`] = `696.1986486992679`; exports[`复杂造型测试: 曲线长度 11`] = `16.405200898113836`;
exports[`复杂造型测试: 曲线长度 12`] = `639.7910377879329`; exports[`复杂造型测试: 曲线长度 12`] = `696.1986486992679`;
exports[`复杂造型测试: 曲线长度 13`] = `2402.511185283596`; exports[`复杂造型测试: 曲线长度 13`] = `639.7910377879329`;
exports[`复杂造型测试: 曲线长度 14`] = `1715.2225461089636`; exports[`复杂造型测试: 曲线长度 14`] = `2402.511185283596`;
exports[`复杂造型测试: 曲线长度 15`] = `493.42887087968916`; exports[`复杂造型测试: 曲线长度 15`] = `1715.2225461089636`;
exports[`复杂造型测试: 曲线长度 16`] = `352.7973262382525`; exports[`复杂造型测试: 曲线长度 16`] = `493.42887087968916`;
exports[`复杂造型测试: 曲线长度 17`] = `342.70973636046426`; exports[`复杂造型测试: 曲线长度 17`] = `352.7973262382525`;
exports[`复杂造型测试: 曲线长度 18`] = `476.0989607667295`; exports[`复杂造型测试: 曲线长度 18`] = `342.70973636046426`;
exports[`复杂造型测试: 曲线长度 19`] = `1167.5479341842504`; exports[`复杂造型测试: 曲线长度 19`] = `476.0989607667295`;
exports[`复杂造型测试: 曲线长度 20`] = `413.7195254587742`; exports[`复杂造型测试: 曲线长度 20`] = `1167.5479341842504`;
exports[`复杂造型测试: 曲线长度 21`] = `275.9275697576068`; exports[`复杂造型测试: 曲线长度 21`] = `413.7195254587742`;
exports[`复杂造型测试: 曲线长度 22`] = `99.71551046503953`; exports[`复杂造型测试: 曲线长度 22`] = `275.9275697576068`;
exports[`复杂造型测试: 曲线长度 23`] = `35.25475681965266`; exports[`复杂造型测试: 曲线长度 23`] = `99.71551046503953`;
exports[`复杂造型测试: 曲线长度 24`] = `169.22283273433305`; exports[`复杂造型测试: 曲线长度 24`] = `35.25475681965266`;
exports[`复杂造型测试: 曲线长度 25`] = `162.171881370416`; exports[`复杂造型测试: 曲线长度 25`] = `169.22283273433305`;
exports[`复杂造型测试: 曲线长度 26`] = `106446.82051696385`; exports[`复杂造型测试: 曲线长度 26`] = `162.171881370416`;
exports[`复杂造型测试: 曲线长度 27`] = `5545.665343214347`; exports[`复杂造型测试: 曲线长度 27`] = `104483.03471871806`;
exports[`复杂造型测试: 曲线长度 28`] = `3600`; exports[`复杂造型测试: 曲线长度 28`] = `2279.1571138841996`;
exports[`复杂造型测试: 曲线长度 29`] = `2581.0848141151123`; exports[`复杂造型测试: 曲线长度 29`] = `5545.665343214347`;
exports[`复杂造型测试: 曲线长度 30`] = `463.19933816470575`; exports[`复杂造型测试: 曲线长度 30`] = `3600`;
exports[`复杂造型测试: 曲线长度 31`] = `713.891109728082`; exports[`复杂造型测试: 曲线长度 31`] = `2581.0848141151123`;
exports[`复杂造型测试: 走刀数量 1`] = `12`; exports[`复杂造型测试: 曲线长度 32`] = `463.19933816470575`;
exports[`复杂造型测试: 走刀数量 2`] = `2`; exports[`复杂造型测试: 曲线长度 33`] = `713.891109728082`;
exports[`带孔造型板件: 曲线长度 1`] = `53389.1518227565`; exports[`复杂造型测试: 走刀数量 1`] = `13`;
exports[`带孔造型板件: 曲线长度 2`] = `4667.086663355046`; exports[`复杂造型测试: 走刀数量 2`] = `3`;
exports[`带孔造型板件: 曲线长度 1`] = `54662.04598627183`;
exports[`带孔造型板件: 曲线长度 2`] = `4678.35714568232`;
exports[`带孔造型板件: 曲线长度 3`] = `3600`; exports[`带孔造型板件: 曲线长度 3`] = `3600`;
@ -138,9 +182,9 @@ exports[`带孔造型板件: 曲线长度 4`] = `2195.9741153279983`;
exports[`带孔造型板件: 曲线长度 5`] = `1209.6929369796912`; exports[`带孔造型板件: 曲线长度 5`] = `1209.6929369796912`;
exports[`带孔造型板件: 曲线长度 6`] = `53389.1518227565`; exports[`带孔造型板件: 曲线长度 6`] = `54662.04598627183`;
exports[`带孔造型板件: 曲线长度 7`] = `4667.086663355046`; exports[`带孔造型板件: 曲线长度 7`] = `4678.35714568232`;
exports[`带孔造型板件: 曲线长度 8`] = `3600`; exports[`带孔造型板件: 曲线长度 8`] = `3600`;
@ -152,17 +196,33 @@ exports[`带孔造型板件: 走刀数量 1`] = `2`;
exports[`带孔造型板件: 走刀数量 2`] = `2`; exports[`带孔造型板件: 走刀数量 2`] = `2`;
exports[`极限刀半径#I11UDE: 曲线长度 1`] = `2434.8330081057957`; exports[`极限刀半径#I11UDE: 曲线长度 1`] = `2589.4683707776608`;
exports[`极限刀半径#I11UDE: 曲线长度 2`] = `10.71238898038469`;
exports[`极限刀半径#I11UDE: 曲线长度 3`] = `10.71238898038469`;
exports[`极限刀半径#I11UDE: 曲线长度 4`] = `10.71238898038521`;
exports[`极限刀半径#I11UDE: 曲线长度 5`] = `10.712388980384734`;
exports[`极限刀半径#I11UDE: 曲线长度 6`] = `10.71238898038408`;
exports[`极限刀半径#I11UDE: 曲线长度 2`] = `4992.8497433755965`; exports[`极限刀半径#I11UDE: 曲线长度 7`] = `10.7123889803843`;
exports[`极限刀半径#I11UDE: 曲线长度 3`] = `2450.188718291298`; exports[`极限刀半径#I11UDE: 曲线长度 8`] = `10.712388980384993`;
exports[`极限刀半径#I11UDE: 曲线长度 4`] = `2419.4772979202935`; exports[`极限刀半径#I11UDE: 曲线长度 9`] = `10.71238898038469`;
exports[`极限刀半径#I11UDE: 走刀数量 1`] = `1`; exports[`极限刀半径#I11UDE: 曲线长度 10`] = `4992.8497433755965`;
exports[`极限刀半径: 曲线长度 1`] = `999.9999999999999`; exports[`极限刀半径#I11UDE: 曲线长度 11`] = `2450.188718291298`;
exports[`极限刀半径#I11UDE: 曲线长度 12`] = `2419.4772979202935`;
exports[`极限刀半径#I11UDE: 走刀数量 1`] = `9`;
exports[`极限刀半径: 曲线长度 1`] = `1314.2477796076937`;
exports[`极限刀半径: 曲线长度 2`] = `3600`; exports[`极限刀半径: 曲线长度 2`] = `3600`;
@ -174,33 +234,193 @@ exports[`极限刀半径: 曲线长度 5`] = `3600`;
exports[`极限刀半径: 曲线长度 6`] = `1552.3359576397822`; exports[`极限刀半径: 曲线长度 6`] = `1552.3359576397822`;
exports[`极限刀半径: 曲线长度 7`] = `1638.9591725161226`; exports[`极限刀半径: 曲线长度 7`] = `1638.9591725161224`;
exports[`极限刀半径: 曲线长度 8`] = `47.12388980384689`;
exports[`极限刀半径: 曲线长度 8`] = `3600`; exports[`极限刀半径: 曲线长度 9`] = `47.12388980384689`;
exports[`极限刀半径: 曲线长度 9`] = `3517.9183450322453`; exports[`极限刀半径: 曲线长度 10`] = `3600`;
exports[`极限刀半径: 曲线长度 10`] = `600`; exports[`极限刀半径: 曲线长度 11`] = `3517.9183450322453`;
exports[`极限刀半径: 曲线长度 11`] = `3600`; exports[`极限刀半径: 曲线长度 12`] = `617.1238898038469`;
exports[`极限刀半径: 曲线长度 12`] = `1040`; exports[`极限刀半径: 曲线长度 13`] = `3600`;
exports[`极限刀半径: 曲线长度 13`] = `390`; exports[`极限刀半径: 曲线长度 14`] = `1040`;
exports[`极限刀半径: 曲线长度 14`] = `3600`; exports[`极限刀半径: 曲线长度 15`] = `390`;
exports[`极限刀半径: 曲线长度 15`] = `900`; exports[`极限刀半径: 曲线长度 16`] = `23.56194490192345`;
exports[`极限刀半径: 曲线长度 17`] = `3600`;
exports[`极限刀半径: 曲线长度 18`] = `900`;
exports[`极限刀半径: 走刀数量 1`] = `1`; exports[`极限刀半径: 走刀数量 1`] = `1`;
exports[`极限刀半径: 走刀数量 2`] = `1`; exports[`极限刀半径: 走刀数量 2`] = `1`;
exports[`极限刀半径: 走刀数量 3`] = `1`; exports[`极限刀半径: 走刀数量 3`] = `3`;
exports[`极限刀半径: 走刀数量 4`] = `1`; exports[`极限刀半径: 走刀数量 4`] = `1`;
exports[`极限刀半径: 走刀数量 5`] = `1`; exports[`极限刀半径: 走刀数量 5`] = `2`;
exports[`超级复杂造型01: 曲线长度 1`] = `23310.391778382174`;
exports[`超级复杂造型01: 曲线长度 2`] = `11849.91310995222`;
exports[`超级复杂造型01: 曲线长度 3`] = `9.894843040787247`;
exports[`超级复杂造型01: 曲线长度 4`] = `2.686492242389678`;
exports[`超级复杂造型01: 曲线长度 5`] = `15.558634753572182`;
exports[`超级复杂造型01: 曲线长度 6`] = `1.5023362215203946`;
exports[`超级复杂造型01: 曲线长度 7`] = `36.738926324214475`;
exports[`超级复杂造型01: 曲线长度 8`] = `2.345373451530522`;
exports[`超级复杂造型01: 曲线长度 9`] = `23.179252903171008`;
exports[`超级复杂造型01: 曲线长度 10`] = `34.11040843800545`;
exports[`超级复杂造型01: 曲线长度 11`] = `3.00516024046907`;
exports[`超级复杂造型01: 曲线长度 12`] = `3.005160240466534`;
exports[`超级复杂造型01: 曲线长度 13`] = `3.0051602404694115`;
exports[`超级复杂造型01: 曲线长度 14`] = `3.0051642696018828`;
exports[`超级复杂造型01: 曲线长度 15`] = `23.17925136224735`;
exports[`超级复杂造型01: 曲线长度 16`] = `2.3453734515378883`;
exports[`超级复杂造型01: 曲线长度 17`] = `36.73892632422056`;
exports[`超级复杂造型01: 曲线长度 18`] = `34.11040843800589`;
exports[`超级复杂造型01: 曲线长度 19`] = `9.894843040789354`;
exports[`超级复杂造型01: 曲线长度 20`] = `2.2726434483396147`;
exports[`超级复杂造型01: 曲线长度 21`] = `2.6864922423941437`;
exports[`超级复杂造型01: 曲线长度 22`] = `15.558634753573351`;
exports[`超级复杂造型01: 曲线长度 23`] = `1.5023362215224114`;
exports[`超级复杂造型01: 曲线长度 24`] = `23.17925136224733`;
exports[`超级复杂造型01: 曲线长度 25`] = `2.345373451535995`;
exports[`超级复杂造型01: 曲线长度 26`] = `36.73892632421837`;
exports[`超级复杂造型01: 曲线长度 27`] = `34.110408438008804`;
exports[`超级复杂造型01: 曲线长度 28`] = `3.005160240470314`;
exports[`超级复杂造型01: 曲线长度 29`] = `3.0051602404691264`;
exports[`超级复杂造型01: 曲线长度 30`] = `2.686492242389917`;
exports[`超级复杂造型01: 曲线长度 31`] = `15.558634753574319`;
exports[`超级复杂造型01: 曲线长度 32`] = `1.5023362215216194`;
exports[`超级复杂造型01: 曲线长度 33`] = `9.894843040786107`;
exports[`超级复杂造型01: 曲线长度 34`] = `2.272644014939738`;
exports[`超级复杂造型01: 曲线长度 35`] = `23.179252903170394`;
exports[`超级复杂造型01: 曲线长度 36`] = `2.3453734515314206`;
exports[`超级复杂造型01: 曲线长度 37`] = `36.73892632421504`;
exports[`超级复杂造型01: 曲线长度 38`] = `34.11040843800676`;
exports[`超级复杂造型01: 曲线长度 39`] = `3.0051602404685336`;
exports[`超级复杂造型01: 曲线长度 40`] = `3.0051630894960395`;
exports[`超级复杂造型01: 曲线长度 41`] = `2.6864922423866937`;
exports[`超级复杂造型01: 曲线长度 42`] = `15.558634753573163`;
exports[`超级复杂造型01: 曲线长度 43`] = `1.5023362215210545`;
exports[`超级复杂造型01: 曲线长度 44`] = `9.894843040790184`;
exports[`超级复杂造型01: 曲线长度 45`] = `2.27264424963326`;
exports[`超级复杂造型01: 曲线长度 46`] = `23.179252903170124`;
exports[`超级复杂造型01: 曲线长度 47`] = `2.345373451550585`;
exports[`超级复杂造型01: 曲线长度 48`] = `36.738926324216564`;
exports[`超级复杂造型01: 曲线长度 49`] = `34.11040843800687`;
exports[`超级复杂造型01: 曲线长度 50`] = `3.005160240469785`;
exports[`超级复杂造型01: 曲线长度 51`] = `3.005164269599573`;
exports[`超级复杂造型01: 曲线长度 52`] = `2.686492242390355`;
exports[`超级复杂造型01: 曲线长度 53`] = `15.558634753572672`;
exports[`超级复杂造型01: 曲线长度 54`] = `1.5023362215214884`;
exports[`超级复杂造型01: 曲线长度 55`] = `9.894843040792889`;
exports[`超级复杂造型01: 曲线长度 56`] = `2.272643448340335`;
exports[`超级复杂造型01: 曲线长度 57`] = `23.17925136224723`;
exports[`超级复杂造型01: 曲线长度 58`] = `2.345373451548128`;
exports[`超级复杂造型01: 曲线长度 59`] = `36.73892632422722`;
exports[`超级复杂造型01: 曲线长度 60`] = `34.11040843800603`;
exports[`超级复杂造型01: 曲线长度 61`] = `3.0051602404692153`;
exports[`超级复杂造型01: 曲线长度 62`] = `3.0051602404670064`;
exports[`超级复杂造型01: 曲线长度 63`] = `2.686492242390764`;
exports[`超级复杂造型01: 曲线长度 64`] = `15.558634753570397`;
exports[`超级复杂造型01: 曲线长度 65`] = `1.5023362215189802`;
exports[`超级复杂造型01: 曲线长度 66`] = `9.894843040791566`;
exports[`超级复杂造型01: 曲线长度 67`] = `2.2726440149400053`;
exports[`超级复杂造型01: 曲线长度 68`] = `5230.469840585598`;
exports[`超级复杂造型01: 曲线长度 69`] = `11906.411531839705`;
exports[`超级复杂造型01: 曲线长度 70`] = `464.88809827474097`;
exports[`超级复杂造型01: 曲线长度 71`] = `464.8880982747457`;
exports[`超级复杂造型01: 曲线长度 72`] = `464.8880982747495`;
exports[`超级复杂造型01: 曲线长度 73`] = `464.888098274753`;
exports[`超级复杂造型01: 曲线长度 74`] = `464.88809827475325`;
exports[`超级复杂造型01: 曲线长度 75`] = `464.8880982747512`;
exports[`超级复杂造型01: 曲线长度 76`] = `9277.910642188759`;
exports[`超级复杂造型01: 走刀数量 1`] = `67`;
exports[`通孔造型测试: 曲线长度 1`] = `1872.616834159402`; exports[`通孔造型测试: 曲线长度 1`] = `1872.616834159402`;
@ -214,12 +434,18 @@ exports[`造型的外框和内框厚度小于刀半径厚度: 曲线长度 1`] =
exports[`造型的外框和内框厚度小于刀半径厚度: 走刀数量 1`] = `0`; exports[`造型的外框和内框厚度小于刀半径厚度: 走刀数量 1`] = `0`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 1`] = `1459.4533999999999`; exports[`造型的外框和内框厚度等于刀直径: 曲线长度 1`] = `1468.0153449019233`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 2`] = `10.71238898038469`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 3`] = `10.712388980384869`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 4`] = `10.71238898038469`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 2`] = `3600`; exports[`造型的外框和内框厚度等于刀直径: 曲线长度 5`] = `3600`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 3`] = `1483.4533999999999`; exports[`造型的外框和内框厚度等于刀直径: 曲线长度 6`] = `1483.4533999999999`;
exports[`造型的外框和内框厚度等于刀直径: 曲线长度 4`] = `1435.4533999999999`; exports[`造型的外框和内框厚度等于刀直径: 曲线长度 7`] = `1435.4533999999999`;
exports[`造型的外框和内框厚度等于刀直径: 走刀数量 1`] = `1`; exports[`造型的外框和内框厚度等于刀直径: 走刀数量 1`] = `4`;

@ -15,13 +15,13 @@ test('2个大圆中间', () =>
let isR = GetPointAtCurveDir(pl, new Vector3(110.19, 17.4)); let isR = GetPointAtCurveDir(pl, new Vector3(110.19, 17.4));
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
let p = new Vector3().fromArray([84.89024786541306, 11.031154321671167, 0]); let p = new Vector3().fromArray([84.89024786541306, 11.031154321671167, 0]);
isR = GetPointAtCurveDir(pl, p); isR = GetPointAtCurveDir(pl, p);
expect(isR).toBeTruthy(); expect(isR).toBe(1);
}); });
test('点在端点且端点平行', () => test('点在端点且端点平行', () =>
@ -64,7 +64,7 @@ test('点在端点上且点在圆心上', () =>
let p = new Vector3(19.48, 8.1097); let p = new Vector3(19.48, 8.1097);
let isR = GetPointAtCurveDir(pl, p); let isR = GetPointAtCurveDir(pl, p);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
}); });
@ -95,7 +95,7 @@ test('存在精度误差,并且点在圆内', () =>
let isR = GetPointAtCurveDir(pl, p); let isR = GetPointAtCurveDir(pl, p);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
} }
}); });
@ -112,7 +112,7 @@ test('大于1凸度的圆', () =>
let isR = GetPointAtCurveDir(pl, pt); let isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
}); });
test('盲区计算', () => test('盲区计算', () =>
@ -127,7 +127,7 @@ test('盲区计算', () =>
let isR = GetPointAtCurveDir(pl, pt); let isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
pl.Reverse(); pl.Reverse();
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
@ -146,7 +146,7 @@ test('参数点在终点上', () =>
let pl = f.ReadObject() as Polyline; let pl = f.ReadObject() as Polyline;
let pt = new Vector3().fromArray([24.40481807693597, 4.679455426066854, 0]); let pt = new Vector3().fromArray([24.40481807693597, 4.679455426066854, 0]);
let isR = GetPointAtCurveDir(pl, pt); let isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
pt = new Vector3().fromArray([30.314368267468268, 10.71117601112483, 0]); pt = new Vector3().fromArray([30.314368267468268, 10.71117601112483, 0]);
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
@ -154,7 +154,7 @@ test('参数点在终点上', () =>
pl.Reverse(); pl.Reverse();
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
pt = new Vector3().fromArray([24.40481807693597, 4.679455426066854, 0]); pt = new Vector3().fromArray([24.40481807693597, 4.679455426066854, 0]);
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
@ -173,7 +173,7 @@ test('点在小角内', () =>
let pt = new Vector3().fromArray([-45.25245903106504, 20.057300217471017, 0]); let pt = new Vector3().fromArray([-45.25245903106504, 20.057300217471017, 0]);
let isR = GetPointAtCurveDir(pl, pt); let isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
pl.Reverse(); pl.Reverse();
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
@ -195,7 +195,7 @@ test('首尾点相等', () =>
pl.Reverse(); pl.Reverse();
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
}); });
@ -209,7 +209,7 @@ test('点在圆弧的弦中心上', () =>
let pt = new Vector3().fromArray([4.999999999999999, 2.5, 0]); let pt = new Vector3().fromArray([4.999999999999999, 2.5, 0]);
let isR = GetPointAtCurveDir(pl, pt); let isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
pt = new Vector3().fromArray([5, 9.5, 0]); pt = new Vector3().fromArray([5, 9.5, 0]);
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
@ -233,11 +233,11 @@ test('圆弧过大导致直线小角错误', () =>
let pt = new Vector3().fromArray([-2246.7733894227954, -220.1844621837422, 0]); let pt = new Vector3().fromArray([-2246.7733894227954, -220.1844621837422, 0]);
let isR = GetPointAtCurveDir(pl, pt); let isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
pt = new Vector3().fromArray([-2184.668414731696, -221.35723534211996, 0]); pt = new Vector3().fromArray([-2184.668414731696, -221.35723534211996, 0]);
//[1,["Circle",1,1,4,false,7,-1,[1,0,0,0,0,1,0,0,0,0,1,0,-2184,-221.357,0,1],1,1]] //[1,["Circle",1,1,4,false,7,-1,[1,0,0,0,0,1,0,0,0,0,1,0,-2184,-221.357,0,1],1,1]]
isR = GetPointAtCurveDir(pl, pt); isR = GetPointAtCurveDir(pl, pt);
expect(isR).toBeFalsy(); expect(isR).toBe(-1);
}); });

@ -16,33 +16,101 @@ exports[`中间区域需要圆裁剪 1`] = `1`;
exports[`中间区域需要圆裁剪 2`] = `"24.71130"`; exports[`中间区域需要圆裁剪 2`] = `"24.71130"`;
exports[`圆求交错误导致的线丢失 1`] = `4148.6552839918695`; exports[`假圆弧交点选点直连 1`] = `1`;
exports[`圆求交错误导致的线丢失 2`] = `4425.280774659357`; exports[`假圆弧交点选点直连 2`] = `"903.79892"`;
exports[`圆求交错误导致的线丢失 3`] = `4021.9003332433485`; exports[`判断点在线上错误导致的偏移错误 1`] = `1`;
exports[`圆求交错误导致的线丢失 4`] = `4581.2242286506635`; exports[`判断点在线上错误导致的偏移错误 2`] = `"119778.26631"`;
exports[`圆求交错误导致的线丢失 5`] = `3900.607906945287`; exports[`双圆偏移导致求延伸点错误 1`] = `1`;
exports[`圆求交错误导致的线丢失 6`] = `4757.46853225238`; exports[`双圆偏移导致求延伸点错误 2`] = `"787.87800"`;
exports[`圆求交错误导致的线丢失 7`] = `3783.7486621001212`; exports[`双圆偏移导致求延伸点错误 3`] = `1`;
exports[`圆求交错误导致的线丢失 8`] = `4972.012479701851`; exports[`双圆偏移导致求延伸点错误 4`] = `"168.83973"`;
exports[`圆求交错误导致的线丢失 9`] = `1148.663268759687`; exports[`双圆可能只有一个交点的问题 1`] = `1`;
exports[`圆求交错误导致的线丢失 10`] = `5979.881810920418`; exports[`双圆可能只有一个交点的问题 2`] = `"6744.69470"`;
exports[`圆求交错误导致的线丢失 11`] = `1049.9599133172633`; exports[`圆弧全丢时需要扇形切割 1`] = `1`;
exports[`圆求交错误导致的线丢失 12`] = `6051.226641876329`; exports[`圆弧全丢时需要扇形切割 2`] = `"4844.93527"`;
exports[`圆求交错误导致的线丢失 13`] = `722.4732418587954`; exports[`圆弧全部丢失 1`] = `1`;
exports[`圆求交错误导致的线丢失 14`] = `6316.980887212943`; exports[`圆弧全部丢失 2`] = `"1623.41712"`;
exports[`圆弧如果连接就自交,需要补圆弧才能解决 1`] = `1`;
exports[`圆弧如果连接就自交,需要补圆弧才能解决 2`] = `"948.21488"`;
exports[`圆弧连接后逆向 1`] = `1`;
exports[`圆弧连接后逆向 2`] = `"4159.59625"`;
exports[`圆弧连接成圆 1`] = `7`;
exports[`圆弧连接成圆 2`] = `"139.57806"`;
exports[`圆弧连接成圆 3`] = `"359.72091"`;
exports[`圆弧连接成圆 4`] = `"486.59311"`;
exports[`圆弧连接成圆 5`] = `"359.72091"`;
exports[`圆弧连接成圆 6`] = `"423.15701"`;
exports[`圆弧连接成圆 7`] = `"423.15701"`;
exports[`圆弧连接成圆 8`] = `"486.59311"`;
exports[`圆弧选点实例 1`] = `1`;
exports[`圆弧选点实例 2`] = `"1.33642"`;
exports[`圆弧错误的直连(需要验证是否可以连接,避免反向连接) 1`] = `1`;
exports[`圆弧错误的直连(需要验证是否可以连接,避免反向连接) 2`] = `"3880.28257"`;
exports[`圆弧错误的直连(需要验证是否可以连接,避免反向连接) 3`] = `1`;
exports[`圆弧错误的直连(需要验证是否可以连接,避免反向连接) 4`] = `"3791.62583"`;
exports[`圆弧错误连接 1`] = `1`;
exports[`圆弧错误连接 2`] = `"3624.05703"`;
exports[`圆求交错误导致的线丢失 1`] = `4148.655275462344`;
exports[`圆求交错误导致的线丢失 2`] = `4425.280774659386`;
exports[`圆求交错误导致的线丢失 3`] = `4021.90031602838`;
exports[`圆求交错误导致的线丢失 4`] = `4581.224228650713`;
exports[`圆求交错误导致的线丢失 5`] = `3900.6078799293045`;
exports[`圆求交错误导致的线丢失 6`] = `4757.468532252452`;
exports[`圆求交错误导致的线丢失 7`] = `3783.7486269390533`;
exports[`圆求交错误导致的线丢失 8`] = `4972.0124797019525`;
exports[`圆求交错误导致的线丢失 9`] = `1148.6626298786346`;
exports[`圆求交错误导致的线丢失 10`] = `5979.881805331884`;
exports[`圆求交错误导致的线丢失 11`] = `1049.959063092095`;
exports[`圆求交错误导致的线丢失 12`] = `6051.226636287797`;
exports[`圆求交错误导致的线丢失 13`] = `722.4732418587961`;
exports[`圆求交错误导致的线丢失 14`] = `6316.980880964775`;
exports[`复杂圆盘选点 1`] = `1`; exports[`复杂圆盘选点 1`] = `1`;
@ -84,6 +152,18 @@ exports[`拱门偏移 3`] = `1`;
exports[`拱门偏移 4`] = `"6.82743"`; exports[`拱门偏移 4`] = `"6.82743"`;
exports[`极限刀半径偏移 1`] = `2`;
exports[`极限刀半径偏移 2`] = `"500.00000"`;
exports[`极限刀半径偏移 3`] = `"250.00000"`;
exports[`正确的裁剪多段线 1`] = `2`;
exports[`正确的裁剪多段线 2`] = `"1.81330"`;
exports[`正确的裁剪多段线 3`] = `"4.43077"`;
exports[`海豚圆选点导致的错误 1`] = `1`; exports[`海豚圆选点导致的错误 1`] = `1`;
exports[`海豚圆选点导致的错误 2`] = `"1591.19822"`; exports[`海豚圆选点导致的错误 2`] = `"1591.19822"`;
@ -92,13 +172,49 @@ exports[`海豚圆选点导致的错误 3`] = `1`;
exports[`海豚圆选点导致的错误 4`] = `"1827.63524"`; exports[`海豚圆选点导致的错误 4`] = `"1827.63524"`;
exports[`点在多段线内 1`] = `1`;
exports[`点在多段线内 2`] = `"1589.94630"`;
exports[`简单图形因为点在线内算法错误导致的丢失 1`] = `8.675189454805244`; exports[`简单图形因为点在线内算法错误导致的丢失 1`] = `8.675189454805244`;
exports[`简单图形因为点在线内算法错误导致的丢失 2`] = `8.252841733482935`; exports[`简单图形因为点在线内算法错误导致的丢失 2`] = `8.252841733482935`;
exports[`简单图形因为点在线内算法错误导致的丢失 3`] = `6.802689012735881`; exports[`简单图形因为点在线内算法错误导致的丢失 3`] = `7.1494048498542835`;
exports[`简单图形因为点在线内算法错误导致的丢失 4`] = `6.693604273021889`;
exports[`精度过高导致无法连接 1`] = `"6721.53910"`;
exports[`精度过高导致的曲线丢失 1`] = `1`;
exports[`精度过高导致的曲线丢失 2`] = `"86945.68009"`;
exports[`精度过高导致的曲线丢失 3`] = `1`;
exports[`精度过高导致的曲线丢失 4`] = `"97661.61008"`;
exports[`精度过高导致直连失败 1`] = `1`;
exports[`精度过高导致直连失败 2`] = `"32040.01360"`;
exports[`精度过高导致直连失败 3`] = `1`;
exports[`精度过高导致直连失败 4`] = `"32045.24858"`;
exports[`精度过高导致连接失败 1`] = `1`;
exports[`简单图形因为点在线内算法错误导致的丢失 4`] = `6.045609380056393`; exports[`精度过高导致连接失败 2`] = `"75154.17850"`;
exports[`精度过高导致连接失败 3`] = `1`;
exports[`精度过高导致连接失败 4`] = `"91209.36327"`;
exports[`精度问题导致的连接错误 1`] = `2`;
exports[`精度问题导致的连接错误 2`] = `"19.40228"`;
exports[`精度问题导致的连接错误 3`] = `"19.40228"`;
exports[`纯圆生成的多段线偏移 1`] = `1`; exports[`纯圆生成的多段线偏移 1`] = `1`;
@ -108,9 +224,9 @@ exports[`纯圆生成的多段线偏移 3`] = `1`;
exports[`纯圆生成的多段线偏移 4`] = `"6328.57819"`; exports[`纯圆生成的多段线偏移 4`] = `"6328.57819"`;
exports[`补充bug测试 1`] = `7385.123391644449`; exports[`补充bug测试 1`] = `7385.123391644346`;
exports[`补充bug测试 2`] = `7455.861403941378`; exports[`补充bug测试 2`] = `7455.861403941371`;
exports[`补圆弧测试 补圆弧测试1 1`] = `1`; exports[`补圆弧测试 补圆弧测试1 1`] = `1`;
@ -200,12 +316,36 @@ exports[`补圆弧测试 补圆弧测试1 43`] = `1`;
exports[`补圆弧测试 补圆弧测试1 44`] = `"192.58327"`; exports[`补圆弧测试 补圆弧测试1 44`] = `"192.58327"`;
exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 1`] = `54789.24964851234`; exports[`被补圆弧的裁剪圆所裁剪导致的曲线丢失(和CAD一样) 1`] = `1`;
exports[`被补圆弧的裁剪圆所裁剪导致的曲线丢失(和CAD一样) 2`] = `"1771.95957"`;
exports[`连续丢圆弧后无法连接 1`] = `1`;
exports[`连续丢圆弧后无法连接 2`] = `"1310.80545"`;
exports[`连续丢圆弧后无法连接 3`] = `7`;
exports[`连续丢圆弧后无法连接 4`] = `"574.66475"`;
exports[`连续丢圆弧后无法连接 5`] = `"1182.81794"`;
exports[`连续丢圆弧后无法连接 6`] = `"574.66475"`;
exports[`连续丢圆弧后无法连接 7`] = `"574.66475"`;
exports[`连续丢圆弧后无法连接 8`] = `"574.66475"`;
exports[`连续丢圆弧后无法连接 9`] = `"574.66475"`;
exports[`连续丢圆弧后无法连接 10`] = `"574.66475"`;
exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 1`] = `54789.24964851236`;
exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 2`] = `54907.281737806145`; exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 2`] = `54907.281737806166`;
exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 3`] = `55497.50212266897`; exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 3`] = `55497.502122668986`;
exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 4`] = `56678.24106604482`; exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 4`] = `56678.24106604484`;
exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 5`] = `57859.374439605526`; exports[`闭合多段线判断精度和重复交点参数导致偏移丢失 5`] = `57859.37443960543`;

@ -1,25 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`补充bug测试#IKWGF 1`] = `1.1376403544773552`; exports[`补充bug测试#IKWGF 1`] = `0.44573953230750973`;
exports[`补充bug测试#IKWGF 2`] = `0.44573953236152686`; exports[`补充bug测试#IKWGF 2`] = `10.732981364094256`;
exports[`补充bug测试#IKWGF 3`] = `10.732981364094256`; exports[`补充bug测试#IKWGF 3`] = `1.137640354477355`;
exports[`补充bug测试#IKWGF 4`] = `12.78691181488093`; exports[`补充bug测试#IKWGF 4`] = `12.786911814880934`;
exports[`补充bug测试#IKWGF 5`] = `0.6246933440840137`; exports[`补充bug测试#IKWGF 5`] = `10.586693841137812`;
exports[`补充bug测试#IKWGF 6`] = `10.586693752451833`; exports[`补充bug测试#IKWGF 6`] = `0.624693344084014`;
exports[`补充bug测试#IKWGF 7`] = `14.067113755971711`; exports[`补充bug测试#IKWGF 7`] = `14.067113755971715`;
exports[`补充bug测试#IKWGF 8`] = `2.168984971098264`; exports[`补充bug测试#IKWGF 8`] = `11.891017922899252`;
exports[`补充bug测试#IKWGF 9`] = `11.89101792289927`; exports[`补充bug测试#IKWGF 9`] = `2.168984971098264`;
exports[`补充bug测试#IKWGF 10`] = `1.0803374679586235`; exports[`补充bug测试#IKWGF 10`] = `0.39474593983901435`;
exports[`补充bug测试#IKWGF 11`] = `0.39474593983890793`; exports[`补充bug测试#IKWGF 11`] = `10.69886845125427`;
exports[`补充bug测试#IKWGF 12`] = `10.69886845125427`; exports[`补充bug测试#IKWGF 12`] = `1.0803374679586233`;

File diff suppressed because one or more lines are too long

@ -6,6 +6,7 @@ import { GangDrill } from "../DatabaseServices/3DSolid/GangDrill";
import { CADFiler } from "../DatabaseServices/CADFiler"; import { CADFiler } from "../DatabaseServices/CADFiler";
import { Board } from "../DatabaseServices/Entity/Board"; import { Board } from "../DatabaseServices/Entity/Board";
import { PromptStatus } from "../Editor/PromptResult"; import { PromptStatus } from "../Editor/PromptResult";
import { deflate } from "../Common/SerializeMaterial";
export class CopyClip export class CopyClip
{ {
@ -43,9 +44,10 @@ export class CopyClip
for (let e of ens) for (let e of ens)
f.WriteObject(e); f.WriteObject(e);
copyTextToClipboard(JSON.stringify({ let str = JSON.stringify({
file: f.Data, file: f.Data,
basePt, basePt,
})); });
copyTextToClipboard(str);
} }
} }

@ -724,7 +724,7 @@ export class FilletUtils
let line = lineRes.Entity as Line; let line = lineRes.Entity as Line;
let arc = arcRes.Entity as Arc; let arc = arcRes.Entity as Arc;
let dir = GetPointAtCurveDir(line, arc.Center) ? 1 : -1; let dir = GetPointAtCurveDir(line, arc.Center);
let lineO = line.GetOffsetCurves(this.FilletRadius * dir)[0]; let lineO = line.GetOffsetCurves(this.FilletRadius * dir)[0];
let arcO = arc.GetOffsetCurves(this.FilletRadius * (arc.IsClockWise ? -1 : 1))[0];// tip面积逆时针为正, 顺时针为负. let arcO = arc.GetOffsetCurves(this.FilletRadius * (arc.IsClockWise ? -1 : 1))[0];// tip面积逆时针为正, 顺时针为负.

@ -2,10 +2,13 @@ import { Vector3 } from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { GetPointAtCurveDir } from '../Common/CurveUtils'; import { GetPointAtCurveDir } from '../Common/CurveUtils';
import { Curve } from '../DatabaseServices/Entity/Curve'; import { Curve } from '../DatabaseServices/Entity/Curve';
import { Polyline } from '../DatabaseServices/Entity/Polyline';
import { Command } from '../Editor/CommandMachine'; import { Command } from '../Editor/CommandMachine';
import { JigUtils } from '../Editor/JigUtils'; import { JigUtils } from '../Editor/JigUtils';
import { PromptStatus } from '../Editor/PromptResult'; import { PromptStatus } from '../Editor/PromptResult';
const OffsetKey = "offset";
//获取偏移距离的返回状态. //获取偏移距离的返回状态.
type GetOffsetStatus = { Status: PromptStatus, offsetDist?: number }; type GetOffsetStatus = { Status: PromptStatus, offsetDist?: number };
@ -13,22 +16,35 @@ type GetOffsetStatus = { Status: PromptStatus, offsetDist?: number };
export class Command_Offset implements Command export class Command_Offset implements Command
{ {
offsetDis: number = 1; offsetDis: number = 1;
isDyn = false;
constructor()
{
let o = window.localStorage.getItem(OffsetKey);
if (o)
this.offsetDis = parseFloat(o) || this.offsetDis;
}
async exec() async exec()
{ {
this.isDyn = false;
let disRes = await app.Editor.GetDistance({ let disRes = await app.Editor.GetDistance({
Msg: "指定偏移距离:", Msg: "指定偏移距离:",
KeyWordList: [{ msg: "通过:", key: "T" }], KeyWordList: [{ msg: "通过:", key: "T" }],
Default: this.offsetDis Default: this.offsetDis
}); });
let isDyn = false;//动态偏移.
if (disRes.StringResult === "T") if (disRes.StringResult === "T")
isDyn = true; this.isDyn = true;
else if (disRes.Status === PromptStatus.OK) else if (disRes.Status === PromptStatus.OK)
this.offsetDis = disRes.Distance; this.UpdateDistance(disRes.Distance);
else else
return; return;
await this.Run();
app.Viewer.OutlinePass.selectedObjects = [];
}//end exec
async Run()
{
let oldUCS = app.Editor.UCSMatrix; let oldUCS = app.Editor.UCSMatrix;
while (true) while (true)
{ {
@ -49,7 +65,7 @@ export class Command_Offset implements Command
{ {
app.Viewer.OutlinePass.selectedObjects = [cu.DrawObject]; app.Viewer.OutlinePass.selectedObjects = [cu.DrawObject];
let state: GetOffsetStatus; let state: GetOffsetStatus;
if (isDyn) if (this.isDyn)
state = await this.GetDynOffsetDist(cu); state = await this.GetDynOffsetDist(cu);
else else
state = await this.GetOffsetDir(cu); state = await this.GetOffsetDir(cu);
@ -65,15 +81,19 @@ export class Command_Offset implements Command
} }
app.Editor.UCSMatrix = oldUCS; app.Editor.UCSMatrix = oldUCS;
}//end exec }
UpdateDistance(offsetDist: number)
{
this.offsetDis = offsetDist || this.offsetDis;
window.localStorage.setItem(OffsetKey, this.offsetDis.toString());
}
//绘制偏移的对象 //绘制偏移的对象
DrawOffset(cu: Curve, offsetDist: number) DrawOffset(cu: Curve, offsetDist: number)
{ {
cu.GetOffsetCurves(offsetDist).forEach(c => for (let c of cu.GetOffsetCurves(offsetDist))
{
app.Database.ModelSpace.Append(c); app.Database.ModelSpace.Append(c);
});
} }
//单一对象,已经确定偏移距离的时候,用户选择偏移方向. //单一对象,已经确定偏移距离的时候,用户选择偏移方向.
@ -87,7 +107,7 @@ export class Command_Offset implements Command
Msg: "指定要偏移的那一侧的点", Msg: "指定要偏移的那一侧的点",
Callback: (p: Vector3) => Callback: (p: Vector3) =>
{ {
let dir = GetPointAtCurveDir(cu, p) ? 1 : -1; let dir = GetPointAtCurveDir(cu, p);
if (dir !== oldDir) if (dir !== oldDir)
{ {
JigUtils.Destroy(); JigUtils.Destroy();
@ -101,7 +121,7 @@ export class Command_Offset implements Command
let status = { Status: ptRes.Status, offsetDist: 0 }; let status = { Status: ptRes.Status, offsetDist: 0 };
if (ptRes.Status === PromptStatus.OK) if (ptRes.Status === PromptStatus.OK)
{ {
let dir = GetPointAtCurveDir(cu, ptRes.Point) ? 1 : -1; let dir = GetPointAtCurveDir(cu, ptRes.Point);
status.offsetDist = this.offsetDis * dir; status.offsetDist = this.offsetDis * dir;
} }
return status; return status;
@ -113,6 +133,9 @@ export class Command_Offset implements Command
let basePoint: Vector3 = new Vector3(); let basePoint: Vector3 = new Vector3();
let isMulti = false; let isMulti = false;
let cuOcsInv = cu.OCSInv;
let cuOCs = cu.OCS;
while (true) while (true)
{ {
let dir: number = 0; let dir: number = 0;
@ -123,8 +146,9 @@ export class Command_Offset implements Command
BasePoint: basePoint, BasePoint: basePoint,
CalcDistance: (baseP, p: Vector3) => CalcDistance: (baseP, p: Vector3) =>
{ {
p.applyMatrix4(cuOcsInv).setZ(0).applyMatrix4(cuOCs);
basePoint.copy(cu.GetClosestPointTo(p, false)); basePoint.copy(cu.GetClosestPointTo(p, false));
dir = GetPointAtCurveDir(cu, p) ? 1 : -1; dir = GetPointAtCurveDir(cu, p);
return p.distanceTo(basePoint) * dir; return p.distanceTo(basePoint) * dir;
}, },
Callback: (dis: number) => Callback: (dis: number) =>
@ -133,7 +157,6 @@ export class Command_Offset implements Command
cu.GetOffsetCurves(dis).forEach(c => JigUtils.Draw(c)); cu.GetOffsetCurves(dis).forEach(c => JigUtils.Draw(c));
} }
}); });
if (distRes.Status === PromptStatus.OK) if (distRes.Status === PromptStatus.OK)
{ {
let offsetDist = distRes.Distance; let offsetDist = distRes.Distance;
@ -156,3 +179,54 @@ export class Command_Offset implements Command
} }
} }
} }
export class Command_DynOffset extends Command_Offset
{
async exec()
{
this.isDyn = true;
await this.Run();
app.Viewer.OutlinePass.selectedObjects = [];
}
}
export class Command_DynOffsetToolPath
{
async exec()
{
let enRes = await app.Editor.GetEntity({ Filter: { filterTypes: [Polyline] } });
if (enRes.Status !== PromptStatus.OK) return;
let pl = enRes.Entity as Polyline;
let basePoint: Vector3 = new Vector3();
let dir: number = 0;
let distRes = await app.Editor.GetDistance(
{
Msg: "指定通过点或输入偏移距离:",
BasePoint: basePoint,
CalcDistance: (baseP, p: Vector3) =>
{
basePoint.copy(pl.GetClosestPointTo(p, false));
dir = GetPointAtCurveDir(pl, p);
return p.distanceTo(basePoint) * dir;
},
Callback: (dis: number) =>
{
JigUtils.Destroy();
pl.GetFeedingToolPath(dis).forEach(c => JigUtils.Draw(c));
}
});
if (distRes.Status === PromptStatus.OK)
{
let offsetDist = distRes.Distance;
if (dir !== Math.sign(offsetDist))
offsetDist = -offsetDist;
let pls = pl.GetFeedingToolPath(offsetDist);
for (let pl of pls)
app.Database.ModelSpace.Append(pl);
}
}
}

@ -1,82 +1,47 @@
import { app } from "../ApplicationServices/Application"; import { app } from "../ApplicationServices/Application";
import { Curve } from "../DatabaseServices/Entity/Curve";
import { Polyline } from "../DatabaseServices/Entity/Polyline"; import { Polyline } from "../DatabaseServices/Entity/Polyline";
import { Command } from "../Editor/CommandMachine"; import { Command } from "../Editor/CommandMachine";
import { PromptStatus } from "../Editor/PromptResult"; import { PromptStatus } from "../Editor/PromptResult";
import { Vector3 } from "three"; import { HotCMD } from "../Hot/HotCommand";
import { TestDraw } from "./test/TestUtil";
//无限内偏移 //无限内偏移
@HotCMD
export class OffsetX implements Command export class OffsetX implements Command
{ {
offsetDis: number = 1; offsetDis: number = 1;
async exec() async exec()
{ {
let ssRes = await app.Editor.GetEntity(); let ssRes = await app.Editor.GetEntity({ Msg: "选择多段线进行偏移测试:", Filter: { filterTypes: [Polyline] } });
if (ssRes.Status != PromptStatus.OK) return; if (ssRes.Status != PromptStatus.OK) return;
let pl = ssRes.Entity as Polyline; let pl = ssRes.Entity as Polyline;
if (!pl) return;
let dis: number, step: number;
if (window["autoDis"])
{
this.offsetDis = 1.2 * Math.max(...pl.BoundingBox.getSize(new Vector3()).toArray());
dis = -this.offsetDis;
step = this.offsetDis / 20;
}
else
{
let disRes = await app.Editor.GetDistance({ let disRes = await app.Editor.GetDistance({
Msg: "指定偏移距离:", Msg: "指定偏移距离:",
KeyWordList: [{ msg: "通过", key: "T" }], KeyWordList: [{ msg: "通过", key: "T" }],
Default: this.offsetDis Default: this.offsetDis
}); });
if (disRes.Status != PromptStatus.OK) return; let offsetDis = Math.abs(disRes.Distance);
this.offsetDis = disRes.Distance; TestDraw(pl.GetFeedingToolPath(offsetDis * Math.sign(pl.Area2)), 3);//外偏移
dis = -this.offsetDis;
if (pl.IsClockWise) dis = -dis;
let disRes1 = await app.Editor.GetDistance({
Msg: "步长:",
KeyWordList: [{ msg: "通过", key: "T" }],
Default: 1
});
if (disRes1.Status != PromptStatus.OK) return;
step = disRes1.Distance;
}
// let step = 0.5;
let offRes: Polyline[] = [];
// offRes.push(...pl.GetOffsetCurves(dis) as Polyline[]);
// for (let i = 0; i < offRes.length; i++) let offsetQueue: Curve[] = [pl];
// {
// let offpl = offRes[i];
// if (offpl.IsClose)
// {
// offRes.push(...offpl.GetOffsetCurves(dis) as Polyline[]);
// }
// }
if (step === 0) while (offsetQueue.length > 0)
{ {
app.Editor.Prompt("步长不能为0,已经帮你转换成" + dis / 10); let pl = offsetQueue.pop() as Polyline;
step = dis / 10; let offsets = pl.GetFeedingToolPath(offsetDis * -Math.sign(pl.Area2));
} for (let c of offsets)
let count = dis / step;
for (let i = 0; i < count; i++)
{ {
offRes.push(...pl.GetOffsetCurves(i * step) as Polyline[]); if (c.IsClose)
offRes.push(...pl.GetOffsetCurves(-i * step) as Polyline[]);
if (i > 50)
{ {
alert("执行次数太多,怕你卡死,帮你停止了!"); TestDraw(c, 4);
break; offsetQueue.push(c);
}
else
TestDraw(c, 5);
} }
} }
offRes.forEach(c => app.Database.ModelSpace.Append(c));
} }
} }

@ -1,5 +1,6 @@
import { Vector3 } from "three"; import { Vector3 } from "three";
import { app } from "../ApplicationServices/Application"; import { app } from "../ApplicationServices/Application";
import { inflate } from "../Common/SerializeMaterial";
import { readClipboardText } from "../Common/Utils"; import { readClipboardText } from "../Common/Utils";
import { CADFiler } from "../DatabaseServices/CADFiler"; import { CADFiler } from "../DatabaseServices/CADFiler";
import { Entity } from "../DatabaseServices/Entity/Entity"; import { Entity } from "../DatabaseServices/Entity/Entity";
@ -14,6 +15,8 @@ export class PasteClip
try try
{ {
let str = await readClipboardText(); let str = await readClipboardText();
if (str.startsWith("zip:"))
str = inflate(str.slice(4));
data = JSON.parse(str); data = JSON.parse(str);
} }
catch (error) catch (error)

@ -9,6 +9,7 @@ import { RightPanelStore } from '../UI/Store/RightPanelStore/RightPanelStore';
export class Save implements Command export class Save implements Command
{ {
NoHistory = true;
async exec() async exec()
{ {
let fileServer = FileServer.GetInstance() as FileServer; let fileServer = FileServer.GetInstance() as FileServer;

@ -3,6 +3,7 @@ import { Command } from '../Editor/CommandMachine';
export class Undo implements Command export class Undo implements Command
{ {
NoHistory = true;
async exec() async exec()
{ {
app.Database.hm.Undo(); app.Database.hm.Undo();
@ -12,6 +13,7 @@ export class Undo implements Command
export class Redo implements Command export class Redo implements Command
{ {
NoHistory = true;
async exec() async exec()
{ {
app.Database.hm.Redo(); app.Database.hm.Redo();

@ -5,6 +5,7 @@ import { Orbit } from "../Geometry/Orbit";
export class ViewChange implements Command export class ViewChange implements Command
{ {
NoHistory = true;
constructor(private viewDir: Vector3, private useWCS = false) constructor(private viewDir: Vector3, private useWCS = false)
{ {
viewDir.normalize(); viewDir.normalize();

@ -62,7 +62,7 @@ export class Command_ClosePt implements Command
dyn.UpdatePrompt("点在线内外?:" + IsPointInPolyLine(cu, p)); dyn.UpdatePrompt("点在线内外?:" + IsPointInPolyLine(cu, p));
closeCir.Center = p; closeCir.Center = p;
closeCir.ColorIndex = GetPointAtCurveDir(cu, p) ? 1 : 2; closeCir.ColorIndex = GetPointAtCurveDir(cu, p) + 3;
} }
} }
}) })

@ -0,0 +1,115 @@
import { app } from "../../../ApplicationServices/Application";
import { Arc } from "../../../DatabaseServices/Entity/Arc";
import { Entity } from "../../../DatabaseServices/Entity/Entity";
import { Point } from "../../../DatabaseServices/Entity/Point";
import { Polyline } from "../../../DatabaseServices/Entity/Polyline";
import { Region } from "../../../DatabaseServices/Entity/Region";
import { OffsetPolyline } from "../../../GraphicsSystem/OffsetPolyline";
import { TestDraw } from "../TestUtil";
export class OffsetTestUtil extends OffsetPolyline
{
constructor(_Polyline: Polyline, _OffsetDist: number, _ToolPath = false)
{
super(_Polyline, _OffsetDist, _ToolPath)
}
//----TEST
TestDrawPolyline()
{
this.OffsetSubCurves();
app.Editor.Prompt("开始绘制多段线")
for (let i = 0; i < this._SubCurves.length; i++)
{
let c = this._SubCurves[i].Clone().ApplyMatrix(this._CacheOCS);
c.ColorIndex = i + 1;
TestDraw(c);
for (let d of this._SubOffsetedCurves)
{
if (d.index === i)
{
let c2 = d.curve.Clone().ApplyMatrix(this._CacheOCS);
c2.ColorIndex = i + 1;
TestDraw(c2);
}
}
}
}
TestDrawLinkSubCurve()
{
app.Editor.Prompt("开始显示曲线连接");
for (let i = 0; i < this._SubOffsetedCurves.length; i++)
{
let d = this._SubOffsetedCurves[i];
let c = d.curve.Clone();
if (d.sp || d.ep)
{
if (d.sp) c.StartPoint = d.sp;
if (d.ep) c.EndPoint = d.ep;
}
c.ColorIndex = d.index + 1;
c.ApplyMatrix(this._CacheOCS);
TestDraw(c);
if (d.paddingCurve)
{
for (let c of d.paddingCurve)
{
let arc = c.Clone().ApplyMatrix(this._CacheOCS) as Arc;
let p = new Point(arc.Center);
TestDraw(p);
p.Erase();
arc.ColorIndex = d.index + 1;
TestDraw(arc);
}
}
}
}
TestDrawTrimCircle()
{
app.Editor.Prompt("开始显示裁剪圆弧");
for (let i = 0; i < this._TrimCircleContours.length; i++)
{
let c = this._TrimCircleContours[i].Clone().ApplyMatrix(this._CacheOCS);
let region = Region.CreateFromCurves([c]);
region.ColorIndex = i + 1;
TestDraw(region);
}
}
TestDrawTriContours()
{
app.Editor.Prompt("开始显示裁剪轮廓");
for (let i = 0; i < this._TrimPolylineContours.length; i++)
{
let c = this._TrimPolylineContours[i].Curve.Clone().ApplyMatrix(this._CacheOCS);
let region = Region.CreateFromCurves([c]);
region.ColorIndex = i + 1;
TestDraw(region);
}
}
TestDrawRetCurves()
{
app.Editor.Prompt("开始绘制最终结果");
for (let i = 0; i < this._RetCurves.length; i++)
{
let c = this._RetCurves[i];
TestDraw(c);
}
}
TestTrimedCurve()
{
let i = 1;
for (let c of this._CurveTrimedTreeNodes)
{
TestDraw(c.curve.ApplyMatrix(this._CacheOCS), i);
i++
}
}
}

@ -0,0 +1,85 @@
import { Box3 } from "three";
import { begin } from "xaop";
import { app } from "../../../ApplicationServices/Application";
import { JigMoveEntity } from "../../../Common/JigMove";
import { CADFiler } from "../../../DatabaseServices/CADFiler";
import { Entity } from "../../../DatabaseServices/Entity/Entity";
import { Polyline } from "../../../DatabaseServices/Entity/Polyline";
import { ObjectSnapMode } from "../../../Editor/ObjectSnapMode";
import { TestDraw } from "../TestUtil";
import { OffsetTestUtil } from "./OffsetTestUtil";
export function LoadEntityFromFileData(data)
{
if (!Array.isArray(data))
data = data.file;
let file = new CADFiler();
file.Data = data;
let ens: Entity[] = [];
let count = file.Read();
if (typeof count !== "number")
{
count = file.Data.length;
file.Reset();
}
for (let i = 0; i < count; i++)
{
ens.push(file.ReadObject() as Entity);
}
return ens;
}
async function TestOffset(cud: Object, offsetDist: number | number[], count?: number)
{
let ds = (typeof offsetDist === "number") ? [offsetDist] : offsetDist;
let ents: Entity[] = [];
let rm = begin(app.Database.ModelSpace, app.Database.ModelSpace.AppendEvent, (e: Entity) =>
{
ents.push(e);
});
app.Editor.GetPointServices.snapServices.SnapModeEnable = ObjectSnapMode.Node;
for (let d of ds)
{
let pl = LoadEntityFromFileData(cud)[0] as Polyline;
app.Editor.UpdateScreen();
let u = new OffsetTestUtil(pl, d, true);
u.Do();
for (let step = 1; step < 6; step++)
{
u.Do();
ents.length = 0;
TestDraw(pl.Clone());
if (step === 1)
{
u.TestDrawPolyline();
}
else if (step === 2)
{
u.TestDrawLinkSubCurve();
}
else if (step === 3)
u.TestDrawTriContours();
else if (step === 4)
u.TestTrimedCurve();
else if (step === 5)
{
let i = 1;
for (let c of u._RetCurves)
{
TestDraw(c, i);
i++;
}
}
let b = new Box3();
for (let e of ents)
b.union(e.BoundingBox);
await JigMoveEntity(ents, b.min)
}
}
rm();
}

@ -0,0 +1,22 @@
import { Object3D } from "three";
import { app } from "../../ApplicationServices/Application";
import { Entity } from "../../DatabaseServices/Entity/Entity";
export function TestDraw(en: Entity | Entity[] | Object3D, colorIndex = 0)
{
if (en instanceof Object3D)
app.Viewer.Scene.add(en);
else if (en instanceof Entity)
{
if (colorIndex > 0)
en.ColorIndex = colorIndex;
app.Database.ModelSpace.Append(en);
}
else
for (let e of en)
{
if (colorIndex > 0)
e.ColorIndex = colorIndex;
app.Database.ModelSpace.Append(e);
}
}

@ -4,19 +4,24 @@ import { app } from "../../ApplicationServices/Application";
import { PromptStatus } from "../../Editor/PromptResult"; import { PromptStatus } from "../../Editor/PromptResult";
import { Board } from "../../DatabaseServices/Entity/Board"; import { Board } from "../../DatabaseServices/Entity/Board";
import { Production } from "../../Production/Product"; import { Production } from "../../Production/Product";
import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Matrix4 } from "three";
@HotCMD @HotCMD
export class Test implements Command export class Test implements Command
{ {
async exec() async exec()
{ {
let enRes = await app.Editor.GetEntity(); let enRes = await app.Editor.GetSelection({});
if (enRes.Status === PromptStatus.OK) if (enRes.Status === PromptStatus.OK)
{ {
let en = enRes.Entity as Board; let en = enRes.SelectSet.SelectEntityList as Polyline[];
console.log(Production.GetBoardSplitOrderData(en)); for (let e of en)
{
if (e.IsClockWise) e.ColorIndex = 1;
}
} }
} }
} }

@ -13,7 +13,7 @@ import { PlaneExt } from '../Geometry/Plane';
import { Stand } from '../Geometry/RegionParse'; import { Stand } from '../Geometry/RegionParse';
import { IntersectOption } from '../GraphicsSystem/IntersectWith'; import { IntersectOption } from '../GraphicsSystem/IntersectWith';
import { arrayLast, changeArrayStartIndex, equalArray } from './ArrayExt'; import { arrayLast, changeArrayStartIndex, equalArray } from './ArrayExt';
import { FixIndex } from './Utils'; import { OffsetPolyline } from '../GraphicsSystem/OffsetPolyline';
//3点获取圆心 //3点获取圆心
export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3) export function getCircleCenter(pt1: Vector3, pt2: Vector3, pt3: Vector3)
@ -102,7 +102,7 @@ export function curveLinkGroup(cus: Curve[]): Array<Array<Curve>>
if (cus.length === 0) return groupCus; if (cus.length === 0) return groupCus;
//曲线节点图 //曲线节点图
let cuMap = new CurveMap(); let cuMap = new CurveMap();
cus.forEach(c => cuMap.addCurveToMap(c)); cus.forEach(c => cuMap.AddCurveToMap(c));
//曲线站点表 //曲线站点表
let stands = cuMap.Stands; let stands = cuMap.Stands;
@ -266,121 +266,26 @@ export function equalCurve(cu1: Curve, cu2: Curve, tolerance = 1e-4)
* *
* @param {Curve} cu * @param {Curve} cu
* @param {Vector3} pt * @param {Vector3} pt
* @returns {boolean} false,true * @returns {boolean} -1,1
*/ */
export function GetPointAtCurveDir(cu: Curve, pt: Vector3): boolean export function GetPointAtCurveDir(cu: Curve, pt: Vector3): number
{ {
if (cu instanceof Circle) if (cu instanceof Circle)
return !cu.PtInCurve(pt); return cu.PtInCurve(pt) ? -1 : 1;
else if (cu instanceof Polyline)
//TODO: 当T字形多段线时,最近点将重叠,导致方向结果出错 {
let u = new OffsetPolyline(cu, 1);
u.InitSubCurves();
return u.GetPointAtCurveDir(pt.clone().applyMatrix4(cu.OCSInv).setZ(0));
}
//最近点 //最近点
let cp = cu.GetClosestPointTo(pt, false); let cp = cu.GetClosestPointTo(pt, false);
if (equalv3(cp, pt, 1e-6)) return 0;
//最近点参数 //最近点参数
let cparam = cu.GetParamAtPoint(cp); let cparam = cu.GetParamAtPoint(cp);
//归一化最近点参数
let floorParam = Math.round(cparam);
//当最近点在参数上时,可能产生退化,在这里重新计算合适的最近点和切线.
if (
cu instanceof Polyline
&& equaln(floorParam, cparam, 1e-2)
&&
(cu.IsClose || (floorParam !== 0 && floorParam !== cu.EndParam))
)
{
let plVerCount = cu.NumberOfVertices;
if (equalv2(cu.GetPoint2dAt(0), cu.GetPoint2dAt(plVerCount - 1)))
plVerCount--;
//分三点,本点,前一个点,后一个点
if (floorParam === cu.EndParam) floorParam = 0;
let fIndex = FixIndex(floorParam - 1, plVerCount);
let p = cu.GetPointAtParam(floorParam);
let cu1 = cu.GetCurveAtIndex(fIndex);
let cu2 = cu.GetCurveAtIndex(floorParam);
let cu1Length = cu1.Length;
let cu2Length = cu2.Length;
let minLength = Math.min(cu1Length, cu2Length);
let fDer: Vector3;
let nDer: Vector3;
if (equaln(cu.GetBuilgeAt(fIndex), 0))
fDer = cu.GetFistDeriv(fIndex).normalize();
else
{
let tp = cu1.GetPointAtDistance(cu1Length - minLength * 0.25);
fDer = tp.negate().add(p).normalize();
}
if (equaln(cu.GetBuilgeAt(floorParam), 0))
nDer = cu.GetFistDeriv(floorParam).normalize();
else
{
let tp = cu2.GetPointAtDistance(minLength * 0.25);
nDer = tp.sub(p).normalize();
}
let l1 = new Line(p.clone().sub(fDer.clone().multiplyScalar(300)), p);
l1.ColorIndex = 1;
let l2 = new Line(p, p.clone().add(nDer.clone().multiplyScalar(200)));
l2.ColorIndex = 2;
let cp1 = l1.GetClosestPointTo(pt, true);
let cp2 = l2.GetClosestPointTo(pt, true);
// T 型曲线
let nDerN = nDer.clone().negate();
if (equalv3(fDer, nDerN))
{
let frontParam = floorParam;
while (frontParam > 1)
{
let fp = cu.GetPointAtParam(frontParam - 1.2);
fDer.copy(p).sub(fp).normalize();
if (!equalv3(fDer, nDerN))
break;
frontParam--;
}
if (frontParam <= 1)
{
let nextParam = floorParam;
let endParam = cu.EndParam - 1;
while (nextParam < endParam)
{
let np = cu.GetPointAtParam(nextParam + 1.2);
nDer = np.sub(p).normalize();
if (!equalv3(fDer, nDerN))
break;
nextParam++;
}
}
}
if (equalv3(fDer, nDer))
return fDer.cross(pt.clone().sub(cp1)).applyMatrix4(cu.OCSInv).z < 0;
let adir = Math.sign(fDer.clone().cross(nDer).applyMatrix4(cu.OCSInv).z);
//判断点是否在小角内.
if (
Math.sign(fDer.cross(pt.clone().sub(cp1)).applyMatrix4(cu.OCSInv).z) === adir
&& Math.sign(nDer.cross(pt.clone().sub(cp2)).applyMatrix4(cu.OCSInv).z) === adir
)
return adir < 0;
else
return adir > 0;
}
let dri = cu.GetFistDeriv(cparam); let dri = cu.GetFistDeriv(cparam);
let cross = dri.cross(pt.clone().sub(cp)).applyMatrix4(cu.OCSInv); let cross = dri.cross(pt.clone().sub(cp)).applyMatrix4(cu.OCSInv);
return cross.z < 0; return -Math.sign(cross.z);
} }
/** /**

@ -0,0 +1,45 @@
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function decimalAdjust(type: string, value: number | (string | number)[], exp: number): number
{
// If the exp is undefined or zero...
if (typeof exp === 'undefined' || +exp === 0)
{
return Math[type](value);
}
value = +value;
exp = +exp;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
{
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
}
// Decimal round
export function round10(value: number, exp: number): number
{
return decimalAdjust('round', value, exp);
};
// Decimal floor
function floor10(value: number, exp: number): number
{
return decimalAdjust('floor', value, exp);
};
// Decimal ceil
function ceil10(value: number, exp: number): number
{
return decimalAdjust('ceil', value, exp);
};

@ -184,6 +184,18 @@ export class Arc extends Curve
{ {
return this.AllAngle * this.m_Radius; return this.AllAngle * this.m_Radius;
} }
GetParamAtPoint2(pt: Vector3): number
{
return this.GetParamAtAngle(this.GetAngleAtPoint(pt));
}
//点在曲线上,已经确定点在曲线的延伸线上
PtOnCurve3(p: Vector3, fuzz = 1e-6): boolean
{
let param = this.GetParamAtPoint2(p);
return this.ParamOnCurve(param, fuzz);
}
protected ApplyScaleMatrix(m: Matrix4): this protected ApplyScaleMatrix(m: Matrix4): this
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
@ -232,7 +244,7 @@ export class Arc extends Curve
{ {
if (this.m_Radius == 0 || if (this.m_Radius == 0 ||
this.AllAngle == 0 || this.AllAngle == 0 ||
!equaln(pt.distanceTo(this.Center), this.m_Radius, 1e-8)) !equaln(pt.distanceTo(this.Center), this.m_Radius, 1e-6))
return NaN; return NaN;
return this.GetParamAtAngle(this.GetAngleAtPoint(pt)); return this.GetParamAtAngle(this.GetAngleAtPoint(pt));

@ -35,14 +35,14 @@ export class Circle extends Curve
{ {
super(); super();
center && this._Matrix.setPosition(center); center && this._Matrix.setPosition(center);
this.m_Radius = radius; this._Radius = radius;
} }
private m_Radius: number; private _Radius: number;
get Shape() get Shape()
{ {
let sp = new Shape(); let sp = new Shape();
sp.ellipse(0, 0, this.m_Radius, this.m_Radius, 0, 2 * Math.PI, false, 0); sp.ellipse(0, 0, this._Radius, this._Radius, 0, 2 * Math.PI, false, 0);
return sp; return sp;
} }
@ -58,12 +58,12 @@ export class Circle extends Curve
} }
get Radius() get Radius()
{ {
return this.m_Radius; return this._Radius;
} }
set Radius(v: number) set Radius(v: number)
{ {
this.WriteAllObjectRecord(); this.WriteAllObjectRecord();
this.m_Radius = clamp(v, 1e-9, 1e19); this._Radius = clamp(v, 1e-9, 1e19);
this.Update(); this.Update();
} }
@ -107,11 +107,15 @@ export class Circle extends Curve
} }
get Area() get Area()
{ {
return Math.PI * Math.pow(this.m_Radius, 2); return Math.PI * this._Radius ** 2;
}
get Area2()
{
return Math.PI * this._Radius ** 2;
} }
get Length() get Length()
{ {
return Math.PI * 2 * this.m_Radius; return Math.PI * 2 * this._Radius;
} }
get IsClose(): boolean get IsClose(): boolean
@ -119,20 +123,23 @@ export class Circle extends Curve
return true; return true;
} }
//曲线为顺时针
get IsClockWise(): boolean { return false; }
GetPointAtParam(param: number) GetPointAtParam(param: number)
{ {
return (polar(new Vector3(), param * 2 * Math.PI, this.m_Radius) as Vector3).applyMatrix4(this._Matrix); return (polar(new Vector3(), param * 2 * Math.PI, this._Radius) as Vector3).applyMatrix4(this._Matrix);
} }
GetPointAtDistance(distance: number) GetPointAtDistance(distance: number)
{ {
let param = distance / (Math.PI * 2 * this.m_Radius); let param = distance / (Math.PI * 2 * this._Radius);
return this.GetPointAtParam(param); return this.GetPointAtParam(param);
} }
GetDistAtParam(param: number) GetDistAtParam(param: number)
{ {
return Math.PI * 2 * this.m_Radius * param; return Math.PI * 2 * this._Radius * param;
} }
GetDistAtPoint(pt: Vector3) GetDistAtPoint(pt: Vector3)
@ -143,7 +150,7 @@ export class Circle extends Curve
GetParamAtDist(d: number) GetParamAtDist(d: number)
{ {
return d / (Math.PI * 2 * this.m_Radius); return d / (Math.PI * 2 * this._Radius);
} }
GetSplitCurves(param: number[] | number) GetSplitCurves(param: number[] | number)
@ -171,7 +178,7 @@ export class Circle extends Curve
let ea = anglelist[i + 1]; let ea = anglelist[i + 1];
if (!equaln(sa, ea, 1e-6)) if (!equaln(sa, ea, 1e-6))
{ {
let arc = new Arc(new Vector3(), this.m_Radius, sa, ea); let arc = new Arc(new Vector3(), this._Radius, sa, ea);
arc.ApplyMatrix(this.OCS); arc.ApplyMatrix(this.OCS);
curvelist.push(arc); curvelist.push(arc);
} }
@ -190,14 +197,14 @@ export class Circle extends Curve
PtOnCurve(pt: Vector3) PtOnCurve(pt: Vector3)
{ {
return equaln(pt.distanceToSquared(this.Center), this.m_Radius * this.m_Radius, 1e-5); return equaln(pt.distanceToSquared(this.Center), this._Radius * this._Radius, 1e-5);
} }
GetOffsetCurves(offsetDist: number) GetOffsetCurves(offsetDist: number)
{ {
if ((offsetDist + this.m_Radius) > 0) if ((offsetDist + this._Radius) > 0)
{ {
let circle = this.Clone(); let circle = this.Clone();
circle.Radius = this.m_Radius + offsetDist; circle.Radius = this._Radius + offsetDist;
return [circle]; return [circle];
} }
return [] return []
@ -241,7 +248,7 @@ export class Circle extends Curve
} }
UpdateDrawObject(type: RenderType, obj: Object3D) UpdateDrawObject(type: RenderType, obj: Object3D)
{ {
obj.children[0].scale.set(this.m_Radius, this.m_Radius, this.m_Radius); obj.children[0].scale.set(this._Radius, this._Radius, this._Radius);
obj.children[0].updateMatrix(); obj.children[0].updateMatrix();
} }
UpdateDrawObjectMaterial(type: RenderType, obj: Object3D, material: Material) UpdateDrawObjectMaterial(type: RenderType, obj: Object3D, material: Material)
@ -262,10 +269,10 @@ export class Circle extends Curve
{ {
let pts = [ let pts = [
new Vector3(), new Vector3(),
new Vector3(0, this.m_Radius), new Vector3(0, this._Radius),
new Vector3(0, -this.m_Radius), new Vector3(0, -this._Radius),
new Vector3(-this.m_Radius, 0), new Vector3(-this._Radius, 0),
new Vector3(this.m_Radius, 0), new Vector3(this._Radius, 0),
]; ];
let ocs = this.OCS; let ocs = this.OCS;
@ -382,14 +389,14 @@ export class Circle extends Curve
{ {
super._ReadFile(file); super._ReadFile(file);
let ver = file.Read(); let ver = file.Read();
this.m_Radius = file.Read(); this._Radius = file.Read();
} }
//对象将自身数据写入到文件. //对象将自身数据写入到文件.
WriteFile(file: CADFiler) WriteFile(file: CADFiler)
{ {
super.WriteFile(file); super.WriteFile(file);
file.Write(1); file.Write(1);
file.Write(this.m_Radius); file.Write(this._Radius);
} }
//#endregion //#endregion
} }

@ -69,6 +69,8 @@ export abstract class Curve extends Entity
GetDistAtParam(param: number): number { return; } GetDistAtParam(param: number): number { return; }
GetDistAtPoint(pt: Vector3): number { return; } GetDistAtPoint(pt: Vector3): number { return; }
GetParamAtPoint(pt: Vector3): number { return; } GetParamAtPoint(pt: Vector3): number { return; }
GetParamAtPoint2(pt: Vector3): number { return this.GetParamAtPoint(pt); }
GetParamAtDist(d: number): number { return; } GetParamAtDist(d: number): number { return; }
/** /**
@ -140,6 +142,12 @@ export abstract class Curve extends Entity
return !(equalv3(this.StartPoint, pt, 1e-6) || equalv3(this.EndPoint, pt, 1e-6)) && this.ParamOnCurve(this.GetParamAtPoint(pt), 0); return !(equalv3(this.StartPoint, pt, 1e-6) || equalv3(this.EndPoint, pt, 1e-6)) && this.ParamOnCurve(this.GetParamAtPoint(pt), 0);
} }
//点在曲线上,已经确定点在曲线的延伸线上
PtOnCurve3(p: Vector3, fuzz = 1e-6): boolean
{
return this.PtOnCurve(p, fuzz);
}
//参数在曲线上 容差,1e-6 //参数在曲线上 容差,1e-6
ParamOnCurve(param: number, fuzz = 1e-6): boolean { return !isNaN(param) && param >= -fuzz && param <= this.EndParam + fuzz; } ParamOnCurve(param: number, fuzz = 1e-6): boolean { return !isNaN(param) && param >= -fuzz && param <= this.EndParam + fuzz; }
GetOffsetCurves(offsetDist: number): Array<Curve> { return; } GetOffsetCurves(offsetDist: number): Array<Curve> { return; }

@ -210,7 +210,7 @@ export class Entity extends CADObject
} }
UpdateRenderType(type: RenderType) UpdateRenderType(type: RenderType)
{ {
if (this.OnlyRenderType || !this.Visible) return; if ((this.OnlyRenderType && this.DrawObject.children.length > 0) || !this.Visible) return;
Object3DRemoveAll(this.DrawObject); Object3DRemoveAll(this.DrawObject);
let obj = this.GetDrawObjectFromRenderType(type); let obj = this.GetDrawObjectFromRenderType(type);
if (obj) this.DrawObject.add(obj); if (obj) this.DrawObject.add(obj);

@ -73,7 +73,7 @@ export class ExtrudeSolid extends Entity
protected grooves: ExtrudeSolid[] = []; protected grooves: ExtrudeSolid[] = [];
protected knifeRadius: number = 3; protected knifeRadius: number = 3;
protected groovesAddLength: number = 3; protected groovesAddLength: number = 0;
protected groovesAddWidth: number = 0; protected groovesAddWidth: number = 0;
protected groovesAddDepth: number = 0; protected groovesAddDepth: number = 0;

@ -227,6 +227,19 @@ export class Line extends Curve
return ret; return ret;
} }
GetParamAtPoint2(pt: Vector3): number
{
let { param } = this.GetClosestAtPoint(pt, true);
return param;
}
//点在曲线上,已经确定点在曲线的延伸线上
PtOnCurve3(p: Vector3, fuzz = 1e-6): boolean
{
let { param } = this.GetClosestAtPoint(p, true);
return this.ParamOnCurve(param, fuzz);
}
GetClosestAtPoint(pt: Vector3, extend: boolean): { closestPt: Vector3, param: number } GetClosestAtPoint(pt: Vector3, extend: boolean): { closestPt: Vector3, param: number }
{ {
let sp = this.StartPoint; let sp = this.StartPoint;

@ -10,7 +10,7 @@ import { ObjectSnapMode } from '../../Editor/ObjectSnapMode';
import { BufferGeometryUtils } from '../../Geometry/BufferGeometryUtils'; import { BufferGeometryUtils } from '../../Geometry/BufferGeometryUtils';
import { AsVector2, AsVector3, equaln, equalv2, equalv3, updateGeometry } from '../../Geometry/GeUtils'; import { AsVector2, AsVector3, equaln, equalv2, equalv3, updateGeometry } from '../../Geometry/GeUtils';
import { IntersectOption, IntersectPolylineAndCurve } from '../../GraphicsSystem/IntersectWith'; import { IntersectOption, IntersectPolylineAndCurve } from '../../GraphicsSystem/IntersectWith';
import { PolyOffsetUtil } from '../../GraphicsSystem/OffsetPolyline'; import { OffsetPolyline } from '../../GraphicsSystem/OffsetPolyline';
import { RenderType } from '../../GraphicsSystem/RenderType'; import { RenderType } from '../../GraphicsSystem/RenderType';
import { Factory } from '../CADFactory'; import { Factory } from '../CADFactory';
import { CADFiler } from '../CADFiler'; import { CADFiler } from '../CADFiler';
@ -877,9 +877,27 @@ export class Polyline extends Curve
PtOnCurve(pt: Vector3): boolean PtOnCurve(pt: Vector3): boolean
{ {
let param = this.GetParamAtPoint(pt); for (let i = 0; i < this.EndParam; i++)
return this.ParamOnCurve(param); {
let c = this.GetCurveAtIndex(i);
if (c.PtOnCurve(pt))
return true;
} }
return false;
}
//点在曲线上,已经确定点在曲线的延伸线上
PtOnCurve3(p: Vector3, fuzz = 1e-6): boolean
{
for (let i = 0; i < this.EndParam; i++)
{
let c = this.GetCurveAtIndex(i);
if (c.PtOnCurve3(p, fuzz))
return true;
}
return false;
}
PtInCurve(pt: Vector3) PtInCurve(pt: Vector3)
{ {
return this.IsClose && IsPointInPolyLine(this, pt); return this.IsClose && IsPointInPolyLine(this, pt);
@ -946,13 +964,15 @@ export class Polyline extends Curve
//偏移 //偏移
GetOffsetCurves(offsetDist: number): Array<Curve> GetOffsetCurves(offsetDist: number): Array<Curve>
{ {
let polyOffestUtil = new PolyOffsetUtil(this, offsetDist); if (equaln(offsetDist, 0)) return [];
return polyOffestUtil.GetOffsetCurves(); let polyOffestUtil = new OffsetPolyline(this, offsetDist);
return polyOffestUtil.Do();
} }
GetFeedingToolPath(offsetDist: number): Array<Curve> GetFeedingToolPath(offsetDist: number): Array<Curve>
{ {
let polyOffestUtil = new PolyOffsetUtil(this, offsetDist); if (equaln(offsetDist, 0)) return [];
return polyOffestUtil.GetOffsetCurves(true); let polyOffestUtil = new OffsetPolyline(this, offsetDist, true);
return polyOffestUtil.Do();
} }
/** /**
* *
@ -1280,7 +1300,7 @@ export class Polyline extends Curve
arc.MoveGripPoints([2], moveVec); arc.MoveGripPoints([2], moveVec);
this.m_LineData[frontIndex].bul = arc.Bul; this.m_LineData[frontIndex].bul = arc.Bul;
} }
if (this.GetBuilgeAt(cuIndex)) if ((cuIndex !== ptCout - 1) && this.GetBuilgeAt(cuIndex))
{ {
let arc = this.GetCurveAtIndex(cuIndex) as Arc; let arc = this.GetCurveAtIndex(cuIndex) as Arc;
arc.MoveGripPoints([0], moveVec); arc.MoveGripPoints([0], moveVec);

@ -67,6 +67,7 @@ export class ObjectCollection<T extends CADObject> extends CADObject
undoRec.WriteObjectHistoryPath(this, hisRec); undoRec.WriteObjectHistoryPath(this, hisRec);
} }
if (obj)
obj.GoodBye(); obj.GoodBye();
} }

@ -126,7 +126,6 @@ export function IsPointInPolyLine(pl: Polyline, pt: Vector3): boolean
} }
continue; continue;
} }
if (equaln(sp.x, pt.x) && sp.y > pt.y) if (equaln(sp.x, pt.x) && sp.y > pt.y)
{ {
let der = arc.GetFistDeriv(0); let der = arc.GetFistDeriv(0);
@ -142,7 +141,7 @@ export function IsPointInPolyLine(pl: Polyline, pt: Vector3): boolean
for (let pti of arc.IntersectWith(insLine, IntersectOption.ExtendArg)) for (let pti of arc.IntersectWith(insLine, IntersectOption.ExtendArg))
{ {
if (pti.y < pt.y || equalv3(sp, pti) || equalv3(ep, pti)) if (pti.y < pt.y || equalv3(sp, pti, 1e-5) || equalv3(ep, pti, 1e-5))
continue; continue;
let der = arc.GetFistDeriv(pti); let der = arc.GetFistDeriv(pti);

@ -5,6 +5,7 @@ import { CommandState } from './CommandState';
import { JigUtils } from './JigUtils'; import { JigUtils } from './JigUtils';
export interface Command export interface Command
{ {
NoHistory?: boolean;
exec: Function;//函数可以返回true,实现放弃命令的任何操作. exec: Function;//函数可以返回true,实现放弃命令的任何操作.
} }
@ -24,9 +25,10 @@ class CommandMachine
arrayRemoveOnce(app.Editor.CommandStore.historyCmdList, cmdName) arrayRemoveOnce(app.Editor.CommandStore.historyCmdList, cmdName)
app.Editor.CommandStore.historyCmdList.push(cmdName); app.Editor.CommandStore.historyCmdList.push(cmdName);
if (cmdName === "U" || cmdName === "REDO") let cmd = this.CommandMap.get(cmdName);
if (cmd.NoHistory)
{ {
await this.CommandMap.get(cmdName).exec(); await cmd.exec();
app.Editor.UpdateScreen(); app.Editor.UpdateScreen();
return; return;
} }
@ -36,7 +38,7 @@ class CommandMachine
let abort: boolean = true; let abort: boolean = true;
try try
{ {
abort = await this.CommandMap.get(cmdName).exec(); abort = await cmd.exec();
} }
catch (error) catch (error)
{ {

@ -92,12 +92,13 @@ import { Fbx } from "../Add-on/loadfbx";
import { LookOverBoardInfos } from "../Add-on/LookOverBoardInfos"; import { LookOverBoardInfos } from "../Add-on/LookOverBoardInfos";
import { MirrorCommand } from "../Add-on/Mirror"; import { MirrorCommand } from "../Add-on/Mirror";
import { Command_Move } from "../Add-on/Move"; import { Command_Move } from "../Add-on/Move";
import { Command_Offset } from "../Add-on/Offset"; import { Command_DynOffset, Command_DynOffsetToolPath, Command_Offset } from "../Add-on/Offset";
import { OffsetX } from "../Add-on/OffsetX"; import { OffsetX } from "../Add-on/OffsetX";
import { Open } from "../Add-on/Open"; import { Open } from "../Add-on/Open";
import { PasteClip } from "../Add-on/PasteClip"; import { PasteClip } from "../Add-on/PasteClip";
import { Pedit } from "../Add-on/Pedit"; import { Pedit } from "../Add-on/Pedit";
import { Command_PLTest } from "../Add-on/polytest"; import { Command_PLTest } from "../Add-on/polytest";
import { Command_Purge } from "../Add-on/Purge";
import { Command_RestoreColor } from "../Add-on/RestoreColor"; import { Command_RestoreColor } from "../Add-on/RestoreColor";
import { Command_Reverse } from "../Add-on/Reverse"; import { Command_Reverse } from "../Add-on/Reverse";
import { Command_Rotate } from "../Add-on/Rotate"; import { Command_Rotate } from "../Add-on/Rotate";
@ -134,7 +135,6 @@ import { CommandServer } from '../DatabaseServices/CommandServer';
import { AutoTempateSizeAction } from '../DatabaseServices/Template/TemplateTest'; import { AutoTempateSizeAction } from '../DatabaseServices/Template/TemplateTest';
import { ICommand } from '../UI/Components/CommandPanel/CommandList'; import { ICommand } from '../UI/Components/CommandPanel/CommandList';
import { commandMachine } from './CommandMachine'; import { commandMachine } from './CommandMachine';
import { Command_Purge } from "../Add-on/Purge";
export function registerCommand() export function registerCommand()
{ {
@ -236,6 +236,9 @@ export function registerCommand()
commandMachine.RegisterCommand("testFilletCode", new TestFillet()); commandMachine.RegisterCommand("testFilletCode", new TestFillet());
commandMachine.RegisterCommand("O", new Command_Offset()); commandMachine.RegisterCommand("O", new Command_Offset());
commandMachine.RegisterCommand("OT", new Command_DynOffset());
commandMachine.RegisterCommand("TO", new Command_DynOffsetToolPath());
commandMachine.RegisterCommand("Length", new Command_Length()); commandMachine.RegisterCommand("Length", new Command_Length());
//绘制灯 //绘制灯

@ -52,11 +52,15 @@ export class Box3Ext extends Box3
interBox.max.setComponent(splitType, Math.max(this.min.getComponent(splitType), b2.min.getComponent(splitType))); interBox.max.setComponent(splitType, Math.max(this.min.getComponent(splitType), b2.min.getComponent(splitType)));
return interBox; return interBox;
} }
intersectsBox(box: this, fuzz = 1e-8) intersectsBox(box: this, fuzz = 1e-8): boolean
{ {
// 重载three.js的相交判断,加入误差 return IntersectsBox(this, box, fuzz);
return box.max.x < this.min.x - fuzz || box.min.x > this.max.x + fuzz ||
box.max.y < this.min.y - fuzz || box.min.y > this.max.y + fuzz ||
box.max.z < this.min.z - fuzz || box.min.z > this.max.z + fuzz ? false : true;
} }
} }
export function IntersectsBox(box1: Box3, box2: Box3, fuzz = 1e-6): boolean
{
return box2.max.x < box1.min.x - fuzz || box2.min.x > box1.max.x + fuzz ||
box2.max.y < box1.min.y - fuzz || box2.min.y > box1.max.y + fuzz ||
box2.max.z < box1.min.z - fuzz || box2.min.z > box1.max.z + fuzz ? false : true;
}

@ -34,12 +34,14 @@ export class CurveMap
return stands; return stands;
} }
addCurveToMap(cu: Curve) AddCurveToMap(cu: Curve)
{ {
let startS = this.GetStand(cu.StartPoint); let sp = cu.StartPoint;
let endS = this.GetStand(cu.EndPoint); let ep = cu.EndPoint;
let routeS2E: Route = { curve: cu, to: endS }; let startS = this.GetStand(sp);
let routeE2S: Route = { curve: cu, to: startS }; let endS = this.GetStand(ep);
let routeS2E: Route = { curve: cu, to: endS, s: sp, e: ep };
let routeE2S: Route = { curve: cu, to: startS, s: ep, e: sp };
startS.routes.push(routeS2E); startS.routes.push(routeS2E);
endS.routes.push(routeE2S); endS.routes.push(routeE2S);
} }

@ -1,6 +1,7 @@
import { Box3, BufferGeometry, Geometry, Line, Matrix4, Mesh, Object3D, Vector, Vector2, Vector3 } from 'three'; import { Box3, BufferGeometry, Geometry, Line, Matrix4, Mesh, Object3D, Vector, Vector2, Vector3 } from 'three';
import { ToFixed } from '../Common/Utils'; import { ToFixed } from '../Common/Utils';
export const IdentityMtx4 = new Matrix4();
export const ZeroVec = new Vector3(); export const ZeroVec = new Vector3();
export const XAxis = new Vector3(1, 0, 0); export const XAxis = new Vector3(1, 0, 0);
export const YAxis = new Vector3(0, 1, 0); export const YAxis = new Vector3(0, 1, 0);
@ -374,3 +375,14 @@ export function SnapPoint(sqCenter: Vector3, snapPt: Vector3, size: number)
return Math.abs(sqCenter.x - snapPt.x) < size return Math.abs(sqCenter.x - snapPt.x) < size
&& Math.abs(sqCenter.y - snapPt.y) < size; && Math.abs(sqCenter.y - snapPt.y) < size;
} }
export function SelectNearP(pts: Vector3[], refPt: Vector3): Vector3
{
if (pts.length > 1)
{
let dist1 = refPt.distanceToSquared(pts[0]);
let dist2 = refPt.distanceToSquared(pts[1]);
return dist1 <= dist2 ? pts[0] : pts[1];
}
return pts[0];
}

@ -12,6 +12,8 @@ export interface Route
{ {
curve: Curve; //路线的曲线 curve: Curve; //路线的曲线
to: Stand; //终点的点 to: Stand; //终点的点
s: Vector3;
e: Vector3;
} }
@ -238,12 +240,12 @@ export class RegionParse
let arcs = this.BreakArc(cu); let arcs = this.BreakArc(cu);
if (arcs.length > 1) if (arcs.length > 1)
{ {
arcs.forEach(a => curveMap.addCurveToMap(a)); arcs.forEach(a => curveMap.AddCurveToMap(a));
this.ExpLineMap.set(cu, arcs); this.ExpLineMap.set(cu, arcs);
continue; continue;
} }
} }
curveMap.addCurveToMap(cu); curveMap.AddCurveToMap(cu);
} }
//排序,根据角度逆时针排序. //排序,根据角度逆时针排序.

@ -6,9 +6,8 @@ import { Circle } from "../DatabaseServices/Entity/Circle";
import { Curve } from "../DatabaseServices/Entity/Curve"; import { Curve } from "../DatabaseServices/Entity/Curve";
import { Line } from "../DatabaseServices/Entity/Line"; import { Line } from "../DatabaseServices/Entity/Line";
import { Polyline } from "../DatabaseServices/Entity/Polyline"; import { Polyline } from "../DatabaseServices/Entity/Polyline";
import { angle, equaln, equalv3, isParallelTo } from "../Geometry/GeUtils"; import { angle, equaln, equalv3, isParallelTo, SelectNearP } from "../Geometry/GeUtils";
import { IntersectOption } from "./IntersectWith"; import { IntersectOption } from "./IntersectWith";
import { PolyOffsetUtil } from "./OffsetPolyline";
/** /**
*线 *线
@ -132,7 +131,7 @@ export function CalcEdgeSealing(cus: Curve[])
&& laterLine.PtOnCurve(p) && laterLine.PtOnCurve(p)
); );
let iPt = PolyOffsetUtil.SelectFitInterPt(tPts.length > 0 ? tPts : iPts, frontLine.EndPoint); let iPt = SelectNearP(tPts.length > 0 ? tPts : iPts, frontLine.EndPoint);
frontLine.EndPoint = iPt; frontLine.EndPoint = iPt;
laterLine.StartPoint = iPt; laterLine.StartPoint = iPt;

@ -56,7 +56,14 @@ function CheckPointOnCurve(intPts: Vector3[], c1: Curve, c2: Curve, extType: Int
{ {
return intPts.filter(p => return intPts.filter(p =>
{ {
return (extType & IntersectOption.ExtendThis || c1.PtOnCurve(p, tolerance)) && (extType & IntersectOption.ExtendArg || c2.PtOnCurve(p, tolerance)) if (!(extType & IntersectOption.ExtendThis))
if (!c1.PtOnCurve3(p, tolerance))
return false;
if (!(extType & IntersectOption.ExtendArg))
if (!c2.PtOnCurve3(p, tolerance))
return false;
return true;
}); });
} }

@ -11,7 +11,7 @@ export class LinkSelf
private curveIndexData: WeakMap<Curve, number> = new WeakMap(); private curveIndexData: WeakMap<Curve, number> = new WeakMap();
sealCus: Set<Curve>[] = []; sealCus: Set<Curve>[] = [];
noSealCus: Curve[][] = []; noSealCus: Curve[][] = [];
private m_Count; private m_Count: number;
private cuMap: CurveMap; private cuMap: CurveMap;
constructor(cus: Curve[]) constructor(cus: Curve[])
{ {
@ -279,7 +279,7 @@ export class LinkSelf
GenerateCurveMap(breakCus: Curve[]) GenerateCurveMap(breakCus: Curve[])
{ {
let cuMap = new CurveMap(); let cuMap = new CurveMap();
breakCus.forEach(c => cuMap.addCurveToMap(c)); breakCus.forEach(c => cuMap.AddCurveToMap(c));
//所有的站点 逆序排序. //所有的站点 逆序排序.
for (let [, stand] of cuMap.m_NodeMap) for (let [, stand] of cuMap.m_NodeMap)
{ {

File diff suppressed because it is too large Load Diff

@ -1,16 +1,16 @@
import { Vector3 } from "three";
import { IsRect, equalCurve } from "../../Common/CurveUtils";
import { Singleton } from "../../Common/Singleton"; import { Singleton } from "../../Common/Singleton";
import { Contour } from "../../DatabaseServices/Contour";
import { Board, IModeling } from "../../DatabaseServices/Entity/Board"; import { Board, IModeling } from "../../DatabaseServices/Entity/Board";
import { Circle } from "../../DatabaseServices/Entity/Circle"; import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Contour } from "../../DatabaseServices/Contour";
import { Curve } from "../../DatabaseServices/Entity/Curve"; import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { Shape } from "../../DatabaseServices/Shape"; import { Shape } from "../../DatabaseServices/Shape";
import { ShapeManager } from "../../DatabaseServices/ShapeManager"; import { ShapeManager } from "../../DatabaseServices/ShapeManager";
import { BoolOpeartionType } from "../BoolOperateUtils"; import { RegionParse, Route } from "../../Geometry/RegionParse";
import { OptimizeToolPath } from "./OptimizeToolPath"; import { BoolOpeartionType, isTargetCurInOrOnSourceCur } from "../BoolOperateUtils";
import { equalCurve, IsRect } from "../../Common/CurveUtils"; import { GetCurveToInDir, OptimizeToolPath, GetOffsetCurves } from "./OptimizeToolPath";
import { Vector3 } from "three";
import { RegionParse } from "../../Geometry/RegionParse";
/** /**
* *
@ -27,40 +27,30 @@ export class FeedingToolPath extends Singleton
{ {
let outline = shape.Outline.Curve.Clone(); let outline = shape.Outline.Curve.Clone();
let dir = this.GetCurveToInDir(outline); let dir = GetCurveToInDir(outline);
let offsetCus: Curve[] = [outline]; let offsetCus: Curve[] = [outline];
//偏移后不闭合的走刀路径
let uncloseCurves: Curve[] = [];
//获得形状外孔轮廓 //获得形状外孔轮廓
let holes: Contour[] = []; let holes: Contour[] = [];
/**用于判断孤岛是否与外轮廓相交 */
let holeOffsetCus: Curve[] = [];
for (let h of shape.Holes) for (let h of shape.Holes)
{ {
if (!isOut) if (!isOut)
holes.push(h.Clone()); holes.push(h.Clone());
else else
{ {
let dir = -this.GetCurveToInDir(h.Curve); let dir = -GetCurveToInDir(h.Curve);
let tmpCus: Curve[]; let cus: Curve[];
if (h.Curve instanceof Polyline) if (h.Curve instanceof Circle)
{ cus = h.Curve.GetOffsetCurves(knifRadius * dir);
tmpCus = h.Curve.GetFeedingToolPath(knifRadius * dir);
if (tmpCus[0] instanceof Polyline && !tmpCus[0].IsClose)
{
uncloseCurves.push(tmpCus[0]);
let reg = new RegionParse(tmpCus[0].Explode() as Curve[], 3);
tmpCus.length = 0;
for (let routes of reg.RegionsOutline)
for (let r of routes)
tmpCus.push(r.curve);
}
}
else else
tmpCus = h.Curve.GetOffsetCurves(knifRadius * dir); cus = h.Curve.GetFeedingToolPath(knifRadius * dir);
let con = Contour.CreateContour(tmpCus); holeOffsetCus.push(...h.Curve.GetOffsetCurves(knifRadius * dir).filter(c => c.IsClose));
if (con)
holes.push(con); holes.push(...this.GetContours(cus as Polyline[], offsetCus));
} }
} }
@ -71,7 +61,7 @@ export class FeedingToolPath extends Singleton
offsetDist += knifRadius; offsetDist += knifRadius;
let retCus: Curve[] = []; let retCus: Curve[] = [];
if (outline instanceof Polyline && isOut && offsetDist === knifRadius) if (outline instanceof Polyline)
retCus.push(...outline.GetFeedingToolPath(offsetDist * dir)); retCus.push(...outline.GetFeedingToolPath(offsetDist * dir));
else else
retCus.push(...outline.GetOffsetCurves(offsetDist * dir)); retCus.push(...outline.GetOffsetCurves(offsetDist * dir));
@ -82,12 +72,11 @@ export class FeedingToolPath extends Singleton
let isInt = false; let isInt = false;
for (let c of retCus) for (let c of retCus)
{ {
if (holes.length > 0 && c.IsClose) if (holes.length > 0)
{ {
isInt = holes.some(h => h.Curve.IntersectWith(c, 0).length > 0 || h.CuInOutline(c)); isInt = holes.some(h => h.Curve.IntersectWith(c, 0).length > 0 || h.CuInOutline(c));
if (isInt) break; if (isInt) break;
} }
c.ColorIndex = outline.ColorIndex; c.ColorIndex = outline.ColorIndex;
offsetCus.push(c); offsetCus.push(c);
} }
@ -97,7 +86,8 @@ export class FeedingToolPath extends Singleton
let holesMg = new ShapeManager(); let holesMg = new ShapeManager();
holesMg.AppendShapeList(holes.map(h => new Shape(h))); holesMg.AppendShapeList(holes.map(h => new Shape(h)));
let shapeMg = new ShapeManager(); let shapeMg = new ShapeManager();
shapeMg.AppendShapeList(retCus.map(c => new Shape(Contour.CreateContour([c])))); let cons = this.GetContours(retCus as Polyline[], offsetCus);
shapeMg.AppendShapeList(cons.map(c => new Shape(c)));
shapeMg.BoolOper(holesMg, BoolOpeartionType.Subtract); shapeMg.BoolOper(holesMg, BoolOpeartionType.Subtract);
for (let s of shapeMg.ShapeList) for (let s of shapeMg.ShapeList)
{ {
@ -107,54 +97,48 @@ export class FeedingToolPath extends Singleton
break; break;
} }
} }
let vailHoles: Contour[] = [];
for (let h of holes) for (let i = 0; i < holes.length; i++)
{ {
let h = holes[i]
//如果加工洞外圈和最外轮廓相交,则去掉 //如果加工洞外圈和最外轮廓相交,则去掉
if (h.Curve.IntersectWith(outline, 0).length > 0) if (h.Curve.IntersectWith(outline, 0).length > 0)
continue; continue;
let isVail = true; let isVail = true;
//若最外轮廓内偏移一个刀半径的曲线 和最内轮廓相交或者被包含,则去掉.且不与洞曲线相等 //若最外轮廓内偏移一个刀半径的曲线 和最内轮廓相交或者被包含,则去掉.且不与洞曲线相等
if (isOut) if (isOut)
{ {
let tmpCus = outline.GetOffsetCurves(dir * offsetDist); let outlineOffsetCus = outline.GetOffsetCurves(dir * knifRadius).filter(c => c.IsClose);
for (let c of tmpCus) let outlineCus = GetOffsetCurves(outline, dir * knifRadius);
for (let j = 0; j < outlineOffsetCus.length; j++)
{ {
if (h.Curve.IntersectWith(c, 0).length > 0) let c = outlineOffsetCus[j];
let ho = holeOffsetCus[i];
if (h.Curve.IntersectWith(outlineCus[j], 0).length > 0)
{ {
if (!(offsetDist === knifRadius && equalCurve(h.Curve, c))) if (!(equalCurve(ho, c) || isTargetCurInOrOnSourceCur(c as Polyline, h.Curve)))
{ {
isVail = false; isVail = false;
break; break;
} }
} }
else if (h.Area > c.Area) else if (ho.Area > c.Area)
{ {
isVail = false; isVail = false;
break; break;
} }
} }
} }
if (isVail) if (isVail)
offsetCus.push(h.Curve); vailHoles.push(h);
} }
if (isOut)
vailHoles = Shape.mergeContours(vailHoles);
offsetCus.push(...uncloseCurves); offsetCus.push(...vailHoles.map(h => h.Curve));
return offsetCus; return offsetCus;
} }
/**
* 线
*/
private GetCurveToInDir(cu: Curve): number
{
let dir = -Math.sign(cu.Area2);
if (cu instanceof Circle)
dir = -1;
return dir;
}
/**用于测试走刀路径 */ /**用于测试走刀路径 */
TestCalcPath(br: Board) TestCalcPath(br: Board)
{ {
@ -211,7 +195,7 @@ export class FeedingToolPath extends Singleton
{ {
//通孔只切一刀 //通孔只切一刀
let outline = shape.Outline.Curve; let outline = shape.Outline.Curve;
let dir = this.GetCurveToInDir(outline); let dir = GetCurveToInDir(outline);
let paths: Curve[]; let paths: Curve[];
if (outline instanceof Circle) if (outline instanceof Circle)
paths = outline.GetOffsetCurves(dir * knifeRadius); paths = outline.GetOffsetCurves(dir * knifeRadius);
@ -256,4 +240,45 @@ export class FeedingToolPath extends Singleton
} }
} }
} }
private GetContours(cus: (Polyline | Circle)[], retCus: Curve[])
{
let cons: Contour[] = [];
for (let c of cus)
{
if (c.IsClose)
{
cons.push(Contour.CreateContour(c));
}
else
{
let expCus = c.Explode() as Curve[];
let regParse = new RegionParse(expCus);
//分析封闭包围区域
const parseRoute = (routeSet: Set<Route>[]) =>
{
for (let routes of routeSet)
{
let cs: Curve[] = [];
for (let r of routes)
cs.push(r.curve);
let c = Contour.CreateContour(cs, false);
if (c && c.Area > 1e-3)
cons.push(c);
}
}
parseRoute(regParse.RegionsOutline);
parseRoute(regParse.RegionsInternal);
for (let c of expCus)
{
if (!regParse.GetCueveUsed(c))
{
retCus.push(c);
}
}
}
}
return cons;
}
} }

@ -1,12 +1,12 @@
import { Curve } from "../../DatabaseServices/Entity/Curve"; import { arrayRemoveIf } from "../../Common/ArrayExt";
import { Shape } from "../../DatabaseServices/Shape"; import { ConverCircleToPolyline, curveLinkGroup, equalCurve } from "../../Common/CurveUtils";
import { matrixAlignCoordSys } from "../../Common/Matrix4Utils"; import { matrixAlignCoordSys } from "../../Common/Matrix4Utils";
import { curveLinkGroup, ConverCircleToPolyline, equalCurve } from "../../Common/CurveUtils";
import { Line } from "../../DatabaseServices/Entity/Line";
import { Circle } from "../../DatabaseServices/Entity/Circle"; import { Circle } from "../../DatabaseServices/Entity/Circle";
import { Curve } from "../../DatabaseServices/Entity/Curve";
import { Line } from "../../DatabaseServices/Entity/Line";
import { Polyline } from "../../DatabaseServices/Entity/Polyline"; import { Polyline } from "../../DatabaseServices/Entity/Polyline";
import { comparePoint, AsVector3, AsVector2 } from "../../Geometry/GeUtils"; import { Shape } from "../../DatabaseServices/Shape";
import { arrayLast, arrayRemoveIf } from "../../Common/ArrayExt"; import { AsVector2, AsVector3, comparePoint } from "../../Geometry/GeUtils";
/** /**
* ,线 * ,线
@ -15,7 +15,7 @@ import { arrayLast, arrayRemoveIf } from "../../Common/ArrayExt";
* @param rad * @param rad
* @returns tool path * @returns tool path
*/ */
export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: number, isTest = false): Curve[] export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: number): Curve[]
{ {
// 去掉最外轮廓 // 去掉最外轮廓
let outline = offsetCus.shift(); let outline = offsetCus.shift();
@ -46,7 +46,13 @@ export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: nu
if (noCloseCus.length > 0) if (noCloseCus.length > 0)
{ {
let culist: Curve[] = []; let culist: Curve[] = [];
noCloseCus.forEach(c => culist.push(...c.Explode() as Curve[])); noCloseCus.forEach(c =>
{
if (c instanceof Polyline)
culist.push(...c.Explode() as Curve[]);
else
culist.push(c);
});
//移除相等的曲线避免重复走刀 //移除相等的曲线避免重复走刀
RempveEqualCurves(culist); RempveEqualCurves(culist);
let groups = curveLinkGroup(culist); let groups = curveLinkGroup(culist);
@ -61,8 +67,10 @@ export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: nu
plList.push(pl); plList.push(pl);
} }
} }
let dir = GetCurveToInDir(outline);
let cantIntCur: Curve[] = [];
cantIntCur.push(...GetOffsetCurves(outline, rad * dir));
let cantIntCur: Curve[] = [outline];
if (originShape.Holes.length > 0) if (originShape.Holes.length > 0)
{ {
for (let h of originShape.Holes) for (let h of originShape.Holes)
@ -70,7 +78,7 @@ export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: nu
let dir = Math.sign(h.Curve.Area2); let dir = Math.sign(h.Curve.Area2);
if (h.Curve instanceof Circle) if (h.Curve instanceof Circle)
dir = 1; dir = 1;
cantIntCur.push(...h.Curve.GetOffsetCurves(rad * dir)); cantIntCur.push(...GetOffsetCurves(h.Curve, rad * dir));
} }
} }
@ -91,7 +99,7 @@ export function OptimizeToolPath(offsetCus: Curve[], originShape: Shape, rad: nu
let isDisVail = false; let isDisVail = false;
isDisVail = cantIntCur.some(c => c.IntersectWith(refLine, 0).length > 0); isDisVail = cantIntCur.some(c => c.IntersectWith(refLine, 0).length > 1);
if (isDisVail) if (isDisVail)
{ {
@ -170,43 +178,42 @@ function ChangePlListStartPt(plList: Polyline[])
} }
} }
} }
/** /**
* 线, * 线,
* @param plList
*/ */
function SortPlByStartPt(plList: Polyline[]) function SortPlByStartPt(pls: Polyline[]): Polyline[]
{ {
if (plList.length <= 1) return plList; if (pls.length <= 1) return pls;
let result = [plList[0]]; let result = [pls[0]];
let usedPl = new WeakSet([plList[0]]); let usedPl = new WeakSet([pls[0]]);
let p = pls[0].StartPoint;
while (true) while (true)
{ {
if (plList.length === result.length) if (pls.length === result.length)
break; break;
let refPt = arrayLast(result).StartPoint;
let vaildPl: Polyline; let vaildPl: Polyline;
let refDist: number; let minDist: number = Infinity;
for (let pl of plList) for (let pl of pls)
{ {
if (usedPl.has(pl)) if (usedPl.has(pl))
continue; continue;
let sPt = pl.StartPoint; let dist = pl.StartPoint.distanceToSquared(p);
if (dist < minDist)
if (!refDist || sPt.distanceToSquared(refPt) < refDist)
{ {
refDist = sPt.distanceToSquared(refPt); minDist = dist;
vaildPl = pl; vaildPl = pl;
} }
} }
p = vaildPl.StartPoint;
result.push(vaildPl); result.push(vaildPl);
usedPl.add(vaildPl); usedPl.add(vaildPl);
} }
plList.length = 0; pls.length = 0;
plList.push(...result); pls.push(...result);
} }
function RempveEqualCurves(cus: Curve[]) function RempveEqualCurves(cus: Curve[])
@ -228,3 +235,17 @@ function RempveEqualCurves(cus: Curve[])
} }
arrayRemoveIf(cus, (c) => needRemoveCurve.has(c)); arrayRemoveIf(cus, (c) => needRemoveCurve.has(c));
} }
export function GetOffsetCurves(cu: Curve, dist: number): Curve[]
{
if (cu instanceof Polyline)
return cu.GetFeedingToolPath(dist);
else
return cu.GetOffsetCurves(dist);
}
/** 获得曲线内偏移方向*/
export function GetCurveToInDir(cu: Curve): number
{
return cu.IsClockWise ? 1 : -1;
}

Loading…
Cancel
Save