Compare commits
628 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2023ba3f7d | |||
| 27c1823a54 | |||
| f111827545 | |||
| 7cdc1ba5a3 | |||
| 1d68a1ee8e | |||
| 6f7b614c3a | |||
| f02f29c543 | |||
| 06cfe1bb96 | |||
| 736353bbac | |||
| f4b3312672 | |||
| 3178bb5f27 | |||
| 552ce70231 | |||
| c2a79b2665 | |||
| f72c949563 | |||
| bdcb00d1bd | |||
| 42fcb1847b | |||
| a7b36280f3 | |||
| cdef3931be | |||
| d3f2587cc2 | |||
| d343f474e4 | |||
| b7fee9696e | |||
| 4f48337f62 | |||
| 96907d5952 | |||
| 3c5d2571fe | |||
| 7005bf43a4 | |||
| 4726cf4d35 | |||
| b971eda771 | |||
| 3ded6fe87d | |||
| 5195c23dfb | |||
| 5f1255a625 | |||
| 82accd45c1 | |||
| e46768b14b | |||
| 32307efd78 | |||
| e84df69f6f | |||
| 669f38a731 | |||
| afef5597b2 | |||
| 4a0bd638fa | |||
| 4bfb38b9d5 | |||
| 0d62cd9bbd | |||
| 913d5f60ca | |||
| 3dddbdf5cd | |||
| 3245f7fe75 | |||
| f144cda136 | |||
| d374e133f0 | |||
| 0c435a646d | |||
| d0ac226753 | |||
| d92344f2bb | |||
| 51c584c6c4 | |||
| 176bbec8a7 | |||
| a508da8b18 | |||
| 91ca84f77a | |||
| d27fdb9904 | |||
| 3b816e2a45 | |||
| 11a46ca58c | |||
| 6e0aec3bec | |||
| 11dd35af44 | |||
| 17fe5f0c9c | |||
| c8e2d88bb7 | |||
| c6ac9fbcf8 | |||
| e636e75b76 | |||
| a01346577f | |||
| 61a5e53351 | |||
| 739c17b4b6 | |||
| 144ef16b0b | |||
| 58c635cb9d | |||
| a39b9a7651 | |||
| 75889983de | |||
| e4a14b629c | |||
| 3640a17632 | |||
| 2a3f809e4e | |||
| d7dd7b9f80 | |||
| cd48e2de3b | |||
| 8f43efe282 | |||
| 025bcbba1d | |||
| d0131deb40 | |||
| 1325f83291 | |||
| 961acdbc76 | |||
| 6789d74abc | |||
| 062c92377e | |||
| 383f4c7abd | |||
| 4cc6161918 | |||
| c0ebbee347 | |||
| e3b4f5bd2d | |||
| 5df3ab6d98 | |||
| 63fb9a638b | |||
| d62d6946c3 | |||
| 7f0237ced4 | |||
| 23621630d5 | |||
| b3abcf73c3 | |||
| 1219e9bd80 | |||
| dced59b9a1 | |||
| 3bf2972089 | |||
| 6dd3ea5cc2 | |||
| 592a92ebdb | |||
| 1321742afe | |||
| f1f93124a0 | |||
| c8e9d1e012 | |||
| 7b0cd0939b | |||
| 3b5ab5089b | |||
| b36d919d8f | |||
| e22a207f03 | |||
| 24dbef52c9 | |||
| 5498b1e25c | |||
| 86851bb67e | |||
| b99e12c56f | |||
| 129b1b919e | |||
| 711c250cfc | |||
| 0f05216474 | |||
| c57b7c95c1 | |||
| 62e041ed8c | |||
| 2983454ce2 | |||
| 6d5046cb6d | |||
| 91fcf43da9 | |||
| aef1a57e1c | |||
| 71316bac6a | |||
| f1c4f06461 | |||
| 412bbd2a8b | |||
| be64cedfc3 | |||
| 2a6b35d658 | |||
| f51c5c36d0 | |||
| 5599901185 | |||
| fb235bf985 | |||
| 717d7a3fe3 | |||
| c91f468dce | |||
| 1f36657efd | |||
| b70ad5c808 | |||
| da56ef91fd | |||
| 9bd7a152d7 | |||
| 5c287d49bb | |||
| 942f15b49d | |||
| 20b61cda42 | |||
| b1b1d6d434 | |||
| c7ad32ef30 | |||
| 6016db837e | |||
| 2051e0b5d9 | |||
| fddb3f5707 | |||
| 096dd84511 | |||
| e16a2078fc | |||
| e388ae34e3 | |||
| b64c747082 | |||
| 8afa3ae47d | |||
| 1eba68e95b | |||
| 047b339006 | |||
| acd7415835 | |||
| a48460ef76 | |||
| 8ab3896e3a | |||
| 2d481c8a71 | |||
| 7968a4e5ed | |||
| 39d295f412 | |||
| 0bf2cc2a77 | |||
| 433f486091 | |||
| fee6604d5e | |||
| c339fced5c | |||
| a87351778d | |||
| 42687457e0 | |||
| 4a541402da | |||
| ecef487746 | |||
| df483b5623 | |||
| e4d3f5f9a4 | |||
| 02e164dcdf | |||
| ead94e7915 | |||
| dfc3c29439 | |||
| ab538f4bf7 | |||
| 00b6f8583a | |||
| 4cf4a99107 | |||
| 137289e843 | |||
| e7b066e75e | |||
| cd0828f3e0 | |||
| 563697f840 | |||
| 61fc814528 | |||
| 7c90dbabea | |||
| 5ee0f3c373 | |||
| 098bdd0076 | |||
| 40b6da6b44 | |||
| b083dabc6b | |||
| 7fcc3ed42d | |||
| 4ed362f226 | |||
| 39d98f79fb | |||
| c79f7ba245 | |||
| 16354ff435 | |||
| f3a191dd62 | |||
| cb0a5092fb | |||
| 8730f55308 | |||
| 932e98d19c | |||
| 3a69dcfa79 | |||
| 5930674d4a | |||
| df6b20d97f | |||
| 4200af5296 | |||
| b0c9c5be2e | |||
| f2bb1deac4 | |||
| 94ec83aa60 | |||
| e183eec3ea | |||
| b179771ec9 | |||
| d7380a09c1 | |||
| afc316cd1d | |||
| b6f820258a | |||
| 116b605cb1 | |||
| 9f5ce42393 | |||
| 9716d93c15 | |||
| 3465179379 | |||
| c7aad8d917 | |||
| 8ddc1c70e1 | |||
| 5230261be8 | |||
| 8cc8d6eb03 | |||
| 7a95e4c5a3 | |||
| 1c0f182bbc | |||
| 736e20e599 | |||
| c71c8e8c12 | |||
| 9c7a29f939 | |||
| 40bb15e46b | |||
| fb957b61d2 | |||
| 4da9dcb062 | |||
| 60f9302c3f | |||
| 2553f15e7b | |||
| e8d31f2020 | |||
| 4c693ccd60 | |||
| c550fb1848 | |||
| e49bd5a2a0 | |||
| 81be6ce7b9 | |||
| 2d6bf3d9dc | |||
| b2244b7f43 | |||
| 53dcd9c863 | |||
| 75f70d2b30 | |||
| 36b1df1a27 | |||
| 5a445c5c0b | |||
| df828ab2ba | |||
| db855ca99b | |||
| d79cb50aca | |||
| 371ff54d9c | |||
| df7b4ff81f | |||
| f22ea484db | |||
| 574041cf18 | |||
| ff2cc4f999 | |||
| 05c0b0a18b | |||
| 1b9738eace | |||
| 8ee5bc74d5 | |||
| 0a8cc414a5 | |||
| 7a682653cd | |||
| 9286ab6535 | |||
| 85736ab03f | |||
| 673f5c7a9b | |||
| 34d0bcbdfe | |||
| 7abf3027d4 | |||
| ffe3d44cac | |||
| dd23b848ac | |||
| 33cca03698 | |||
| d4d14dd866 | |||
| d6f0fdac50 | |||
| 080605510c | |||
| 1a7b789ef3 | |||
| cc4183a677 | |||
| c2bae56656 | |||
| 38a5c0cbb3 | |||
| 81a8eb698e | |||
| ee4bb7d7c4 | |||
| 8b0d5bddbf | |||
| ba75033f0a | |||
| eb2b90c6f2 | |||
| 3b5c34cb05 | |||
| 2fe22a62c2 | |||
| ff6307fcca | |||
| c6e80a0b6a | |||
| b957cc75be | |||
| fc18539472 | |||
| de7229aee7 | |||
| 53e66032a0 | |||
| 2fc6c30c8f | |||
| f05c5f1261 | |||
| 6af5591cf6 | |||
| 41cbe862e5 | |||
| 057b8273e2 | |||
| 6421c12408 | |||
| 0aca5aeb07 | |||
| bdbd3583b8 | |||
| 626d5b0e51 | |||
| 0bffa0039c | |||
| 9819c8cee8 | |||
| 53ab676750 | |||
| afa4872c97 | |||
| bf56d53faf | |||
| f03adb9206 | |||
| 529fa2e4a0 | |||
| 6df1b90e95 | |||
| 9cba0e6d15 | |||
| f16de3a20c | |||
| 8cfa41d09f | |||
| b59b501366 | |||
| 504bb50b13 | |||
| 969f1266e7 | |||
| fa680b7799 | |||
| e185c85d5e | |||
| acb0a5bd5e | |||
| 62ce576d4d | |||
| 161d3d9b17 | |||
| d88baa070f | |||
| 2b087dde51 | |||
| 7894a8fdc8 | |||
| 0f14e8335a | |||
| 7edf4bced8 | |||
| 4a5639780b | |||
| 0a21a582be | |||
| 0e663c02c4 | |||
| 21afe8165c | |||
| 0247fe5e7c | |||
| 50bad83fba | |||
| 9c93d6c2f3 | |||
| 4d9a50cf94 | |||
| bbdaac5d8d | |||
| 0417c43bcf | |||
| 15585b8f11 | |||
| 59755ec8a5 | |||
| b16dd260d8 | |||
| d37a5a37b7 | |||
| 79dfb4ae87 | |||
| 8b75b6e4c3 | |||
| bcaad08b61 | |||
| cbdeffd93a | |||
| 0ce477a3e7 | |||
| 44eb4d1834 | |||
| 2e26b73208 | |||
| de3fa3201e | |||
| f068aafbb5 | |||
| daedb07135 | |||
| 702e1e446d | |||
| ea87db1ae1 | |||
| b65800843a | |||
| e4c5d8645d | |||
| 85b06c29b4 | |||
| 5254d0c5ca | |||
| 292c2bf87a | |||
| 9d038142a8 | |||
| c5573e438b | |||
| 8c7a0ac026 | |||
| e45bbf2afd | |||
| fc6de68d83 | |||
| a008c169ae | |||
| 3cd6c9299f | |||
| 8e5801d656 | |||
| 1691b7f84a | |||
| 76e4197729 | |||
| fb8bac8681 | |||
| 55a9685add | |||
| afa4be3717 | |||
| 57c03a54c9 | |||
| 91a9adaea4 | |||
| 8657fa32c5 | |||
| b7a4f0bff3 | |||
| f0716e2727 | |||
| b1acf7f4f0 | |||
| 851c053f7c | |||
| 71276a8de3 | |||
| b2e799e1d6 | |||
| eb9aaef53a | |||
| 49340d2629 | |||
| 0b9c9f375c | |||
| cd56f80790 | |||
| 65d826168b | |||
| ea012988df | |||
| 67f3df353f | |||
| 9d34df708d | |||
| 72947f1e36 | |||
| 1cdae73b24 | |||
| a2825b2b6d | |||
| 5bc7036e98 | |||
| 7e545aecd7 | |||
| 0fc8291ef5 | |||
| 0d668c1a4a | |||
| 4b1270f231 | |||
| 9263dc0516 | |||
| b0f7cb93fd | |||
| add3788db4 | |||
| 37c23faae3 | |||
| fa6f12ba3b | |||
| 730dd396f4 | |||
| 3b9f6773f2 | |||
| 97315f6ca4 | |||
| b2be420e36 | |||
| 4ee34b79f8 | |||
| e4ee403d24 | |||
| b709776f5f | |||
| b5a2490fd4 | |||
| 7a18cd1c5c | |||
| 26e1448bbb | |||
| a1ebdb4eb6 | |||
| 6603061f81 | |||
| 1c3d7bf2a6 | |||
| a4a030b776 | |||
| 64a8294ea0 | |||
| 847383d82d | |||
| c16d916a63 | |||
| 91cae44533 | |||
| 56c3e28ac3 | |||
| 3238c86cec | |||
| f050e682ef | |||
| 01c875b34f | |||
| 50b8a8aa94 | |||
| 9f1aad5e49 | |||
| a38c50197b | |||
| fe54dde44e | |||
| 62a3405d6a | |||
| cb9dd807ce | |||
| d60d38a24b | |||
| e598e7986f | |||
| 9bebd2f2ad | |||
| 36d5c39094 | |||
| 1b08f4bbdd | |||
| 4a952b1c9b | |||
| 7a25927054 | |||
| cf022921a7 | |||
| dc798aaaba | |||
| eed89dab37 | |||
| 990bc1a1e4 | |||
| 03433fe3af | |||
| e02611504b | |||
| a835433be4 | |||
| da8f40db17 | |||
| 5468e3f4fa | |||
| 88684e305f | |||
| f8ca8029d7 | |||
| aa9c46cbb5 | |||
| f0cf3c9559 | |||
| 9a638b9470 | |||
| b07fbfc72e | |||
| 0317c37557 | |||
| a98b6bcc09 | |||
| c19861a911 | |||
| 8f8597d442 | |||
| 0c0eb9ef8f | |||
| 4ffb7087bd | |||
| dc070c4556 | |||
| 60729d5f39 | |||
| da7e9dd6e2 | |||
| aeff9fb418 | |||
| e9e897593b | |||
| bfc09d135c | |||
| 0998d0fffc | |||
| 93c87ee720 | |||
| a67a0502fa | |||
| cec0a48be4 | |||
| 0cc63d40eb | |||
| 623eb6e630 | |||
| 1f22299096 | |||
| 3f6c439983 | |||
| 8e22267476 | |||
| aa2b6ccde5 | |||
| ec6cb79a8d | |||
| 76dceb4fc9 | |||
| b1564f7de0 | |||
| 21e4bd6d93 | |||
| 2101d72abe | |||
| 7a01f67c8b | |||
| 2267343afe | |||
| 9a5fe24781 | |||
| 4050aa11c5 | |||
| b75ddae396 | |||
| 2d3f8487ee | |||
| 964647d7e6 | |||
| f78dd0fa83 | |||
| 55ce22b06c | |||
| 50df4f3503 | |||
| 5c8f0c79f6 | |||
| de3f187ddf | |||
| f649954ee1 | |||
| 6e08f2a878 | |||
| 887922a715 | |||
| 640fef2e0a | |||
| 1a338a1a82 | |||
| 4f3fe68283 | |||
| 3908e11d18 | |||
| 4e6c5112e4 | |||
| e1ab88302f | |||
| 2b4090619b | |||
| b90289e42b | |||
| 5e84408685 | |||
| b53c2f833a | |||
| b5fcceaa75 | |||
| f0bfbb6c85 | |||
| 2710f735d1 | |||
| ddffbd2c88 | |||
| fde952499d | |||
| b28102a8cc | |||
| f46db233dc | |||
| df10b45c6b | |||
| 1b13580340 | |||
| 742305b99b | |||
| 1261de4dbb | |||
| b50588f974 | |||
| 9b87de9fa2 | |||
| 5bab4a9aa8 | |||
| c3e7d3d8c7 | |||
| 89c22ffd06 | |||
| 5375752609 | |||
| 0a8f26c993 | |||
| cba9c253e1 | |||
| 71f3bf8809 | |||
| d491536eb4 | |||
| e68465c80b | |||
| dfb8fd2160 | |||
| 746fa61e08 | |||
| d0e0c46e2c | |||
| 19c7f63303 | |||
| 87f6a29db3 | |||
| b04d1ed7a9 | |||
| 54dba7ab41 | |||
| 146c06d27f | |||
| 7c45c1e287 | |||
| d6dc5b8428 | |||
| 28695f9138 | |||
| 66cec4a872 | |||
| 8d1d3f766a | |||
| befed079c8 | |||
| b9138029db | |||
| 2246dbc284 | |||
| 67180b3569 | |||
| 3a2aa2c679 | |||
| 9dd4e043d4 | |||
| 4748bd5ac8 | |||
| 649f97e933 | |||
| 21feed172d | |||
| e853ff7f13 | |||
| 95ff8b21b9 | |||
| a7be952e11 | |||
| 7a67ce9333 | |||
| 695350d3f6 | |||
| aade1d19f1 | |||
| fd4677d099 | |||
| f7a28447fb | |||
| 79b470b18b | |||
| f6d3873ecb | |||
| 92a8cdad99 | |||
| 0c346e2bc7 | |||
| d54caf4ae3 | |||
| ff9ea34ae1 | |||
| c7035305e2 | |||
| bc3c1e377e | |||
| 98eff1b0b9 | |||
| 052cc9e841 | |||
| b6a7ce4eef | |||
| 7a66ad27d8 | |||
| b4878f1ac0 | |||
| 447ebe11e5 | |||
| 8981057d29 | |||
| 3270b573a8 | |||
| 6df0cf3203 | |||
| d67cca385e | |||
| f9d67442d6 | |||
| dea96ccbcc | |||
| 0f4be10330 | |||
| 121abf5864 | |||
| 38e836de2b | |||
| 376c4e3693 | |||
| 48ffd52b16 | |||
| 9a16259ff5 | |||
| 10ae269882 | |||
| 9d845179a4 | |||
| 88bf84cca1 | |||
| 5ba8f1df36 | |||
| c4a05bcb2f | |||
| 5841c9cae0 | |||
| 4fd03a78de | |||
| 420c072670 | |||
| 36477623b8 | |||
| 84d859dfe2 | |||
| 09220bfd68 | |||
| 42aaf6f3eb | |||
| 3f1f365451 | |||
| 9a29ee0e27 | |||
| 619905d720 | |||
| 36ce855ef3 | |||
| 9b0f2c7f59 | |||
| c637ccec47 | |||
| 8f27154604 | |||
| 5d02732db6 | |||
| 36657e17c4 | |||
| e2008bd479 | |||
| e32b85bc2d | |||
| 6dfc50e630 | |||
| b4820ff255 | |||
| 515247a394 | |||
| b5c649821f | |||
| 9ba0c6f4cc | |||
| 35fc94d8cb | |||
| a0316e280c | |||
| 84bcc715a8 | |||
| b34d31029b | |||
| f67865f9cc | |||
| f48053a541 | |||
| 8e917aa6d2 | |||
| f08dee836b | |||
| 261e9ac0c8 | |||
| b51d0c3e64 | |||
| ac23938dd0 | |||
| b9bac347e8 | |||
| 980a1f62df | |||
| 10c5d0fffe | |||
| d7d36b670a | |||
| 581551ee3e | |||
| 487ce0c84b | |||
| 5679733028 | |||
| cd0fc4e449 | |||
| e20b4b5b78 | |||
| b931582120 | |||
| bf14ab1332 | |||
| 3b81a6b92e | |||
| 01bf44cf1e | |||
| b5d879cd3d | |||
| 2b3c285190 | |||
| 99bb83211c | |||
| b854c9588b | |||
| 2361225321 | |||
| eaf1138624 | |||
| ef5c67a4d5 | |||
| ffd714d069 | |||
| dc082d495e | |||
| e8e57ff793 | |||
| 3e16c4b56c | |||
| 77d3fcc7af | |||
| 7322bf5034 | |||
| d340505593 | |||
| 247849d112 | |||
| 1d4bccac4b | |||
| cc7aa66904 | |||
| 303a270359 | |||
| 5f56152a8b | |||
| d6567e94c4 | |||
| a3f05c41fe | |||
| 3143c00729 | |||
| 621bf93ee9 |
@@ -317,6 +317,8 @@ AdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst, bool bNeedSameProp)
|
||||
pCrvCo->RemoveSmallDefects( 2 * LIN_TOL_MIN, ANG_TOL_STD_DEG, true) ;
|
||||
// unisco eventuali tratti allineati
|
||||
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, bNeedSameProp) ;
|
||||
// richiudo i loop per sicurezza
|
||||
pCrvCo->Close() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -134,7 +134,8 @@ GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd,
|
||||
|
||||
// calcolo arco non riuscito, se i punti sono allineati nel giusto verso per essere una retta
|
||||
// verifico se i punti sono allineati nel giusto verso
|
||||
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) {
|
||||
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO ||
|
||||
AreSamePointApprox( ptOther, ptStart) || AreSamePointApprox( ptEnd, ptOther)) {
|
||||
// creo l'oggetto retta
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine))
|
||||
|
||||
+8
-8
@@ -133,22 +133,22 @@ Attribs::Load( NgeReader& ngeIn)
|
||||
unsigned char ucLev ;
|
||||
if ( ! ngeIn.ReadUchar( ucLev, ","))
|
||||
return false ;
|
||||
m_Data[LEVEL] = CLIP( ucLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
m_Data[LEVEL] = Clamp( ucLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
// modo
|
||||
unsigned char ucMode ;
|
||||
if ( ! ngeIn.ReadUchar( ucMode, ","))
|
||||
return false ;
|
||||
m_Data[MODE] = CLIP( ucMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
m_Data[MODE] = Clamp( ucMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
// stato (se SEL è convertito in ON)
|
||||
unsigned char ucStat ;
|
||||
if ( ! ngeIn.ReadUchar( ucStat, ","))
|
||||
return false ;
|
||||
m_Data[STATUS] = CLIP( ucStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
m_Data[STATUS] = Clamp( ucStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
// marcatura (sempre OFF)
|
||||
unsigned char ucMark ;
|
||||
if ( ! ngeIn.ReadUchar( ucMark, ";"))
|
||||
return false ;
|
||||
m_Data[MARK] = CLIP( ucMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
m_Data[MARK] = Clamp( ucMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
// materiale
|
||||
if ( ! ngeIn.ReadInt( m_Material, ";"))
|
||||
return false ;
|
||||
@@ -185,22 +185,22 @@ Attribs::DataFromString( const string& sParam)
|
||||
int nLev ;
|
||||
if ( ! FromString( vsParams[0], nLev))
|
||||
return false ;
|
||||
m_Data[LEVEL] = CLIP( nLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
m_Data[LEVEL] = Clamp( nLev, GDB_LV_USER, GDB_LV_TEMP) ;
|
||||
// modo
|
||||
int nMode ;
|
||||
if ( ! FromString( vsParams[1], nMode))
|
||||
return false ;
|
||||
m_Data[MODE] = CLIP( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
m_Data[MODE] = Clamp( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ;
|
||||
// stato (ammessi solo OFF e ON)
|
||||
int nStat ;
|
||||
if ( ! FromString( vsParams[2], nStat))
|
||||
return false ;
|
||||
m_Data[STATUS] = CLIP( nStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
m_Data[STATUS] = Clamp( nStat, GDB_ST_OFF, GDB_ST_ON) ;
|
||||
// marcatura (ammesso solo OFF)
|
||||
int nMark ;
|
||||
if ( ! FromString( vsParams[3], nMark))
|
||||
return false ;
|
||||
m_Data[MARK] = CLIP( nMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
m_Data[MARK] = Clamp( nMark, GDB_MK_OFF, GDB_MK_OFF) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
#include "/EgtDev/Include/EGkGdbConst.h"
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include "/EgtDev/Include/EgtStringBase.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
|
||||
class NgeWriter ;
|
||||
class NgeReader ;
|
||||
class GeomDB ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#define CLIP( nV, nMIN, nMAX) (( nV < nMIN) ? nMIN : (( nV > nMAX) ? nMAX : nV))
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class Attribs
|
||||
{
|
||||
@@ -46,14 +44,14 @@ class Attribs
|
||||
bool Load( NgeReader& ngeIn) ;
|
||||
void SetLevel( int nLev)
|
||||
{ m_OldData[LEVEL] = m_Data[LEVEL] ;
|
||||
m_Data[LEVEL] = CLIP( nLev, GDB_LV_USER, GDB_LV_TEMP) ; }
|
||||
m_Data[LEVEL] = Clamp( nLev, GDB_LV_USER, GDB_LV_TEMP) ; }
|
||||
void RevertLevel( void)
|
||||
{ std::swap( m_Data[LEVEL], m_OldData[LEVEL]) ; }
|
||||
int GetLevel( void) const
|
||||
{ return m_Data[LEVEL] ; }
|
||||
void SetMode( int nMode)
|
||||
{ m_OldData[MODE] = m_Data[MODE] ;
|
||||
m_Data[MODE] = CLIP( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ; }
|
||||
m_Data[MODE] = Clamp( nMode, GDB_MD_STD, GDB_MD_HIDDEN) ; }
|
||||
void RevertMode( void)
|
||||
{ std::swap( m_Data[MODE], m_OldData[MODE]) ; }
|
||||
int GetMode( void) const
|
||||
@@ -61,13 +59,13 @@ class Attribs
|
||||
void SetStatus( int nStat)
|
||||
{ if ( m_Data[STATUS] != GDB_ST_SEL)
|
||||
m_OldData[STATUS] = m_Data[STATUS] ;
|
||||
m_Data[STATUS] = CLIP( nStat, GDB_ST_OFF, GDB_ST_SEL) ; }
|
||||
m_Data[STATUS] = Clamp( nStat, GDB_ST_OFF, GDB_ST_SEL) ; }
|
||||
void RevertStatus( void)
|
||||
{ SetStatus( m_OldData[STATUS]) ; }
|
||||
int GetStatus( void) const
|
||||
{ return m_Data[STATUS] ; }
|
||||
void SetMark( void)
|
||||
{ m_Data[MARK] = GDB_MK_ON ; }
|
||||
void SetMark( int nMark)
|
||||
{ m_Data[MARK] = Clamp( nMark, GDB_MK_OFF, GDB_MK_ON_2) ; }
|
||||
void ResetMark( void)
|
||||
{ m_Data[MARK] = GDB_MK_OFF ; }
|
||||
int GetMark( void) const
|
||||
|
||||
+9
-6
@@ -83,7 +83,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
|
||||
const PolyLine& PL, double& dDist)
|
||||
const PolyLine& PL, double& dDist, double dTol)
|
||||
{
|
||||
// calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco
|
||||
PtrOwner<ICurve> pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ;
|
||||
@@ -122,7 +122,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
}
|
||||
}
|
||||
}
|
||||
// non c'è intersezione, assegno valore medio
|
||||
// non c'è intersezione, assegno valore medio
|
||||
if ( dU < -0.5)
|
||||
dU = 0.5 ;
|
||||
// elimino casi vicino agli estremi, danno solo problemi
|
||||
@@ -142,7 +142,10 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
Point3d ptPrev = ptCurr ;
|
||||
while ( bPnt) {
|
||||
double dLen = Dist( ptCurr, ptPrev) ;
|
||||
int nStep = ( dLen < STEP ? 2 : 1) * int( dLen / STEP) + 1 ;
|
||||
int nStep = int( dLen / STEP) + 1 ;
|
||||
int nMinStep = ( dLen > 50 * dTol ? 3 : ( dLen > 10 * dTol ? 2 : 1)) ;
|
||||
int nMaxStep = 10 ;
|
||||
nStep = Clamp( nStep, nMinStep, nMaxStep) ;
|
||||
for ( int i = 1 ; i <= nStep ; ++ i) {
|
||||
double dCoeff = double( i) / nStep ;
|
||||
Point3d ptP = Media( ptPrev, ptCurr, dCoeff) ;
|
||||
@@ -163,7 +166,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir
|
||||
static ICurve*
|
||||
CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg)
|
||||
{
|
||||
// se i due punti coincidono, non si può fare alcunché
|
||||
// se i due punti coincidono, non si può fare alcunché
|
||||
if ( AreSamePointApprox( ptP0, ptP1))
|
||||
return nullptr ;
|
||||
|
||||
@@ -205,14 +208,14 @@ CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dD
|
||||
double dDir0RelDeg = DiffAngle( dDir0Deg, dDirDiffDeg) ;
|
||||
// direzione iniziale secondo arco limite rispetto a direzione P0->P1 (dalla finale simmetrico e invert)
|
||||
double dDir1RelDeg = - DiffAngle( dDir1Deg, dDirDiffDeg) ;
|
||||
// nel caso di direzioni a 180deg si sceglie la più compatta
|
||||
// nel caso di direzioni a 180deg si sceglie la più compatta
|
||||
if ( abs( abs( dDir1RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
|
||||
dDir1RelDeg = ( dDir0RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
|
||||
else if ( abs( abs( dDir0RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
|
||||
dDir0RelDeg = ( dDir1RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
|
||||
// intervallo angolare ammissibile a partire da direzione iniziale primo arco ammissibile ( == Dir0)
|
||||
double dDeltaAngDeg = - dDir0RelDeg + dDir1RelDeg ;
|
||||
// se non è nella regione, prendo l'altra parte di arco
|
||||
// se non è nella regione, prendo l'altra parte di arco
|
||||
if ( ! AngleInSpan( dDirStartRelDeg, dDir0RelDeg, dDeltaAngDeg))
|
||||
pArc->ToExplementary() ;
|
||||
// inverto per avere parametrizzazione crescente allontanandosi da Dir0 e avvicinandosi a Dir1
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
ICurve* GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg,
|
||||
const PolyLine& PL, double& dDist) ;
|
||||
const PolyLine& PL, double& dDist, double dTol) ;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CAvSilhouetteSurfTm.h Data : 16.06.24 Versione : 2.6f2
|
||||
// Contenuto : Dichiarazione della classe calcolo multi-silhouette.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 10.06.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CAvToolSurfTm.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class CAvParSilhouettesSurfTm : public ICAvParSilhouettesSurfTm
|
||||
{
|
||||
public :
|
||||
// generica
|
||||
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol) override ;
|
||||
bool SetData( const CISURFTMPVECTOR& vpStm, const Frame3d& frPlanes, double dTol,
|
||||
double dSideAng, double dDiam, double dCornRad, double dMaxMat, double dOffsR,
|
||||
double dMaxDepth) override ;
|
||||
bool GetSilhouette( double dLevel, POLYLINEVECTOR& vPL) override ;
|
||||
|
||||
public :
|
||||
CAvParSilhouettesSurfTm( void) ;
|
||||
|
||||
private :
|
||||
bool Prepare( void) ;
|
||||
|
||||
private :
|
||||
CISURFTMPVECTOR m_vpStm ;
|
||||
CAvToolSurfTm m_cavTstm ;
|
||||
Frame3d m_frGrid ;
|
||||
double m_dTol ;
|
||||
double m_dSharpedTol ;
|
||||
int m_nStepX ;
|
||||
int m_nStepY ;
|
||||
double m_dRad ;
|
||||
double m_dCornRad ;
|
||||
double m_dMaxMat ;
|
||||
double m_dSideAng ;
|
||||
double m_dOffsR ;
|
||||
double m_dDimZ ;
|
||||
double m_dLevelOffs ;
|
||||
double m_dMaxDepth ;
|
||||
bool m_bGridOk ;
|
||||
bool m_bTool ;
|
||||
DBLVECTOR m_vdGrid ;
|
||||
} ;
|
||||
+518
-54
@@ -1,13 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2018-2018
|
||||
// EgalTech 2018-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CAvToolSurfTm.cpp Data : 08.05.18 Versione : 1.9e2
|
||||
// File : CAvToolSurfTm.cpp Data : 07.06.24 Versione : 2.6f2
|
||||
// Contenuto : Implementazione della classe CAvToolSurfTm.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 27.04.18 DS Creazione modulo.
|
||||
//
|
||||
// 07.06.24 DS Con tolleranza lineare negativa non si controlla il punto medio.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -24,6 +24,7 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const int STEP_PE = 50 ;
|
||||
const double MAX_MOVE = 20000 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICAvToolSurfTm*
|
||||
@@ -37,10 +38,29 @@ CreateCAvToolSurfTm( void)
|
||||
// CAvToolSurfTm
|
||||
//----------------------------------------------------------------------------
|
||||
CAvToolSurfTm::CAvToolSurfTm( void)
|
||||
: m_Tool( false)
|
||||
: m_frMove( false), m_Tool( false)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::Clear( void)
|
||||
{
|
||||
// pulisco la lista dei puntatori a Stm
|
||||
m_vSTM.clear() ;
|
||||
// pulisco e inizializzo la prima posizione della lista delle basi per gli indici dei triangoli
|
||||
m_vBaseInd.clear() ;
|
||||
m_vBaseInd.emplace_back( 0) ;
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
// reset utensile
|
||||
m_Tool.Clear() ;
|
||||
// reset riferimento
|
||||
m_frMove.Reset( false) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
||||
@@ -50,6 +70,9 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
||||
// pulisco e inizializzo la prima posizione della lista delle basi per gli indici dei triangoli
|
||||
m_vBaseInd.clear() ;
|
||||
m_vBaseInd.emplace_back( 0) ;
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
// non tocco l'utensile
|
||||
// aggiungo la superficie
|
||||
return AddSurfTm( Stm) ;
|
||||
}
|
||||
@@ -58,7 +81,7 @@ CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm)
|
||||
bool
|
||||
CAvToolSurfTm::AddSurfTm( const ISurfTriMesh& Stm)
|
||||
{
|
||||
// verifico validità superficie
|
||||
// verifico validità superficie
|
||||
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &Stm) ;
|
||||
if ( pStm == nullptr || ! pStm->IsValid())
|
||||
return false ;
|
||||
@@ -99,7 +122,8 @@ CAvToolSurfTm::SetGenTool( const ICurveComposite* pToolOutline)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist)
|
||||
CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, Vector3d* pvtTriaN) const
|
||||
{
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
@@ -107,20 +131,78 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Imposto il riferimento di movimento
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
m_frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
m_frMove.Set( ORIG, vtMove) ;
|
||||
// Eseguo controllo
|
||||
// Se riferimento di movimento già presente
|
||||
if ( m_frMove.IsValid()) {
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimenti di movimento uguali, sfrutto HashGrid 2d
|
||||
if ( AreSameFrame( frMove, m_frMove)) {
|
||||
// Eseguo controllo
|
||||
Point3d ptCurr = ptT ;
|
||||
Vector3d vtTriaN ;
|
||||
dTotDist = MyTestPositionHG( ptCurr, vtDir, vtTriaN) ;
|
||||
if ( pvtTriaN != nullptr)
|
||||
*pvtTriaN = vtTriaN ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
}
|
||||
// Altrimenti eseguo controllo diretto
|
||||
Point3d ptCurr = ptT ;
|
||||
dTotDist = MyTestPosition( ptCurr, vtDir) ;
|
||||
Vector3d vtTriaN ;
|
||||
dTotDist = MyTestPosition( ptCurr, vtDir, vtMove, vtTriaN) ;
|
||||
if ( pvtTriaN != nullptr)
|
||||
*pvtTriaN = vtTriaN ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol)
|
||||
CAvToolSurfTm::TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, VCT3DVECTOR& vVtN) const
|
||||
{
|
||||
// Funzione per calcolo collisione tra utensile e superfici ;
|
||||
// dToTDist è la distanza di traslazione del punto ptT lungo vtDir per evitare la collisione,
|
||||
// vVtN è la normale del triangolo che genera collsione ( NB. Nel caso di più triangoli concorrenti,
|
||||
// vengono restituite tutte le normali trovate)
|
||||
|
||||
// Inizializzazione parametri
|
||||
dTotDist = 0 ;
|
||||
vVtN.clear() ;
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se riferimento di movimento già presente
|
||||
if ( m_frMove.IsValid()) {
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimenti di movimento uguali, sfrutto HashGrid 2d
|
||||
if ( AreSameFrame( frMove, m_frMove)) {
|
||||
// Eseguo controllo
|
||||
Point3d ptCurr = ptT ;
|
||||
dTotDist = MyTestPositionHGAdv( ptCurr, vtDir, vVtN) ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
}
|
||||
// Altrimenti eseguo controllo diretto
|
||||
Point3d ptCurr = ptT ;
|
||||
dTotDist = MyTestPositionAdv( ptCurr, vtDir, vtMove, vVtN) ;
|
||||
return ( dTotDist > - EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
|
||||
{
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
@@ -128,17 +210,139 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimento di movimento non presente o diverso dal calcolato
|
||||
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
|
||||
// Salvo nuovo riferimento
|
||||
m_frMove = frMove ;
|
||||
// Ricalcolo HashGrid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
}
|
||||
// Determino il numero di punti dell'insieme
|
||||
m_nTotPnt = int( vPntM.size()) ;
|
||||
// Recupero il numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
|
||||
m_nCurrPnt = 0 ;
|
||||
bOk = TestSubSeries( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = m_nTotPnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
m_nCurrPnt = 0 ;
|
||||
m_bBreak = false ;
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeries, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
int nNextPE = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nFin ;
|
||||
}
|
||||
}
|
||||
if ( m_nCurrPnt > nNextPE) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
|
||||
nNextPE += STEP_PE ;
|
||||
if ( nRes == 1)
|
||||
m_bBreak = true ;
|
||||
}
|
||||
}
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
|
||||
{
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti da verificare
|
||||
for ( int i = nFirst ; i <= nLast ; ++ i) {
|
||||
// verifico il punto
|
||||
Vector3d vtTriaN ;
|
||||
double dMove = MyTestPositionHG( vPntM[i].first, vtDir, vtTriaN) ;
|
||||
vPntM[i].second = dMove ;
|
||||
if ( dMove < - EPS_SMALL)
|
||||
return false ;
|
||||
++ m_nCurrPnt ;
|
||||
// se singolo thread
|
||||
if ( nId == -1) {
|
||||
// gestione eventi (ogni STEP_PE punti)
|
||||
if (( m_nCurrPnt % STEP_PE) == 0) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
|
||||
if ( nRes == 1)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti multithread
|
||||
else {
|
||||
if ( m_bBreak)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff)
|
||||
{
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
// Imposto il riferimento di movimento
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
m_frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
// Controllo la tolleranza lineare (se negativa non vanno fatti controlli sui punti medi)
|
||||
if ( dLinTol > -EPS_ZERO)
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
else
|
||||
m_frMove.Set( ORIG, vtMove) ;
|
||||
// Predispongo Hash Grid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
dLinTol = -1 ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimento di movimento non presente o diverso dal calcolato
|
||||
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
|
||||
// Salvo nuovo riferimento
|
||||
m_frMove = frMove ;
|
||||
// Ricalcolo HashGrid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
}
|
||||
// Determino il numero di punti del path
|
||||
m_nTotPnt = int( lPntM.size()) ;
|
||||
// Recupero il numero massimo di thread concorrenti
|
||||
@@ -146,8 +350,9 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
|
||||
bOk = TestSubPath( -1, lPntM, vtDir, dLinTol) ;
|
||||
ProcessEvents( 100, 0) ;
|
||||
m_nCurrPnt = 0 ;
|
||||
bOk = TestSubPath( -1, lPntM, vtDir, dLinTol, dProgCoeff) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
@@ -167,7 +372,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
m_bBreak = false ;
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPath, this, i, ref( vlPntM[i]), cref( vtDir), dLinTol) ;
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubPath, this, i, ref( vlPntM[i]), cref( vtDir), dLinTol, dProgCoeff) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
int nNextPE = 0 ;
|
||||
@@ -179,7 +384,7 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
}
|
||||
}
|
||||
if ( m_nCurrPnt > nNextPE) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt), 10) ;
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
|
||||
nNextPE += STEP_PE ;
|
||||
if ( nRes == 1)
|
||||
m_bBreak = true ;
|
||||
@@ -191,18 +396,98 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
lPntM.pop_back() ;
|
||||
lPntM.splice( lPntM.end(), vlPntM[i]) ;
|
||||
}
|
||||
ProcessEvents( 100, 0) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol)
|
||||
CAvToolSurfTm::TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff)
|
||||
{
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
// NB. la posizione del punto non viene modificata :
|
||||
// get<0> vPntM[i] è il punto su cui viene posizionata la testa dell'utensile ( const)
|
||||
// get<1> vPntM[i] è il parametro di traslazione del punto lungo vtDir per evitare collisioni con i triangoli
|
||||
// get<2> vPntM[i] è un vettore di Vector3d contenente tutte le normali di tangenza ( a meno di 10 * EPS_SMALL)
|
||||
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Calcolo nuovo riferimento di movimento
|
||||
Frame3d frMove ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
else
|
||||
frMove.Set( ORIG, vtMove) ;
|
||||
// Se riferimento di movimento non presente o diverso dal calcolato
|
||||
if ( ! m_frMove.IsValid() || ! AreSameFrame( frMove, m_frMove)) {
|
||||
// Salvo nuovo riferimento
|
||||
m_frMove = frMove ;
|
||||
// Ricalcolo HashGrid
|
||||
if ( ! PrepareHashGrid())
|
||||
return false ;
|
||||
}
|
||||
// Determino il numero di punti del path
|
||||
m_nTotPnt = int( vPntM.size()) ;
|
||||
// Recupero il numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
// Se un solo thread o pochi punti
|
||||
if ( nThreadMax <= 1 || m_nTotPnt < 500) {
|
||||
m_nCurrPnt = 0 ;
|
||||
bOk = TestSubSeriesAdv( -1, vPntM, vtDir, 0, m_nTotPnt - 1, dProgCoeff) ;
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = m_nTotPnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, m_nTotPnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
m_nCurrPnt = 0 ;
|
||||
m_bBreak = false ;
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i)
|
||||
vRes[i] = async( launch::async, &CAvToolSurfTm::TestSubSeriesAdv, this, i, ref( vPntM), cref( vtDir), vFstLst[i].first, vFstLst[i].second, dProgCoeff) ;
|
||||
// attendo i risultati
|
||||
int nFin = 0 ;
|
||||
int nNextPE = 0 ;
|
||||
while ( nFin < nPartCnt) {
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nFin ;
|
||||
}
|
||||
}
|
||||
if ( m_nCurrPnt > nNextPE) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 10) ;
|
||||
nNextPE += STEP_PE ;
|
||||
if ( nRes == 1)
|
||||
m_bBreak = true ;
|
||||
}
|
||||
}
|
||||
ProcessEvents( int( 100 * dProgCoeff), 0) ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff)
|
||||
{
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti
|
||||
@@ -212,12 +497,13 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
while ( itPntMCurr != lPntM.end()) {
|
||||
// verifico il punto
|
||||
ptCurr = itPntMCurr->first ;
|
||||
double dMove = MyTestPositionHG( itPntMCurr->first, vtDir) ;
|
||||
itPntMCurr->second = - dMove ;
|
||||
Vector3d vtTriaN ;
|
||||
double dMove = MyTestPositionHG( itPntMCurr->first, vtDir, vtTriaN) ;
|
||||
itPntMCurr->second = dMove ;
|
||||
if ( dMove < - EPS_SMALL)
|
||||
return false ;
|
||||
// se esiste il punto precedente devo verificare il medio
|
||||
if ( itPntMPrev != lPntM.end()) {
|
||||
// se esiste il punto precedente e richiesto devo verificare il medio
|
||||
if ( itPntMPrev != lPntM.end() && dLinTol > 0) {
|
||||
MyTestMidPointHG( lPntM, itPntMPrev, itPntMCurr, ptPrev, ptCurr, vtDir, dLinTol, 1) ;
|
||||
}
|
||||
// passo al successivo
|
||||
@@ -229,7 +515,7 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
if ( nId == -1) {
|
||||
// gestione eventi (ogni STEP_PE punti)
|
||||
if (( m_nCurrPnt % STEP_PE) == 0) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt), 0) ;
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
|
||||
if ( nRes == 1)
|
||||
return false ;
|
||||
}
|
||||
@@ -243,10 +529,44 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff)
|
||||
{
|
||||
// Se vettore vuoto, non devo fare alcunché
|
||||
if ( vPntM.empty())
|
||||
return true ;
|
||||
// Ciclo sui punti da verificare
|
||||
for ( int i = nFirst ; i <= nLast ; ++ i) {
|
||||
// verifico il punto
|
||||
Point3d ptCurr = get<0>( vPntM[i]) ;
|
||||
get<1>( vPntM[i]) = MyTestPositionHGAdv( ptCurr, vtDir, get<2>( vPntM[i])) ;
|
||||
if ( get<1>( vPntM[i]) < - EPS_SMALL)
|
||||
return false ;
|
||||
++ m_nCurrPnt ;
|
||||
// se singolo thread
|
||||
if ( nId == -1) {
|
||||
// gestione eventi (ogni STEP_PE punti)
|
||||
if (( m_nCurrPnt % STEP_PE) == 0) {
|
||||
int nRes = ProcessEvents( int( m_nCurrPnt * 100. / m_nTotPnt * dProgCoeff), 0) ;
|
||||
if ( nRes == 1)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti multithread
|
||||
else {
|
||||
if ( m_bBreak)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev)
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const
|
||||
{
|
||||
// se superato limite di ricursione, esco
|
||||
const int MAX_LEV = 10 ;
|
||||
@@ -256,7 +576,8 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
Point3d ptMid = Media( ptPrev, ptCurr, 0.5) ;
|
||||
// ne effettuo la correzione per evitare la collisione
|
||||
Point3d ptNewMid = ptMid ;
|
||||
double dMidMove = MyTestPositionHG( ptNewMid, vtDir) ;
|
||||
Vector3d vtTriaN ;
|
||||
double dMidMove = MyTestPositionHG( ptNewMid, vtDir, vtTriaN) ;
|
||||
if ( dMidMove < - EPS_SMALL)
|
||||
return false ;
|
||||
// massima distanza ammissibile
|
||||
@@ -265,7 +586,7 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
if ( abs(( Media( itPntMPrev->first, itPntMCurr->first, 0.5) - ptNewMid) * m_frMove.VersZ()) > 0.5 * dLinTol ||
|
||||
SqDist( itPntMPrev->first, itPntMCurr->first) > dMaxSqDist) {
|
||||
// aggiungo
|
||||
lPntM.emplace( itPntMCurr, ptNewMid, - dMidMove) ;
|
||||
lPntM.emplace( itPntMCurr, ptNewMid, dMidMove) ;
|
||||
auto itPntMMid = itPntMCurr ;
|
||||
-- itPntMMid ;
|
||||
// verifico intervallo precedente
|
||||
@@ -278,20 +599,48 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir)
|
||||
CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const
|
||||
{
|
||||
// box dell'utensile con suo movimento
|
||||
BBox3d b3Tool ;
|
||||
// utensile
|
||||
b3Tool.Add( ptT) ;
|
||||
b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ;
|
||||
if ( vtDir.IsX())
|
||||
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsY())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsZ())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
|
||||
else {
|
||||
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ;
|
||||
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ;
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// aggiungo movimento
|
||||
BBox3d b3Moved = b3Tool ;
|
||||
b3Moved.Translate( MAX_MOVE * vtMove) ;
|
||||
b3Tool.Add( b3Moved) ;
|
||||
|
||||
// determino movimento minimo per evitare collisione con superfici
|
||||
double dTotDist = 0 ;
|
||||
vtTriaN = V_NULL ;
|
||||
for ( auto pStm : m_vSTM) {
|
||||
Triangle3d Tria ;
|
||||
for ( int nTria = pStm->GetFirstTriangle( Tria) ;
|
||||
nTria != SVT_NULL ;
|
||||
nTria = pStm->GetNextTriangle( nTria, Tria)) {
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * m_frMove.VersZ() ;
|
||||
INTVECTOR vTria ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
|
||||
for ( int nTria : vTria) {
|
||||
Triangle3d Tria ;
|
||||
if ( pStm->GetTriangle( nTria, Tria)) {
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * vtMove ;
|
||||
vtTriaN = Tria.GetN() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,7 +649,61 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
|
||||
CAvToolSurfTm::MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const
|
||||
{
|
||||
// box dell'utensile con suo movimento
|
||||
BBox3d b3Tool ;
|
||||
// utensile
|
||||
b3Tool.Add( ptT) ;
|
||||
b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ;
|
||||
if ( vtDir.IsX())
|
||||
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsY())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
|
||||
else if ( vtDir.IsZ())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
|
||||
else {
|
||||
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ;
|
||||
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ;
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// aggiungo movimento
|
||||
BBox3d b3Moved = b3Tool ;
|
||||
b3Moved.Translate( MAX_MOVE * vtMove) ;
|
||||
b3Tool.Add( b3Moved) ;
|
||||
|
||||
// determino movimento minimo per evitare collisione con superfici
|
||||
double dTotDist = 0 ;
|
||||
vVtTriaN.clear() ;
|
||||
for ( auto pStm : m_vSTM) {
|
||||
INTVECTOR vTria ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) {
|
||||
for ( int nTria : vTria) {
|
||||
Triangle3d Tria ;
|
||||
if ( pStm->GetTriangle( nTria, Tria)) {
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
// se devo traslare il punto, c'è collisione
|
||||
if ( dDist > EPS_SMALL) {
|
||||
if ( dDist > 10 * EPS_SMALL) {
|
||||
vVtTriaN.clear() ;
|
||||
dTotDist += dDist ;
|
||||
ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ;
|
||||
}
|
||||
vVtTriaN.push_back( Tria.GetN()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const
|
||||
{
|
||||
// calcolo box utensile nel riferimento di movimento
|
||||
BBox3d b3Tool ;
|
||||
@@ -320,8 +723,10 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
// ciclo sui triangoli che intersecano box in 2d
|
||||
|
||||
// ciclo sui triangoli che intersecano box in 2d
|
||||
double dTotDist = 0 ;
|
||||
vtTriaN = V_NULL ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Tool, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
@@ -337,11 +742,70 @@ CAvToolSurfTm::MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir)
|
||||
if ( dDist > EPS_SMALL) {
|
||||
dTotDist += dDist ;
|
||||
ptT += dDist * m_frMove.VersZ() ;
|
||||
vtTriaN = Tria.GetN() ;
|
||||
}
|
||||
else if ( dDist < -EPS_SMALL)
|
||||
return -1 ;
|
||||
}
|
||||
}
|
||||
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CAvToolSurfTm::MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const
|
||||
{
|
||||
// calcolo box utensile nel riferimento di movimento
|
||||
BBox3d b3Tool ;
|
||||
Point3d ptTL = ptT ; ptTL.ToLoc( m_frMove) ;
|
||||
Vector3d vtDirL = vtDir ; vtDirL.ToLoc( m_frMove) ;
|
||||
b3Tool.Add( ptTL) ;
|
||||
b3Tool.Add( ptTL - vtDirL * m_Tool.GetHeigth()) ;
|
||||
if ( vtDirL.IsX())
|
||||
b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ;
|
||||
else if ( vtDirL.IsY())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ;
|
||||
else if ( vtDirL.IsZ())
|
||||
b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ;
|
||||
else {
|
||||
double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDirL.x * vtDirL.x) ;
|
||||
double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDirL.y * vtDirL.y) ;
|
||||
double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDirL.z * vtDirL.z) ;
|
||||
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
|
||||
}
|
||||
|
||||
// ciclo sui triangoli che intersecano box in 2d
|
||||
double dTotDist = 0. ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Tool, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
// recupero la superficie
|
||||
int nInd = vnIds[i] ;
|
||||
int nSurf = GetSurfInd( nInd) ;
|
||||
if ( nSurf == -1)
|
||||
return -1 ;
|
||||
// recupero il triangolo
|
||||
int nT = nInd - m_vBaseInd[nSurf] ;
|
||||
Triangle3d Tria ;
|
||||
if ( ! m_vSTM[nSurf]->GetTriangle( nT, Tria))
|
||||
return -1 ;
|
||||
// calcolo della collisione
|
||||
double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, m_frMove.VersZ()) ;
|
||||
if ( dDist < - EPS_SMALL)
|
||||
return -1 ;
|
||||
// se devo traslare il punto, c'è collisione
|
||||
if ( dDist > EPS_SMALL) {
|
||||
if ( dDist > 10 * EPS_SMALL) {
|
||||
vVtTriaN.clear() ;
|
||||
dTotDist += dDist ;
|
||||
ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ;
|
||||
}
|
||||
vVtTriaN.push_back( Tria.GetN()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dTotDist ;
|
||||
}
|
||||
|
||||
@@ -352,7 +816,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
|
||||
// pulisco HashGrid 2d
|
||||
m_HGrids.Clear() ;
|
||||
// verifico esistenza superfici
|
||||
if ( m_vSTM.size() == 0 || m_vBaseInd.size() < m_vSTM.size() + 1)
|
||||
if ( m_vSTM.empty() || m_vBaseInd.size() < m_vSTM.size() + 1)
|
||||
return false ;
|
||||
// creo HashGrid 2d
|
||||
const int LIM_HG_TRIA = 256 ;
|
||||
@@ -379,7 +843,7 @@ CAvToolSurfTm::PrepareHashGrid( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
CAvToolSurfTm::GetSurfInd( int nT)
|
||||
CAvToolSurfTm::GetSurfInd( int nT) const
|
||||
{
|
||||
// verifico la presenza di almeno un intervallo
|
||||
if ( m_vBaseInd.size() < 2)
|
||||
|
||||
+32
-7
@@ -34,22 +34,47 @@ class CAvToolSurfTm : public ICAvToolSurfTm
|
||||
{ return m_Tool.GetRadius() ; }
|
||||
double GetToolHeight( void) const override
|
||||
{ return m_Tool.GetHeigth() ; }
|
||||
double GetToolTipHeight( void) const override
|
||||
{ return m_Tool.GetTipHeigth() ; } ;
|
||||
double GetToolTipRadius( void) const override
|
||||
{ return m_Tool.GetTipRadius() ; } ;
|
||||
double GetToolCornRadius( void) const override
|
||||
{ return m_Tool.GetCornRadius() ; } ;
|
||||
CISURFTMPVECTOR GetvStm( void) const {
|
||||
CISURFTMPVECTOR vcStm ;
|
||||
for ( int i = 0 ; i < int( m_vSTM.size()) ; ++ i)
|
||||
vcStm.emplace_back( CloneSurfTriMesh( m_vSTM[i])) ;
|
||||
return vcStm ;
|
||||
}
|
||||
const ICurveComposite& GetToolOutline( bool bApprox = false) const override
|
||||
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
|
||||
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, double& dTotDist) override ;
|
||||
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol) override ;
|
||||
|
||||
bool TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, Vector3d* pvtTriaN = nullptr) const override ;
|
||||
bool TestPositionAdv( const Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove,
|
||||
double& dTotDist, VCT3DVECTOR& vVtN) const override ;
|
||||
|
||||
bool TestSeries( PNTUVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ;
|
||||
bool TestSeriesAdv( PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dProgCoeff = 1) override ;
|
||||
|
||||
bool TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d& vtMove, double dLinTol, double dProgCoeff = 1) override ;
|
||||
|
||||
public :
|
||||
CAvToolSurfTm( void) ;
|
||||
bool Clear( void) ;
|
||||
|
||||
private :
|
||||
bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol) ;
|
||||
double MyTestPosition( Point3d& ptT, const Vector3d& vtDir) ;
|
||||
double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir) ;
|
||||
bool TestSubSeries( int nId, PNTUVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
|
||||
bool TestSubSeriesAdv( int nId, PNTUVVECTVECTOR& vPntM, const Vector3d& vtDir, int nFirst, int nLast, double dProgCoeff) ;
|
||||
bool TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, double dLinTol, double dProgCoeff) ;
|
||||
double MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const ;
|
||||
double MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const ;
|
||||
double MyTestPositionHG( Point3d& ptT, const Vector3d& vtDir, Vector3d& vtTriaN) const ;
|
||||
double MyTestPositionHGAdv( Point3d& ptT, const Vector3d& vtDir, VCT3DVECTOR& vVtTriaN) const ;
|
||||
bool MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPntMPrev, const PNTULIST::iterator& itPntMCurr,
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) ;
|
||||
const Point3d& ptPrev, const Point3d& ptCurr, const Vector3d& vtDir, double dLinTol, int nLev) const ;
|
||||
bool PrepareHashGrid( void) ;
|
||||
int GetSurfInd( int nT) ;
|
||||
int GetSurfInd( int nT) const ;
|
||||
|
||||
private :
|
||||
typedef std::vector<const SurfTriMesh*> CSURFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh
|
||||
|
||||
+1
-1
@@ -2503,7 +2503,7 @@ DiskSegmentEscapeDistLongMot( const Point3d& ptDiskCen, double dDiskRad,
|
||||
double dSegDist = 0. ;
|
||||
for ( int nSol = 0 ; nSol < nRoot ; ++ nSol) {
|
||||
// Soluzione interna al segmento
|
||||
if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen) {
|
||||
if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen + EPS_ZERO) {
|
||||
Point3d ptC = ptSeg + vdRoots[nSol] * vtSeg ;
|
||||
// Distanza del punto soluzione dal piano del disco nella posizione iniziale
|
||||
double dCurDist = PointPlaneSignedDist( ptC, ptDiskCen, vtMove) ;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2024
|
||||
// EgalTech 2020-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CDeClosedSurfTmClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
|
||||
// File : CDeClosedSurfTmClosedSurfTm.h Data : 23.01.26 Versione : 3.1a3
|
||||
// Contenuto : Implementazione funzione verifica collisione tra
|
||||
// SurfTm e SurfTm.
|
||||
//
|
||||
// Modifiche : 13.11.20 LM Creazione modulo.
|
||||
// 24.03.24 DS Aggiunta TestSurfTmSurfTm.
|
||||
// 23.01.26 DS In TestSurfTmSurfTm aggiunto flag per collisione quando una delle due è chiusa e contiene l'altra.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -45,10 +46,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
BBox3d b3BoxA, b3BoxB ;
|
||||
pSrfA->GetLocalBBox( b3BoxA) ;
|
||||
pSrfB->GetLocalBBox( b3BoxB) ;
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxB.Expand( dSafeDist) ;
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
if ( ! b3BoxA.Overlaps( b3BoxB))
|
||||
return false ;
|
||||
// Recupero i triangoli di A che interferiscono col box di B
|
||||
@@ -61,13 +62,13 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
continue ;
|
||||
BBox3d b3BoxTriaA ;
|
||||
trTriaA.GetLocalBBox( b3BoxTriaA) ;
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxTriaA.Expand( dSafeDist) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ;
|
||||
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Al termine della chiamata i TempInt dei triangoli valgono 0.
|
||||
pSrfB->ResetTempInts() ;
|
||||
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
|
||||
@@ -84,14 +85,14 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
// Ciclo sui vertici del triangolo.
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
// Se il triangolo adiacente al triangolo corrente su questo edge
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
int nAdjTriaTempFlag ;
|
||||
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
|
||||
continue ;
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
|
||||
return true ;
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
|
||||
double dEdgeLen = vtEdgeV.Len() ;
|
||||
vtEdgeV /= dEdgeLen ;
|
||||
@@ -111,10 +112,10 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
}
|
||||
}
|
||||
// Non ho trovato collisioni fra triangoli delle superfici.
|
||||
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
|
||||
// Se il BBox della prima superficie non è interno a quello della seconda e viceversa, non c'è collisione
|
||||
if ( ! b3BoxA.Encloses( b3BoxB) && ! b3BoxB.Encloses( b3BoxA))
|
||||
return false ;
|
||||
// La collisione c'è se una superficie è dentro l'altra.
|
||||
// La collisione c'è se una superficie è dentro l'altra.
|
||||
Point3d ptPointA, ptPointB ;
|
||||
pSrfA->GetFirstVertex( ptPointA) ;
|
||||
pSrfB->GetFirstVertex( ptPointB) ;
|
||||
@@ -127,7 +128,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
|
||||
// Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist)
|
||||
TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist, bool bTestEnclosion)
|
||||
{
|
||||
// Recupero le superfici base
|
||||
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
|
||||
@@ -140,10 +141,10 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
BBox3d b3BoxA, b3BoxB ;
|
||||
pSrfA->GetLocalBBox( b3BoxA) ;
|
||||
pSrfB->GetLocalBBox( b3BoxB) ;
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxB.Expand( dSafeDist) ;
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
|
||||
if ( ! b3BoxA.Overlaps( b3BoxB))
|
||||
return false ;
|
||||
// Recupero i triangoli di A che interferiscono col box di B
|
||||
@@ -156,13 +157,13 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
continue ;
|
||||
BBox3d b3BoxTriaA ;
|
||||
trTriaA.GetLocalBBox( b3BoxTriaA) ;
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
|
||||
if ( dSafeDist > EPS_SMALL)
|
||||
b3BoxTriaA.Expand( dSafeDist) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ;
|
||||
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Settare tutti i triangoli come già processati.
|
||||
// Al termine della chiamata i TempInt dei triangoli valgono 0.
|
||||
pSrfB->ResetTempInts() ;
|
||||
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
|
||||
@@ -179,14 +180,14 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
// Ciclo sui vertici del triangolo.
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
// Se il triangolo adiacente al triangolo corrente su questo edge
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
// non è stato processato, processo il vertice e l'edge.
|
||||
int nAdjTriaTempFlag ;
|
||||
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
|
||||
continue ;
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
|
||||
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
|
||||
return true ;
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
|
||||
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
|
||||
double dEdgeLen = vtEdgeV.Len() ;
|
||||
vtEdgeV /= dEdgeLen ;
|
||||
@@ -205,6 +206,25 @@ TestSurfTmSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double d
|
||||
pSrfB->SetTempInt( nTB, 1) ;
|
||||
}
|
||||
}
|
||||
// Non c'è interferenza
|
||||
// Se non richiesto test di inclusione, non c'è interferenza
|
||||
if ( ! bTestEnclosion)
|
||||
return false ;
|
||||
// Se la prima superficie è chiusa, verifico se include totalmente la seconda
|
||||
if ( pSrfA->IsClosed() && b3BoxA.Encloses( b3BoxB)) {
|
||||
Point3d ptPointB ;
|
||||
pSrfB->GetFirstVertex( ptPointB) ;
|
||||
DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ;
|
||||
if ( DistPoinBSrfA.IsPointInside() || DistPoinBSrfA.IsEpsilon( dSafeDist))
|
||||
return true ;
|
||||
}
|
||||
// Se la seconda superficie è chiusa, verifico se include totalmente la prima
|
||||
if ( pSrfB->IsClosed() && b3BoxB.Encloses( b3BoxA)) {
|
||||
Point3d ptPointA ;
|
||||
pSrfA->GetFirstVertex( ptPointA) ;
|
||||
DistPointSurfTm DistPoinASrfB( ptPointA, *pSrfB) ;
|
||||
if ( DistPoinASrfB.IsPointInside() || DistPoinASrfB.IsEpsilon( dSafeDist))
|
||||
return true ;
|
||||
}
|
||||
// Non c'è interferenza
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CalcDerivate.cpp Data : 03.02.26 Versione : 1.5h1
|
||||
// Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 03.02.26 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CalcDerivate.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EgtNumCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
vPrevDer.clear() ;
|
||||
vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
vPrevDer.reserve( nSize) ;
|
||||
vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
|
||||
vPrevDer.push_back( vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
// se non ci sono almeno 5 punti
|
||||
if ( nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[nSize-3] - vPar[nSize-1], vPnt[nSize-3], vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti, uso arco sui primi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = vPrevDer[0] ;
|
||||
vtNextDer = vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso arco sugli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
// se secondo punto
|
||||
if ( i == 1) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se penultimo punto
|
||||
else if ( i == nSize - 2) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[1] + vPar[i+1], vPnt[1], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// salvo la derivata
|
||||
vPrevDer.push_back( vtPrevDer) ;
|
||||
vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
vPrevDer.clear() ;
|
||||
vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
vPrevDer.reserve( nSize) ;
|
||||
vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ;
|
||||
vPrevDer.push_back( vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
if ( ! CalcBesselMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti, uso i primi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1],
|
||||
vPar[i+2], vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = vPrevDer[0] ;
|
||||
vtNextDer = vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso gli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1],
|
||||
vPar[i], vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
if ( ! CalcBesselMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i],
|
||||
vPar[i+1], vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// salvo la derivata
|
||||
vPrevDer.push_back( vtPrevDer) ;
|
||||
vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EgtNumCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -179,3 +181,6 @@ CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP
|
||||
}
|
||||
return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ;
|
||||
}
|
||||
|
||||
bool ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
|
||||
bool ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ;
|
||||
+8199
-1832
File diff suppressed because it is too large
Load Diff
+27
-23
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2014
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ChainCurves.cpp Data : 20.07.14 Versione : 1.5g3
|
||||
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
|
||||
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
|
||||
// curve composite a partire dalle curve date.
|
||||
//
|
||||
//
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EGkGeomDB.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkCurveComposite.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -43,10 +44,10 @@ bool
|
||||
ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
|
||||
const Point3d& ptEnd, const Vector3d& vtEnd)
|
||||
{
|
||||
// verifico validità Id
|
||||
// verifico validità Id
|
||||
if ( nId <= 0)
|
||||
return false ;
|
||||
// verifico non sia già stata aggiunta la stessa entità
|
||||
// verifico non sia già stata aggiunta la stessa entità
|
||||
if ( ! m_sCrvId.insert( nId).second)
|
||||
return true ;
|
||||
// inserisco i dati della curva nel vettore
|
||||
@@ -68,7 +69,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
m_bIsFork = false ;
|
||||
m_vFork.clear() ;
|
||||
|
||||
// recupero l'entità più vicina al punto di start
|
||||
// recupero l'entità più vicina al punto di start
|
||||
int nStart ;
|
||||
INTVECTOR vStart ;
|
||||
if ( ! m_PointGrid.FindNearest( ptStart, vStart) ||
|
||||
@@ -82,7 +83,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
// tolgo dal grid
|
||||
RemoveEntityFromGrid( nId) ;
|
||||
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
bool bSkip = false ;
|
||||
if ( bHaltOnFork) {
|
||||
auto iIter = GetForkPoint( m_vCrvData[nId].ptEnd) ;
|
||||
@@ -93,7 +94,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
}
|
||||
}
|
||||
|
||||
// concateno dopo la fine dell'entità di partenza
|
||||
// concateno dopo la fine dell'entità di partenza
|
||||
INTVECTOR vIdsAfter ;
|
||||
bool bClosed = false ;
|
||||
if ( ! bSkip && ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd,
|
||||
@@ -102,7 +103,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
// se devo fermarmi su biforcazione, verifico se sono già su vecchia biforcazione
|
||||
bool bRevSkip = false ;
|
||||
if ( bHaltOnFork) {
|
||||
auto iIter = GetForkPoint( m_vCrvData[nId].ptStart) ;
|
||||
@@ -113,7 +114,7 @@ ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECT
|
||||
}
|
||||
}
|
||||
|
||||
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
|
||||
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
|
||||
INTVECTOR vIdsBefore ;
|
||||
if ( ! bClosed) {
|
||||
bool bRevClosed ;
|
||||
@@ -258,7 +259,7 @@ ChainCurves::RemoveEntityFromGrid( int nId)
|
||||
bool
|
||||
ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& nStart)
|
||||
{
|
||||
// numero di entità candidate
|
||||
// numero di entità candidate
|
||||
int nSize = int( vStart.size()) ;
|
||||
|
||||
// se nessuna, errore
|
||||
@@ -273,7 +274,7 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
|
||||
|
||||
// altrimenti, cerco la migliore
|
||||
int nI = - 1 ;
|
||||
double dSqDistMin = SQ_INFINITO ;
|
||||
double dDistMin = INFINITO ;
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
// recupero indice e verso
|
||||
int nId = abs( vStart[i]) - 1 ;
|
||||
@@ -281,9 +282,12 @@ ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int&
|
||||
// calcolo un punto vicino all'estremo lungo la tangente
|
||||
Point3d ptNear = ( bEquiv ? m_vCrvData[nId].ptStart + m_vCrvData[nId].vtStart :
|
||||
m_vCrvData[nId].ptEnd - m_vCrvData[nId].vtEnd) ;
|
||||
double dSqDist = SqDist( ptStart, ptNear) ;
|
||||
if ( dSqDist < dSqDistMin) {
|
||||
dSqDistMin = dSqDist ;
|
||||
double dDist = Dist( ptStart, ptNear) ;
|
||||
// tengo il segmento più vicino al punto
|
||||
// favorendo eventualmente quello equiverso se entro EPS da un concorrente
|
||||
if ( dDist < dDistMin - EPS_SMALL ||
|
||||
((dDist < dDistMin + EPS_SMALL) && bEquiv && vStart[nI] < 0)) {
|
||||
dDistMin = dDist ;
|
||||
nI = i ;
|
||||
}
|
||||
}
|
||||
@@ -302,7 +306,7 @@ bool
|
||||
ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext)
|
||||
{
|
||||
INTVECTOR vMyNext = vNext ;
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
int nM = -1 ;
|
||||
Point3d ptRef ;
|
||||
double dSqMinDist = m_dToler * m_dToler ;
|
||||
@@ -319,19 +323,19 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < int( vMyNext.size()) ; ++ i) {
|
||||
// salto l'entità più vicina
|
||||
// salto l'entità più vicina
|
||||
if ( i == nM)
|
||||
continue ;
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyNext[i]) - 1 ;
|
||||
bool bEquiv = ( vMyNext[i] > 0) ;
|
||||
// verifico se più vicino al più vicino
|
||||
// verifico se più vicino al più vicino
|
||||
double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
|
||||
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd)) ;
|
||||
if ( dRefSqDist < dCurrSqDist)
|
||||
vMyNext[i] = 0 ;
|
||||
}
|
||||
// cerco la direzione più vicina
|
||||
// cerco la direzione più vicina
|
||||
int nI = -1 ;
|
||||
int nF = 0 ;
|
||||
INTVECTOR vFork ;
|
||||
@@ -343,7 +347,7 @@ ChainCurves::ChooseNext( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyNext[i]) - 1 ;
|
||||
bool bEquiv = ( vMyNext[i] > 0) ;
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
++ nF ;
|
||||
vFork.push_back( vMyNext[i]) ;
|
||||
// se vietata inversione, salto se controverso
|
||||
@@ -387,7 +391,7 @@ bool
|
||||
ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev)
|
||||
{
|
||||
INTVECTOR vMyPrev = vPrev ;
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
// scarto quelle entità che sono più vicine all'altro estremo del più vicino
|
||||
int nM = -1 ;
|
||||
Point3d ptRef ;
|
||||
double dSqMinDist = m_dToler * m_dToler ;
|
||||
@@ -404,19 +408,19 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < int( vMyPrev.size()) ; ++ i) {
|
||||
// salto l'entità più vicina
|
||||
// salto l'entità più vicina
|
||||
if ( i == nM)
|
||||
continue ;
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyPrev[i]) - 1 ;
|
||||
bool bEquiv = ( vMyPrev[i] < 0) ;
|
||||
// verifico se più vicino al più vicino
|
||||
// verifico se più vicino al più vicino
|
||||
double dCurrSqDist = SqDist( ptCurr, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
|
||||
double dRefSqDist = SqDist( ptRef, ( bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart)) ;
|
||||
if ( dRefSqDist < dCurrSqDist)
|
||||
vMyPrev[i] = 0 ;
|
||||
}
|
||||
// cerco la direzione più vicina
|
||||
// cerco la direzione più vicina
|
||||
int nI = - 1 ;
|
||||
int nF = 0 ;
|
||||
double dProScaMax = - 1.1 ;
|
||||
@@ -428,7 +432,7 @@ ChainCurves::ChoosePrev( const Point3d& ptCurr, const Vector3d& vtCurr, const IN
|
||||
// recupero indice e verso
|
||||
int nId = abs( vMyPrev[i]) - 1 ;
|
||||
bool bEquiv = ( vMyPrev[i] < 0) ;
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
// incremento contatore indice entità tra cui scegliere
|
||||
++ nF ;
|
||||
vFork.push_back( vMyPrev[i]) ;
|
||||
// se vietata inversione, salto se controverso
|
||||
|
||||
@@ -127,7 +127,7 @@ GetHSVFromColor( const Color& cCol)
|
||||
hsv.dSat = dDelta / dMax ;
|
||||
if ( cCol.GetRed() >= dMax) // tra giallo e magenta
|
||||
hsv.dHue = ( cCol.GetGreen() - cCol.GetBlue()) / dDelta ;
|
||||
else if( cCol.GetGreen() >= dMax) // tra ciano e giallo
|
||||
else if ( cCol.GetGreen() >= dMax) // tra ciano e giallo
|
||||
hsv.dHue = 2.0 + ( cCol.GetBlue() - cCol.GetRed()) / dDelta ;
|
||||
else // tra magenta e ciano
|
||||
hsv.dHue = 4.0 + ( cCol.GetRed() - cCol.GetGreen()) / dDelta ;
|
||||
|
||||
+4
-3
@@ -398,7 +398,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
|
||||
if ( dLenA > ( dRad - EPS_ZERO))
|
||||
dLenH = 0 ;
|
||||
else
|
||||
dLenH= sqrt( dRad * dRad - dLenA * dLenA) ;
|
||||
dLenH = sqrt( dRad * dRad - dLenA * dLenA) ;
|
||||
// versore dal punto medio della corda al centro
|
||||
Vector3d vtH = vtA / dLenA ;
|
||||
vtH.Rotate( Z_AX, 0, ( bCCW ? 1 : -1)) ;
|
||||
@@ -410,6 +410,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
|
||||
m_dRad = dRad ;
|
||||
// calcolo il versore di start
|
||||
m_VtS = ( ptStart - m_PtCen) / m_dRad ;
|
||||
m_VtS.Normalize() ;
|
||||
// calcolo l'angolo al centro
|
||||
bool bDet ;
|
||||
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
|
||||
@@ -1293,7 +1294,7 @@ CurveArc::Invert( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveArc::SimpleOffset( double dDist, int nType)
|
||||
CurveArc::SimpleOffset( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1328,7 +1329,7 @@ CurveArc::SimpleOffset( double dDist, int nType)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveArc::MyExtendedOffset( double dDist, bool bAll, int nType)
|
||||
CurveArc::MyExtendedOffset( double dDist, bool bAll)
|
||||
{
|
||||
// bAll == true fa accettare raggi nulli ==> da usare solo internamente
|
||||
// quando si è sicuri di aumentare subito il raggio o di cancellare
|
||||
|
||||
+4
-4
@@ -116,7 +116,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
@@ -178,8 +178,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
bool ChangeDeltaN( double dNewDeltaN) override ;
|
||||
bool ChangeAngCenter( double dNewAngCenDeg) override ;
|
||||
bool ChangeStartPoint( double dU) override ;
|
||||
bool ExtendedOffset( double dDist, int nType = OFF_FILLET) override
|
||||
{ return MyExtendedOffset( dDist, false, nType) ; }
|
||||
bool ExtendedOffset( double dDist) override
|
||||
{ return MyExtendedOffset( dDist, false) ; }
|
||||
bool ToExplementary( void) override ;
|
||||
bool Flip( void) override ;
|
||||
|
||||
@@ -200,7 +200,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
{ if ( ! CopyFrom( caSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "CurveArc : copy error")
|
||||
return *this ; }
|
||||
bool MyExtendedOffset( double dDist, bool bAll, int nType = OFF_FILLET) ;
|
||||
bool MyExtendedOffset( double dDist, bool bAll) ;
|
||||
bool MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, double dLinTol) const ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
+1330
-144
File diff suppressed because it is too large
Load Diff
@@ -33,4 +33,6 @@ bool CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) ;
|
||||
bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ;
|
||||
bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
|
||||
+285
-20
@@ -13,6 +13,7 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveAux.h"
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointCrvBezier.h"
|
||||
@@ -92,8 +93,11 @@ CurveBezier::Init( int nDeg, bool bIsRational)
|
||||
bool
|
||||
CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl)
|
||||
{
|
||||
// verifico validità indice
|
||||
if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg)
|
||||
// verifico validità indice e punto
|
||||
if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg || ! ptCtrl.IsValid())
|
||||
return false ;
|
||||
|
||||
if ( abs( ptCtrl.x) > INFINITO || abs( ptCtrl.y) > INFINITO || abs( ptCtrl.z) > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore
|
||||
@@ -122,8 +126,11 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
|
||||
if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg)
|
||||
return false ;
|
||||
|
||||
// verifico che il peso non sia nullo o negativo
|
||||
if ( dW < EPS_SMALL)
|
||||
// verifico che il punto sia valido e il peso non sia nullo o negativo
|
||||
if ( ! ptCtrl.IsValid() || dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
|
||||
return false ;
|
||||
|
||||
if ( abs( ptCtrl.x) > INFINITO || abs( ptCtrl.y) > INFINITO || abs( ptCtrl.z) > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore e il peso
|
||||
@@ -141,6 +148,32 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::SetControlWeight( int nInd, double dW)
|
||||
{
|
||||
// verifico validità, razionalità e indice
|
||||
if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg)
|
||||
return false ;
|
||||
|
||||
// verifico che il peso non sia nullo o negativo
|
||||
if ( dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore e il peso
|
||||
m_vWeCtrl[nInd] = dW ;
|
||||
|
||||
// annullo analisi presenza singolarità
|
||||
m_dParSing = - 2 ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
@@ -240,7 +273,7 @@ CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
bool
|
||||
CurveBezier::FromLine( const ICurveLine& crLine)
|
||||
{
|
||||
if ( ! crLine.IsValid())
|
||||
if ( m_nStatus != OK || ! crLine.IsValid())
|
||||
return false ;
|
||||
double dWeight = 1 ;
|
||||
int nCount = 0 ;
|
||||
@@ -340,8 +373,11 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc)
|
||||
{
|
||||
if ( &cbSrc == this)
|
||||
return true ;
|
||||
if ( ! cbSrc.IsValid())
|
||||
return false ;
|
||||
if ( ! Init( cbSrc.m_nDeg, cbSrc.m_bRat))
|
||||
return false ;
|
||||
m_dParSing = cbSrc.m_dParSing ;
|
||||
m_vPtCtrl = cbSrc.m_vPtCtrl ;
|
||||
if ( cbSrc.m_bRat)
|
||||
m_vWeCtrl = cbSrc.m_vWeCtrl ;
|
||||
@@ -489,21 +525,21 @@ bool
|
||||
CurveBezier::Validate( void)
|
||||
{
|
||||
if ( m_nStatus == TO_VERIFY) {
|
||||
for ( const auto& ptP : m_vPtCtrl) {
|
||||
if ( ! ptP.IsValid()) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
for ( const auto& ptP : m_vPtCtrl) {
|
||||
if ( ! ptP.IsValid()) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( m_nStatus == TO_VERIFY) {
|
||||
for ( const auto& dWe : m_vWeCtrl) {
|
||||
if ( ! isfinite( dWe)) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
for ( const auto& dWe : m_vWeCtrl) {
|
||||
if ( ! isfinite( dWe)) {
|
||||
m_nStatus = ERR ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( m_nStatus == TO_VERIFY)
|
||||
m_nStatus = ( ( m_nDeg >= 1 && m_vPtCtrl.size() >= 2) ? OK : ERR) ;
|
||||
|
||||
@@ -1542,7 +1578,7 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo
|
||||
return false ;
|
||||
vtDir.ToSpherical( nullptr, nullptr, &dDir1Deg) ;
|
||||
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ;
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
}
|
||||
@@ -1630,6 +1666,10 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo
|
||||
ICurve*
|
||||
CurveBezier::CopyParamRange( double dUStart, double dUEnd) const
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return nullptr ;
|
||||
|
||||
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
|
||||
if ( dUStart < - EPS_PARAM || dUStart > 1 + EPS_PARAM ||
|
||||
dUEnd < - EPS_PARAM || dUEnd > 1 + EPS_PARAM)
|
||||
@@ -1772,6 +1812,10 @@ CurveBezier::TrimEndAtParam( double dUTrim)
|
||||
bool
|
||||
CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
|
||||
if ( dUStartTrim < - EPS_PARAM || dUStartTrim > 1 + EPS_PARAM ||
|
||||
dUEndTrim < - EPS_PARAM || dUEndTrim > 1 + EPS_PARAM)
|
||||
@@ -1779,18 +1823,34 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
// verifico che i trim non cancellino interamente la curva
|
||||
if ( dUStartTrim > dUEndTrim - EPS_PARAM)
|
||||
return false ;
|
||||
// se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim
|
||||
Point3d ptStart ;
|
||||
if ( m_bRat)
|
||||
GetPointD1D2( dUStartTrim, ptStart) ;
|
||||
// trim finale
|
||||
if ( ! TrimEndAtParam( dUEndTrim))
|
||||
return false ;
|
||||
// trim iniziale con il parametro opportunamente ricalcolato
|
||||
double dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
||||
return TrimStartAtParam( dNewUStartTrim) ;
|
||||
double dNewUStartTrim ;
|
||||
if ( m_bRat)
|
||||
GetParamAtPoint( ptStart, dNewUStartTrim) ;
|
||||
else
|
||||
dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
||||
//trim iniziale
|
||||
if ( ! TrimStartAtParam( dNewUStartTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// lunghezze negative vengono considerate nulle
|
||||
dLenTrim = max( dLenTrim, 0.) ;
|
||||
|
||||
@@ -1800,13 +1860,20 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
return TrimStartAtParam( dUTrim) ;
|
||||
if ( ! TrimStartAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// lunghezze negative vengono considerate nulle
|
||||
dLenTrim = max( dLenTrim, 0.) ;
|
||||
|
||||
@@ -1816,13 +1883,20 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
return TrimEndAtParam( dUTrim) ;
|
||||
if ( ! TrimEndAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::ExtendStartByLen( double dLenExt)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// la lunghezza deve essere positiva
|
||||
if ( dLenExt < - EPS_ZERO)
|
||||
return false ;
|
||||
@@ -1874,6 +1948,10 @@ CurveBezier::ExtendStartByLen( double dLenExt)
|
||||
bool
|
||||
CurveBezier::ExtendEndByLen( double dLenExt)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// la lunghezza deve essere positiva
|
||||
if ( dLenExt < - EPS_ZERO)
|
||||
return false ;
|
||||
@@ -2208,3 +2286,190 @@ CurveBezier::ResetVoronoiObject() const
|
||||
delete m_pVoronoiObj ;
|
||||
m_pVoronoiObj = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::MakeRational( void)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( m_bRat)
|
||||
return true ;
|
||||
// creo il vettore dei pesi e li setto tutti a 1
|
||||
m_vWeCtrl.assign( m_nDeg + 1, 1) ;
|
||||
// aggiorno il flag rational
|
||||
m_bRat = true ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::MakeRationalStandardForm( void)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( ! m_bRat)
|
||||
return false ;
|
||||
double dW0 = m_vWeCtrl.front() ;
|
||||
double dWn = m_vWeCtrl.back() ;
|
||||
if ( dW0 > 1 - EPS_ZERO && dWn > 1 - EPS_ZERO)
|
||||
return true ;
|
||||
if ( dW0 < EPS_ZERO || dWn < EPS_ZERO)
|
||||
return false ;
|
||||
|
||||
// formula del Farin
|
||||
double dCoeff = pow( dW0 / dWn, 1. / m_nDeg) ;
|
||||
for ( int i = 0 ; i < m_nDeg + 1 ; ++i)
|
||||
m_vWeCtrl[i] *= Pow( dCoeff, i) / dW0 ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::MakeNonRational( double dTol)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( ! m_bRat)
|
||||
return true ;
|
||||
|
||||
// controllo se i pesi sono tutti == 1 allora è una finta razionale e mi basta fare una copia dei punti di controllo
|
||||
bool bIsActualRat = false ;
|
||||
for ( int i = 0 ; i < m_nDeg ; ++i) {
|
||||
if ( abs( m_vWeCtrl[i] - 1) > EPS_SMALL) {
|
||||
bIsActualRat = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
bool bOk = true ;
|
||||
if ( ! bIsActualRat) {
|
||||
// semplicemente tolgo il booleano della razionalità e i punti restano gli stessi
|
||||
m_bRat = false ;
|
||||
}
|
||||
else {
|
||||
// provo ad approssimare la curva di bezier con una controparte non razionale
|
||||
int nDeg = m_nDeg ;
|
||||
// se ho una curva razionale di grado 2 verifico se è un arco, in quel caso la converto in una curva di grado 3 non razionale con la funzione dedicata
|
||||
if ( nDeg == 2 && m_bRat) {
|
||||
// prendo due punti sulla curva e calcolo l'intersezione dei due assi dei segmenti formati da pt2-pt0 e pt3-pt1
|
||||
Point3d pt0 ; GetStartPoint( pt0) ;
|
||||
Point3d pt1 ; GetPointD1D2( 0.3, pt1) ;
|
||||
Point3d pt2 ; GetPointD1D2( 0.6, pt2) ;
|
||||
Point3d pt3 ; GetEndPoint( pt3) ;
|
||||
|
||||
Vector3d vtDir1 = pt2 - pt0 ;
|
||||
Vector3d vtDir2 = pt3 - pt1 ;
|
||||
Vector3d vtN = vtDir2 ^ vtDir1 ;
|
||||
|
||||
CurveLine cl1 ; cl1.Set( pt1, pt1 + (vtDir1 ^ vtN) * 5) ;
|
||||
CurveLine cl2 ; cl1.Set( pt2, pt2 + (vtDir2 ^ vtN) * 5) ;
|
||||
IntersLineLine ill( cl1, cl2, false) ;
|
||||
IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
||||
Point3d ptCen = iccInfo.IciA[0].ptI ;
|
||||
|
||||
// se sia l'inizio che la fine della curva distano uguale dal punto di intersezione tra i due assi trovati allora la curva è un arco di circonferenza
|
||||
if ( abs(Dist( pt0, ptCen) - Dist( pt3, ptCen)) < EPS_SMALL) {
|
||||
PtrOwner<ICurveBezier> pNew ( ApproxArcCurveBezierWithSingleCubic( this, ptCen, vtN)) ;
|
||||
|
||||
if ( IsNull( pNew) || ! pNew->IsValid())
|
||||
return false ;
|
||||
Init( 3, false) ;
|
||||
for ( int i = 0 ; i < 3 ; ++i)
|
||||
SetControlPoint( i, pNew->GetControlPoint(i)) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
// punto di rientro in caso fallisca il primo tentativo
|
||||
retry :
|
||||
nDeg += 2 ;
|
||||
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
|
||||
pNewBez->Init( nDeg, false) ;
|
||||
PNTVECTOR vPntCtrl ;
|
||||
PNTVECTOR vPntSampling ;
|
||||
for ( int p = 0 ; p < nDeg + 1 ; ++p) {
|
||||
Point3d pt ; GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
vPntCtrl.push_back( pt) ;
|
||||
}
|
||||
vPntSampling = vPntCtrl ;
|
||||
int c = 0 ;
|
||||
double dErr = INFINITO ;
|
||||
while ( dErr > dTol && c < 100) {
|
||||
double dErrMax = 0 ;
|
||||
// calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale
|
||||
for ( int p = 0 ; p < nDeg + 1 ; ++p) {
|
||||
Point3d pt ; pNewBez->GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
Vector3d vDiff = vPntSampling[p] - pt ;
|
||||
double dErrLoc = vDiff.Len() ;
|
||||
if ( dErrLoc > dErrMax)
|
||||
dErrMax = dErrLoc ;
|
||||
// aggiorno il vettore dei punti di controllo della nuova curva
|
||||
vPntCtrl[p] += vDiff ;
|
||||
}
|
||||
dErr = dErrMax ;
|
||||
// aggiorno i punti di controllo della nuova curva
|
||||
for ( int i = 0 ; i < nDeg + 1 ; ++i)
|
||||
pNewBez->SetControlPoint( i, vPntCtrl[i]) ;
|
||||
++c ;
|
||||
}
|
||||
|
||||
// calcolo l'errore di approssimazione sulla curva
|
||||
CalcApproxError( this, pNewBez, dErr) ;
|
||||
bOk = dErr < dTol ;
|
||||
if ( bOk) {
|
||||
// aggiorno la curva di bezier originale con quella approssimata
|
||||
Init( nDeg, false) ;
|
||||
for ( int i = 0 ; i < nDeg + 1 ; ++i) {
|
||||
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
|
||||
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
|
||||
}
|
||||
}
|
||||
else if ( nDeg < m_nDeg + 4)
|
||||
goto retry ;
|
||||
}
|
||||
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::IsALine( void) const
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
Point3d ptStart ; GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; GetEndPoint( ptEnd) ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
Point3d ptCtrl = GetControlPoint( i) ;
|
||||
DistPointLine dpl( ptCtrl, ptStart, ptEnd) ;
|
||||
double dDist = 0 ; dpl.GetDist( dDist) ;
|
||||
if ( dDist > EPS_SMALL)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PNTVECTOR
|
||||
CurveBezier::GetAllControlPoints( void) const
|
||||
{
|
||||
PNTVECTOR vPntCtrl ;
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return vPntCtrl ;
|
||||
|
||||
return m_vPtCtrl ;
|
||||
}
|
||||
+7
-1
@@ -116,7 +116,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override
|
||||
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
@@ -137,6 +137,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
bool Init( int nDeg, bool bIsRational) override ;
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ;
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
|
||||
bool SetControlWeight( int nInd, double dW) override ;
|
||||
bool FromArc( const ICurveArc& crArc) override ;
|
||||
bool FromLine( const ICurveLine& crLine) override ;
|
||||
int GetDegree( void) const override
|
||||
@@ -148,6 +149,11 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
double GetControlWeight( int nInd, bool* pbOk = NULL) const override ;
|
||||
bool GetControlPolygonLength( double& dLen) const override ;
|
||||
int GetSingularParam( double& dPar) const override ;
|
||||
bool MakeRational( void) override ;
|
||||
bool MakeRationalStandardForm( void) override ;
|
||||
bool MakeNonRational( double dTol) override ;
|
||||
bool IsALine( void) const override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ; // non aggiunta in interfaccia
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+15
-211
@@ -202,213 +202,14 @@ CurveByApprox::CalcParameterization( void)
|
||||
bool
|
||||
CurveByApprox::CalcAkimaTangents( bool bDetectCorner)
|
||||
{
|
||||
// pulisco i vettori delle tangenti
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
// se non ci sono almeno 5 punti
|
||||
if ( nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti, uso arco sui primi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso arco sugli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
// se secondo punto
|
||||
if ( i == 1) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se penultimo punto
|
||||
else if ( i == nSize - 2) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveByApprox::CalcBesselTangents( void)
|
||||
{
|
||||
// pulisco i vettori delle tangenti
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti, uso i primi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso gli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -439,12 +240,12 @@ CurveByApprox::CalcSplitPoints( double dLinTol, double dAngTolDeg, double dLinFe
|
||||
m_vSplits.push_back(i) ;
|
||||
continue ;
|
||||
}
|
||||
// verifico linearità del tratto precedente
|
||||
// verifico linearità del tratto precedente
|
||||
bool bPrevLin = vtPrev.SqLen() > dSqLinFea &&
|
||||
( m_vNextDer[i-1] * m_vPrevDer[i]) > dAngTolCos &&
|
||||
( vtPrev ^ m_vNextDer[i-1]).SqLen() < dSqLinTol &&
|
||||
( vtPrev ^ m_vPrevDer[i]).SqLen() < dSqLinTol ;
|
||||
// verifico linearità del tratto successivo
|
||||
// verifico linearità del tratto successivo
|
||||
bool bNextLin = vtNext.SqLen() > dSqLinFea &&
|
||||
( m_vNextDer[i] * m_vPrevDer[i+1]) > dAngTolCos &&
|
||||
( vtNext ^ m_vNextDer[i]).SqLen() < dSqLinTol &&
|
||||
@@ -483,7 +284,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
PtrOwner<ICurve> pCrv ;
|
||||
double dMaxDist ;
|
||||
|
||||
// se la polilinea ha più di 2 punti
|
||||
// se la polilinea ha più di 2 punti
|
||||
if ( PL.GetPointNbr() > 2) {
|
||||
// calcolo punti e direzioni agli estremi della polilinea usando la curva di Bezier
|
||||
int nI ;
|
||||
@@ -501,11 +302,12 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
ptP1 = m_vPnt[nI] ;
|
||||
m_vPrevDer[nI].ToSpherical( nullptr, nullptr, &dDir1Deg) ;
|
||||
// costruisco un biarco sulla polilinea (secondo metodo di Z. Sir)
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist)) ;
|
||||
pCrv.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, PL, dMaxDist, dLinTol)) ;
|
||||
// forzo la spezzatura della curva
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
dMaxDist = 2 * dLinTol ;
|
||||
}
|
||||
// se la polilinea è formata da 2 punti
|
||||
// se la polilinea è formata da 2 punti
|
||||
else if ( PL.GetPointNbr() == 2) {
|
||||
// se molto vicini, esco
|
||||
double dLen ;
|
||||
@@ -524,13 +326,15 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
|
||||
// se raggiunto il massimo livello di recursione, forzo l'accettazione del biarco
|
||||
if ( nLev >= MAX_LEV) {
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
dMaxDist = 0 ;
|
||||
// segnalo situazione per debug
|
||||
if ( GetEGkDebugLev() >= 5)
|
||||
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions")
|
||||
}
|
||||
|
||||
// se lunghezza abbastanza picccola, forzo l'accettazione della curva
|
||||
// se lunghezza abbastanza piccola, forzo l'accettazione della curva
|
||||
double dLen ;
|
||||
if ( PL.GetApproxLength( dLen) && dLen < 10 * EPS_SMALL)
|
||||
dMaxDist = 0 ;
|
||||
@@ -561,7 +365,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
return false ;
|
||||
}
|
||||
|
||||
// spezzo l'intervallo in due parti a metà
|
||||
// spezzo l'intervallo in due parti a metà
|
||||
double dParStart, dParEnd ;
|
||||
if ( ! PL.GetFirstU( dParStart) || ! PL.GetLastU( dParEnd))
|
||||
return false ;
|
||||
@@ -569,9 +373,9 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
PolyLine PL2 ;
|
||||
if ( ! PL.Split( dParMid, PL2))
|
||||
return false ;
|
||||
// prima metà
|
||||
// prima metà
|
||||
if ( ! BiArcOrSplit( nLev + 1, PL, dLinTol, dAngTolDeg, PA))
|
||||
return false ;
|
||||
// seconda metà
|
||||
// seconda metà
|
||||
return BiArcOrSplit( nLev + 1, PL2, dLinTol, dAngTolDeg, PA) ;
|
||||
}
|
||||
|
||||
+34
-225
@@ -50,7 +50,37 @@ CurveByInterp::AddPoint( const Point3d& ptP)
|
||||
ICurve*
|
||||
CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
{
|
||||
// calcolo le tangenti
|
||||
// se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs)
|
||||
if ( nType == CUBIC_BEZIERS_LONG) {
|
||||
// creo la curva composita
|
||||
PtrOwner<ICurve> pCrv ;
|
||||
//pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ;
|
||||
//debug
|
||||
pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 0.1, 100)) ;
|
||||
if ( IsNull(pCrv) || ! pCrv->IsValid())
|
||||
return nullptr ;
|
||||
return Release( pCrv) ;
|
||||
}
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo le distanze tra i punti per derivarne i parametri
|
||||
m_vPar.reserve( nSize) ;
|
||||
double dPar = 0 ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
|
||||
for ( int i = 1 ; i < nSize ; ++ i) {
|
||||
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
|
||||
dPar += dDist ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
}
|
||||
|
||||
// calcolo le tangenti
|
||||
if ( nMethod == BESSEL) {
|
||||
if ( ! CalcBesselTangents())
|
||||
return nullptr ;
|
||||
@@ -110,233 +140,12 @@ CurveByInterp::GetCurve( int nMethod, int nType)
|
||||
bool
|
||||
CurveByInterp::CalcAkimaTangents( bool bDetectCorner)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
m_vPar.clear() ;
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le distanze tra i punti per derivarne i parametri
|
||||
m_vPar.reserve( nSize) ;
|
||||
double dPar = 0 ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
for ( int i = 1 ; i < nSize ; ++ i) {
|
||||
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
|
||||
dPar += dDist ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
}
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
// se non ci sono almeno 5 punti
|
||||
if ( nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti, uso arco sui primi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso arco sugli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
// se secondo punto
|
||||
if ( i == 1) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se penultimo punto
|
||||
else if ( i == nSize - 2) {
|
||||
// se curva aperta o non ci sono almeno 5 punti
|
||||
if ( ! bClosed || nSize < 5) {
|
||||
if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], bDetectCorner,
|
||||
vtPrevDer, vtNextDer))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveByInterp::CalcBesselTangents( void)
|
||||
{
|
||||
// pulisco i vettori dei parametri e delle tangenti
|
||||
m_vPar.clear() ;
|
||||
m_vPrevDer.clear() ;
|
||||
m_vNextDer.clear() ;
|
||||
|
||||
// numero di punti
|
||||
int nSize = int( m_vPnt.size()) ;
|
||||
|
||||
// sono necessari almeno due punti
|
||||
if ( nSize < 2)
|
||||
return false ;
|
||||
|
||||
// calcolo le distanze tra i punti per derivarne i parametri
|
||||
m_vPar.reserve( nSize) ;
|
||||
double dPar = 0 ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
for ( int i = 1 ; i < nSize ; ++ i) {
|
||||
double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ;
|
||||
dPar += dDist ;
|
||||
m_vPar.push_back( dPar) ;
|
||||
}
|
||||
|
||||
// calcolo le derivate
|
||||
m_vPrevDer.reserve( nSize) ;
|
||||
m_vNextDer.reserve( nSize) ;
|
||||
// se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce
|
||||
if ( nSize == 2) {
|
||||
// non esiste derivata prima del primo punto
|
||||
m_vPrevDer.emplace_back( 0, 0, 0) ;
|
||||
m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ;
|
||||
m_vPrevDer.push_back( m_vNextDer[0]) ;
|
||||
// non esiste derivata dopo il secondo e ultimo punto
|
||||
m_vNextDer.emplace_back( 0, 0, 0) ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se curva chiusa (primo e ultimo punto coincidono)
|
||||
bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ;
|
||||
// calcolo le derivate
|
||||
for ( int i = 0 ; i < nSize ; ++ i) {
|
||||
Vector3d vtPrevDer ;
|
||||
Vector3d vtNextDer ;
|
||||
// primo punto
|
||||
if ( i == 0) {
|
||||
// se curva chiusa, come precedente uso il penultimo punto
|
||||
if ( bClosed) {
|
||||
if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = vtNextDer ;
|
||||
}
|
||||
// altrimenti, uso i primi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1],
|
||||
m_vPar[i+2], m_vPnt[i+2], vtNextDer))
|
||||
return false ;
|
||||
vtPrevDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// ultimo punto
|
||||
else if ( i == nSize - 1) {
|
||||
// se curva chiusa, le tg devono coincidere con quelle del primo
|
||||
if ( bClosed) {
|
||||
vtPrevDer = m_vPrevDer[0] ;
|
||||
vtNextDer = m_vNextDer[0] ;
|
||||
}
|
||||
// altrimenti, uso gli ultimi tre punti
|
||||
else {
|
||||
if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1],
|
||||
m_vPar[i], m_vPnt[i], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = Vector3d( 0, 0, 0) ;
|
||||
}
|
||||
}
|
||||
// punti intermedi
|
||||
else {
|
||||
if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i],
|
||||
m_vPar[i+1], m_vPnt[i+1], vtPrevDer))
|
||||
return false ;
|
||||
vtNextDer = vtPrevDer ;
|
||||
}
|
||||
// salvo la derivata
|
||||
m_vPrevDer.push_back( vtPrevDer) ;
|
||||
m_vNextDer.push_back( vtNextDer) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ;
|
||||
}
|
||||
+99
-45
@@ -192,7 +192,7 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
return false ;
|
||||
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK && ! ( m_CrvSmplS.empty() && m_nStatus == TO_VERIFY))
|
||||
if ( m_nStatus != OK && ! ( m_CrvSmplS.empty() && ( m_nStatus == TO_VERIFY || m_nStatus == IS_A_POINT)))
|
||||
return false ;
|
||||
|
||||
// controllo la tolleranza
|
||||
@@ -224,8 +224,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyStart( ptEnd))
|
||||
return false ;
|
||||
if ( ! pCrv->ModifyStart( ptEnd)) {
|
||||
CurveLine crvLine ;
|
||||
if ( ! crvLine.Set( ptEnd, ptCrvEnd) || ! pCrv.Set( crvLine.Clone()))
|
||||
return false ;
|
||||
}
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
@@ -246,8 +249,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyEnd( ptStart))
|
||||
return false ;
|
||||
if ( ! pCrv->ModifyEnd( ptStart)) {
|
||||
CurveLine crvLine ;
|
||||
if ( ! crvLine.Set( ptCrvStart, ptStart) || ! pCrv.Set( crvLine.Clone()))
|
||||
return false ;
|
||||
}
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
@@ -291,9 +297,15 @@ CurveComposite::Close( void)
|
||||
return true ;
|
||||
// se molto vicini li modifico
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, 10 * EPS_SMALL)) {
|
||||
// se un solo arco
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC) {
|
||||
CurveArc* pArc = GetBasicCurveArc( m_CrvSmplS.front()) ;
|
||||
return pArc->ChangeAngCenter( pArc->GetAngCenter() > 0 ? ANG_FULL : -ANG_FULL) ;
|
||||
}
|
||||
// caso generale
|
||||
Point3d ptMid = Media( ptStart, ptEnd) ;
|
||||
if ( ! ModifyStart( ptMid) ||
|
||||
! ModifyEnd( ptMid))
|
||||
if ( ! m_CrvSmplS.front()->ModifyStart( ptMid) ||
|
||||
! m_CrvSmplS.back()->ModifyEnd( ptMid))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti aggiungo la linea di chiusura
|
||||
@@ -369,9 +381,10 @@ CurveComposite::FromPolyLine( const PolyLine& PL)
|
||||
return false ;
|
||||
|
||||
// ciclo di inserimento dei segmenti che uniscono i punti
|
||||
double dParIni, dParFin ;
|
||||
Point3d ptIni, ptFin ;
|
||||
PL.GetFirstPoint( ptIni) ;
|
||||
while ( PL.GetNextPoint( ptFin)) {
|
||||
PL.GetFirstUPoint( &dParIni, &ptIni) ;
|
||||
while ( PL.GetNextUPoint( &dParFin, &ptFin)) {
|
||||
// se i punti della coppia coincidono, passo alla coppia successiva
|
||||
if ( AreSamePointApprox( ptIni, ptFin))
|
||||
continue ;
|
||||
@@ -382,10 +395,14 @@ CurveComposite::FromPolyLine( const PolyLine& PL)
|
||||
// assegno i punti estremi
|
||||
if ( ! pCrvLine->Set( ptIni, ptFin))
|
||||
return false ;
|
||||
// assegno i parametri degli estremi
|
||||
pCrvLine->SetTempParam( dParIni, 0) ;
|
||||
pCrvLine->SetTempParam( dParFin, 1) ;
|
||||
// aggiungo la retta alla curva composita
|
||||
if ( ! AddSimpleCurve( Release( pCrvLine)))
|
||||
return false ;
|
||||
// aggiorno dati prossimo punto iniziale
|
||||
dParIni = dParFin ;
|
||||
ptIni = ptFin ;
|
||||
}
|
||||
|
||||
@@ -598,6 +615,10 @@ CurveComposite::CopyFrom( const CurveComposite& ccSrc)
|
||||
if ( ! AddCurve( *pCrv))
|
||||
return false ;
|
||||
}
|
||||
if ( ccSrc.m_nStatus == IS_A_POINT) {
|
||||
m_ptStart = ccSrc.m_ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -656,7 +677,7 @@ CurveComposite::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
while ( pCrvSmpl != nullptr && i < MAX_CRV) {
|
||||
// assegno ed emetto nome e tipo della curva semplice
|
||||
sOut += "#" + ToString( i) + " " + pCrvSmpl->GetTitle() + szNewLine ;
|
||||
// salvataggio della curva semplice
|
||||
// dati della curva semplice
|
||||
if ( ! pCrvSmpl->Dump( sOut, bMM, szNewLine))
|
||||
return false ;
|
||||
// passo alla successiva
|
||||
@@ -868,19 +889,28 @@ CurveComposite::Validate( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::TestClosure( void)
|
||||
CurveComposite::TestClosure( double dLinTol)
|
||||
{
|
||||
// se non è chiusa, esco subito
|
||||
if ( ! IsClosed())
|
||||
// se non valida o vuota, esco subito
|
||||
if ( m_nStatus != OK || m_CrvSmplS.empty())
|
||||
return true ;
|
||||
// se non è chiusa entro la tolleranza, esco subito
|
||||
Point3d ptStart, ptEnd ;
|
||||
if ( ! m_CrvSmplS.front()->GetStartPoint( ptStart) ||
|
||||
! m_CrvSmplS.back()->GetEndPoint( ptEnd) ||
|
||||
! AreSamePointEpsilon( ptStart, ptEnd, dLinTol))
|
||||
return true ;
|
||||
// se singola retta, esco subito
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_LINE)
|
||||
return true ;
|
||||
// verifico ed eventualmente aggiusto coincidenza punti estremi
|
||||
Point3d ptStart ; m_CrvSmplS.front()->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; m_CrvSmplS.back()->GetEndPoint( ptEnd) ;
|
||||
// se distanza superiore al limite ridotto forzo i punti a coincidere
|
||||
if ( ! AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT)) {
|
||||
// se un solo arco
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC)
|
||||
return GetBasicCurveArc( m_CrvSmplS.front())->ChangeAngCenter( ANG_FULL) ;
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC) {
|
||||
CurveArc* pArc = GetBasicCurveArc( m_CrvSmplS.front()) ;
|
||||
return pArc->ChangeAngCenter( pArc->GetAngCenter() > 0 ? ANG_FULL : -ANG_FULL) ;
|
||||
}
|
||||
// caso generale
|
||||
Point3d ptM = Media( ptStart, ptEnd) ;
|
||||
return ( m_CrvSmplS.front()->ModifyStart( ptM) &&
|
||||
@@ -940,6 +970,8 @@ CurveComposite::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) con
|
||||
return false ;
|
||||
}
|
||||
} break ;
|
||||
default :
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// recupero dati sulla planarità della polilinea
|
||||
@@ -1682,7 +1714,7 @@ CurveComposite::Invert( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::SimpleOffset( double dDist, int nType)
|
||||
CurveComposite::SimpleOffset( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// se distanza di offset nulla, non devo fare alcunché
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
@@ -1704,7 +1736,7 @@ CurveComposite::SimpleOffset( double dDist, int nType)
|
||||
}
|
||||
|
||||
// eseguo l'offset nel piano XY
|
||||
bool bOk = SimpleOffsetXY( dDist, nType) ;
|
||||
bool bOk = SimpleOffsetXY( dDist, nType, dMaxAngExt) ;
|
||||
|
||||
// riporto la curva nel riferimento originale
|
||||
if ( bNeedRef)
|
||||
@@ -1764,10 +1796,11 @@ bool
|
||||
CurveComposite::AddPoint( const Point3d& ptStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != TO_VERIFY)
|
||||
if ( m_nStatus != TO_VERIFY && m_nStatus != IS_A_POINT)
|
||||
return false ;
|
||||
// assegno il punto
|
||||
// assegno il punto e setto lo stato
|
||||
m_ptStart = ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1811,7 +1844,7 @@ bool
|
||||
CurveComposite::AddLine( const Point3d& ptNew, bool bEndOrStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK && m_nStatus != TO_VERIFY)
|
||||
if ( m_nStatus != OK && m_nStatus != IS_A_POINT)
|
||||
return false ;
|
||||
// costruisco la linea
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
@@ -2975,7 +3008,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast)
|
||||
m_CrvSmplS.pop_front() ;
|
||||
}
|
||||
// eseguo mini verifica
|
||||
m_nStatus = ( m_CrvSmplS.size() > 0 ? OK : TO_VERIFY) ;
|
||||
m_nStatus = ( ! m_CrvSmplS.empty() ? OK : TO_VERIFY) ;
|
||||
// assegno estrusione e spessore della curva composita
|
||||
pCrv->SetExtrusion( m_VtExtr) ;
|
||||
pCrv->SetThickness( m_dThick) ;
|
||||
@@ -3020,7 +3053,7 @@ CurveComposite::ArcsToBezierCurves( void)
|
||||
// se arco, devo trasformare in una o più curve di Bezier
|
||||
if ( (*Iter)->GetType() == CRV_ARC) {
|
||||
// eseguo trasformazione
|
||||
PtrOwner<ICurve> pNewCrv( ArcToBezierCurve( (*Iter))) ;
|
||||
PtrOwner<ICurve> pNewCrv( ArcToBezierCurve( GetCurveArc( *Iter))) ;
|
||||
if ( IsNull( pNewCrv))
|
||||
return false ;
|
||||
// se risultato è singola curva
|
||||
@@ -3154,11 +3187,26 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// se precedente molto corta
|
||||
double dLenP ;
|
||||
if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) {
|
||||
// se abbastanza allineata alla successiva
|
||||
// se abbastanza allineata alla successiva
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
Point3d ptStart ;
|
||||
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ;
|
||||
bool bModifStart = ( pCrvC->GetType() != CRV_ARC) ;
|
||||
if ( ! bModifStart) {
|
||||
/* nel caso in cui la curva corrente sia un arco, bisogna controllare che la somma tra
|
||||
l'angolo al centro e l'angolo sotteso dalla curva precedente non superi l'angolo giro; in
|
||||
caso positivo, la modifica del punto inziale dell'arco ( curva corrente) rimoverebbe
|
||||
tutti gli angoli superiori a 360deg [curve a ricciolo per regioni non svuotate in Pocketing] */
|
||||
Point3d ptS ; pCrvP->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pCrvC->GetStartPoint( ptE) ;
|
||||
const ICurveArc* pArcC = GetBasicCurveArc( pCrvC) ;
|
||||
double dAngRef = ( Dist( ptS, ptE) / pArcC->GetRadius()) * RADTODEG ;
|
||||
bModifStart = ( abs( pArcC->GetAngCenter()) + dAngRef < ANG_FULL - 10 * EPS_ANG_SMALL) ;
|
||||
|
||||
}
|
||||
if ( bModifStart) {
|
||||
Point3d ptStart ;
|
||||
return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se corrente molto corta
|
||||
@@ -3167,10 +3215,24 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// se abbastanza allineata alla precedente
|
||||
Vector3d vtDirP, vtDirC ;
|
||||
if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) {
|
||||
Point3d ptEnd ;
|
||||
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ;
|
||||
bool bModifEnd = ( pCrvP->GetType() != CRV_ARC) ;
|
||||
if ( ! bModifEnd) {
|
||||
/* nel caso in cui la curva predecente sia un arco, bisogna controllare che la somma tra
|
||||
l'angolo al centro e l'angolo sotteso dalla curva corrente non superi l'angolo giro; in
|
||||
caso positivo, la modifica del punto finale dell'arco ( curva precedente) rimoverebbe
|
||||
tutti gli angoli superiori a 360deg [curve a ricciolo per regioni non svuotate in Pocketing] */
|
||||
Point3d ptS ; pCrvP->GetEndPoint( ptS) ;
|
||||
Point3d ptE ; pCrvC->GetEndPoint( ptE) ;
|
||||
const CurveArc* pArcP = GetBasicCurveArc( pCrvP) ;
|
||||
double dAngRef = ( Dist( ptS, ptE) / pArcP->GetRadius()) * RADTODEG ;
|
||||
bModifEnd = ( abs( pArcP->GetAngCenter()) + dAngRef < ANG_FULL - 10. * EPS_ANG_SMALL) ;
|
||||
}
|
||||
if ( bModifEnd) {
|
||||
Point3d ptEnd ;
|
||||
return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// coefficiente deduzione tolleranza
|
||||
const double COEFF_TOL = 0.7 ;
|
||||
// se entrambe rette
|
||||
@@ -3250,11 +3312,12 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
if ( ! bPlaneArcs) {
|
||||
ptP1.Scale( frRef, 1, 1, 0) ;
|
||||
ptP2.Scale( frRef, 1, 1, 0) ;
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
ptC1Fin.Scale( frRef, 1, 1, 0) ;
|
||||
}
|
||||
|
||||
// verifico se circonferenza completa
|
||||
bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ;
|
||||
bool bCirc = ( AreSamePointEpsilon( ptP1, ptP3, dCurrLinTol)) ;
|
||||
if ( bCirc) {
|
||||
pArcC->GetMidPoint( ptP3) ;
|
||||
if ( ! bPlaneArcs)
|
||||
@@ -3263,6 +3326,10 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
|
||||
// se vicino a circonferenza arco per 3 punti potrebbe non dare il risultato desiderato quindi faccio controllo su raggio e centro
|
||||
if ( Dist( NewArc.GetCenter(), ptC1Fin) > 2 * dCurrLinTol || abs( NewArc.GetRadius() - pArcP->GetRadius()) > 2 * dCurrLinTol)
|
||||
return 0 ;
|
||||
|
||||
// verifico normale al piano dell'arco
|
||||
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
|
||||
NewArc.InvertN() ;
|
||||
@@ -3780,19 +3847,6 @@ CurveComposite::ResetVoronoiObject() const
|
||||
m_pVoronoiObj = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::FromPoint(Point3d& ptStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != TO_VERIFY)
|
||||
return false ;
|
||||
// assegno il punto e setto lo stato
|
||||
m_ptStart = ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::GetOnlyPoint(Point3d& ptStart) const
|
||||
|
||||
+4
-5
@@ -113,7 +113,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const override ;
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
@@ -177,8 +177,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ;
|
||||
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool FromPoint( Point3d& ptStart) override ; // funzione per settare la curva ad un unico punto
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ; // funzione per recuperare l'unico punto da cui è composta la curva ( degenere)
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -199,17 +198,17 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
return *this ; }
|
||||
bool RelocateFrom( CurveComposite& ccSrc) ;
|
||||
bool GetApproxLength( double& dLen) const ;
|
||||
bool TestClosure( double dLinTol = EPS_SMALL) ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const CurveComposite& ccSrc) ;
|
||||
bool Validate( void) ;
|
||||
bool TestClosure( void) ;
|
||||
bool AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
|
||||
bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ;
|
||||
bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ;
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ;
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
|
||||
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
|
||||
|
||||
+14
-10
@@ -19,6 +19,7 @@
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -30,14 +31,14 @@ static const int TP_IS_VERT_LINE = 1 ;
|
||||
static bool IsVerticalLine( const ICurve* pCrv, double* pdLenZ) ;
|
||||
static bool VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
|
||||
static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
|
||||
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType,
|
||||
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
|
||||
CurveComposite& ccAux) ;
|
||||
static bool AddFirstLastVerticalLines( CurveComposite& ccOffs, double dLenVertFirst, double dLenVertLast) ;
|
||||
static bool MediaInternalAngleDeltaZ( CurveComposite& ccOffs) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::SimpleOffsetXY( double dDist, int nType)
|
||||
CurveComposite::SimpleOffsetXY( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// creo una copia formata solo da rette e archi che giacciono nel piano XY (VtExtr è Z+)
|
||||
CurveComposite ccCopy ;
|
||||
@@ -98,7 +99,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType)
|
||||
CurveComposite ccTemp ;
|
||||
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrv2, ccTemp) ||
|
||||
VerifyAndAdjustInternalAngle( pCrvPrev, pCrv2, ccTemp) ||
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, ccTemp)) {
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, dMaxAngExt, ccTemp)) {
|
||||
if ( ccTemp.GetCurveCount() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
|
||||
return false ;
|
||||
}
|
||||
@@ -122,7 +123,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType)
|
||||
CurveComposite ccTemp ;
|
||||
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrvNext, ccTemp) ||
|
||||
VerifyAndAdjustInternalAngle( pCrvPrev, pCrvNext, ccTemp) ||
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, ccTemp)) {
|
||||
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, dMaxAngExt, ccTemp)) {
|
||||
int nCrvCount = ccTemp.GetCurveCount() ;
|
||||
if ( nCrvCount > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
|
||||
return false ;
|
||||
@@ -174,7 +175,7 @@ bool
|
||||
VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
return false ;
|
||||
|
||||
// pulisco la curva ausiliaria
|
||||
@@ -218,7 +219,7 @@ bool
|
||||
VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
return false ;
|
||||
|
||||
// pulisco la curva ausiliaria
|
||||
@@ -259,11 +260,11 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAu
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType,
|
||||
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
|
||||
CurveComposite& ccAux)
|
||||
{
|
||||
// verifica dei puntatori
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr || &ccAux == nullptr)
|
||||
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
||||
return false ;
|
||||
|
||||
// pulisco la curva ausiliaria
|
||||
@@ -272,6 +273,9 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nT
|
||||
// elimino dal tipo le parti estranee all'angolo esterno
|
||||
nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ;
|
||||
|
||||
// porto il massimo angolo per tipo Extend in limiti accettabili (90° - 150°)
|
||||
dMaxAngExt = Clamp( dMaxAngExt, ANG_RIGHT, 1.667 * ANG_RIGHT) ;
|
||||
|
||||
// calcolo direzioni tangenti sull'estremo in comune
|
||||
Vector3d vtDir1, vtDir2 ;
|
||||
if ( ! pCrv1->GetEndDir( vtDir1) || ! pCrv2->GetStartDir( vtDir2))
|
||||
@@ -319,8 +323,8 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nT
|
||||
( dDist > 0 && dAngDeg < 0)))
|
||||
return false ;
|
||||
|
||||
// se l'angolo esterno supera il retto, offset extend diventa offset chamfer
|
||||
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL)
|
||||
// se l'angolo esterno supera il limite, offset extend diventa offset chamfer
|
||||
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > dMaxAngExt + EPS_ANG_SMALL)
|
||||
nType = ICurve::OFF_CHAMFER ;
|
||||
|
||||
// se angolo esterno molto piccolo, semplifico tutto
|
||||
|
||||
+1
-1
@@ -577,7 +577,7 @@ CurveLine::Invert( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveLine::SimpleOffset( double dDist, int nType)
|
||||
CurveLine::SimpleOffset( double dDist, int nType, double dMaxAngExt)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
|
||||
{ return ApproxWithArcs( dLinTol, dAngTolDeg, PA) ; }
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) override ;
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
|
||||
@@ -50,7 +50,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
|
||||
}
|
||||
// altrimenti, per curve successive
|
||||
else {
|
||||
// verifico se la distanza minima dal box è superiore al minimo già trovato
|
||||
// verifico se la distanza minima dal box è superiore al minimo già trovato
|
||||
BBox3d b3B ;
|
||||
if ( pCrvSmpl->GetLocalBBox( b3B) &&
|
||||
b3B.SqDistFromPoint( ptP) <= m_dDist * m_dDist) {
|
||||
@@ -105,7 +105,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
// con minima distanza più bassa
|
||||
// con minima distanza più bassa
|
||||
else if ( dCurrDist < m_dDist) {
|
||||
// aggiorno i minimi
|
||||
m_dDist = dCurrDist ;
|
||||
|
||||
+19
-6
@@ -47,6 +47,8 @@ DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve, bool bI
|
||||
case CRV_COMPO :
|
||||
CrvCompositeCalculate( ptP, Curve) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
// salvo il punto
|
||||
m_ptP = ptP ;
|
||||
@@ -150,7 +152,7 @@ DistPointCurve::GetMinDistPoint( double dNearParam, Point3d& ptMinDist, int& nFl
|
||||
}
|
||||
}
|
||||
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
double dParam ;
|
||||
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
|
||||
if ( i == 0 ||
|
||||
@@ -195,7 +197,7 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
|
||||
}
|
||||
}
|
||||
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
|
||||
if ( i == 0 ||
|
||||
abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) {
|
||||
@@ -230,9 +232,20 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
|
||||
Vector3d vtTg = 0.5 * ( vtPreTg + vtPostTg) ;
|
||||
// se tangenti opposte, si deve ricalcolare spostandosi un poco
|
||||
if ( ! vtTg.Normalize()) {
|
||||
double dDeltaU = 1000 * EPS_PARAM ;
|
||||
if ( ! m_pCurve->GetPointTang( m_Info[nInd].dPar - dDeltaU, ICurve::FROM_MINUS, ptQ, vtPreTg) ||
|
||||
! m_pCurve->GetPointTang( m_Info[nInd].dPar + dDeltaU, ICurve::FROM_PLUS, ptQ, vtPostTg))
|
||||
double dDeltaU = 1000 * EPS_PARAM ;
|
||||
double dParPre = m_Info[nInd].dPar - dDeltaU ;
|
||||
double dParPost = m_Info[nInd].dPar + dDeltaU ;
|
||||
// verifico se il parametro deve essere modificato per adattarsi a curva chiusa
|
||||
if ( m_pCurve->IsClosed()) {
|
||||
double dParS, dParE ;
|
||||
m_pCurve->GetDomain( dParS, dParE) ;
|
||||
if ( dParPre < dParS)
|
||||
dParPre = dParE - dDeltaU ;
|
||||
if ( dParPost > dParE)
|
||||
dParPost = dParS + dDeltaU ;
|
||||
}
|
||||
if ( ! m_pCurve->GetPointTang( dParPre, ICurve::FROM_MINUS, ptQ, vtPreTg) ||
|
||||
! m_pCurve->GetPointTang( dParPost, ICurve::FROM_PLUS, ptQ, vtPostTg))
|
||||
return false ;
|
||||
vtTg = 0.5 * ( vtPreTg + vtPostTg) ;
|
||||
if ( ! vtTg.Normalize( EPS_ZERO))
|
||||
@@ -262,7 +275,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
|
||||
if ( m_dDist < 0 || m_Info.empty())
|
||||
return false ;
|
||||
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
// cerco punto discreto più vicino (anche estremi di zone continue)
|
||||
int nInd ;
|
||||
double dParam ;
|
||||
for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) {
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointSurfBz.cpp Data : 29.10.25 Versione : 2.7j3
|
||||
// Contenuto : Implementazione della classe distanza Punto da superficie Bezier.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 29.10.25 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
|
||||
: m_dDist( -1), m_bIsInside( false)
|
||||
{
|
||||
// Bezier non valida
|
||||
if ( &pSrfBz == nullptr || ! pSrfBz.IsValid())
|
||||
return ;
|
||||
// Calcolo la distanza
|
||||
Calculate( ptP, pSrfBz) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = srfBz.IsClosed() ;
|
||||
|
||||
// Lavoro con l'oggetto superficie trimesh di base
|
||||
const ISurfTriMesh* pStmRef = srfBz.GetAuxSurfRefined() ;
|
||||
if ( pStmRef == nullptr)
|
||||
return ;
|
||||
|
||||
DistPointSurfTm dpst( ptP, *pStmRef) ;
|
||||
|
||||
//recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo
|
||||
Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ;
|
||||
int nT ; dpst.GetMinDistTriaIndex( nT) ;
|
||||
//salvo il punto corrispondente nel parametrico
|
||||
srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ;
|
||||
// salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto
|
||||
srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ;
|
||||
|
||||
// salvo la distanza minima
|
||||
m_dDist = Dist( ptP, m_ptMinDistPoint) ;
|
||||
// se il punto è sulla superficie
|
||||
if ( m_dDist < EPS_SMALL) {
|
||||
m_bIsInside = false ;
|
||||
return ;
|
||||
}
|
||||
else {
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * m_vtN < - EPS_SMALL) ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetDist( double& dDist) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
dDist = m_dDist ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
ptMinDistPoint = m_ptMinDistPoint ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
ptParamPoint = m_ptParam ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfBz::GetNorm( Vector3d& vtN) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
vtN = m_vtN ;
|
||||
return true ;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2018-2020
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointSurfTm.cpp Data : 19.12.20 Versione : 2.2l3
|
||||
// Contenuto : Implementazione della classe distanza Punto da Trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.12.18 LM Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfFr.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DistPointSurfFr::DistPointSurfFr( const Point3d& ptP, const ISurfFlatRegion& frSurf)
|
||||
: m_dDist( -1)
|
||||
{
|
||||
// FlatRegion non valida
|
||||
if ( &frSurf == nullptr || ! frSurf.IsValid())
|
||||
return ;
|
||||
// Calcolo la distanza
|
||||
Calculate( ptP, frSurf) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
DistPointSurfFr::Calculate( const Point3d& ptP, const ISurfFlatRegion& frSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = -1 ;
|
||||
|
||||
// Converto regione in classe base
|
||||
const SurfFlatRegion* pSfr = GetBasicSurfFlatRegion( &frSurf) ;
|
||||
if ( pSfr == nullptr)
|
||||
return ;
|
||||
|
||||
// ciclo sulle parti della regione
|
||||
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; nC ++) {
|
||||
// ciclo sui loop della parte di regione
|
||||
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; nL ++) {
|
||||
PtrOwner<ICurve> pLoop( pSfr->GetLoop( nC, nL)) ;
|
||||
if ( IsNull( pLoop)) {
|
||||
m_dDist = -1 ;
|
||||
return ;
|
||||
}
|
||||
DistPointCurve DPL( ptP, *pLoop) ;
|
||||
double dDist ;
|
||||
if ( DPL.GetDist( dDist) && ( m_dDist < -EPS_SMALL || dDist < m_dDist)) {
|
||||
m_dDist = dDist ;
|
||||
int nFlag ;
|
||||
m_nMinChunk = nC ;
|
||||
m_nMinLoop = nL ;
|
||||
DPL.GetParamAtMinDistPoint( 0, m_dMinPar, nFlag) ;
|
||||
DPL.GetMinDistPoint( 0, m_ptMinDistPoint, nFlag) ;
|
||||
DPL.GetSideAtMinDistPoint( 0, pSfr->GetNormVersor(), m_nSide) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata, aggiorno minima distanza sul piano
|
||||
if ( m_dDist > - EPS_SMALL) {
|
||||
Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ;
|
||||
m_dDistOnPlane = min( Dist( ptOn, m_ptMinDistPoint), m_dDist) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetDist( double& dDist) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
dDist = m_dDist ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetDistOnRegionPlane( double& dDist) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
dDist = m_dDistOnPlane ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetPointAtMinDist( Point3d& ptMinDist) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
ptMinDist = m_ptMinDistPoint ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetParamAtMinDist( int& nMinChunk, int& nMinLoop, double& dMinPar) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
nMinChunk = m_nMinChunk ;
|
||||
nMinLoop = m_nMinLoop ;
|
||||
dMinPar = m_dMinPar ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfFr::GetSideAtMinDist( int& nSide) const
|
||||
{
|
||||
if ( m_dDist < 0)
|
||||
return false ;
|
||||
nSide = m_nSide ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsPointInsideSurfFr( const Point3d& ptP, const ISurfFlatRegion* pSfr, double dMinDist, bool& bInside, int& nChunk)
|
||||
{
|
||||
// default non include
|
||||
bInside = false ;
|
||||
nChunk = -1 ;
|
||||
// verifica regione
|
||||
if ( pSfr == nullptr || ! pSfr->IsValid())
|
||||
return false ;
|
||||
// verifico se la proiezione del punto sul piano della regione sta nel suo box
|
||||
Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ;
|
||||
BBox3d b3Box ;
|
||||
pSfr->GetLocalBBox( b3Box) ;
|
||||
b3Box.Expand( dMinDist) ;
|
||||
if ( ! b3Box.Encloses( ptOn))
|
||||
return true ;
|
||||
// determino dove sta il punto
|
||||
DistPointSurfFr DPR( ptP, *pSfr) ;
|
||||
double dDist ; int nMinCh, nMinL; double dMinPar ; int nSide ;
|
||||
if ( DPR.GetDistOnRegionPlane( dDist) && DPR.GetParamAtMinDist( nMinCh, nMinL, dMinPar) && DPR.GetSideAtMinDist( nSide)) {
|
||||
if ( abs( dMinDist) < EPS_SMALL)
|
||||
bInside = ( nSide != PRS_OUT) ;
|
||||
else if ( dMinDist < 0)
|
||||
bInside = ( nSide == PRS_IN && dDist > abs( dMinDist) - EPS_SMALL) ;
|
||||
else
|
||||
bInside = ( nSide != PRS_OUT || dDist < dMinDist + EPS_SMALL) ;
|
||||
if ( bInside)
|
||||
nChunk = nMinCh ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+52
-32
@@ -21,10 +21,10 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Calcola la differenza fra i bounding-box A e B.
|
||||
// L'insieme differenza non è un bounding-box, ma è esprimibile come unione di al più sei bounding-box.
|
||||
// L'insieme differenza non è un bounding-box, ma è esprimibile come unione di al più sei bounding-box.
|
||||
// Se l'insieme differenza fra i box non ha misura nulla viene restituito true, false altrimenti.
|
||||
// I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto
|
||||
// nel box B; uno di questi si verifica se il box A è vuoto.
|
||||
// I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto
|
||||
// nel box B; uno di questi si verifica se il box A è vuoto.
|
||||
// Nel vettore vBoxDiff vengono restituiti i box la cui unione costituisce la differenza fra A e B.
|
||||
static bool
|
||||
BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff)
|
||||
@@ -34,7 +34,7 @@ BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDi
|
||||
// Se box A vuoto, risultato vuoto
|
||||
if ( boxA.IsEmpty())
|
||||
return false ;
|
||||
// Se box B vuoto o i box non si intersecano, risultato è ancora A
|
||||
// Se box B vuoto o i box non si intersecano, risultato è ancora A
|
||||
BBox3d boxInt ;
|
||||
if ( boxB.IsSmall() || ! boxA.FindIntersection( boxB, boxInt)) {
|
||||
vBoxDiff.emplace_back( boxA) ;
|
||||
@@ -94,7 +94,9 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
// Controllo se la superficie è chiusa
|
||||
// Vettore di indici dei triangoli più vicini inizialmente vuoto
|
||||
m_vnMinDistTriaIndex.clear() ;
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = tmSurf.IsClosed() ;
|
||||
|
||||
// Lavoro con l'oggetto superficie trimesh di base
|
||||
@@ -107,8 +109,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( b3Stm.IsEmpty())
|
||||
return ;
|
||||
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
|
||||
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
|
||||
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
|
||||
@@ -118,17 +120,17 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
BBox3d boxPPrev( ptP) ;
|
||||
BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ;
|
||||
// Variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima
|
||||
double dMinSqDist = DBL_MAX ;
|
||||
double dMinDist = DBL_MAX ;
|
||||
int nMinDistTriaIndex = SVT_NULL ;
|
||||
Point3d ptMinDistPoint ;
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
pStm->ResetTempInts() ;
|
||||
bool bContinue = true ;
|
||||
|
||||
// creazione del vettore dei triangoli più vicini a ptP
|
||||
// creazione del vettore dei triangoli più vicini a ptP
|
||||
vector<pair<int, Triangle3d>> vTria ; // <indice triangolo, Triangolo>
|
||||
while ( bContinue) {
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
BOXVECTOR vBox ;
|
||||
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
|
||||
// Ciclo sui box differenza
|
||||
@@ -136,7 +138,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
for ( const auto& b3Box : vBox) {
|
||||
// interseco il box con quello della superficie e ne verifico la distanza minima dal punto
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.SqDistFromPoint( ptP) > dMinSqDist)
|
||||
if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.DistFromPoint( ptP) > dMinDist)
|
||||
continue ;
|
||||
// ricerca sui triangoli nel box
|
||||
bCollide = true ;
|
||||
@@ -149,17 +151,22 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, trCurTria)) {
|
||||
pStm->SetTempInt( nT, 1) ;
|
||||
DistPointTriangle distPT( ptP, trCurTria) ;
|
||||
double dCurSqDist ;
|
||||
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetSqDist( dCurSqDist)) {
|
||||
if ( abs( dCurSqDist - dMinSqDist) < EPS_SMALL) // se distanze uguali...
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo
|
||||
else if ( dCurSqDist < dMinSqDist) { // se minore...
|
||||
vTria.clear() ; // pulisco il vettore
|
||||
dMinSqDist = dCurSqDist ;
|
||||
double dCurrDist ;
|
||||
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetDist( dCurrDist)) {
|
||||
// se distanze uguali...
|
||||
if ( abs( dCurrDist - dMinDist) < EPS_SMALL)
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
// se minore...
|
||||
else if ( dCurrDist < dMinDist) {
|
||||
// pulisco il vettore
|
||||
vTria.clear() ;
|
||||
dMinDist = dCurrDist ;
|
||||
nMinDistTriaIndex = nT ;
|
||||
distPT.GetMinDistPoint( ptMinDistPoint) ;
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +174,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
}
|
||||
}
|
||||
// Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
|
||||
if ( ! bCollide || dMinSqDist < SQ_EPS_SMALL)
|
||||
if ( ! bCollide || dMinDist < EPS_SMALL)
|
||||
bContinue = false ;
|
||||
else {
|
||||
boxPPrev = boxP ;
|
||||
@@ -179,11 +186,15 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( nMinDistTriaIndex == SVT_NULL)
|
||||
return ;
|
||||
|
||||
// Inizializzo il vettore dei triangoli a minima distanza
|
||||
for ( auto& Tria : vTria)
|
||||
m_vnMinDistTriaIndex.emplace_back( Tria.first) ;
|
||||
|
||||
// salvo la distanza minima
|
||||
m_dDist = sqrt( max( dMinSqDist, 0.)) ;
|
||||
m_dDist = dMinDist ;
|
||||
// salvo il punto a distanza minima
|
||||
m_ptMinDistPoint = ptMinDistPoint ;
|
||||
// se il punto è sulla TriMesh...
|
||||
// se il punto è sulla TriMesh...
|
||||
if ( m_dDist < EPS_SMALL) {
|
||||
m_nMinDistTriaIndex = nMinDistTriaIndex ;
|
||||
m_bIsInside = false ;
|
||||
@@ -215,7 +226,7 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
// 1) calcolo i centroidi dei triangoli in questione
|
||||
// 2) ottengo il punto medio di questi centroidi
|
||||
// 3) controllo quale triangolo interseca il segmento che parte da ptP e arriva a tale punto
|
||||
// 4) userò questo triangolo per classificare ptP
|
||||
// 4) userò questo triangolo per classificare ptP
|
||||
if ( bOutside == bInside) {
|
||||
// calcolo il baricentro complessivo
|
||||
Point3d ptBar_tot ;
|
||||
@@ -236,9 +247,6 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
}
|
||||
else // se informazioni coerenti
|
||||
m_bIsInside = bInside ;
|
||||
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -277,6 +285,18 @@ DistPointSurfTm::GetMinDistTriaIndex( int& nMinDistIndex) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointSurfTm::GetMinDistTriaIndices( INTVECTOR& vMinDistTriaIndex) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < - EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
vMinDistTriaIndex = m_vnMinDistTriaIndex ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
@@ -291,8 +311,8 @@ GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
if ( b3Stm.IsEmpty())
|
||||
return SVT_NULL ;
|
||||
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
// Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate.
|
||||
// Termino quando non trovo più triangoli che possano soddisfare la richiesta.
|
||||
Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ;
|
||||
double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ;
|
||||
double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ;
|
||||
@@ -304,11 +324,11 @@ GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
// Variabili distanza minima
|
||||
int nVert = SVT_NULL ;
|
||||
double dMinSqDist = DBL_MAX ;
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
pStm->ResetTempInts() ;
|
||||
bool bContinue = true ;
|
||||
while ( bContinue) {
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
BOXVECTOR vBox ;
|
||||
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
|
||||
// Ciclo sui box differenza
|
||||
|
||||
+12
-3
@@ -159,11 +159,20 @@ InitFontManager( const string& sNfeFontDir, const string& sDefaultFont)
|
||||
{
|
||||
// recupero il font manager
|
||||
FontManager& fntMgr = FontManager::GetFontManager() ;
|
||||
|
||||
// lo inizializzo
|
||||
fntMgr.Init( sNfeFontDir, sDefaultFont) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
SetDefaultFont( const string& sDefaultFont)
|
||||
{
|
||||
// recupero il font manager
|
||||
FontManager& fntMgr = FontManager::GetFontManager() ;
|
||||
// imposto il dato
|
||||
fntMgr.SetDefaultFont( sDefaultFont) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const string&
|
||||
GetNfeFontDir( void)
|
||||
@@ -185,11 +194,11 @@ GetDefaultFont( void)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static pfProcEvents s_pFunProcEvents = nullptr ;
|
||||
static psfProcEvents s_pFunProcEvents = nullptr ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool
|
||||
SetEGkProcessEvents( pfProcEvents pFun)
|
||||
SetEGkProcessEvents( psfProcEvents pFun)
|
||||
{
|
||||
s_pFunProcEvents = pFun ;
|
||||
return ( pFun != nullptr) ;
|
||||
|
||||
Binary file not shown.
+21
-8
@@ -22,7 +22,7 @@
|
||||
<ProjectGuid>{9A98A202-2853-454A-84CA-DCD1714176C9}</ProjectGuid>
|
||||
<RootNamespace>EgtGeomKernel</RootNamespace>
|
||||
<Keyword>MFCDLLProj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.20348.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@@ -30,7 +30,7 @@
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<PlatformToolset>v141_xp</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
@@ -46,7 +46,7 @@
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<PlatformToolset>v141_xp</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
@@ -116,7 +116,7 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -151,7 +151,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -199,7 +199,7 @@ copy $(TargetPath) \EgtProg\DllD64</Command>
|
||||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -245,7 +245,7 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
|
||||
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
|
||||
<IntelJCCErratum>true</IntelJCCErratum>
|
||||
</ClCompile>
|
||||
@@ -281,6 +281,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="BBox3d.cpp" />
|
||||
<ClCompile Include="BiArcs.cpp" />
|
||||
<ClCompile Include="CalcPocketing.cpp" />
|
||||
<ClCompile Include="CalcDerivate.cpp" />
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvToolSurfTm.cpp" />
|
||||
<ClCompile Include="CAvToolTriangle.cpp" />
|
||||
@@ -309,6 +311,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CurveByApprox.cpp" />
|
||||
<ClCompile Include="CurveByInterp.cpp" />
|
||||
<ClCompile Include="CurveCompositeOffset.cpp" />
|
||||
<ClCompile Include="DistPointSurfBz.cpp" />
|
||||
<ClCompile Include="DistPointSurfFr.cpp" />
|
||||
<ClCompile Include="IntersCurvePlane.cpp" />
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
@@ -318,10 +323,15 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="Trimming.cpp" />
|
||||
<ClCompile Include="MultiGeomDB.cpp" />
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
||||
<ClCompile Include="VolZmapOffset.cpp" />
|
||||
<ClCompile Include="PolygonElevation.cpp" />
|
||||
<ClCompile Include="Quaternion.cpp" />
|
||||
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
||||
<ClCompile Include="RotationXplaneFrame.cpp" />
|
||||
<ClCompile Include="SbzFromCurves.cpp" />
|
||||
<ClCompile Include="SbzStandard.cpp" />
|
||||
<ClCompile Include="Voronoi.cpp" />
|
||||
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
|
||||
@@ -335,11 +345,14 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkMultiGeomDB.h" />
|
||||
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
|
||||
<ClInclude Include="..\Include\EGkQuaternion.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
<ClInclude Include="CDeConeFrustumTria.h" />
|
||||
@@ -425,7 +438,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="OffsetCurveOnX.cpp" />
|
||||
<ClCompile Include="Polygon3d.cpp" />
|
||||
<ClCompile Include="AdjustLoops.cpp" />
|
||||
<ClCompile Include="ProjectCurveSurfTm.cpp" />
|
||||
<ClCompile Include="ProjectCurveSurf.cpp" />
|
||||
<ClCompile Include="RemoveCurveDefects.cpp" />
|
||||
<ClCompile Include="SelfIntersCurve.cpp" />
|
||||
<ClCompile Include="SfrCreate.cpp" />
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
<Filter Include="File di origine\GeoCollisionDetection">
|
||||
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoStriping">
|
||||
<UniqueIdentifier>{54901321-08f6-4428-80c7-a1f859136a32}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vector3d.cpp">
|
||||
@@ -486,7 +489,7 @@
|
||||
<ClCompile Include="IntersLineCaps.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ProjectCurveSurfTm.cpp">
|
||||
<ClCompile Include="ProjectCurveSurf.cpp">
|
||||
<Filter>File di origine\GeoProject</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SubtractProjectedFacesOnStmFace.cpp">
|
||||
@@ -537,6 +540,36 @@
|
||||
<ClCompile Include="Quaternion.cpp">
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SbzFromCurves.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DistPointSurfFr.cpp">
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VolZmapOffset.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MultiGeomDB.cpp">
|
||||
<Filter>File di origine\Gdb</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DistPointSurfBz.cpp">
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersCurvePlane.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CalcDerivate.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1214,6 +1247,15 @@
|
||||
<ClInclude Include="..\Include\EGkDistPointLine.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkMultiGeomDB.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+1
-1
@@ -1087,7 +1087,7 @@ ExtDimension::Update( void) const
|
||||
if ( m_nType == DT_RADIAL)
|
||||
sVal = "R " + sVal ;
|
||||
else if ( m_nType == DT_DIAMETRAL)
|
||||
sVal = u8"\u00D8 " + sVal ;
|
||||
sVal = reinterpret_cast<const char *>( u8"\u00D8") + sVal ;
|
||||
ReplaceString( m_sCalcText, IS_MEASURE, sVal) ;
|
||||
}
|
||||
// punto di inserimento del testo
|
||||
|
||||
@@ -147,6 +147,10 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// verifico il minimo raggio
|
||||
if ( dRadius < 10 * EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// eseguo calcoli
|
||||
Point3d ptCen, ptTg1, ptTg2 ;
|
||||
int nSide1, nSide2 ;
|
||||
@@ -165,6 +169,11 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// verifico dimensione minima
|
||||
double dLen = Dist( ptTg1, ptTg2) ;
|
||||
if ( dLen < 2 * EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// orientamento tra le curve
|
||||
bool bCCW = ( dSinA > 0) ;
|
||||
|
||||
@@ -207,6 +216,10 @@ CreateChamfer( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// verifico lo smusso minimo
|
||||
if ( dDist < 10 * EPS_SMALL)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo un riferimento sul piano perpendicolare alla normale
|
||||
Frame3d frIntr ;
|
||||
if ( ! frIntr.Set( ORIG, vtNorm))
|
||||
|
||||
+3
-1
@@ -29,6 +29,8 @@ class FontManager
|
||||
|
||||
public :
|
||||
bool Init( const std::string& sNfeFontDir, const std::string& sDefaultFont) ;
|
||||
bool SetDefaultFont( const std::string& sDefaultFont)
|
||||
{ m_sDefaultFont = sDefaultFont ; return true ; }
|
||||
bool SetCurrFont( const std::string& sFont, int nWeight, bool bItalic,
|
||||
double dHeight, double dRatio, double dAddAdvance) ;
|
||||
const std::string& GetNfeFontDir( void) const
|
||||
@@ -54,7 +56,7 @@ class FontManager
|
||||
OsFont m_OsFont ;
|
||||
|
||||
private :
|
||||
FontManager( void) {}
|
||||
FontManager( void) : m_bCurrNfeFont( false) {}
|
||||
FontManager( FontManager const& copy) = delete ;
|
||||
FontManager& operator=( FontManager const& copy) = delete ;
|
||||
} ;
|
||||
|
||||
+2
-2
@@ -493,7 +493,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
// salvo la linea, se contiene qualcosa
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
@@ -523,7 +523,7 @@ NfeFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECT
|
||||
dMaxW = vtMove.x ;
|
||||
}
|
||||
// salvo eventuale ultima linea
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
|
||||
+2
-2
@@ -619,7 +619,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
|
||||
int nLbLen ;
|
||||
if ( IsLineBreak( vCode, i, nLbLen)) {
|
||||
// salvo la linea, se contiene qualcosa
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
@@ -646,7 +646,7 @@ OsFont::GetTextLines( const string& sText, int nInsPos, PNTVECTOR& vPt, STRVECTO
|
||||
dMaxW = vtMove.x ;
|
||||
}
|
||||
// salvo eventuale ultima linea
|
||||
if ( vTmpCode.size() > 0) {
|
||||
if ( ! vTmpCode.empty()) {
|
||||
string sLine ;
|
||||
SetCodePoints( vTmpCode, sLine) ;
|
||||
vLine.push_back( sLine) ;
|
||||
|
||||
+5
-5
@@ -2267,7 +2267,7 @@ bool
|
||||
GdbExecutor::SurfTriMeshEnd( const STRVECTOR& vsParams)
|
||||
{
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// recupero la superficie
|
||||
ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ;
|
||||
@@ -6632,7 +6632,7 @@ GdbExecutor::ExecuteDeselect( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
// deselezione di tutto
|
||||
else if ( sCmd2 == "ALL") {
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// cancello selezione oggetti
|
||||
if ( ! m_pGDB->ClearSelection())
|
||||
@@ -7773,7 +7773,7 @@ bool
|
||||
GdbExecutor::ExecuteNew( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
{
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// pulizia e reinizializzazione del DB geometrico
|
||||
m_pGDB->Clear() ;
|
||||
@@ -7946,7 +7946,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
// chiudo il file di uscita Tsc
|
||||
else if ( sCmd2 == "CLOSE") {
|
||||
// nessun parametro
|
||||
if ( vsParams.size() != 0)
|
||||
if ( ! vsParams.empty())
|
||||
return false ;
|
||||
// scrivo terminazioni e chiudo il file
|
||||
return m_OutTsc.Close() ;
|
||||
@@ -7969,7 +7969,7 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams)
|
||||
else if ( sCmd2 == "SETGR") {
|
||||
Frame3d frF ;
|
||||
// nessun parametro
|
||||
if ( vsParams.size() == 0)
|
||||
if ( vsParams.empty())
|
||||
frF.Reset() ;
|
||||
// un parametro ( Id del gruppo)
|
||||
else if ( vsParams.size() == 1) {
|
||||
|
||||
+2
-2
@@ -336,7 +336,7 @@ GdbGeo::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoe
|
||||
// curva originale
|
||||
ICurve* pCrv = GetCurve( m_pGeoObj) ;
|
||||
// trasformo in curva di Bezier (semplice o composta)
|
||||
ICurve* pCrvNew = ArcToBezierCurve( pCrv) ;
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc( pCrv)) ;
|
||||
if ( pCrvNew == nullptr)
|
||||
return false ;
|
||||
// assegno alla nuova curva estrusione e spessore di quella originale
|
||||
@@ -389,7 +389,7 @@ GdbGeo::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDi
|
||||
if ( ! pArc->IsPlane() ||
|
||||
! AreSameOrOppositeVectorExact( pArc->GetNormVersor(), vtNorm)) {
|
||||
// trasformo in curva di Bezier (semplice o composta)
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurve( m_pGeoObj)) ;
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc( m_pGeoObj)) ;
|
||||
if ( pCrvNew == nullptr)
|
||||
return false ;
|
||||
// assegno alla nuova curva estrusione e spessore di quella originale
|
||||
|
||||
+2
-2
@@ -1254,13 +1254,13 @@ GdbIterator::GetCalcStatus( int& nStat) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbIterator::SetMark( void)
|
||||
GdbIterator::SetMark( int nMark)
|
||||
{
|
||||
if ( m_pGDB == nullptr || m_pCurrObj == nullptr)
|
||||
return false ;
|
||||
|
||||
// imposto la marcatura
|
||||
return m_pCurrObj->SetMark() ;
|
||||
return m_pCurrObj->SetMark( nMark) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ class GdbIterator : public IGdbIterator
|
||||
bool RevertStatus( void) override ;
|
||||
bool GetStatus( int& nStat) const override ;
|
||||
bool GetCalcStatus( int& nStat) const override ;
|
||||
bool SetMark( void) override ;
|
||||
bool SetMark( int nMark = GDB_MK_ON) override ;
|
||||
bool ResetMark( void) override ;
|
||||
bool GetMark( int& nMark) const override ;
|
||||
bool GetCalcMark( int& nMark) const override ;
|
||||
|
||||
+18
-4
@@ -101,6 +101,20 @@ GdbObj::CopyFrom( const GdbObj* pSou)
|
||||
return ( CopyAttribsFrom( pSou) && CopyTextureDataFrom( pSou) && CopyUserObjFrom( pSou)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::CopyStippleDataFrom( const GdbObj* pSou)
|
||||
{
|
||||
// se l'oggetto sorgente non esiste
|
||||
if ( pSou == nullptr)
|
||||
return false ;
|
||||
// copio stipple
|
||||
m_nStpFactor = pSou->m_nStpFactor ;
|
||||
m_nStpPattern = pSou->m_nStpPattern ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::CopyAttribsFrom( const GdbObj* pSou)
|
||||
@@ -612,14 +626,14 @@ GdbObj::GetCalcStatus( int& nStat, int nLev) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GdbObj::SetMark( void)
|
||||
GdbObj::SetMark( int nMark)
|
||||
{
|
||||
// verifico esistenza (con eventuale creazione) degli attributi
|
||||
if ( GetSafeAttribs() == nullptr)
|
||||
return false ;
|
||||
|
||||
// assegno la marcatura
|
||||
m_pAttribs->SetMark() ;
|
||||
m_pAttribs->SetMark( nMark) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -659,8 +673,8 @@ GdbObj::GetCalcMark( int& nMark) const
|
||||
nObjMark = m_pAttribs->GetMark() ;
|
||||
|
||||
// se la marcatura è ON, non ho bisogno di sapere altro
|
||||
if ( nObjMark == GDB_MK_ON) {
|
||||
nMark = GDB_MK_ON ;
|
||||
if ( nObjMark == GDB_MK_ON || nObjMark == GDB_MK_ON_2) {
|
||||
nMark = nObjMark ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ class GdbObj
|
||||
GdbObj( void) ;
|
||||
bool CopyFrom( const GdbObj* pSou) ;
|
||||
bool CopyAttribsFrom( const GdbObj* pSou) ;
|
||||
bool CopyStippleDataFrom( const GdbObj* pSou) ;
|
||||
bool CopyTextureDataFrom( const GdbObj* pSou) ;
|
||||
bool CopyUserObjFrom( const GdbObj* pSou) ;
|
||||
|
||||
@@ -81,7 +82,7 @@ class GdbObj
|
||||
bool IsSelected( void) const ;
|
||||
bool GetStatus( int& nStat) const ;
|
||||
bool GetCalcStatus( int& nStat, int nLev = 0) const ;
|
||||
bool SetMark( void) ;
|
||||
bool SetMark( int nMark) ;
|
||||
bool ResetMark( void) ;
|
||||
bool GetMark( int& nMark) const ;
|
||||
bool GetCalcMark( int& nMark) const ;
|
||||
|
||||
+35
-35
@@ -28,41 +28,6 @@
|
||||
#define GEOOBJ_NGEIDTOTYPE( nNgeId) GeoObjFactory::NgeIdToType( nNgeId)
|
||||
#define GEOOBJ_CREATE( nKey) GeoObjFactory::Create( nKey)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
class GeoObjRegister
|
||||
{
|
||||
public :
|
||||
static bool DoRegister( int nKey, int nNgeId)
|
||||
{ if ( ! GeoObjFactory::Register( nKey, NgeAscKeyW[nNgeId], nNgeId, Create))
|
||||
return false ;
|
||||
GetTypePrivate() = nKey ;
|
||||
GetKeyPrivate() = NgeAscKeyW[nNgeId] ;
|
||||
GetNgeIdPrivate() = nNgeId ;
|
||||
return true ; }
|
||||
static IGeoObj* Create( void)
|
||||
{ return new( std::nothrow) T ; }
|
||||
static int GetType( void)
|
||||
{ return GetTypePrivate() ; }
|
||||
static const std::string& GetKey( void)
|
||||
{ return GetKeyPrivate() ; }
|
||||
static int GetNgeId( void)
|
||||
{ return GetNgeIdPrivate() ; }
|
||||
|
||||
private :
|
||||
GeoObjRegister( void) {}
|
||||
~GeoObjRegister( void) {}
|
||||
static int& GetTypePrivate( void)
|
||||
{ static int s_nType ;
|
||||
return s_nType ; }
|
||||
static std::string& GetKeyPrivate( void)
|
||||
{ static std::string s_sKey ;
|
||||
return s_sKey ; }
|
||||
static int& GetNgeIdPrivate( void)
|
||||
{ static int s_nNgeId ;
|
||||
return s_nNgeId ; }
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class GeoObjFactory
|
||||
{
|
||||
@@ -117,3 +82,38 @@ class GeoObjFactory
|
||||
{ static CreatorMap s_CreatorMap ;
|
||||
return s_CreatorMap ; }
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
class GeoObjRegister
|
||||
{
|
||||
public :
|
||||
static bool DoRegister( int nKey, int nNgeId)
|
||||
{ if ( ! GeoObjFactory::Register( nKey, NgeAscKeyW[nNgeId], nNgeId, Create))
|
||||
return false ;
|
||||
GetTypePrivate() = nKey ;
|
||||
GetKeyPrivate() = NgeAscKeyW[nNgeId] ;
|
||||
GetNgeIdPrivate() = nNgeId ;
|
||||
return true ; }
|
||||
static IGeoObj* Create( void)
|
||||
{ return new( std::nothrow) T ; }
|
||||
static int GetType( void)
|
||||
{ return GetTypePrivate() ; }
|
||||
static const std::string& GetKey( void)
|
||||
{ return GetKeyPrivate() ; }
|
||||
static int GetNgeId( void)
|
||||
{ return GetNgeIdPrivate() ; }
|
||||
|
||||
private :
|
||||
GeoObjRegister( void) {}
|
||||
~GeoObjRegister( void) {}
|
||||
static int& GetTypePrivate( void)
|
||||
{ static int s_nType ;
|
||||
return s_nType ; }
|
||||
static std::string& GetKeyPrivate( void)
|
||||
{ static std::string s_sKey ;
|
||||
return s_sKey ; }
|
||||
static int& GetNgeIdPrivate( void)
|
||||
{ static int s_nNgeId ;
|
||||
return s_nNgeId ; }
|
||||
} ;
|
||||
|
||||
+15
-13
@@ -38,20 +38,22 @@ using namespace std ;
|
||||
class LockAddErase
|
||||
{
|
||||
public :
|
||||
LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
|
||||
LockAddErase( atomic_flag& bAddEraseOn, bool bUse = true)
|
||||
: m_bAddEraseOn( bAddEraseOn), m_bUse( bUse)
|
||||
{ if ( ! m_bUse) return ;
|
||||
while ( m_bAddEraseOn.test_and_set()) {
|
||||
this_thread::sleep_for( chrono::nanoseconds{ 1}) ;
|
||||
while ( m_bAddEraseOn.test_and_set( memory_order_acquire)) {
|
||||
m_bAddEraseOn.wait( true, memory_order_relaxed) ;
|
||||
}
|
||||
} ;
|
||||
|
||||
~LockAddErase( void)
|
||||
{ if ( ! m_bUse) return ;
|
||||
m_bAddEraseOn.clear() ;
|
||||
m_bAddEraseOn.clear( memory_order_release) ;
|
||||
m_bAddEraseOn.notify_one() ;
|
||||
} ;
|
||||
|
||||
private :
|
||||
std::atomic_flag& m_bAddEraseOn ;
|
||||
atomic_flag& m_bAddEraseOn ;
|
||||
bool m_bUse ;
|
||||
} ;
|
||||
|
||||
@@ -611,7 +613,7 @@ GeomDB::GetGdbObj( int nId) const
|
||||
// radice
|
||||
else if ( nId == GDB_ID_ROOT)
|
||||
return &m_GrpRadix ;
|
||||
// un nodo qualubque
|
||||
// un nodo qualunque
|
||||
else
|
||||
return m_IdManager.FindObj( nId) ;
|
||||
}
|
||||
@@ -658,7 +660,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLo
|
||||
return false ;
|
||||
}
|
||||
// inserisco come figlio, in testa alla lista del padre
|
||||
else if ( nSonBeforeAfter == GDB_FIRST_SON){
|
||||
else if ( nSonBeforeAfter == GDB_FIRST_SON) {
|
||||
GdbGroup* pGroup = ::GetGdbGroup( pGRef) ;
|
||||
if ( pGroup == nullptr)
|
||||
return false ;
|
||||
@@ -877,7 +879,7 @@ GeomDB::GetFirstNameInGroup( int nGroupId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbO->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbO->m_nId) ;
|
||||
// passo al successivo
|
||||
pGdbO = pGdbO->GetNext() ;
|
||||
@@ -905,7 +907,7 @@ GeomDB::GetNextName( int nId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbNext->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbNext->m_nId) ;
|
||||
// passo al successivo
|
||||
pGdbNext = pGdbNext->GetNext() ;
|
||||
@@ -933,7 +935,7 @@ GeomDB::GetLastNameInGroup( int nGroupId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbO->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbO->m_nId) ;
|
||||
// passo al precedente
|
||||
pGdbO = pGdbO->GetPrev() ;
|
||||
@@ -961,7 +963,7 @@ GeomDB::GetPrevName( int nId, const string& sName) const
|
||||
// se ha il nome o la parte iniziale di nome cercato
|
||||
string sObjName ;
|
||||
if ( pGdbPrev->GetName( sObjName) &&
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.find( sToFind) == 0)))
|
||||
(( ! bWild && sObjName == sToFind) || ( bWild && sObjName.rfind( sToFind, 0) == 0)))
|
||||
return ( pGdbPrev->m_nId) ;
|
||||
// passo al precedente
|
||||
pGdbPrev = pGdbPrev->GetPrev() ;
|
||||
@@ -2310,7 +2312,7 @@ GeomDB::GetCalcStatus( int nId, int& nStat) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GeomDB::SetMark( int nId)
|
||||
GeomDB::SetMark( int nId, int nMark)
|
||||
{
|
||||
// recupero l'oggetto
|
||||
GdbObj* pGdbObj = GetGdbObj( nId) ;
|
||||
@@ -2318,7 +2320,7 @@ GeomDB::SetMark( int nId)
|
||||
return false ;
|
||||
|
||||
// imposto la marcatura
|
||||
return pGdbObj->SetMark() ;
|
||||
return pGdbObj->SetMark( nMark) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,10 @@ class GeomDB : public IGeomDB
|
||||
friend class GdbObj ;
|
||||
friend class GdbGroup ;
|
||||
friend class GdbGeo ;
|
||||
friend int CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ;
|
||||
friend int CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ;
|
||||
friend int DuplicateGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId) ;
|
||||
friend int DuplicateGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, bool bSkipTemp) ;
|
||||
|
||||
public :
|
||||
~GeomDB( void) override ;
|
||||
@@ -136,7 +140,7 @@ class GeomDB : public IGeomDB
|
||||
bool RevertStatus( int nId) override ;
|
||||
bool GetStatus( int nId, int& nStat) const override ;
|
||||
bool GetCalcStatus( int nId, int& nStat) const override ;
|
||||
bool SetMark( int nId) override ;
|
||||
bool SetMark( int nId, int nMark = GDB_MK_ON) override ;
|
||||
bool ResetMark( int nId) override ;
|
||||
bool GetMark( int nId, int& nMark) const override ;
|
||||
bool GetCalcMark( int nId, int& nMark) const override ;
|
||||
|
||||
+13
-13
@@ -116,7 +116,7 @@ HashGrid1d::~HashGrid1d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
@@ -396,8 +396,10 @@ HashGrid1d::Enlarge( void)
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_CellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
pCell->m_neighborOffset = nullptr ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
m_cell = nullptr ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_CellCount *= 2 ;
|
||||
@@ -569,7 +571,7 @@ HashGrids1d::Update( void)
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
if ( ! m_objsToAdd.empty()) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
@@ -634,24 +636,22 @@ HashGrids1d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids1d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_ObjsList.clear() ;
|
||||
m_ObjsMap.clear() ;
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
for ( auto pGrid : m_GridList)
|
||||
delete pGrid ;
|
||||
m_GridList.clear() ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -125,7 +125,7 @@ HashGrid2d::~HashGrid2d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_xyCellCount ; ++ pCell) {
|
||||
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_xyCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
@@ -445,8 +445,10 @@ HashGrid2d::Enlarge( void)
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_xyCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
pCell->m_neighborOffset = nullptr ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
m_cell = nullptr ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_xCellCount *= 2 ;
|
||||
@@ -623,7 +625,7 @@ HashGrids2d::Update( void)
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
if ( ! m_objsToAdd.empty()) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
@@ -688,24 +690,22 @@ HashGrids2d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
HashGrids2d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_ObjsList.clear() ;
|
||||
m_ObjsMap.clear() ;
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
for ( auto pGrid : m_GridList)
|
||||
delete pGrid ;
|
||||
m_GridList.clear() ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -132,7 +132,7 @@ HashGrid3d::~HashGrid3d( void)
|
||||
{
|
||||
Clear() ;
|
||||
|
||||
for ( Cell* pCell = m_cell ; pCell < m_cell + m_xyzCellCount ; ++ pCell) {
|
||||
for ( Cell* pCell = m_cell ; pCell != nullptr && pCell < m_cell + m_xyzCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
}
|
||||
@@ -486,8 +486,10 @@ HashGrid3d::Enlarge( void)
|
||||
for ( auto pCell = m_cell ; pCell < m_cell + m_xyzCellCount ; ++ pCell) {
|
||||
if ( pCell->m_neighborOffset != m_stdNeighborOffset)
|
||||
delete[] pCell->m_neighborOffset ;
|
||||
pCell->m_neighborOffset = nullptr ;
|
||||
}
|
||||
delete[] m_cell ;
|
||||
m_cell = nullptr ;
|
||||
|
||||
// ... the number of cells is doubled in each coordinate direction, ...
|
||||
m_xCellCount *= 2 ;
|
||||
@@ -667,7 +669,7 @@ HashGrids3d::Update( void)
|
||||
// Salvo stato di precedente attivazione delle griglie
|
||||
bool bGridActivePrev = m_bGridActive ;
|
||||
// Inseriamo gli oggetti presenti nel vettore m_objsToAdd
|
||||
if ( m_objsToAdd.size() > 0 ) {
|
||||
if ( ! m_objsToAdd.empty()) {
|
||||
for ( auto pObj : m_objsToAdd) {
|
||||
if ( m_bGridActive)
|
||||
addGrid( *pObj) ;
|
||||
@@ -731,7 +733,7 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
sort( vnIds.begin(), vnIds.end()) ;
|
||||
vnIds.erase( unique( vnIds.begin(), vnIds.end()), vnIds.end()) ;
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -739,17 +741,15 @@ HashGrids3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
void
|
||||
HashGrids3d::Clear( void)
|
||||
{
|
||||
for ( auto pGrid : m_GridList) {
|
||||
delete pGrid ;
|
||||
}
|
||||
m_GridList.clear() ;
|
||||
|
||||
m_bGridActive = false ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
|
||||
m_ObjsList.clear() ;
|
||||
m_ObjsMap.clear() ;
|
||||
m_objsToAdd.clear() ;
|
||||
|
||||
m_nonGridObjs.clear() ;
|
||||
for ( auto pGrid : m_GridList)
|
||||
delete pGrid ;
|
||||
m_GridList.clear() ;
|
||||
m_bActivate = true ;
|
||||
m_bGridActive = false ;
|
||||
m_b3Objs.Reset() ;
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -17,6 +17,9 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static const double EPS_INTER_ARC = 0.1 * EPS_SMALL ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
{
|
||||
@@ -60,15 +63,15 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
vtDir /= dDist ;
|
||||
|
||||
// cerchi esterni -> nessuna intersezione
|
||||
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_SMALL)
|
||||
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_INTER_ARC)
|
||||
return ;
|
||||
|
||||
// cerchi interni -> nessuna intersezione
|
||||
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_SMALL)
|
||||
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_INTER_ARC)
|
||||
return ;
|
||||
|
||||
// cerchi coincidenti -> sovrapposizioni e/o intersezioni agli estremi
|
||||
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_SMALL) {
|
||||
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_INTER_ARC) {
|
||||
// coefficiente da parametro dell'arco 1 a lunghezza
|
||||
double dU2L = abs( m_Arc1.GetAngCenter()) * DEGTORAD * m_Arc1.GetRadius() ;
|
||||
// determino se sono equiversi o controversi
|
||||
@@ -236,7 +239,7 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
double dSqH = m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA ;
|
||||
|
||||
// cerchi tangenti esterni -> una intersezione
|
||||
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_SMALL) {
|
||||
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_INTER_ARC) {
|
||||
// tolleranza tangenziale sull'intersezione
|
||||
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
|
||||
// calcolo il punto di intersezione
|
||||
@@ -358,7 +361,7 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
|
||||
}
|
||||
|
||||
// cerchi tangenti interni -> una intersezione
|
||||
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_SMALL) {
|
||||
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_INTER_ARC) {
|
||||
// tolleranza tangenziale sull'intersezione
|
||||
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
|
||||
// determino quale dei due contiene l'altro
|
||||
|
||||
@@ -371,12 +371,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// caso NULL-NULL per corrente di prima curva
|
||||
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
if ( m_Info[i].IciB[ki].dU > m_Info[j].IciB[kj].dU + EPS_PARAM)
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
|
||||
EraseCurrentInfo( i, j) ;
|
||||
}
|
||||
// caso NULL-NULL per precedente di prima curva
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
|
||||
m_Info[i].IciA[0].nPrevTy = m_Info[j].IciA[0].nPrevTy ;
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
|
||||
if ( m_Info[j].IciB[kj].dU < m_Info[i].IciB[ki].dU - EPS_PARAM)
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
|
||||
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
|
||||
EraseOtherInfo( i, j) ;
|
||||
}
|
||||
|
||||
+90
-16
@@ -47,7 +47,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
|
||||
// ciclo sulle curve per verificare se da approssimare
|
||||
for ( int i = 0 ; i < 2 ; ++ i) {
|
||||
// se curva è arco da approssimare oppure è curva di Bezier
|
||||
// se curva è arco da approssimare oppure è curva di Bezier
|
||||
if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) ||
|
||||
m_pCurve[i]->GetType() == CRV_BEZIER) {
|
||||
// approssimo con rette
|
||||
@@ -78,6 +78,8 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
case CRV_COMPO :
|
||||
LineCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
case CRV_ARC :
|
||||
@@ -91,6 +93,8 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
case CRV_COMPO :
|
||||
ArcCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
case CRV_COMPO :
|
||||
@@ -104,8 +108,12 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
|
||||
case CRV_COMPO :
|
||||
CrvCompoCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
// per curve approssimate, sistemo...
|
||||
AdjustIntersParams( ( pCalcCrv[0] != m_pCurve[0]), ( pCalcCrv[1] != m_pCurve[1])) ;
|
||||
@@ -119,7 +127,7 @@ IntersCurveCurve::IsArcToApprox( const ICurve& Curve)
|
||||
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
// verifico se non è nel piano XY o ha più di un giro al centro
|
||||
// verifico se non è nel piano XY o ha più di un giro al centro
|
||||
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
|
||||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
|
||||
}
|
||||
@@ -244,10 +252,10 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
|
||||
bool
|
||||
IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB)
|
||||
{
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
if ( m_Info.size() == 0)
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
if ( m_Info.empty())
|
||||
return true ;
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
if ( ! bAdjCrvA && ! bAdjCrvB)
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
@@ -283,6 +291,24 @@ IntersCurveCurve::GetIntersCount( void)
|
||||
return m_nIntersCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersCurveCurve::GetInters3DCount( void)
|
||||
{
|
||||
int nCount = 0 ;
|
||||
for( int i = 0 ; i < m_nIntersCount ; ++i) {
|
||||
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
else {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
}
|
||||
return nCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersCurveCurve::GetCrossIntersCount( void)
|
||||
@@ -332,6 +358,30 @@ IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
|
||||
{
|
||||
if ( nInd < 0 || nInd >= GetInters3DCount())
|
||||
return false ;
|
||||
int nCount = - 1 ;
|
||||
for( int i = 0 ; i < m_nIntersCount ; ++i) {
|
||||
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
else {
|
||||
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
|
||||
++nCount ;
|
||||
}
|
||||
if( nCount == nInd) {
|
||||
aInfo = m_Info[nInd] ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d& ptI)
|
||||
@@ -339,11 +389,11 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
|
||||
if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
|
||||
return false ;
|
||||
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
bool bFound = false ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
||||
// se è un'intersezione singola
|
||||
// se è un'intersezione singola
|
||||
if ( ! m_Info[i].bOverlap) {
|
||||
// faccio la verifica sul punto
|
||||
Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ;
|
||||
@@ -408,7 +458,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nIntersCount >= 1)
|
||||
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
|
||||
}
|
||||
@@ -425,7 +475,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nIntersCount >= 1)
|
||||
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
|
||||
}
|
||||
@@ -490,7 +540,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
double dU2 = Info[j].IciA[1].dU ;
|
||||
if ( dU2 < dU1 && pCurve->IsClosed())
|
||||
dU2 += dEndPar ;
|
||||
// se cade nell'intervallo è da saltare
|
||||
// se cade nell'intervallo è da saltare
|
||||
if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) {
|
||||
bToSkip = true ;
|
||||
break ;
|
||||
@@ -509,7 +559,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
double dCurrPar = dStartPar ;
|
||||
double dCurrLen = 0 ;
|
||||
double dEndLen ; pCurve->GetLength( dEndLen) ;
|
||||
// se è chiusa, recupero come finisce
|
||||
// se è chiusa, recupero come finisce
|
||||
if ( pCurve->IsClosed()) {
|
||||
if ( ! InfoCorr[nNumInters-1].bOverlap)
|
||||
nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ;
|
||||
@@ -527,7 +577,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
// se è definito un tratto precedente
|
||||
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
|
||||
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
@@ -549,7 +599,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
// altrimenti, salvo il tipo
|
||||
else
|
||||
nLastTy = InfoCorr[i].IciA[0].nNextTy ;
|
||||
// se è definito un tratto in sovrapposizione
|
||||
// se è definito un tratto in sovrapposizione
|
||||
if ( InfoCorr[i].bOverlap) {
|
||||
// assegno i dati
|
||||
CrvClass segClass ;
|
||||
@@ -589,7 +639,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
|
||||
double dStartParB, dEndParB ;
|
||||
if ( ! pCurveB->GetDomain( dStartParB, dEndParB))
|
||||
return false ;
|
||||
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
|
||||
// se almeno un punto di ciascuna curva è esterno al box dell'altra, sono sicuramente esterne
|
||||
BBox3d boxCrvA, boxCrvB ;
|
||||
if ( ! pCurveA->GetLocalBBox( boxCrvA) ||
|
||||
! pCurveB->GetLocalBBox( boxCrvB))
|
||||
@@ -632,13 +682,37 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
|
||||
IntersCurveCurve iCC( clLine, *pCurveB) ;
|
||||
// dichiaro la classe della curva per default
|
||||
int nClass = CRVC_OUT ;
|
||||
// se c'è almeno una intersezione
|
||||
// se c'è almeno una intersezione
|
||||
if ( iCC.GetIntersCount() > 0) {
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
IntCrvCrvInfo aInfo ;
|
||||
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
||||
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
nClass = CRVC_IN ;
|
||||
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
|
||||
nClass = CRVC_OUT ;
|
||||
else if ( aInfo.IciA[0].nPrevTy == ICCT_NULL) {
|
||||
// se il primo punto scelto non va bene allora ne cerco uno che mi dia informazioni sull'essere interno o esterno
|
||||
CurveLine clLine ;
|
||||
Point3d ptNewChoice ; pCurveA->GetPointD1D2( 0.25, ICurve::FROM_MINUS, ptNewChoice) ;
|
||||
if ( ! clLine.SetPDL( ptNewChoice, 0, dLen))
|
||||
return false ;
|
||||
// calcolo l'intersezione
|
||||
IntersCurveCurve iCC( clLine, *pCurveB) ;
|
||||
if ( iCC.GetIntersCount() > 0) {
|
||||
// se quanto precede la prima intersezione è interno, allora la curva è interna
|
||||
IntCrvCrvInfo aInfo ;
|
||||
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
||||
if ( aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
nClass = CRVC_IN ;
|
||||
else if ( aInfo.IciA[0].nPrevTy == ICCT_OUT)
|
||||
nClass = CRVC_OUT ;
|
||||
else
|
||||
return false ; // se arrivo qui potrei ritentare la ricerca
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// altrimenti sono esterni tra loro
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,451 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersCurvePlane.cpp Data : 07.11.25 Versione : 2.7k1
|
||||
// Contenuto : Implementazione della classe intersezione curva-piano.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.11.25 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "IntersLineArc.h"
|
||||
#include "IntersArcArc.h"
|
||||
#include "IntersCrvCompoCrvCompo.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
IntersCurvePlane::IntersCurvePlane( const ICurve& Curve, const Point3d& ptOrig, const Vector3d& vtN)
|
||||
{
|
||||
// Le intersezioni sono calcolate nel piano XY locale.
|
||||
// Il flag bAreSegments vale solo per intersezione tra due linee e riguarda entrambe.
|
||||
|
||||
// inizializzazioni
|
||||
m_nIntersCount = 0 ;
|
||||
m_pCurve = &Curve ;
|
||||
m_plPlane.Set( ptOrig, vtN) ;
|
||||
|
||||
// puntatore alla curva usata nei calcoli (originali o temporanee)
|
||||
const ICurve* pCalcCrv ;
|
||||
// per eventuale esplosione temporanea delle curve
|
||||
PtrOwner<ICurve> pTmpCrv ;
|
||||
|
||||
// se curva è arco da approssimare oppure è curva di Bezier
|
||||
if ( m_pCurve->GetType() == CRV_ARC || m_pCurve->GetType() == CRV_BEZIER || m_pCurve->GetType() == CRV_COMPO) {
|
||||
// approssimo con rette
|
||||
PolyLine PL ;
|
||||
if ( ! m_pCurve->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return ;
|
||||
pTmpCrv.Set( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pTmpCrv))
|
||||
return ;
|
||||
if ( ! GetBasicCurveComposite( pTmpCrv)->FromPolyLine( PL))
|
||||
return ;
|
||||
pCalcCrv = pTmpCrv ;
|
||||
}
|
||||
else
|
||||
pCalcCrv = m_pCurve ;
|
||||
|
||||
m_Info.clear() ;
|
||||
if ( pCalcCrv->GetType() == CRV_LINE) {
|
||||
CalcIntersLinePlane( m_plPlane, *pCalcCrv) ;
|
||||
}
|
||||
else if ( pCalcCrv->GetType() == CRV_COMPO){
|
||||
for ( int i = 0 ; i < GetBasicCurveComposite( pCalcCrv)->GetCurveCount(); ++i) {
|
||||
const ICurve& subCurve = *GetBasicCurveComposite( pCalcCrv)->GetCurve( i) ;
|
||||
CalcIntersLinePlane( m_plPlane, subCurve, i) ;
|
||||
}
|
||||
OrderAndCompleteIntersections() ;
|
||||
}
|
||||
|
||||
// per curve approssimate, sistemo...
|
||||
AdjustIntersParams( pCalcCrv != m_pCurve) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Curve, int nCrv)
|
||||
{
|
||||
if ( Curve.GetType() != CRV_LINE)
|
||||
return false ;
|
||||
Point3d ptStart ; Curve.GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; Curve.GetEndPoint( ptEnd) ;
|
||||
Point3d ptInt ;
|
||||
double dLen = 0 ; Curve.GetLength( dLen) ;
|
||||
int nIntersType = IntersLinePlane( ptStart, ptEnd, m_plPlane, ptInt, true) ;
|
||||
// intersezione con attraversamento
|
||||
if ( nIntersType == ILPT_YES) {
|
||||
IntCrvPlnInfo icpi ;
|
||||
icpi.Ici[0].ptI = ptInt ;
|
||||
icpi.Ici[0].dU = Dist( ptInt, ptStart) / dLen + nCrv ;
|
||||
Vector3d vtPos = ptStart - m_plPlane.GetPoint() ;
|
||||
icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
|
||||
icpi.Ici[0].nNextTy = icpi.Ici[0].nPrevTy == ICPT_IN ? ICPT_OUT : ICPT_IN ;
|
||||
m_Info.push_back( icpi) ;
|
||||
}
|
||||
// intersezione con tocco
|
||||
else if ( nIntersType == ILPT_START || nIntersType == ILPT_END) {
|
||||
IntCrvPlnInfo icpi ;
|
||||
icpi.Ici[0].ptI = ptInt ;
|
||||
icpi.Ici[0].dU = nIntersType == ILPT_START ? 0 : 1 + nCrv ;
|
||||
|
||||
if ( nIntersType == ILPT_START) {
|
||||
Vector3d vtPos = ptEnd - m_plPlane.GetPoint() ;
|
||||
icpi.Ici[0].nNextTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
|
||||
icpi.Ici[0].nPrevTy = ICPT_NULL ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtPos = ptStart - m_plPlane.GetPoint() ;
|
||||
icpi.Ici[0].nPrevTy = vtPos * m_plPlane.GetVersN() > 0 ? ICPT_OUT : ICPT_IN ;
|
||||
icpi.Ici[0].nNextTy = ICPT_NULL ;
|
||||
}
|
||||
m_Info.push_back( icpi) ;
|
||||
}
|
||||
// intersezione con sovrapposizione
|
||||
else if ( nIntersType == ILPT_INPLANE) {
|
||||
IntCrvPlnInfo icpi ;
|
||||
icpi.bOverlap = true ;
|
||||
icpi.Ici[0].ptI = ptStart ;
|
||||
icpi.Ici[0].dU = 0 + nCrv;
|
||||
icpi.Ici[1].ptI = ptEnd ;
|
||||
icpi.Ici[1].dU = 1 + nCrv ;
|
||||
icpi.Ici[0].nPrevTy = ICPT_NULL ;
|
||||
icpi.Ici[0].nNextTy = ICPT_ON ;
|
||||
icpi.Ici[1].nPrevTy = ICPT_ON ;
|
||||
icpi.Ici[1].nNextTy = ICPT_NULL ;
|
||||
m_Info.push_back( icpi) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
IntersCurvePlane::OrderAndCompleteIntersections()
|
||||
{
|
||||
if ( m_Info.size() < 2)
|
||||
return ;
|
||||
// cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione
|
||||
// riempio le info PrevTy e NexyTy
|
||||
sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ;
|
||||
for ( int curr = m_Info.size() - 1 ; curr > - 1 ; --curr) {
|
||||
int prev = curr == 0 ? m_Info.size() - 1 : curr - 1 ;
|
||||
int next = curr == m_Info.size() - 1 ? 0 : curr + 1 ;
|
||||
bool bErasedCurr = false ;
|
||||
// solo le intersezioni di sovrapposizione o puntuali sullo start o end delle curve possono avere il PrevTy o NextTy non definito
|
||||
if ( ! m_Info[curr].bOverlap) {
|
||||
if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) {
|
||||
if ( ! m_Info[prev].bOverlap) {
|
||||
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ;
|
||||
// se ho due puntuali che coincidono cancello il successivo tra i due ( corrente)
|
||||
if ( AreSamePointApprox( m_Info[curr].Ici[0].ptI, m_Info[prev].Ici[0].ptI)) {
|
||||
m_Info.erase(m_Info.begin() + curr) ;
|
||||
bErasedCurr = true ;
|
||||
}
|
||||
}
|
||||
// se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello
|
||||
else {
|
||||
m_Info[prev].Ici[1].nNextTy = m_Info[curr].Ici[0].nNextTy ;
|
||||
m_Info.erase(m_Info.begin() + curr) ;
|
||||
bErasedCurr = true ;
|
||||
}
|
||||
}
|
||||
if ( ! bErasedCurr && m_Info[curr].Ici[0].nNextTy == ICPT_NULL){
|
||||
if ( ! m_Info[prev].bOverlap)
|
||||
m_Info[curr].Ici[0].nNextTy = m_Info[next].Ici[0].nPrevTy ;
|
||||
// se ho un'intersezione puntuale che in realtà è la fine di un tratto di sovrapposizione, la cancello
|
||||
else {
|
||||
m_Info[next].Ici[0].nPrevTy = m_Info[curr].Ici[0].nPrevTy ;
|
||||
m_Info.erase(m_Info.begin() + curr) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( m_Info[curr].Ici[0].nPrevTy == ICPT_NULL) {
|
||||
if ( ! m_Info[prev].bOverlap)
|
||||
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[0].nNextTy ;
|
||||
else
|
||||
m_Info[curr].Ici[0].nPrevTy = m_Info[prev].Ici[1].nNextTy ;
|
||||
}
|
||||
if ( m_Info[curr].Ici[1].nNextTy == ICPT_NULL) {
|
||||
if ( ! m_Info[next].bOverlap)
|
||||
m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[0].nPrevTy ;
|
||||
else
|
||||
m_Info[curr].Ici[0].nNextTy = m_Info[prev].Ici[1].nPrevTy ;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_nIntersCount = m_Info.size() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::IsArcToApprox( const ICurve& Curve)
|
||||
{
|
||||
// recupero l'arco
|
||||
const CurveArc* pArc = GetBasicCurveArc( &Curve) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
// verifico se non è nel piano XY o ha più di un giro al centro
|
||||
return ( ( ! pArc->GetNormVersor().IsZplus() && ! pArc->GetNormVersor().IsZminus()) ||
|
||||
abs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::AdjustIntersParams( bool bAdjCrv)
|
||||
{
|
||||
// se non ci sono intersezioni, non va fatto alcunché
|
||||
if ( m_Info.empty())
|
||||
return true ;
|
||||
// se le curve originali non sono state approssimate, non va fatto alcunché
|
||||
if ( ! bAdjCrv)
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
for ( auto& aInfo : m_Info) {
|
||||
// se curve originali approssimate, devo ricalcolare i parametri dei punti di intersezione
|
||||
if ( bAdjCrv) {
|
||||
if ( ! m_pCurve->GetParamAtPoint( aInfo.Ici[0].ptI, aInfo.Ici[0].dU, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
if ( aInfo.bOverlap && ! m_pCurve->GetParamAtPoint( aInfo.Ici[1].ptI, aInfo.Ici[1].dU, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersCurvePlane::GetIntersCount( void)
|
||||
{
|
||||
return m_nIntersCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam)
|
||||
{
|
||||
if ( m_nIntersCount == 0)
|
||||
return false ;
|
||||
|
||||
// ricerca del punto più vicino tra le intersezioni singole
|
||||
bool bFound = false ;
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
|
||||
// se è un'intersezione singola
|
||||
if ( ! m_Info[i].bOverlap) {
|
||||
// faccio la verifica sul punto
|
||||
Point3d ptP = m_Info[i].Ici[0].ptI ;
|
||||
double dSqDist = SqDist( ptNear, ptP) ;
|
||||
if ( dSqDist < dMinSqDist) {
|
||||
dMinSqDist = dSqDist ;
|
||||
ptI = ptP ;
|
||||
dParam = m_Info[i].Ici[0].dU ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
// recupero il tratto di sovrapposizione
|
||||
double dUStartTrim, dUEndTrim ;
|
||||
dUStartTrim = m_Info[i].Ici[0].dU ;
|
||||
dUEndTrim = m_Info[i].Ici[1].dU ;
|
||||
PtrOwner<ICurve> pCrv( m_pCurve->CopyParamRange( dUStartTrim, dUEndTrim)) ;
|
||||
if ( IsNull( pCrv))
|
||||
continue ;
|
||||
// cerco il punto
|
||||
int nFlag ;
|
||||
Point3d ptP ;
|
||||
if ( DistPointCurve( ptNear, *pCrv).GetMinDistPoint( 0.5, ptP, nFlag)) {
|
||||
// faccio la verifica
|
||||
double dSqDist = SqDist( ptNear, ptP) ;
|
||||
if ( dSqDist < dMinSqDist) {
|
||||
dMinSqDist = dSqDist ;
|
||||
ptI = ptP ;
|
||||
m_pCurve->GetParamAtPoint( ptP, dParam) ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bFound ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::GetCurveClassification( double dLenMin, CRVPLNCVECTOR& ccClass)
|
||||
{
|
||||
// pulisco vettore classificazioni
|
||||
ccClass.clear() ;
|
||||
|
||||
// verifico definizione della curva
|
||||
if ( m_pCurve == nullptr)
|
||||
return false ;
|
||||
|
||||
// se esiste almeno una intersezione
|
||||
if ( m_nIntersCount >= 1)
|
||||
return CalcCurveClassification( m_pCurve, m_Info, dLenMin, ccClass) ;
|
||||
// altrimenti la curva è completamente interna oppure completamente esterna
|
||||
else
|
||||
return CalcCurveInOrOut( m_pCurve, ccClass) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::CalcCurveClassification( const ICurve* pCurve, const ICPIVECTOR& Info, double dLenMin, CRVPLNCVECTOR& ccClass)
|
||||
{
|
||||
// numero intersezioni
|
||||
int nNumInters = int( Info.size()) ;
|
||||
if ( nNumInters < 1)
|
||||
return false ;
|
||||
// recupero il dominio parametrico della curva in esame
|
||||
double dStartPar, dEndPar ;
|
||||
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
|
||||
return false ;
|
||||
// limito lunghezza minima
|
||||
dLenMin = max( dLenMin, EPS_ZERO) ;
|
||||
// elimino intersezioni senza attraversamento che giacciono in intervalli di sovrapposizione
|
||||
ICPIVECTOR InfoCorr ;
|
||||
InfoCorr.reserve( Info.size()) ;
|
||||
for ( size_t i = 0 ; i < Info.size() ; ++ i) {
|
||||
// se intersezione puntuale senza attraversamento
|
||||
if ( ! Info[i].bOverlap && Info[i].Ici[0].nPrevTy == Info[i].Ici[0].nNextTy) {
|
||||
// confronto con le intersezioni con sovrapposizione
|
||||
bool bToSkip = false ;
|
||||
for ( size_t j = 0 ; j < Info.size() ; ++ j) {
|
||||
// se coincide o puntuale
|
||||
if ( j == i || ! Info[j].bOverlap)
|
||||
continue ;
|
||||
// determino l'intervallo parametrico tenendo conto di eventuale avvolgimento attorno all'inizio
|
||||
double dU1 = Info[j].Ici[0].dU ;
|
||||
double dU2 = Info[j].Ici[1].dU ;
|
||||
if ( dU2 < dU1 && pCurve->IsClosed())
|
||||
dU2 += dEndPar ;
|
||||
// se cade nell'intervallo è da saltare
|
||||
if ( Info[i].Ici[0].dU >= dU1 && Info[i].Ici[0].dU <= dU2) {
|
||||
bToSkip = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bToSkip)
|
||||
continue ;
|
||||
}
|
||||
// salvo dati intersezione
|
||||
InfoCorr.emplace_back( Info[i]) ;
|
||||
}
|
||||
// aggiorno numero di intersezioni da considerare
|
||||
nNumInters = int( InfoCorr.size()) ;
|
||||
// recupero la classificazione all'inizio della curva
|
||||
int nLastTy = ICCT_NULL ;
|
||||
double dCurrPar = dStartPar ;
|
||||
double dCurrLen = 0 ;
|
||||
double dEndLen ; pCurve->GetLength( dEndLen) ;
|
||||
// se è chiusa, recupero come finisce
|
||||
if ( pCurve->IsClosed()) {
|
||||
if ( ! InfoCorr[nNumInters-1].bOverlap)
|
||||
nLastTy = InfoCorr[nNumInters-1].Ici[0].nNextTy ;
|
||||
else {
|
||||
nLastTy = InfoCorr[nNumInters-1].Ici[1].nNextTy ;
|
||||
// se attraversa il punto di giunzione (parametro di fine minore di quello di inizio)
|
||||
if ( InfoCorr[nNumInters-1].Ici[1].dU < InfoCorr[nNumInters-1].Ici[0].dU) {
|
||||
dCurrPar = InfoCorr[nNumInters-1].Ici[1].dU ;
|
||||
double dTmpLen ; pCurve->GetLengthAtParam( dCurrPar, dTmpLen) ;
|
||||
dCurrLen = dTmpLen - dEndLen ;
|
||||
dEndPar = dCurrPar ;
|
||||
dEndLen = dTmpLen ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].Ici[0].dU, dLenU) ;
|
||||
if ( InfoCorr[i].Ici[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
int nPrevTy = InfoCorr[i].Ici[0].nPrevTy ;
|
||||
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
|
||||
nPrevTy == ICCT_NULL || nPrevTy == ICCT_ON)
|
||||
return false ;
|
||||
// assegno i dati
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = InfoCorr[i].Ici[0].dU ;
|
||||
segClass.nClass = (( nPrevTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
// salvo dati correnti
|
||||
dCurrPar = InfoCorr[i].Ici[0].dU ;
|
||||
dCurrLen = dLenU ;
|
||||
nLastTy = InfoCorr[i].Ici[0].nNextTy ;
|
||||
}
|
||||
// altrimenti, salvo il tipo
|
||||
else
|
||||
nLastTy = InfoCorr[i].Ici[0].nNextTy ;
|
||||
// se è definito un tratto in sovrapposizione
|
||||
if ( InfoCorr[i].bOverlap) {
|
||||
// assegno i dati
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = InfoCorr[i].Ici[1].dU ;
|
||||
segClass.nClass = CRVPLN_ON ;
|
||||
ccClass.push_back( segClass) ;
|
||||
// salvo dati correnti
|
||||
dCurrPar = InfoCorr[i].Ici[1].dU ;
|
||||
dCurrLen = dLenU ;
|
||||
nLastTy = InfoCorr[i].Ici[1].nNextTy ;
|
||||
}
|
||||
}
|
||||
// eventuale tratto finale rimasto
|
||||
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia valida
|
||||
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
|
||||
return false ;
|
||||
// assegno i dati
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dCurrPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = (( nLastTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::CalcCurveInOrOut( const ICurve* pCurve, CRVPLNCVECTOR& ccClass)
|
||||
{
|
||||
// controllo di non avere intersezioni
|
||||
int nNumInters = int( m_Info.size()) ;
|
||||
if ( nNumInters > 0)
|
||||
return false ;
|
||||
|
||||
// se non ho intersezioni tra curva e piano devo solo capire da che parte del piano sta la curva
|
||||
CrvPlaneClass cpClass ;
|
||||
double dStartPar, dEndPar ;
|
||||
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
|
||||
return false ;
|
||||
Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
|
||||
Vector3d vtCrv = ptStart - m_plPlane.GetPoint() ;
|
||||
CrvPlaneClass segClass ;
|
||||
segClass.dParS = dStartPar ;
|
||||
segClass.dParE = dEndPar ;
|
||||
segClass.nClass = ( (vtCrv * m_plPlane.GetVersN() < 0) ? CRVC_IN : CRVC_OUT) ;
|
||||
ccClass.push_back( segClass) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ static void
|
||||
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
if ( vInfo.empty())
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
|
||||
+17
-5
@@ -113,7 +113,7 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
|
||||
double dU1, dU2 ;
|
||||
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
|
||||
|
||||
// Se non c'è intersezione
|
||||
// Se non c'è intersezione
|
||||
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
|
||||
return true ;
|
||||
|
||||
@@ -144,8 +144,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
|
||||
else if ( dU2 < EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_OUT, 0) ;
|
||||
else {
|
||||
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
|
||||
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
|
||||
if ( dU1 < - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_TG_INSIDE, 0.) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
|
||||
if ( dU2 > dLen + EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_TG_INSIDE, dLen) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
@@ -162,8 +168,14 @@ IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3
|
||||
else if ( dU2 < EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_OUT, 0) ;
|
||||
else {
|
||||
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
|
||||
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
|
||||
if ( dU1 < - EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_INSIDE, 0.) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
|
||||
if ( dU2 > dLen + EPS_SMALL)
|
||||
vInters.emplace_back( ILBT_INSIDE, dLen) ;
|
||||
else
|
||||
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
|
||||
+59
-24
@@ -19,20 +19,18 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Il punto è esterno al FatSegment se dista da questo più di Tol e la sua proiezione sta sul segmento
|
||||
bool
|
||||
IsPointOutFatSegment( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
|
||||
// Posizione del punto rispetto alla linea (+1=a destra, 0=nella banda di tolleranza, -1=a sinistra)
|
||||
static int
|
||||
GetPointToLineSide( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol)
|
||||
{
|
||||
// distanza del punto dalla linea del segmento (con compensazione piccolissimi errori)
|
||||
if ( abs( CrossXY( ( ptP - ptS), vtDir)) < ( dTol + EPS_ZERO) * dLenXY)
|
||||
return false ;
|
||||
// distanza con segno della proiezione del punto sul segmento dall'inizio per lunghezza segmento
|
||||
double dDistXY = ScalarXY( ( ptP - ptS), vtDir) ;
|
||||
// se il punto non si proietta sul segmento entro la tolleranza
|
||||
if ( dDistXY < - dTol * dLenXY || dDistXY > ( dLenXY + dTol) * dLenXY)
|
||||
return false ;
|
||||
// altrimenti
|
||||
return true ;
|
||||
double dCross = CrossXY( ( ptP - ptS), vtDir) ;
|
||||
double dFat = ( dTol + EPS_ZERO) * dLenXY ;
|
||||
if ( dCross > dFat)
|
||||
return +1 ;
|
||||
else if ( dCross < - dFat)
|
||||
return -1 ;
|
||||
else
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -44,7 +42,7 @@ IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2,
|
||||
m_bOverlaps = false ;
|
||||
m_nNumInters = 0 ;
|
||||
|
||||
// verifico validità linee
|
||||
// verifico validità linee
|
||||
if ( ! Line1.IsValid() || ! Line2.IsValid())
|
||||
return ;
|
||||
|
||||
@@ -130,30 +128,66 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
if ( ! boxL1.OverlapsXY( boxL2))
|
||||
return ;
|
||||
|
||||
// linea 1 : Start, End, Direzione e Lunghezza
|
||||
// segmento 1 : Start, End, Direzione e Lunghezza
|
||||
Point3d ptS1 = Line1.GetStart() ;
|
||||
Point3d ptE1 = Line1.GetEnd() ;
|
||||
Vector3d vtDir1 = ptE1 - ptS1 ;
|
||||
double dLen1XY = vtDir1.LenXY() ;
|
||||
if ( dLen1XY < EPS_SMALL)
|
||||
return ;
|
||||
// linea 2 : Start, Direzione e Lunghezza
|
||||
// segmento 2 : Start, Direzione e Lunghezza
|
||||
Point3d ptS2 = Line2.GetStart() ;
|
||||
Point3d ptE2 = Line2.GetEnd() ;
|
||||
Vector3d vtDir2 = ptE2 - ptS2 ;
|
||||
double dLen2XY = vtDir2.LenXY() ;
|
||||
if ( dLen2XY < EPS_SMALL)
|
||||
return ;
|
||||
// posizioni estremi segmento 1 rispetto a linea 2
|
||||
int nS1Side = GetPointToLineSide( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ;
|
||||
int nE1Side = GetPointToLineSide( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ;
|
||||
if ( ( nS1Side == 1 && nE1Side == 1) || ( nS1Side == -1 && nE1Side == -1))
|
||||
return ;
|
||||
// posizioni estremi segmento 2 rispetto a linea 1
|
||||
int nS2Side = GetPointToLineSide( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ;
|
||||
int nE2Side = GetPointToLineSide( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ;
|
||||
if ( ( nS2Side == 1 && nE2Side == 1) || ( nS2Side == -1 && nE2Side == -1))
|
||||
return ;
|
||||
// prodotto vettoriale nel piano XY tra le direzioni delle linee
|
||||
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
|
||||
// flag per linee parallele
|
||||
bool bParallel = ( abs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ;
|
||||
// flag per segmenti che si allontanano significativamente
|
||||
bool bFarEnds = ( /*( abs( dCrossXY) > SIN_EPS_ANG_SMALL * ( dLen1XY * dLen2XY)) ||*/
|
||||
IsPointOutFatSegment( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ||
|
||||
IsPointOutFatSegment( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) ||
|
||||
IsPointOutFatSegment( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) ||
|
||||
IsPointOutFatSegment( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL)) ;
|
||||
bool bFarEnds = ( nS1Side != 0 || nE1Side != 0 || nS2Side != 0 || nE2Side != 0) ;
|
||||
|
||||
// analisi casi speciali di quasi parallelismo
|
||||
// segmento sovrapposto all'altro
|
||||
double dDist1, dDist2 ;
|
||||
if ( nS1Side == 0 || nE1Side == 0 || nS1Side == nE1Side) {
|
||||
dDist1 = CrossXY( ptS1 - ptS2, vtDir2) ;
|
||||
dDist2 = CrossXY( ptE1 - ptS2, vtDir2) ;
|
||||
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen2XY) {
|
||||
bParallel = true ;
|
||||
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
|
||||
}
|
||||
}
|
||||
else if ( nS2Side == 0 || nE2Side == 0 || nS2Side == nE2Side) {
|
||||
dDist1 = CrossXY( ptS2 - ptS1, vtDir1) ;
|
||||
dDist2 = CrossXY( ptE2 - ptS1, vtDir1) ;
|
||||
if ( abs( dDist1 - dDist2) < EPS_SMALL * dLen1XY) {
|
||||
bParallel = true ;
|
||||
bFarEnds = ! ( (nS1Side == 0 && nE1Side == 0) || (nS2Side == 0 && nE2Side == 0)) ;
|
||||
}
|
||||
}
|
||||
// estremità sovrapposte di poco
|
||||
if ( ! bParallel && abs( dCrossXY) < ( 0.1 * DEGTORAD) * ( dLen1XY * dLen2XY)) {
|
||||
if (( nS1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptS1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nS1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptS1, ptE2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nS2Side == 0 && ScalarXY( vtDir1, vtDir2) > 0 && ! AreSamePointXYEpsilon( ptE1, ptS2, 2 * EPS_SMALL)) ||
|
||||
( nE1Side == 0 && nE2Side == 0 && ScalarXY( vtDir1, vtDir2) < 0 && ! AreSamePointXYEpsilon( ptE1, ptE2, 2 * EPS_SMALL))) {
|
||||
bParallel = true ;
|
||||
bFarEnds = false ;
|
||||
}
|
||||
}
|
||||
|
||||
// se non sono paralleli e si allontanano tra loro abbastanza
|
||||
if ( ! bParallel && bFarEnds) {
|
||||
@@ -168,6 +202,8 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
nPos1 = ICurve::PP_END ; // vicino a fine
|
||||
else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1)
|
||||
nPos1 = ICurve::PP_MID ; // nell'interno
|
||||
else
|
||||
return ;
|
||||
// verifica posizione intersezione su seconda linea
|
||||
int nPos2 = ICurve::PP_NULL ; // fuori
|
||||
if ( abs( m_Info.IciB[0].dU * dLen2XY) < EPS_SMALL)
|
||||
@@ -176,8 +212,7 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
nPos2 = ICurve::PP_END ; // vicino a fine
|
||||
else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1)
|
||||
nPos2 = ICurve::PP_MID ; // nell'interno
|
||||
// se soluzione non accettata, esco
|
||||
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
|
||||
else
|
||||
return ;
|
||||
// limito i parametri a stare sui segmenti (0...1)
|
||||
m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ;
|
||||
@@ -190,7 +225,7 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
m_Info.IciA[0].nNextTy = ICCT_NULL ;
|
||||
m_Info.IciB[0].nPrevTy = ICCT_NULL ;
|
||||
m_Info.IciB[0].nNextTy = ICCT_NULL ;
|
||||
// si incontrano alle estremità, non si può dire alcunché
|
||||
// si incontrano alle estremità, non si può dire alcunché
|
||||
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
|
||||
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
|
||||
; // rimangono tutti NULL
|
||||
|
||||
+272
-15
@@ -14,11 +14,17 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfFr.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfBez.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -28,7 +34,6 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
|
||||
const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz)
|
||||
{
|
||||
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz
|
||||
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
// usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta
|
||||
DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ;
|
||||
double dDistNew = 0, dDistPre = 0 ;
|
||||
@@ -42,18 +47,18 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
|
||||
while ( dDistNew > EPS_SMALL && nCount < 100) {
|
||||
dDistPre = dDistNew ;
|
||||
Point3d ptIBzNew1 ;
|
||||
pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
|
||||
pSurfBz->GetPointD1D2( ( ptSP.x + dh), ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
|
||||
DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ;
|
||||
dplNewU.GetDist( dDistNew) ;
|
||||
double dfdU = ( dDistNew - dDistPre) / dh ;
|
||||
Point3d ptIBzNew2 ;
|
||||
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
|
||||
pSurfBz->GetPointD1D2( ptSP.x, ( ptSP.y + dh), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
|
||||
DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ;
|
||||
dplNewV.GetDist( dDistNew) ;
|
||||
double dfdV = ( dDistNew - dDistPre) / dh ;
|
||||
// mi avvicino cercando di annullare la distanza in un colpo solo
|
||||
double dr = - dDistPre / ( dfdU + dfdV) ;
|
||||
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU), ( ptSP.y + dr * dfdV), ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ;
|
||||
dplNew.GetDist( dDistNew) ;
|
||||
++ nCount ;
|
||||
@@ -67,11 +72,11 @@ static void
|
||||
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
|
||||
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
|
||||
{
|
||||
if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) {
|
||||
if ( nILT == ILTA_IN || nILT == ILTA_EDGE || nILT == ILTA_VERT || nILT == ILTA_NO_TRIA) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
|
||||
}
|
||||
else if ( nILT == ILTT_SEGM || nILT == ILTT_SEGM_ON_EDGE) {
|
||||
else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
double dU2 = ( ptIBz2 - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
|
||||
@@ -83,13 +88,13 @@ static void
|
||||
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
if ( vInfo.empty())
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
{ double dUa = ( ( a.nILTA == ILTA_SEGM || a.nILTA == ILTA_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTA == ILTA_SEGM || b.nILTA == ILTA_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
@@ -137,16 +142,16 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
|
||||
double dU0, dV0 ;
|
||||
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
|
||||
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
|
||||
ptSP = ptSP + Point3d( dU0, dV0, 0) ;
|
||||
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
|
||||
return false ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
|
||||
pSurfBz->GetPointNrmD1D2(ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
|
||||
double dCos = vtN * vtL ;
|
||||
double dCos2 = 0 ;
|
||||
// eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione)
|
||||
if ( InfoTm.nILTT == ILTT_SEGM || InfoTm.nILTT == ILTT_SEGM_ON_EDGE ) {
|
||||
if ( InfoTm.nILTT == ILTA_SEGM || InfoTm.nILTT == ILTA_SEGM_ON_EDGE ) {
|
||||
pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI2, ptSP2, InfoTm.nILTT) ;
|
||||
if ( ! RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) {
|
||||
int nVert[3] ;
|
||||
@@ -157,7 +162,7 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
|
||||
return false ;
|
||||
}
|
||||
pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
|
||||
pSurfBz->GetPointNrmD1D2( ptSP2.x, ptSP2.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
|
||||
dCos2 = vtN * vtL ;
|
||||
}
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ;
|
||||
@@ -176,7 +181,7 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
if ( Info.nILTA == ILTA_VERT || Info.nILTA == ILTA_EDGE || Info.nILTA == ILTA_IN) {
|
||||
int nFlag = LSBT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LSBT_OUT ;
|
||||
@@ -185,7 +190,7 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
else if ( Info.nILTA == ILTA_SEGM || Info.nILTA == ILTA_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
@@ -232,3 +237,255 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
|
||||
ILSBIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
|
||||
// funzione pensata per funzionare solo con una monopatch bilineare
|
||||
if ( nDegU > 1 || nDegV > 1 || nSpanU > 1 || nSpanV > 1 || bRat)
|
||||
return false ;
|
||||
|
||||
int nInters = int( vInfo.size()) ;
|
||||
|
||||
PNTVECTOR vPntCtrl ;
|
||||
for ( int p = 0 ; p < 4 ; ++p) {
|
||||
bool bOk = false ;
|
||||
vPntCtrl.push_back( pSurfBz->GetControlPoint( p, &bOk)) ;
|
||||
}
|
||||
|
||||
Vector3d a = vPntCtrl[3] - vPntCtrl[1] + ( vPntCtrl[0] - vPntCtrl[2]) ;
|
||||
Vector3d b = vPntCtrl[1] - vPntCtrl[0] ;
|
||||
Vector3d c = vPntCtrl[2] - vPntCtrl[0] ;
|
||||
Vector3d d = vPntCtrl[0] - ORIG ;
|
||||
|
||||
double A1 = a.x * vtL.z - a.z * vtL.x ;
|
||||
double B1 = b.x * vtL.z - b.z * vtL.x ;
|
||||
double C1 = c.x * vtL.z - c.z * vtL.x ;
|
||||
double A2 = a.y * vtL.z - a.z * vtL.y ;
|
||||
double B2 = b.y * vtL.z - b.z * vtL.y ;
|
||||
double C2 = c.y * vtL.z - c.z * vtL.y ;
|
||||
|
||||
double D1 = ( d.x - ptL.x) * vtL.z - ( d.z - ptL.z) * vtL.x ;
|
||||
double D2 = ( d.y - ptL.y) * vtL.z - ( d.z - ptL.z) * vtL.y ;
|
||||
|
||||
DBLVECTOR vdCoeff, vdRoots ;
|
||||
vdCoeff = { (B2 * D1 - B1 * D2), ( A2 * D1 - A1 * D2 + B2 * C1 - B1 * C2), ( A2 * C1 - A1 * C2)} ;
|
||||
int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||
bool bFound = false ;
|
||||
for ( int w = 0 ; w < nRoots ; ++w) {
|
||||
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO ) {
|
||||
double dU = 0, dV = vdRoots[w] ;
|
||||
// verifico che non sia una soluzione con molteplicità > 1
|
||||
bool bAlreadyFound = false ;
|
||||
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
|
||||
bAlreadyFound = abs( dV - vdRoots[k]) < EPS_PARAM ;
|
||||
if ( ! bAlreadyFound) {
|
||||
dU = (dV * (C1 - C2) + ( D1 - D2)) / ( dV * ( A2 - A1) + ( B2 - B1)) ;
|
||||
if ( dU > - EPS_ZERO && dU < 1 + EPS_ZERO) {
|
||||
Point3d ptIBez, ptIBez2 ;
|
||||
Vector3d vtN ;
|
||||
pSurfBz->GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez, vtN) ;
|
||||
Point3d ptSP( dU, dV, 0), ptSP2 ;
|
||||
double dCos = vtN * vtL, dCos2 = 0 ;
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP, ptIBez, dCos, ptSP2, ptIBez2, dCos2, vInfo) ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se tutti i coefficienti sono zero allora potrei avere una linea che giace sulla superficie
|
||||
// per trovare i punti di inizio e fine sovrapposizione trovo i punti a minima distanza tra la linea e gli edge della superficie
|
||||
if ( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) {
|
||||
ICRVCOMPOPOVECTOR vCrvEdge( 4) ;
|
||||
vCrvEdge[0].Set(pSurfBz->GetCurveOnU( 0)) ;
|
||||
vCrvEdge[1].Set(pSurfBz->GetCurveOnV( 1)) ;
|
||||
vCrvEdge[2].Set(pSurfBz->GetCurveOnU( 1)) ;
|
||||
vCrvEdge[3].Set(pSurfBz->GetCurveOnV( 0)) ;
|
||||
double dAngTolDeg = 5 ;
|
||||
for ( int i = 0 ; i < 4 ; ++i) {
|
||||
PolyLine plApprox ; vCrvEdge[0]->ApproxWithLines( EPS_SMALL, dAngTolDeg, ICurve::ApprLineType::APL_STD, plApprox) ;
|
||||
//CurveComposite cCC ;
|
||||
//cCC.FromPolyLine( plApprox) ;
|
||||
int nClosestLine = -1 ;
|
||||
double dMinDist = INFINITO ;
|
||||
Point3d pt ; plApprox.GetFirstPoint( pt) ;
|
||||
Point3d ptClosest ;
|
||||
int c = 0 ;
|
||||
int nTot = plApprox.GetPointNbr() ;
|
||||
for ( int j = 0 ; j < nTot ; ++j) {
|
||||
DistPointLine dpl( pt, ptL, vtL, dLen, bFinite) ;
|
||||
double dDist = INFINITO ;
|
||||
dpl.GetDist( dDist) ;
|
||||
if ( dDist < dMinDist) {
|
||||
nClosestLine = c ;
|
||||
dMinDist = dDist ;
|
||||
}
|
||||
plApprox.GetNextPoint( pt) ;
|
||||
++ c ;
|
||||
}
|
||||
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
if ( nClosestLine < nTot - 1 && nClosestLine > 0) {
|
||||
// tra i due tratti dell'approssimazione che arrivano al punto selezionato come più vicino, devo trovare quale si avvicina di più
|
||||
Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
|
||||
Point3d ptEnd ;
|
||||
for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
|
||||
plApprox.GetNextPoint( ptStart) ;
|
||||
plApprox.GetNextPoint( ptEnd) ;
|
||||
// linea precedente al punto
|
||||
Vector3d vtLinePre = ptEnd - ptStart ;
|
||||
double dLenPre = vtLinePre.Len() ;
|
||||
DistLineLine dllPre( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
|
||||
double dDistPre = INFINITO ;
|
||||
dllPre.GetDist( dDistPre) ;
|
||||
// linea che inzia con quel punto
|
||||
ptStart = ptEnd ;
|
||||
plApprox.GetNextPoint( ptEnd) ;
|
||||
Vector3d vtLineCurr = ptEnd - ptStart ;
|
||||
double dLenCurr = vtLineCurr.Len() ;
|
||||
DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
|
||||
double dDistCurr = INFINITO ;
|
||||
dllCurr.GetDist( dDistCurr) ;
|
||||
|
||||
if ( dDistPre < dDistCurr)
|
||||
dllPre.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
else
|
||||
dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
}
|
||||
else if ( nClosestLine == 0) {
|
||||
// il punto più vicino è sulla prima linea
|
||||
Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
|
||||
Point3d ptEnd ; plApprox.GetNextPoint( ptEnd) ;
|
||||
Vector3d vtLineCurr = ptEnd - ptStart ;
|
||||
double dLenCurr = vtLineCurr.Len() ;
|
||||
DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
|
||||
dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
}
|
||||
else if ( nClosestLine == nTot- 1) {
|
||||
// il punto più vicino è sull'ultima linea
|
||||
Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
|
||||
Point3d ptEnd ;
|
||||
for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
|
||||
plApprox.GetNextPoint( ptStart) ;
|
||||
plApprox.GetNextPoint( ptEnd) ;
|
||||
Vector3d vtLinePre = ptEnd - ptStart ;
|
||||
double dLenPre = vtLinePre.Len() ;
|
||||
DistLineLine dllCurr( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
|
||||
dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
}
|
||||
|
||||
double dU1 = 0, dV1 = 0, dU2 = 0, dV2 = 0 ;
|
||||
// se ho trovato due punti vuol dire che la linea coincide con un edge e ho trovato tutto quello che serve
|
||||
if ( ! AreSamePointExact( ptInt2, ORIG)) {
|
||||
if ( i == 0) {
|
||||
//dV1 = 0 ; dV2 = 0 ;
|
||||
vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
vCrvEdge[0]->GetParamAtPoint( ptInt2, dU2) ;
|
||||
}
|
||||
else if ( i == 1) {
|
||||
//dU1 = 1 ; dU2 = 1 ;
|
||||
vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
vCrvEdge[1]->GetParamAtPoint( ptInt2, dV2) ;
|
||||
}
|
||||
else if ( i == 2){
|
||||
//dV1 = 1 ; dV2 = 1 ;
|
||||
vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
vCrvEdge[2]->GetParamAtPoint( ptInt2, dU2) ;
|
||||
}
|
||||
else if ( i == 3){
|
||||
//dU1 = 0 ; dU2 = 0 ;
|
||||
vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
vCrvEdge[3]->GetParamAtPoint( ptInt2, dV2) ;
|
||||
}
|
||||
Point3d ptIBez1, ptIBez2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
|
||||
pSurfBz->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez2, vtN2) ;
|
||||
Point3d ptSP1( dU1, dV1, 0) ;
|
||||
double dCos1 = vtN1 * vtL ;
|
||||
Point3d ptSP2( dU2, dV2, 0) ;
|
||||
double dCos2 = vtN2 * vtL ;
|
||||
// se avevo già trovato un punto singolo che coincide col primo punto di questa intersezione sovrapposta, allora cancello l'intersezione singola che
|
||||
// avevo salvato e aggiungo quella sovrapposto che ho trovato ora
|
||||
if ( bFound) {
|
||||
int nNewTot = int(vInfo.size()) ;
|
||||
int nNewInters = nNewTot - nInters ;
|
||||
bool bAlreadyFound = false ;
|
||||
for ( int i = 0 ; i < nNewInters ; ++i) {
|
||||
bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) || AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP2) ;
|
||||
if ( bAlreadyFound) {
|
||||
vInfo.erase( vInfo.begin() + nNewTot - i) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
// se ho trovato un punto a distanza zero dalla linea allora ho trovato l'intersezione
|
||||
else if ( dMinDist < EPS_SMALL) {
|
||||
if ( i == 0) {
|
||||
//dV1 = 0 ;
|
||||
vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
}
|
||||
else if ( i == 1) {
|
||||
//dU1 = 1 ;
|
||||
vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
}
|
||||
else if ( i == 2) {
|
||||
//dV1 = 1 ;
|
||||
vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
}
|
||||
else if ( i == 3) {
|
||||
//dU1 = 0 ;
|
||||
vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
}
|
||||
Point3d ptSP1( dU1, dV1, 0), ptSP2 ;
|
||||
// se avevo trovato già altri punti controllo di non essere esattamente su una diagonale ( e quindi avere un'intersezione con ogni edge, ma due sono doppie)
|
||||
if ( bFound) {
|
||||
int nNewTot = int(vInfo.size()) ;
|
||||
int nNewInters = nNewTot - nInters ;
|
||||
bool bAlreadyFound = false ;
|
||||
for ( int i = 0 ; i < nNewInters ; ++i)
|
||||
bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) ;
|
||||
if ( bAlreadyFound)
|
||||
continue ;
|
||||
}
|
||||
|
||||
Point3d ptIBez1, ptIBez2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
|
||||
double dCos1 = vtN1 * vtL, dCos2 = 0 ;
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se la superficie è trimmed verifico che i punti trovati siano all'interno del parametrico trimmato
|
||||
if ( bTrimmed && bFound) {
|
||||
int nNewTot = int(vInfo.size()) ;
|
||||
int nNewInters = nNewTot - nInters ;
|
||||
const ISurfFlatRegion* pFRTrim = pSurfBz->GetTrimRegion() ;
|
||||
for ( int i = 0 ; i < nNewInters ; ++i) {
|
||||
Point3d ptTest = vInfo[nNewTot - i].ptUV * SBZ_TREG_COEFF ;
|
||||
bool bInside = false ;
|
||||
double dDist = INFINITO ;
|
||||
IsPointInsideSurfFr( ptTest, pFRTrim, dDist, bInside) ;
|
||||
if ( ! bInside)
|
||||
vInfo.erase( vInfo.begin() + nNewTot - i) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -1662,7 +1662,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
|
||||
// Riordino le soluzioni
|
||||
for ( int ni = 0 ; ni < int( vdPar.size()) - 1 ; ++ ni) {
|
||||
for ( int nj = ni ; nj < int( vdPar.size()) ; ++ nj) {
|
||||
if( vdPar[ni] > vdPar[nj]) {
|
||||
if ( vdPar[ni] > vdPar[nj]) {
|
||||
swap( vdPar[ni], vdPar[nj]) ;
|
||||
}
|
||||
}
|
||||
@@ -1670,7 +1670,7 @@ LineTorus( const Point3d& ptLine, const Vector3d& vtLine,
|
||||
|
||||
// Studio le soluzioni
|
||||
int nIntType = T_ERROR ;
|
||||
if ( vdPar.size() == 0)
|
||||
if ( vdPar.empty())
|
||||
nIntType = T_NO_INT ;
|
||||
else if ( vdPar.size() == 1) {
|
||||
nIntType = T_ONE_TAN ;
|
||||
|
||||
+107
-22
@@ -23,20 +23,20 @@ using namespace std ;
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
|
||||
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
|
||||
int nStm, int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
Point3d ptInt, ptInt2 ;
|
||||
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, bFinite) ;
|
||||
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
|
||||
double dU = ( ptInt - ptL) * vtDir ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ;
|
||||
vInfo.emplace_back( nRes, dU, nStm, nT, dCosDN, ptInt) ;
|
||||
}
|
||||
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
|
||||
double dU = ( ptInt - ptL) * vtDir ;
|
||||
double dU2 = ( ptInt2 - ptL) * vtDir ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
|
||||
vInfo.emplace_back( nRes, dU, dU2, nStm, nT, dCosDN, ptInt, ptInt2) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ static void
|
||||
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
if ( vInfo.empty())
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntLinStmInfo& a, const IntLinStmInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
@@ -108,7 +108,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
Triangle3d Tria ;
|
||||
Stm.GetTriangle( nT, Tria) ;
|
||||
// aggiorno info con intersezione
|
||||
UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ;
|
||||
UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, 0, nT, Tria, vInfo, bFinite) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,19 +124,23 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
// Intersezione di molte linee parallele con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfTriMesh& Stm)
|
||||
: m_bOk( false), m_frLines( frLines), m_pSTm( &Stm)
|
||||
: m_bOk( false), m_frLines( frLines), m_vpSTm( {&Stm})
|
||||
{
|
||||
// verifico esistenza superficie
|
||||
if ( m_pSTm == nullptr || ! m_pSTm->IsValid())
|
||||
if ( m_vpSTm[0] == nullptr || ! m_vpSTm[0]->IsValid())
|
||||
return ;
|
||||
|
||||
// creo HashGrid 2d
|
||||
const int LIM_HG_TRIA = 127 ;
|
||||
m_HGrids.SetActivationGrid( m_pSTm->GetTriangleCount() > LIM_HG_TRIA) ;
|
||||
// aggiorno il vettore degli indici di base per mappare i triangoli con le rispettivi superfici
|
||||
// ( in questo caso la superficie è unica, quindi ho solo due elementi)
|
||||
m_vBaseInd = { 0, m_vpSTm[0]->GetTriangleCount()} ;
|
||||
|
||||
// riempio HashGrid
|
||||
// creo HashGrid 2d ed eventualmente attivo la griglia
|
||||
const int LIM_HG_TRIA = 127 ;
|
||||
m_HGrids.SetActivationGrid( m_vBaseInd.back() > LIM_HG_TRIA) ;
|
||||
|
||||
// riempio HashGrid
|
||||
Triangle3d Tria ;
|
||||
int nT = Stm.GetFirstTriangle( Tria) ;
|
||||
int nT = m_vpSTm[0]->GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// calcolo il BBox del triangolo nel riferimento scelto
|
||||
Tria.ToLoc( m_frLines) ;
|
||||
@@ -145,10 +149,55 @@ IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfT
|
||||
b3Tria.Add( Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
// inserisco nella griglia
|
||||
if ( ! m_HGrids.Add( nT, b3Tria))
|
||||
if ( ! m_HGrids.Add( nT, b3Tria)) // ( 0 + nT, Tria)
|
||||
return ;
|
||||
// passo al prossimo triangolo
|
||||
nT = Stm.GetNextTriangle( nT, Tria) ;
|
||||
// passo al prossimo triangolo
|
||||
nT = m_vpSTm[0]->GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
// aggiorno
|
||||
m_bOk = m_HGrids.Update() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di molte linee parallele con un vettore di superfici TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const CISURFTMPVECTOR& vStm)
|
||||
: m_bOk( false), m_frLines( frLines), m_vpSTm( vStm), m_vBaseInd( {0})
|
||||
{
|
||||
// verifico esistenza superfici
|
||||
if ( m_vpSTm.empty())
|
||||
return ;
|
||||
for ( const ISurfTriMesh* pStm : m_vpSTm) {
|
||||
if ( pStm == nullptr || ! pStm->IsValid())
|
||||
return ;
|
||||
}
|
||||
|
||||
// aggiorno il vettore degli indici di base per mappare i triangoli con le rispettivi superfici
|
||||
// NB. dal costruttore è già inizializzato a {0}
|
||||
for ( int i = 0 ; i < int( m_vpSTm.size()) ; ++ i)
|
||||
m_vBaseInd.emplace_back( m_vBaseInd.back() + m_vpSTm[i]->GetTriangleCount()) ;
|
||||
|
||||
// creo HashGrid 2d ed eventualmente attivo la griglia
|
||||
const int LIM_HG_TRIA = 256 ;
|
||||
m_HGrids.SetActivationGrid( m_vBaseInd.back() > LIM_HG_TRIA) ;
|
||||
|
||||
// riempio HashGrid
|
||||
for ( int i = 0 ; i < int( m_vpSTm.size()) ; ++ i) {
|
||||
Triangle3d Tria ;
|
||||
int nT = m_vpSTm[i]->GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// calcolo il BBox del triangolo nel riferimento scelto
|
||||
Tria.ToLoc( m_frLines) ;
|
||||
BBox3d b3Tria ;
|
||||
b3Tria.Add( Tria.GetP( 0)) ;
|
||||
b3Tria.Add( Tria.GetP( 1)) ;
|
||||
b3Tria.Add( Tria.GetP( 2)) ;
|
||||
// inserisco nella griglia ( aggiungo shift per indice del triangolo)
|
||||
if ( ! m_HGrids.Add( m_vBaseInd[i] + nT, b3Tria))
|
||||
return ;
|
||||
// passo al prossimo triangolo
|
||||
nT = m_vpSTm[i]->GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
}
|
||||
// aggiorno
|
||||
m_bOk = m_HGrids.Update() ;
|
||||
@@ -162,7 +211,7 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
if ( &vInfo == nullptr)
|
||||
return false ;
|
||||
vInfo.clear() ;
|
||||
// verifico validità
|
||||
// verifico validità
|
||||
if ( ! m_bOk)
|
||||
return false ;
|
||||
|
||||
@@ -174,15 +223,22 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
Point3d ptLL = ptL ;
|
||||
ptLL.ToGlob( m_frLines) ;
|
||||
|
||||
// recupero indici triangoli che intersecano box in 2d
|
||||
// recupero indici triangoli che intersecano box in 2d
|
||||
INTVECTOR vnIds ;
|
||||
if ( m_HGrids.Find( b3Line, vnIds)) {
|
||||
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
|
||||
int nT = vnIds[i] ;
|
||||
// recupero la superficie
|
||||
int nInd = vnIds[i] ;
|
||||
int nSurf = GetSurfInd( nInd) ;
|
||||
if ( nSurf == -1)
|
||||
return false ;
|
||||
// recupero il triangolo
|
||||
int nT = nInd - m_vBaseInd[nSurf] ;
|
||||
Triangle3d Tria ;
|
||||
m_pSTm->GetTriangle( nT, Tria) ;
|
||||
if ( ! m_vpSTm[nSurf]->GetTriangle( nT, Tria))
|
||||
return false ;
|
||||
// aggiorno info con intersezione
|
||||
UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nT, Tria, vInfo, bFinite) ;
|
||||
UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nSurf, nT, Tria, vInfo, bFinite) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +248,35 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
IntersParLinesSurfTm::GetSurfInd( int nT) const
|
||||
{
|
||||
// verifico la presenza di almeno un intervallo
|
||||
if ( m_vBaseInd.size() < 2)
|
||||
return -1 ;
|
||||
// se la superficie è unica, allora non devo cercarla
|
||||
if ( int( m_vBaseInd.size()) == 2)
|
||||
return 0 ;
|
||||
// ricerca binaria dell'intervallo contenente la posizione del triangolo
|
||||
int nS = 0 ;
|
||||
int nE = int( m_vBaseInd.size()) - 1 ;
|
||||
while ( true) {
|
||||
if ( nT < m_vBaseInd[nS] || nT >= m_vBaseInd[nE])
|
||||
return -1 ;
|
||||
if ( nE - nS == 1)
|
||||
return nS ;
|
||||
int nM = ( nS + nE) / 2 ;
|
||||
if ( nT == m_vBaseInd[nM])
|
||||
return nM ;
|
||||
if ( nT < m_vBaseInd[nM])
|
||||
nE = nM ;
|
||||
else
|
||||
nS = nM ;
|
||||
}
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
@@ -217,7 +302,7 @@ FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
|
||||
|
||||
@@ -42,5 +42,5 @@ Inters3Planes( const Plane3d& plPlane1, const Plane3d& plPlane2, const Plane3d&
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptL, vtL) != IPPT_YES)
|
||||
return IPPT_NO ;
|
||||
// intersezione della linea con il terzo piano
|
||||
return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt) == ILPT_YES ? IPPT_YES : IPPT_NO) ;
|
||||
return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt, false) == ILPT_YES ? IPPT_YES : IPPT_NO) ;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di unpiano con la superficie di un solido VolZmap
|
||||
// Intersezione di un piano con la superficie di un solido VolZmap
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
|
||||
@@ -28,9 +28,6 @@ IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR&
|
||||
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
|
||||
if ( pVzm == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vpLoop == nullptr)
|
||||
return false ;
|
||||
|
||||
// eseguo intersezione
|
||||
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
|
||||
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : MultiGeomDB.cpp Data : 08.10.25 Versione : 2.7j1
|
||||
// Contenuto : Implementazione delle funzioni tra due GeomDB.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 08.10.25 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeomDB.h"
|
||||
#include "/EgtDev/Include/EGkMultiGeomDB.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
|
||||
{
|
||||
// recupero l'oggetto da copiare dal GeomDB sorgente
|
||||
PtrOwner<IGeoObj> pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ;
|
||||
if ( IsNull( pGObj))
|
||||
return GDB_ID_NULL ;
|
||||
// se in globale
|
||||
if ( bGlob) {
|
||||
// recupero il riferimento del sorgente
|
||||
Frame3d frSou ;
|
||||
if ( ! pSouGDB->GetGlobFrame( nSouId, frSou))
|
||||
return GDB_ID_NULL ;
|
||||
// recupero il riferimento del gruppo destinazione
|
||||
Frame3d frDest ;
|
||||
int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ;
|
||||
if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest))
|
||||
return GDB_ID_NULL ;
|
||||
// porto la copia da riferimento sorgente a quello destinazione
|
||||
pGObj->LocToLoc( frSou, frDest) ;
|
||||
}
|
||||
// lo inserisco nel GeomDB destinazione
|
||||
int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, nSonBeforeAfter, Release( pGObj)) ;
|
||||
if ( nNewId == GDB_ID_NULL)
|
||||
return GDB_ID_NULL ;
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
|
||||
{
|
||||
// recupero il riferimento del gruppo
|
||||
Frame3d frFrame = *( pSouGDB->GetGroupFrame( nSouId)) ;
|
||||
// se in globale
|
||||
if ( bGlob) {
|
||||
// recupero il riferimento del gruppo in globale
|
||||
if ( ! pSouGDB->GetGroupGlobFrame( nSouId, frFrame))
|
||||
return GDB_ID_NULL ;
|
||||
// recupero il riferimento del gruppo destinazione
|
||||
Frame3d frDest ;
|
||||
int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ;
|
||||
if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest))
|
||||
return GDB_ID_NULL ;
|
||||
// porto la copia da riferimento sorgente a quello destinazione
|
||||
frFrame.ToLoc( frDest) ;
|
||||
}
|
||||
// inserisco un nuovo gruppo nel GeomDB destinazione
|
||||
int nNewId = pDstGDB->InsertGroup( nDestId, nRefId, nSonBeforeAfter, frFrame) ;
|
||||
if ( nNewId == GDB_ID_NULL)
|
||||
return GDB_ID_NULL ;
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// copio gli eventuali figli
|
||||
int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ;
|
||||
while ( nSonSouId != GDB_ID_NULL) {
|
||||
// nuovo identificativo oggetto destinazione
|
||||
int nSonNewId = GDB_ID_NULL ;
|
||||
// recupero il tipo di oggetto sorgente
|
||||
int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ;
|
||||
// se l'oggetto da copiare è geometrico
|
||||
if ( nSonSouType == GDB_TY_GEO)
|
||||
nSonNewId = CopyGeoObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ;
|
||||
// se altrimenti è un gruppo
|
||||
else if ( nSonSouType == GDB_TY_GROUP)
|
||||
nSonNewId = CopyGroupObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ;
|
||||
// se copia non riuscita, esco con errore
|
||||
if ( nSonNewId == GDB_ID_NULL)
|
||||
return GDB_ID_NULL ;
|
||||
// passo al figlio successivo
|
||||
nSonSouId = pSouGDB->GetNext( nSonSouId) ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob)
|
||||
{
|
||||
// adatto e verifico i GeomDB
|
||||
const GeomDB* pSouGDB = static_cast<GeomDB*>( pSouGeomDB) ;
|
||||
GeomDB* pDstGDB = static_cast<GeomDB*>( pDestGeomDB) ;
|
||||
if ( pSouGDB == nullptr || pDstGDB == nullptr)
|
||||
return GDB_ID_NULL ;
|
||||
// il sorgente non può essere il gruppo radice
|
||||
if ( nSouId == GDB_ID_ROOT)
|
||||
return GDB_ID_NULL ;
|
||||
// nuovo identificativo oggetto destinazione
|
||||
int nNewId = GDB_ID_NULL ;
|
||||
// recupero il tipo di oggetto sorgente
|
||||
int nSouType = pSouGDB->GetGdbType( nSouId) ;
|
||||
// se l'oggetto da copiare è geometrico
|
||||
if ( nSouType == GDB_TY_GEO) {
|
||||
nNewId = CopyGeoObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ;
|
||||
}
|
||||
// se altrimenti è un gruppo
|
||||
else if ( nSouType == GDB_TY_GROUP) {
|
||||
nNewId = CopyGroupObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter)
|
||||
{
|
||||
return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, false) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
CopyGlob( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter)
|
||||
{
|
||||
return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, true) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
DuplicateGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId)
|
||||
{
|
||||
// recupero l'oggetto da copiare dal GeomDB sorgente
|
||||
PtrOwner<IGeoObj> pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ;
|
||||
if ( IsNull( pGObj))
|
||||
return GDB_ID_NULL ;
|
||||
// lo inserisco nel GeomDB destinazione
|
||||
int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, GDB_LAST_SON, Release( pGObj)) ;
|
||||
if ( nNewId != nDestId) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
DuplicateGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, bool bSkipTemp)
|
||||
{
|
||||
int nNewId = GDB_ID_ROOT ;
|
||||
if ( nSouId != GDB_ID_ROOT) {
|
||||
// recupero il riferimento del gruppo
|
||||
Frame3d frFrame = *( pSouGDB->GetGroupFrame( nSouId)) ;
|
||||
// inserisco un nuovo gruppo nel GeomDB destinazione
|
||||
nNewId = pDstGDB->InsertGroup( nDestId, nRefId, GDB_LAST_SON, frFrame) ;
|
||||
if ( nNewId != nSouId) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// copio le caratteristiche non geometriche
|
||||
const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ;
|
||||
GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ;
|
||||
if ( pSouGDB == nullptr || pDstGdbObj == nullptr ||
|
||||
! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) ||
|
||||
! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) {
|
||||
pDstGDB->Erase( nNewId) ;
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
}
|
||||
// copio gli eventuali figli
|
||||
int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ;
|
||||
while ( nSonSouId != GDB_ID_NULL) {
|
||||
// verifico se non richiesto di saltare i temporanei oppure non lo è
|
||||
int nLevel ;
|
||||
if ( ! bSkipTemp || ! pSouGDB->GetLevel( nSonSouId, nLevel) || nLevel != GDB_LV_TEMP) {
|
||||
// nuovo identificativo oggetto destinazione
|
||||
int nSonNewId = GDB_ID_NULL ;
|
||||
// recupero il tipo di oggetto sorgente
|
||||
int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ;
|
||||
// se l'oggetto da copiare è geometrico
|
||||
if ( nSonSouType == GDB_TY_GEO)
|
||||
nSonNewId = DuplicateGeoObj( pSouGDB, nSonSouId, pDstGDB, nSonSouId, nNewId) ;
|
||||
// se altrimenti è un gruppo
|
||||
else if ( nSonSouType == GDB_TY_GROUP)
|
||||
nSonNewId = DuplicateGroupObj( pSouGDB, nSonSouId, pDstGDB, nSonSouId, nNewId, bSkipTemp) ;
|
||||
// se copia non riuscita, esco con errore
|
||||
if ( nSonNewId != nSonSouId)
|
||||
return GDB_ID_NULL ;
|
||||
}
|
||||
// passo al figlio successivo
|
||||
nSonSouId = pSouGDB->GetNext( nSonSouId) ;
|
||||
}
|
||||
|
||||
return nNewId ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DuplicateGeomDB( IGeomDB* pSouGeomDB, IGeomDB* pDestGeomDB, bool bSkipTemp)
|
||||
{
|
||||
// adatto e verifico i GeomDB
|
||||
const GeomDB* pSouGDB = static_cast<GeomDB*>( pSouGeomDB) ;
|
||||
GeomDB* pDstGDB = static_cast<GeomDB*>( pDestGeomDB) ;
|
||||
if ( pSouGDB == nullptr || pDstGDB == nullptr)
|
||||
return false ;
|
||||
// verifico che la destinazione sia vuota
|
||||
if ( pDstGDB->GetFirstInGroup( GDB_ID_ROOT) != GDB_ID_NULL)
|
||||
return false ;
|
||||
// eseguo la copia di tutto (se richiesto salto gli oggetti temporanei)
|
||||
return ( DuplicateGroupObj( pSouGDB, GDB_ID_ROOT, pDstGDB, GDB_ID_ROOT, GDB_ID_ROOT, bSkipTemp) != GDB_ID_NULL) ;
|
||||
}
|
||||
+63
-74
@@ -17,6 +17,7 @@
|
||||
#include "NgeKeyW.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtStringConverter.h"
|
||||
#include "/EgtDev/Extern/zlib/Include/zlib.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -34,8 +35,12 @@ NgeReader::Init( const string& sFileIn)
|
||||
break ;
|
||||
case NGE_BINARY :
|
||||
m_bBinary = true ;
|
||||
m_InFile.open( stringtoW( sFileIn), ios::in | ios::binary, _SH_DENYWR) ;
|
||||
return ( ! m_InFile.fail()) ;
|
||||
m_InFile = gzopen_w( stringtoW( sFileIn), "rb") ;
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
const int DIM_BUFFER = 65536 ;
|
||||
gzbuffer( m_InFile, DIM_BUFFER) ;
|
||||
return true ;
|
||||
break ;
|
||||
}
|
||||
return false ;
|
||||
@@ -46,10 +51,12 @@ bool
|
||||
NgeReader::Close( void)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
bool bOk = ( m_InFile.good() && m_InFile.is_open()) ;
|
||||
if ( m_InFile.is_open())
|
||||
m_InFile.close() ;
|
||||
return bOk ;
|
||||
if ( m_InFile != nullptr) {
|
||||
bool bOk = ( gzclose( m_InFile) == Z_OK) ;
|
||||
m_InFile = nullptr ;
|
||||
return bOk ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return m_Scan.Terminate() ;
|
||||
@@ -59,31 +66,24 @@ NgeReader::Close( void)
|
||||
int
|
||||
NgeReader::NgeType( const string& sFile)
|
||||
{
|
||||
// apertura del file di ingresso
|
||||
ifstream InFile ;
|
||||
InFile.open( stringtoW( sFile), ios::in | ios::binary) ;
|
||||
if ( InFile.fail())
|
||||
// apertura file
|
||||
gzFile_s* InFile = gzopen_w( stringtoW( sFile), "rb") ;
|
||||
if ( InFile == nullptr)
|
||||
return NGE_ERROR ;
|
||||
|
||||
// lettura dei primi 31 byte
|
||||
char cBuff[32] ;
|
||||
InFile.read( cBuff, 31) ;
|
||||
cBuff[InFile.gcount()] = '\0' ;
|
||||
|
||||
// chiusura del file
|
||||
InFile.close() ;
|
||||
|
||||
// verifico se file compresso (gz)
|
||||
if ( cBuff[0] == '\x1F' && cBuff[1] == '\x8B')
|
||||
return NGE_ASCII ;
|
||||
|
||||
// verifico se iniziano con "START"
|
||||
string sBuff = cBuff ;
|
||||
size_t nPos = sBuff.find( "START") ;
|
||||
if ( nPos != string::npos && nPos < 10)
|
||||
return NGE_ASCII ;
|
||||
else
|
||||
// lettura dei primi caratteri
|
||||
char szBuff[9] = "\0\0\0\0\0\0\0\0" ;
|
||||
int nLen = gzread( InFile, &szBuff, 8) ;
|
||||
if ( gzclose( InFile) != Z_OK || nLen == Z_ERRNO)
|
||||
return NGE_ERROR ;
|
||||
// se binario
|
||||
if ( szBuff[0] == '\x0F' && szBuff[1] == '\x0F')
|
||||
return NGE_BINARY ;
|
||||
// se testo
|
||||
string sBuff{ szBuff} ;
|
||||
if ( sBuff.find( "START") != string::npos)
|
||||
return NGE_ASCII ;
|
||||
// altrimenti errore
|
||||
return NGE_ERROR ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -91,7 +91,7 @@ int
|
||||
NgeReader::GetCurrPos( void)
|
||||
{
|
||||
if ( m_bBinary)
|
||||
return int( m_InFile.tellg()) ;
|
||||
return int( gztell( m_InFile)) ;
|
||||
else
|
||||
return m_Scan.GetCurrLineNbr() ;
|
||||
}
|
||||
@@ -131,10 +131,9 @@ bool
|
||||
NgeReader::ReadUchar( unsigned char& ucVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &ucVal, sizeof( ucVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &ucVal, sizeof( ucVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -154,10 +153,9 @@ bool
|
||||
NgeReader::ReadBool( bool& bVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &bVal, sizeof( bVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &bVal, sizeof( bVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -173,10 +171,9 @@ bool
|
||||
NgeReader::ReadInt( int& nVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &nVal, sizeof( nVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &nVal, sizeof( nVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -203,10 +200,9 @@ bool
|
||||
NgeReader::ReadDouble( double& dVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &dVal, sizeof( dVal)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &dVal, sizeof( dVal)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -222,10 +218,9 @@ bool
|
||||
NgeReader::ReadVector( Vector3d& vtV, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &vtV.v, sizeof( vtV.v)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &vtV.v, sizeof( vtV.v)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -241,10 +236,9 @@ bool
|
||||
NgeReader::ReadPoint( Point3d& ptP, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &ptP.v, sizeof( ptP.v)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -260,11 +254,10 @@ bool
|
||||
NgeReader::ReadPointW( Point3d& ptP, double& dW, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
m_InFile.read( (char*) &dW, sizeof( dW)) ;
|
||||
return m_InFile.good() ;
|
||||
return ( gzread( m_InFile, &ptP.v, sizeof( ptP.v)) != Z_ERRNO &&
|
||||
gzread( m_InFile, &dW, sizeof( dW)) != Z_ERRNO) ;
|
||||
}
|
||||
else {
|
||||
// recupero il token
|
||||
@@ -280,17 +273,13 @@ bool
|
||||
NgeReader::ReadFrame( Frame3d& frF, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
Point3d ptOrig ;
|
||||
m_InFile.read( (char*) &ptOrig.v, sizeof( ptOrig.v)) ;
|
||||
Vector3d vtDirX ;
|
||||
m_InFile.read( (char*) &vtDirX.v, sizeof( vtDirX.v)) ;
|
||||
Vector3d vtDirY ;
|
||||
m_InFile.read( (char*) &vtDirY.v, sizeof( vtDirY.v)) ;
|
||||
Vector3d vtDirZ ;
|
||||
m_InFile.read( (char*) &vtDirZ.v, sizeof( vtDirZ.v)) ;
|
||||
if ( ! m_InFile.good())
|
||||
Point3d ptOrig ; Vector3d vtDirX, vtDirY, vtDirZ ;
|
||||
if ( gzread( m_InFile, &ptOrig.v, sizeof( ptOrig.v)) == Z_ERRNO ||
|
||||
gzread( m_InFile, &vtDirX.v, sizeof( vtDirX.v)) == Z_ERRNO ||
|
||||
gzread( m_InFile, &vtDirY.v, sizeof( vtDirY.v)) == Z_ERRNO ||
|
||||
gzread( m_InFile, &vtDirZ.v, sizeof( vtDirZ.v)) == Z_ERRNO)
|
||||
return false ;
|
||||
return frF.Set( ptOrig, vtDirX, vtDirY, vtDirZ) ;
|
||||
}
|
||||
@@ -308,18 +297,20 @@ bool
|
||||
NgeReader::ReadString( string& sVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
const int MAX_STR_DIM = 65535 ;
|
||||
if ( ! m_InFile.is_open())
|
||||
return false ;
|
||||
int nDim ;
|
||||
m_InFile.read( (char*) &nDim, sizeof( nDim)) ;
|
||||
if ( nDim > MAX_STR_DIM || ! m_InFile.good())
|
||||
if ( gzread( m_InFile, &nDim, sizeof( nDim)) == Z_ERRNO || nDim > MAX_STR_DIM)
|
||||
return false ;
|
||||
if ( nDim == 0) {
|
||||
sVal = "" ;
|
||||
return true ;
|
||||
}
|
||||
char* szBuff = new( nothrow) char[ nDim + 1] ;
|
||||
if ( szBuff == nullptr)
|
||||
return false ;
|
||||
m_InFile.read( szBuff, nDim) ;
|
||||
if ( ! m_InFile.good()) {
|
||||
if ( gzread( m_InFile, szBuff, nDim) == Z_ERRNO) {
|
||||
delete[] szBuff ;
|
||||
return false ;
|
||||
}
|
||||
@@ -348,12 +339,11 @@ NgeReader::ReadKey( int& nKey)
|
||||
return true ;
|
||||
}
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
// leggo il dato
|
||||
int nVal ;
|
||||
m_InFile.read( (char*) &nVal, sizeof( nVal)) ;
|
||||
if ( ! m_InFile.good())
|
||||
if ( gzread( m_InFile, &nVal, sizeof( nVal)) == Z_ERRNO)
|
||||
return false ;
|
||||
// ricavo l'indice
|
||||
for ( int i = 0 ; i <= NGE_LAST_ID ; ++ i) {
|
||||
@@ -386,11 +376,10 @@ bool
|
||||
NgeReader::ReadCol( Color& cCol, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_InFile.is_open())
|
||||
if ( m_InFile == nullptr)
|
||||
return false ;
|
||||
unsigned char ucCol[4] ;
|
||||
m_InFile.read( (char*) &ucCol, sizeof( ucCol)) ;
|
||||
if ( ! m_InFile.good())
|
||||
if ( gzread( m_InFile, &ucCol, sizeof( ucCol)) == Z_ERRNO)
|
||||
return false ;
|
||||
cCol.Set( ucCol[0], ucCol[1], ucCol[2], ucCol[3]) ;
|
||||
return true ;
|
||||
|
||||
+7
-5
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
// EgalTech 2014-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : NgeReader.h Data : 14.04.14 Versione : 1.5d5
|
||||
// File : NgeReader.h Data : 29.12.25 Versione : 2.7l6
|
||||
// Contenuto : Dichiarazione della classe NgeReader.
|
||||
//
|
||||
//
|
||||
@@ -18,14 +18,16 @@
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include "/EgtDev/Include/EGnScanner.h"
|
||||
#include "/EgtDev/Include/EgtStringBase.h"
|
||||
#include <fstream>
|
||||
|
||||
struct gzFile_s ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class NgeReader
|
||||
{
|
||||
public :
|
||||
NgeReader( void)
|
||||
: m_iPosStart( std::string::npos), m_bUngetKey( false), m_nFileVer() {}
|
||||
: m_bBinary( false), m_InFile( nullptr), m_iPosStart( std::string::npos),
|
||||
m_bUngetKey( false), m_nLastKey(), m_nFileVer() {}
|
||||
~NgeReader( void)
|
||||
{ Close() ; }
|
||||
bool Init( const std::string& sFileIn) ;
|
||||
@@ -60,7 +62,7 @@ class NgeReader
|
||||
private :
|
||||
bool m_bBinary ;
|
||||
// per file binari
|
||||
std::ifstream m_InFile ;
|
||||
gzFile_s* m_InFile ;
|
||||
// per file ASCII
|
||||
Scanner m_Scan ;
|
||||
std::string::size_type m_iPosStart ;
|
||||
|
||||
+64
-86
@@ -23,23 +23,23 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool
|
||||
WriteStringOutTxt( gzFile OutTxtFile, const char* szVal, const char* szSep, bool bEndL)
|
||||
static bool
|
||||
WriteStringOutTxt( gzFile OutFile, const char* szVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
// verifico apertura file
|
||||
if ( OutTxtFile == nullptr)
|
||||
if ( OutFile == nullptr)
|
||||
return false ;
|
||||
// scrivo stringa
|
||||
if ( gzputs( OutTxtFile, szVal) == Z_ERRNO)
|
||||
if ( gzputs( OutFile, szVal) == Z_ERRNO)
|
||||
return false ;
|
||||
// se fornito, scrivo separatore
|
||||
if ( szSep != nullptr && szSep[0] != '\0') {
|
||||
if ( gzputs( OutTxtFile, szSep) == Z_ERRNO)
|
||||
if ( gzputs( OutFile, szSep) == Z_ERRNO)
|
||||
return false ;
|
||||
}
|
||||
// se richiesto, scrivo fine linea
|
||||
if ( bEndL) {
|
||||
if ( gzputs( OutTxtFile, "\r\n") == Z_ERRNO)
|
||||
if ( gzputs( OutFile, "\r\n") == Z_ERRNO)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
@@ -50,27 +50,22 @@ bool
|
||||
NgeWriter::Init( const string& sFileOut, int nFlag)
|
||||
{
|
||||
// salvo tipo file
|
||||
m_bBinary = ( nFlag == GDB_SV_BIN) ;
|
||||
m_bBinary = ( nFlag == GDB_SV_BIN || nFlag == GDB_SV_CMPBIN) ;
|
||||
|
||||
// apertura del file di uscita
|
||||
if ( m_bBinary) {
|
||||
ios_base::openmode nMode = ios::out | ( m_bBinary ? ios::binary : 0) ;
|
||||
int nProt = _SH_DENYWR ;
|
||||
m_OutBinFile.open( stringtoW( sFileOut), nMode, nProt) ;
|
||||
return m_OutBinFile.good() ;
|
||||
if ( nFlag == GDB_SV_TXT || nFlag == GDB_SV_BIN) {
|
||||
m_OutFile = gzopen_w( stringtoW( sFileOut), "wbT") ;
|
||||
return ( m_OutFile != nullptr) ;
|
||||
}
|
||||
else {
|
||||
if ( nFlag == GDB_SV_TXT)
|
||||
m_OutTxtFile = gzopen_w( stringtoW( sFileOut), "wbT") ;
|
||||
else // GDB_SV_CMPTXT
|
||||
m_OutTxtFile = gzopen_w( stringtoW( sFileOut), "wb") ;
|
||||
if ( m_OutTxtFile == nullptr)
|
||||
else { // GDB_SV_CMPTXT o GDB_SV_CMPBIN
|
||||
m_OutFile = gzopen_w( stringtoW( sFileOut), "wb") ;
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
const int DIM_BUFFER = 65536 ;
|
||||
if ( gzbuffer( m_OutTxtFile, DIM_BUFFER) != Z_OK)
|
||||
if ( gzbuffer( m_OutFile, DIM_BUFFER) != Z_OK)
|
||||
return false ;
|
||||
const int COMPR_LEVEL = 3 ; // 0 = no compression ... 9 = max compression
|
||||
if ( gzsetparams( m_OutTxtFile, COMPR_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
if ( gzsetparams( m_OutFile, COMPR_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
@@ -80,20 +75,12 @@ NgeWriter::Init( const string& sFileOut, int nFlag)
|
||||
bool
|
||||
NgeWriter::Close( void)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
bool bOk = ( m_OutBinFile.good() && m_OutBinFile.is_open()) ;
|
||||
if ( m_OutBinFile.is_open())
|
||||
m_OutBinFile.close() ;
|
||||
if ( m_OutFile != nullptr) {
|
||||
bool bOk = ( gzclose( m_OutFile) == Z_OK) ;
|
||||
m_OutFile = nullptr ;
|
||||
return bOk ;
|
||||
}
|
||||
else {
|
||||
if ( m_OutTxtFile != nullptr) {
|
||||
bool bOk = ( gzclose( m_OutTxtFile) == Z_OK) ;
|
||||
m_OutTxtFile = nullptr ;
|
||||
return bOk ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -101,13 +88,12 @@ bool
|
||||
NgeWriter::WriteUchar( unsigned char ucVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &ucVal, sizeof( ucVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &ucVal, sizeof( ucVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( ucVal).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( ucVal).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,13 +102,12 @@ bool
|
||||
NgeWriter::WriteBool( bool bVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &bVal, sizeof( bVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &bVal, sizeof( bVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( bVal).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( bVal).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,13 +116,12 @@ bool
|
||||
NgeWriter::WriteInt( int nVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &nVal, sizeof( nVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &nVal, sizeof( nVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( nVal).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( nVal).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,13 +130,12 @@ bool
|
||||
NgeWriter::WriteDouble( double dVal, const char* szSep, bool bEndL, int nPrec)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &dVal, sizeof( dVal)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &dVal, sizeof( dVal)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( dVal, nPrec).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( dVal, nPrec).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,15 +144,14 @@ bool
|
||||
NgeWriter::WriteString( const string& sVal, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
int nDim = int( sVal.size()) ;
|
||||
m_OutBinFile.write( (char*) &nDim, sizeof( nDim)) ;
|
||||
m_OutBinFile.write( sVal.c_str(), sVal.size()) ;
|
||||
return m_OutBinFile.good() ;
|
||||
int nDim = ssize( sVal) ;
|
||||
return ( gzwrite( m_OutFile, &nDim, sizeof( nDim)) > 0 &&
|
||||
( nDim == 0 || gzwrite( m_OutFile, sVal.c_str(), sVal.size()) > 0)) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, sVal.c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, sVal.c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,13 +160,12 @@ bool
|
||||
NgeWriter::WriteVector( const Vector3d& vtV, const char* szSep, bool bEndL, int nPrec)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &vtV.v, sizeof( vtV.v)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &vtV.v, sizeof( vtV.v)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( vtV, nPrec).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( vtV, nPrec).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,13 +174,12 @@ bool
|
||||
NgeWriter::WritePoint( const Point3d& ptP, const char* szSep, bool bEndL, int nPrec)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &ptP.v, sizeof( ptP.v)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( ptP, nPrec).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( ptP, nPrec).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,14 +188,13 @@ bool
|
||||
NgeWriter::WritePointW( const Point3d& ptP, double dW, const char* szSep, bool bEndL, int nPrecP, int nPrecW)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &ptP.v, sizeof( ptP.v)) ;
|
||||
m_OutBinFile.write( (char*) &dW, sizeof( dW)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &ptP.v, sizeof( ptP.v)) > 0 &&
|
||||
gzwrite( m_OutFile, &dW, sizeof( dW)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( ptP, dW, nPrecP, nPrecW).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( ptP, dW, nPrecP, nPrecW).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,16 +203,15 @@ bool
|
||||
NgeWriter::WriteFrame( const Frame3d& frF, const char* szSep, bool bEndL, int nPrecP, int nPrecV)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &frF.Orig().v, sizeof( frF.Orig().v)) ;
|
||||
m_OutBinFile.write( (char*) &frF.VersX().v, sizeof( frF.VersX().v)) ;
|
||||
m_OutBinFile.write( (char*) &frF.VersY().v, sizeof( frF.VersY().v)) ;
|
||||
m_OutBinFile.write( (char*) &frF.VersZ().v, sizeof( frF.VersZ().v)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &frF.Orig().v, sizeof( frF.Orig().v)) > 0 &&
|
||||
gzwrite( m_OutFile, &frF.VersX().v, sizeof( frF.VersX().v)) > 0 &&
|
||||
gzwrite( m_OutFile, &frF.VersY().v, sizeof( frF.VersY().v)) > 0 &&
|
||||
gzwrite( m_OutFile, &frF.VersZ().v, sizeof( frF.VersZ().v)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( frF, nPrecP, nPrecV).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( frF, nPrecP, nPrecV).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,13 +223,12 @@ NgeWriter::WriteKey( int nKey)
|
||||
return false ;
|
||||
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
m_OutBinFile.write( (char*) &NgeBinKeyW[nKey], sizeof( int)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, &NgeBinKeyW[nKey], sizeof( int)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, NgeAscKeyW[nKey].c_str(), nullptr, true) ;
|
||||
return WriteStringOutTxt( m_OutFile, NgeAscKeyW[nKey].c_str(), nullptr, true) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,18 +237,17 @@ bool
|
||||
NgeWriter::WriteCol( const Color& cCol, const char* szSep, bool bEndL)
|
||||
{
|
||||
if ( m_bBinary) {
|
||||
if ( ! m_OutBinFile.is_open())
|
||||
if ( m_OutFile == nullptr)
|
||||
return false ;
|
||||
unsigned char ucCol[4] ;
|
||||
ucCol[0] = cCol.GetIntRed() ;
|
||||
ucCol[1] = cCol.GetIntGreen() ;
|
||||
ucCol[2] = cCol.GetIntBlue() ;
|
||||
ucCol[3] = cCol.GetIntAlpha() ;
|
||||
m_OutBinFile.write( (char*) ucCol, sizeof( ucCol)) ;
|
||||
return m_OutBinFile.good() ;
|
||||
return ( gzwrite( m_OutFile, ucCol, sizeof( ucCol)) > 0) ;
|
||||
}
|
||||
else {
|
||||
return WriteStringOutTxt( m_OutTxtFile, ToString( cCol).c_str(), szSep, bEndL) ;
|
||||
return WriteStringOutTxt( m_OutFile, ToString( cCol).c_str(), szSep, bEndL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,9 +255,11 @@ NgeWriter::WriteCol( const Color& cCol, const char* szSep, bool bEndL)
|
||||
bool
|
||||
NgeWriter::WriteRemark( const string& sVal)
|
||||
{
|
||||
if ( m_bBinary)
|
||||
if ( m_bBinary) {
|
||||
return true ;
|
||||
else
|
||||
return ( WriteStringOutTxt( m_OutTxtFile, "//", nullptr, false) &&
|
||||
WriteStringOutTxt( m_OutTxtFile, sVal.c_str(), nullptr, true)) ;
|
||||
}
|
||||
else {
|
||||
return ( WriteStringOutTxt( m_OutFile, "//", nullptr, false) &&
|
||||
WriteStringOutTxt( m_OutFile, sVal.c_str(), nullptr, true)) ;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-9
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
// EgalTech 2014-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : NgeWriter.h Data : 12.04.14 Versione : 1.5d5
|
||||
// File : NgeWriter.h Data : 29.12.25 Versione : 2.7l6
|
||||
// Contenuto : Dichiarazione della classe NgeWriter.
|
||||
//
|
||||
//
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "NgeConst.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include <fstream>
|
||||
|
||||
struct gzFile_s ;
|
||||
|
||||
@@ -24,7 +23,7 @@ struct gzFile_s ;
|
||||
class NgeWriter
|
||||
{
|
||||
public :
|
||||
NgeWriter( void) : m_bBinary( false), m_OutTxtFile( nullptr) {}
|
||||
NgeWriter( void) : m_bBinary( false), m_OutFile( nullptr) {}
|
||||
~NgeWriter( void)
|
||||
{ Close() ; }
|
||||
bool Init( const std::string& sFileOut, int nFlag) ;
|
||||
@@ -44,9 +43,6 @@ class NgeWriter
|
||||
bool WriteRemark( const std::string& sVal /* bEndL = true*/) ;
|
||||
|
||||
private :
|
||||
bool m_bBinary ;
|
||||
// per file binari
|
||||
std::ofstream m_OutBinFile ;
|
||||
// per file ASCII
|
||||
gzFile_s* m_OutTxtFile ;
|
||||
bool m_bBinary ;
|
||||
gzFile_s* m_OutFile ;
|
||||
} ;
|
||||
|
||||
+155
-33
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetAux.cpp Data : 23.11.23 Versione : 2.5k5
|
||||
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -16,20 +16,24 @@
|
||||
#include "CurveArc.h"
|
||||
#include "CurveLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool IsFillet( const ICurve* pCrv, double dDist) ;
|
||||
static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
|
||||
static bool AdjustIntersections( ICRVCOMPOPVECTOR& CrvList) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
|
||||
{
|
||||
// identifico le sottocurve di tipo fillet e assegno loro temp param 1.0 per riconoscerle nella funzione AdjustCurveFillets
|
||||
for ( int i = 0 ; i < pCrvCo->GetCurveCount() ; i ++) {
|
||||
// recupero la curva
|
||||
PtrOwner<ICurve> pCrv( pCrvCo->GetCurve(i)->Clone()) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
if ( IsFillet( pCrv, dDist))
|
||||
if ( IsFillet( pCrvCo->GetCurve( i), dDist))
|
||||
pCrvCo->SetCurveTempParam( i, 1.0) ;
|
||||
else
|
||||
pCrvCo->SetCurveTempParam( i, 0.0) ;
|
||||
@@ -39,12 +43,14 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsFillet( ICurve* pCrv, double dDist)
|
||||
IsFillet( const ICurve* pCrv, double dDist)
|
||||
{
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// deve essere un arco
|
||||
if ( pCrv->GetType() != CRV_ARC)
|
||||
return false ;
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
// deve avere raggio uguale alla distanza di offset
|
||||
if ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL)
|
||||
return false ;
|
||||
@@ -54,36 +60,76 @@ IsFillet( ICurve* pCrv, double dDist)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType)
|
||||
AdjustCurveFillets( ICURVEPOVECTOR& vOffset, double dDist, int nType)
|
||||
{
|
||||
ICURVEPLIST CrvLst ;
|
||||
PtrOwner<ICurve> pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv)) {
|
||||
// se identificato come fillet lo trasformo in smusso o estensione
|
||||
if ( pCrv->GetTempParam() > EPS_SMALL) {
|
||||
CurveComposite ccTemp ;
|
||||
ModifyFillet( pCrv, dDist, nType, ccTemp) ;
|
||||
// metto in lista le curve risultanti
|
||||
if ( ccTemp.GetCurveCount() > 0) {
|
||||
PtrOwner<ICurve> pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv2)) {
|
||||
CrvLst.push_back( Release( pCrv2)) ;
|
||||
pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
if ( vOffset.empty())
|
||||
return true ;
|
||||
|
||||
// suddivido le curve di offset individuando i fillet e isolandoli dagli altri tratti
|
||||
ICRVCOMPOPVECTOR vCrvs ;
|
||||
for ( int i = 0 ; i < int( vOffset.size()) ; i ++) {
|
||||
CurveComposite* pCompo = GetBasicCurveComposite( vOffset[i]) ;
|
||||
if ( pCompo == nullptr)
|
||||
return false ;
|
||||
bool bNewCrv = true ;
|
||||
PtrOwner<ICurve> pCrv( pCompo->RemoveFirstOrLastCurve(false)) ;
|
||||
while ( ! IsNull( pCrv)) {
|
||||
if ( pCrv->GetTempParam() > EPS_SMALL) {
|
||||
// se fillet calcolo il nuovo raccordo
|
||||
CurveComposite* ccTemp = CreateBasicCurveComposite() ;
|
||||
ModifyFillet( pCrv, dDist, nType, *ccTemp) ;
|
||||
// assegno temp param per identificarlo nei conti successivi
|
||||
ccTemp->SetTempParam( 1) ;
|
||||
vCrvs.push_back( ccTemp) ;
|
||||
bNewCrv = true ;
|
||||
}
|
||||
else {
|
||||
// aggiungo la curva
|
||||
if ( bNewCrv) {
|
||||
bNewCrv = false ;
|
||||
CurveComposite* pCompo = ConvertCurveToBasicComposite( Release( pCrv)) ;
|
||||
if ( pCompo == nullptr)
|
||||
return false ;
|
||||
vCrvs.push_back( pCompo) ;
|
||||
}
|
||||
else
|
||||
vCrvs.back()->AddCurve( Release( pCrv)) ;
|
||||
}
|
||||
// passo alla curva successiva
|
||||
pCrv.Set( pCompo->RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
// altrimenti salvo in lista
|
||||
else
|
||||
CrvLst.push_back( Release( pCrv)) ;
|
||||
// passo alla curva successiva
|
||||
pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
// rimetto le curve nella composita
|
||||
for ( auto pCrv : CrvLst) {
|
||||
pCrvCo->AddCurve( pCrv) ;
|
||||
vOffset.clear() ;
|
||||
|
||||
// gestione delle intersezioni
|
||||
if ( ! AdjustIntersections( vCrvs))
|
||||
return false ;
|
||||
|
||||
// concateno i tratti ottenuti
|
||||
ChainCurves ChainCrv ;
|
||||
ChainCrv.Init( false, 2 * EPS_SMALL, vCrvs.size()) ;
|
||||
for ( int i = 0 ; i < int( vCrvs.size()); ++ i) {
|
||||
Point3d ptS, ptE ;
|
||||
Vector3d vtS, vtE ;
|
||||
vCrvs[i]->GetStartPoint( ptS) ;
|
||||
vCrvs[i]->GetEndPoint( ptE) ;
|
||||
vCrvs[i]->GetStartDir( vtS) ;
|
||||
vCrvs[i]->GetEndDir( vtE) ;
|
||||
ChainCrv.AddCurve( i + 1, ptS, vtS, ptE, vtE) ;
|
||||
}
|
||||
// recupero i concatenamenti
|
||||
Point3d ptRef ; vCrvs[0]->GetStartPoint( ptRef) ;
|
||||
INTVECTOR vIds ;
|
||||
while ( ChainCrv.GetChainFromNear( ptRef, false, vIds)) {
|
||||
PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCompo))
|
||||
return false ;
|
||||
for ( auto i : vIds)
|
||||
pCompo->AddCurve( vCrvs[i-1]) ;
|
||||
pCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
pCompo->GetEndPoint( ptRef) ;
|
||||
vOffset.emplace_back( Release( pCompo)) ;
|
||||
}
|
||||
// unisco tratti allineati
|
||||
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -177,3 +223,79 @@ ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux)
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
AdjustIntersections( ICRVCOMPOPVECTOR& vCrvs)
|
||||
{
|
||||
// sistema le curve nel vettore vCrvs eliminando le parti coinvolte nelle intersezioni
|
||||
|
||||
vector<Intervals> vIntervals( vCrvs.size()) ;
|
||||
INTVECTOR vFillets ;
|
||||
for ( int i = 0 ; i < int( vCrvs.size()) ; i ++) {
|
||||
// salvo i parametri della curva
|
||||
double dParS, dParE ;
|
||||
vCrvs[i]->GetDomain( dParS, dParE) ;
|
||||
vIntervals[i].Set( dParS, dParE) ;
|
||||
// verifico se raccordo
|
||||
if ( vCrvs[i]->GetTempParam() > EPS_SMALL)
|
||||
vFillets.emplace_back( i) ;
|
||||
}
|
||||
|
||||
// verifico se i raccordi intersecano le altre curve
|
||||
bool bInters = false ;
|
||||
for ( int i = 0 ; i < int( vFillets.size()) ; i ++) {
|
||||
int nIdx = vFillets[i] ;
|
||||
for ( int j = 0 ; j < int( vCrvs.size()) ; j ++) {
|
||||
if ( j == nIdx)
|
||||
continue ;
|
||||
|
||||
IntersCurveCurve intCC( *vCrvs[nIdx], *vCrvs[j]) ;
|
||||
int nCnt = intCC.GetIntersCount() ;
|
||||
if ( nCnt > 1) {
|
||||
// aggiorno gli intervalli della curva sottraendo la parte coinvolta dall'intersezione
|
||||
for ( int k = 0 ; k < nCnt - 1 ; k = k+2) {
|
||||
IntCrvCrvInfo iccInfo1, iccInfo2 ;
|
||||
intCC.GetIntCrvCrvInfo( k, iccInfo1) ;
|
||||
// verifico non sia intersezione nell'estremo iniziale o sovrapposizione
|
||||
if ( iccInfo1.IciA[0].dU < EPS_SMALL || iccInfo1.bOverlap) {
|
||||
k-- ;
|
||||
continue ;
|
||||
}
|
||||
intCC.GetIntCrvCrvInfo( k+1, iccInfo2) ;
|
||||
|
||||
vIntervals[nIdx].Subtract( iccInfo1.IciA[0].dU, iccInfo2.IciA[0].dU) ;
|
||||
vIntervals[j].Subtract( iccInfo1.IciB[0].dU, iccInfo2.IciB[0].dU) ;
|
||||
bInters = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bInters)
|
||||
return true ;
|
||||
|
||||
// aggiorno le curve eliminando i tratti coinvolti nelle intersezioni
|
||||
for ( int i = 0 ; i < int( vIntervals.size()) ; i++) {
|
||||
if ( vIntervals[i].GetCount() > 1) {
|
||||
PtrOwner<CurveComposite> pCompo( CloneBasicCurveComposite( vCrvs[i])) ;
|
||||
if ( IsNull( pCompo))
|
||||
return false ;
|
||||
double dParS, dParE ;
|
||||
vIntervals[i].GetFirst( dParS, dParE) ;
|
||||
vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ;
|
||||
while ( vIntervals[i].GetNext( dParS, dParE)) {
|
||||
CurveComposite* pCrv = ConvertCurveToBasicComposite( pCompo->CopyParamRange( dParS, dParE)) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
vCrvs.emplace_back( pCrv) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
double dParS, dParE ;
|
||||
vIntervals[i].GetFirst( dParS, dParE) ;
|
||||
vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+2
-4
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetAux.h Data : 23.11.23 Versione : 2.5k5
|
||||
// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -16,6 +16,4 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ;
|
||||
bool IsFillet( ICurve* pCrv, double dDist) ;
|
||||
bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ;
|
||||
bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ;
|
||||
bool AdjustCurveFillets( ICURVEPOVECTOR& vCrvs, double dDist, int nType) ;
|
||||
+88
-32
@@ -60,6 +60,8 @@ OffsetCurve::Reset( void)
|
||||
}
|
||||
}
|
||||
m_CrvLst.clear() ;
|
||||
m_ptOffs = P_INVALID ;
|
||||
m_vtOut = V_INVALID ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// verifico che la curva esista
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
// verifico se la curva è un segmento di retta
|
||||
// verifico se la curva è un segmento di retta
|
||||
bool bIsLine = false ;
|
||||
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
|
||||
if ( pLine != nullptr)
|
||||
@@ -85,7 +87,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( pCompo != nullptr && pCompo->IsALine( m_dLinTol, ptStart, ptEnd))
|
||||
bIsLine = true ;
|
||||
}
|
||||
// verifico che la curva sia piana (per le linee è comunque sempre vero)
|
||||
// verifico che la curva sia piana (per le linee è comunque sempre vero)
|
||||
Plane3d plPlane ;
|
||||
if ( ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL) && ! bIsLine)
|
||||
return false ;
|
||||
@@ -167,7 +169,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// -------------------- OFFSET STANDARD ---------------------------------
|
||||
if ( ! USE_VORONOI) {
|
||||
|
||||
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
|
||||
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
|
||||
if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( m_dLinTol, ANG_TOL_STD_DEG))
|
||||
return false ;
|
||||
|
||||
@@ -187,11 +189,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( ! ccCopy.MergeCurves( m_dLinTol, ANG_TOL_STD_DEG, bClosed, true))
|
||||
return false ;
|
||||
|
||||
// verifico se il punto iniziale è stato modificato
|
||||
// verifico se il punto iniziale è stato modificato
|
||||
Point3d ptNewStart ; ccCopy.GetStartPoint( ptNewStart) ;
|
||||
bChangeStart = ( ! AreSamePointApprox( ptNewStart, ptStart)) ;
|
||||
|
||||
// calcolo le lunghezze delle diverse entità
|
||||
// calcolo le lunghezze delle diverse entità
|
||||
DBLVECTOR vLens ;
|
||||
{
|
||||
const ICurve* pCrv1 = ccCopy.GetFirstCurve() ;
|
||||
@@ -203,7 +205,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
pCrv1 = ccCopy.GetNextCurve() ;
|
||||
}
|
||||
}
|
||||
// calcolo gli angoli tra le diverse entità
|
||||
// calcolo gli angoli tra le diverse entità
|
||||
DBLVECTOR vAngs ;
|
||||
{
|
||||
vAngs.push_back( 0) ;
|
||||
@@ -230,7 +232,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
vAngs.push_back( 0) ;
|
||||
}
|
||||
|
||||
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
|
||||
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
|
||||
CurveComposite ccCopy2 ;
|
||||
if ( ! ccCopy2.CopyFrom( &ccCopy))
|
||||
return false ;
|
||||
@@ -241,11 +243,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( IsNull( pCrv1))
|
||||
return false ;
|
||||
pCrv1->SetTempProp( nInd1) ;
|
||||
if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET)) {
|
||||
if ( ! pCrv1->SimpleOffset( dDist)) {
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv1) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
|
||||
if ( pArc->MyExtendedOffset( dDist, true))
|
||||
pCrv1->SetTempProp( - nInd1) ;
|
||||
}
|
||||
// curve successive
|
||||
@@ -253,11 +255,11 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
while ( ! IsNull( pCrv2)) {
|
||||
// eseguo semplice offset
|
||||
pCrv2->SetTempProp( nInd1 + 1) ;
|
||||
if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET)) {
|
||||
if ( ! pCrv2->SimpleOffset( dDist)) {
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv2) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
|
||||
if ( pArc->MyExtendedOffset( dDist, true))
|
||||
pCrv2->SetTempProp( - ( nInd1 + 1)) ;
|
||||
}
|
||||
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
||||
@@ -285,9 +287,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
|
||||
// se originale chiuso, devo confrontare anche ultima e prima curva
|
||||
if ( bClosed && m_CrvLst.size() >= 2) {
|
||||
// la curva precedente è l'ultima dell'offset
|
||||
// la curva precedente è l'ultima dell'offset
|
||||
ICurve* pCrv1 = m_CrvLst.back() ;
|
||||
// la curva successiva ora è la prima dell'offset
|
||||
// la curva successiva ora è la prima dell'offset
|
||||
ICurve* pCrv2 = m_CrvLst.front() ;
|
||||
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
||||
CurveComposite ccTemp ;
|
||||
@@ -334,7 +336,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
bool bNextInt = NextIsLine( iIter, m_CrvLst, bClosed) &&
|
||||
NextIsLonger( nInd1, vLens, bClosed) &&
|
||||
( ( dDist < 0 && vAngs[nInd1] > 0) || ( dDist > 0 && vAngs[nInd1] < 0)) ;
|
||||
// calcolo la massima estensione di offset (Voronoi con entità adiacenti)
|
||||
// calcolo la massima estensione di offset (Voronoi con entità adiacenti)
|
||||
double dMaxDist = INFINITO ;
|
||||
if ( bPrevInt && bNextInt) {
|
||||
double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ;
|
||||
@@ -502,7 +504,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
|
||||
// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
|
||||
if ( ! bClosed) {
|
||||
// ciconferenza sull'estremità iniziale
|
||||
// ciconferenza sull'estremità iniziale
|
||||
Point3d ptStart ; ccCopy.GetStartPoint( ptStart) ;
|
||||
PtrOwner<CurveArc> pCircS( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( pCircS) || ! pCircS->Set( ptStart, Z_AX, abs( dDist)))
|
||||
@@ -551,7 +553,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// passo alla successiva
|
||||
++ iIter ;
|
||||
}
|
||||
// circonferenza sull'estremità finale
|
||||
// circonferenza sull'estremità finale
|
||||
Point3d ptEnd ; ccCopy.GetEndPoint( ptEnd) ;
|
||||
PtrOwner<CurveArc> pCircE( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( pCircE) || ! pCircE->Set( ptEnd, Z_AX, abs( dDist)))
|
||||
@@ -672,12 +674,20 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
}
|
||||
|
||||
// nono passo : se con smusso o estensione, sostituisco i fillet con questi
|
||||
// NB questa parte non è gestita in modo efficiente perchè dovrebbe essere sempre disabilitata.
|
||||
// Le funzioni sono state ottimizzate per lavorare con voronoi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) {
|
||||
CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ;
|
||||
IdentifyFillets( pCrvCo, dDist) ;
|
||||
AdjustCurveFillets( pCrvCo, dDist, nType) ;
|
||||
}
|
||||
ICURVEPOVECTOR vCrvs ;
|
||||
vCrvs.reserve( m_CrvLst.size()) ;
|
||||
for ( auto pCrv : m_CrvLst) {
|
||||
IdentifyFillets( GetCurveComposite( pCrv), dDist) ;
|
||||
vCrvs.emplace_back( pCrv) ;
|
||||
}
|
||||
if ( ! AdjustCurveFillets( vCrvs, dDist, nType))
|
||||
return false ;
|
||||
m_CrvLst.clear() ;
|
||||
for ( int j = 0 ; j < int( vCrvs.size()) ; j ++)
|
||||
m_CrvLst.emplace_back( Release( vCrvs[j])) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,6 +707,27 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
// calcolo offset con Voronoi
|
||||
ICURVEPOVECTOR vOffs ;
|
||||
voronoiObj->CalcOffset( vOffs, dDist, nType) ;
|
||||
if ( vOffs.empty()) {
|
||||
// se non ho ottenuto offset e sono circa al valore limite ritento con valore leggermente diverso per le tolleranze di vroni
|
||||
double dMaxOffs ;
|
||||
if ( ! pCrv->IsClosed() || ( voronoiObj->CalcLimitOffset( 0, dDist < 0, dMaxOffs) && abs( dMaxOffs - abs( dDist)) < EPS_SMALL)) {
|
||||
double dCorr = ( dDist > 0 ? - VRONI_OFFS_TOL : VRONI_OFFS_TOL) ;
|
||||
voronoiObj->CalcOffset( vOffs, dDist + dCorr, nType) ;
|
||||
}
|
||||
// se ancora vuoto calcolo i punti speciali di offset ( punti e direzioni sui bisettore alla distanza richiesta)
|
||||
if ( vOffs.empty()) {
|
||||
PNTVECTVECTOR vPntOffs ;
|
||||
voronoiObj->CalcSpecialPointOffset( vPntOffs, dDist) ;
|
||||
// NB al momento vengono gestiti solo i casi in cui vi è un unico punto di offset. Se si ottengono più punti di offset
|
||||
// ( e.g. alcune curve aperte) non se ne restiusce nessuno. Da estendere, se necessario, individuando i punti dal lato
|
||||
// di offset richiesto
|
||||
if ( vPntOffs.size() == 1) {
|
||||
m_ptOffs = vPntOffs[0].first ;
|
||||
m_vtOut = vPntOffs[0].second ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++)
|
||||
m_CrvLst.emplace_back( Release( vOffs[i])) ;
|
||||
|
||||
@@ -724,10 +755,21 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||
pCrv->ToGlob( frCopy) ;
|
||||
}
|
||||
if ( m_ptOffs.IsValid()) {
|
||||
m_ptOffs.Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||
m_ptOffs.ToGlob( frCopy) ;
|
||||
m_vtOut.Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
|
||||
m_vtOut.ToGlob( frCopy) ;
|
||||
}
|
||||
|
||||
}
|
||||
else if ( bNeedRef) {
|
||||
for ( auto pCrv : m_CrvLst)
|
||||
pCrv->ToGlob( frCopy) ;
|
||||
if ( m_ptOffs.IsValid()) {
|
||||
m_ptOffs.ToGlob( frCopy) ;
|
||||
m_vtOut.ToGlob( frCopy) ;
|
||||
}
|
||||
}
|
||||
|
||||
// assegno estrusione e spessore come curva originale e unisco parti allineate
|
||||
@@ -805,6 +847,20 @@ OffsetCurve::GetShorterCurve( void)
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OffsetCurve::GetPointOffset( Point3d& ptOffs, Vector3d& vtOut)
|
||||
{
|
||||
// verifico se valori validi da restituire
|
||||
if ( ! m_ptOffs.IsValid() || ! m_vtOut.IsValid())
|
||||
return false ;
|
||||
|
||||
ptOffs = m_ptOffs ;
|
||||
vtOut = m_vtOut ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool bClosed)
|
||||
@@ -817,7 +873,7 @@ PreviousIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bo
|
||||
// se non esiste e curva chiusa prendo l'ultimo
|
||||
if ( iPrev == CrvLst.end() && bClosed)
|
||||
-- iPrev ;
|
||||
// se non esiste o non è una linea, test fallito
|
||||
// se non esiste o non è una linea, test fallito
|
||||
if ( iPrev == CrvLst.end() || (*iPrev)->GetType() != CRV_LINE )
|
||||
return false ;
|
||||
// test superato
|
||||
@@ -830,7 +886,7 @@ PreviousIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed)
|
||||
{
|
||||
// massimo indice nel vettore
|
||||
int nMax = int( vLens.size()) - 1 ;
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
if ( nInd1 < 1 || nInd1 > nMax + 1)
|
||||
return false ;
|
||||
// indice del precedente nel vettore di lunghezze
|
||||
@@ -854,7 +910,7 @@ NextIsLine( ICURVEPLIST::const_iterator iIter, const ICURVEPLIST& CrvLst, bool b
|
||||
// se non esiste e curva chiusa prendo il primo
|
||||
if ( iNext == CrvLst.end() && bClosed)
|
||||
iNext = CrvLst.begin() ;
|
||||
// se non esiste o non è una linea, test fallito
|
||||
// se non esiste o non è una linea, test fallito
|
||||
if ( iNext == CrvLst.end() || (*iNext)->GetType() != CRV_LINE )
|
||||
return false ;
|
||||
// test superato
|
||||
@@ -867,7 +923,7 @@ NextIsLonger( int nInd1, const DBLVECTOR& vLens, bool bClosed)
|
||||
{
|
||||
// massimo indice nel vettore
|
||||
int nMax = int( vLens.size()) - 1 ;
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
// verifico validità indice (questo indice è incrementato di 1)
|
||||
if ( nInd1 < 1 || nInd1 > nMax + 1)
|
||||
return false ;
|
||||
// indice del successivo nel vettore di lunghezze
|
||||
@@ -946,7 +1002,7 @@ VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
nRes = 4 ;
|
||||
return true ;
|
||||
}
|
||||
// se coincidono esattamente, va bene così
|
||||
// se coincidono esattamente, va bene così
|
||||
if ( AreSamePointExact( ptP1, ptP2)) {
|
||||
nRes = 0 ;
|
||||
return true ;
|
||||
@@ -976,7 +1032,7 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes)
|
||||
IntersCurveCurve intCC( *pCrv1, *pCrv2) ;
|
||||
if ( intCC.GetIntersCount() == 0)
|
||||
return false ;
|
||||
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
|
||||
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
|
||||
Point3d ptP1, ptP2 ;
|
||||
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
||||
return false ;
|
||||
@@ -1024,7 +1080,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
vtDir2.Invert() ;
|
||||
}
|
||||
|
||||
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposte)
|
||||
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposte)
|
||||
if ( abs( dAngDeg) < ( ANG_STRAIGHT - 10 * EPS_ANG_ZERO) &&
|
||||
( ( dDist < 0 && dAngDeg > 0) ||
|
||||
( dDist > 0 && dAngDeg < 0)))
|
||||
@@ -1066,7 +1122,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
return false ;
|
||||
ptP1a = ptP1 + vtDir1 * dLen ;
|
||||
ptP2a = ptP2 - vtDir2 * dLen ;
|
||||
// se prima c'è linea posso allungarla
|
||||
// se prima c'è linea posso allungarla
|
||||
if ( pCrv1->GetType() == CRV_LINE)
|
||||
pCrv1->ModifyEnd( ptP1a) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
@@ -1085,7 +1141,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
if ( ! ccAux.AddCurve( Release( pCrv)))
|
||||
return false ;
|
||||
}
|
||||
// se dopo c'è linea posso allungarla
|
||||
// se dopo c'è linea posso allungarla
|
||||
if ( pCrv2->GetType() == CRV_LINE)
|
||||
pCrv2->ModifyStart( ptP2a) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
@@ -1108,7 +1164,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
||||
return false ;
|
||||
ptPc = ptP1 + vtDir1 * dLen ;
|
||||
// se prima c'è linea o angolo molto piccolo posso allungarla
|
||||
// se prima c'è linea o angolo molto piccolo posso allungarla
|
||||
if ( ( pCrv1->GetType() == CRV_LINE) || bAngSmall)
|
||||
pCrv1->ModifyEnd( ptPc) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
@@ -1119,7 +1175,7 @@ VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, doub
|
||||
if ( ! ccAux.AddCurve( Release( pCrv)))
|
||||
return false ;
|
||||
}
|
||||
// se dopo c'è linea o angolo molto piccolo posso allungarla
|
||||
// se dopo c'è linea o angolo molto piccolo posso allungarla
|
||||
if ( ( pCrv2->GetType() == CRV_LINE) || bAngSmall)
|
||||
pCrv2->ModifyStart( ptPc) ;
|
||||
// altrimenti, devo aggiungere una nuova linea
|
||||
|
||||
+2
-2
@@ -195,7 +195,7 @@ PointGrid3d::Find( const Point3d& ptTest, double dTol, INTVECTOR& vnIds) const
|
||||
}
|
||||
}
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -221,7 +221,7 @@ PointGrid3d::Find( const BBox3d& b3Test, INTVECTOR& vnIds) const
|
||||
}
|
||||
}
|
||||
|
||||
return ( vnIds.size() > 0) ;
|
||||
return ( ! vnIds.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+42
-31
@@ -14,36 +14,29 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "PointsPCA.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PointsPCA::PointsPCA( void)
|
||||
{
|
||||
// azzero numero punti
|
||||
m_dTotW = 0 ;
|
||||
// azzero il baricentro
|
||||
m_ptCen.Set( 0, 0, 0) ;
|
||||
// azzero matrice di covarianza
|
||||
m_CovMat.setZero() ;
|
||||
// inizializzo il rank ad un valore assurdo
|
||||
m_nRank = - 1 ;
|
||||
// inizializzo baricentro
|
||||
m_ptCen.Set( 0, 0, 0) ;
|
||||
// inizializzo il peso totale
|
||||
m_dTotW = 0 ;
|
||||
// riservo memoria per la matrice di punti e pesi
|
||||
m_vPntW.reserve( 128) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
PointsPCA::AddPoint( const Point3d& ptP, double dW)
|
||||
{
|
||||
// incremento numero punti
|
||||
m_dTotW += dW ;
|
||||
// aggiorno il baricentro
|
||||
m_ptCen += dW * ptP ;
|
||||
// aggiorno la matrice di covarianza (solo triangolo superiore perchč simmetrica)
|
||||
m_CovMat(0,0) += dW * ( ptP.x * ptP.x) ;
|
||||
m_CovMat(1,1) += dW * ( ptP.y * ptP.y) ;
|
||||
m_CovMat(2,2) += dW * ( ptP.z * ptP.z) ;
|
||||
m_CovMat(0,1) += dW * ( ptP.x * ptP.y) ;
|
||||
m_CovMat(0,2) += dW * ( ptP.x * ptP.z) ;
|
||||
m_CovMat(1,2) += dW * ( ptP.y * ptP.z) ;
|
||||
// salvo i dati
|
||||
m_vPntW.emplace_back( ptP, dW) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -58,29 +51,47 @@ PointsPCA::Finalize( void)
|
||||
m_nRank = 0 ;
|
||||
|
||||
// se non sono stati assegnati punti, esco
|
||||
if ( m_dTotW < EPS_ZERO)
|
||||
if ( m_vPntW.empty())
|
||||
return false ;
|
||||
|
||||
// fattore di scala per numero di punti
|
||||
// calcolo del peso totale
|
||||
for ( const auto& PntW : m_vPntW)
|
||||
m_dTotW += PntW.second ;
|
||||
if ( m_dTotW < EPS_ZERO)
|
||||
return false ;
|
||||
// fattore di scala
|
||||
double dScale = 1 / m_dTotW ;
|
||||
|
||||
// calcolo del baricentro
|
||||
for ( const auto& PntW : m_vPntW)
|
||||
m_ptCen += PntW.second * PntW.first ;
|
||||
m_ptCen *= dScale ;
|
||||
|
||||
// completo la matrice di covarianza
|
||||
m_CovMat(0,0) = m_CovMat(0,0) * dScale - m_ptCen.x * m_ptCen.x ;
|
||||
m_CovMat(1,1) = m_CovMat(1,1) * dScale - m_ptCen.y * m_ptCen.y ;
|
||||
m_CovMat(2,2) = m_CovMat(2,2) * dScale - m_ptCen.z * m_ptCen.z ;
|
||||
m_CovMat(0,1) = m_CovMat(0,1) * dScale - m_ptCen.x * m_ptCen.y ;
|
||||
m_CovMat(0,2) = m_CovMat(0,2) * dScale - m_ptCen.x * m_ptCen.z ;
|
||||
m_CovMat(1,2) = m_CovMat(1,2) * dScale - m_ptCen.y * m_ptCen.z ;
|
||||
m_CovMat(1,0) = m_CovMat(0,1) ;
|
||||
m_CovMat(2,0) = m_CovMat(0,2) ;
|
||||
m_CovMat(2,1) = m_CovMat(1,2) ;
|
||||
// matrice di covarianza
|
||||
Eigen::Matrix3d CovMat ;
|
||||
CovMat.setZero() ;
|
||||
for ( const auto& PntW : m_vPntW) {
|
||||
Point3d ptP( PntW.first.x - m_ptCen.x, PntW.first.y - m_ptCen.y, PntW.first.z - m_ptCen.z) ;
|
||||
CovMat(0,0) += PntW.second * ( ptP.x * ptP.x) ;
|
||||
CovMat(1,1) += PntW.second * ( ptP.y * ptP.y) ;
|
||||
CovMat(2,2) += PntW.second * ( ptP.z * ptP.z) ;
|
||||
CovMat(0,1) += PntW.second * ( ptP.x * ptP.y) ;
|
||||
CovMat(0,2) += PntW.second * ( ptP.x * ptP.z) ;
|
||||
CovMat(1,2) += PntW.second * ( ptP.y * ptP.z) ;
|
||||
}
|
||||
CovMat(0,0) = CovMat(0,0) * dScale ;
|
||||
CovMat(1,1) = CovMat(1,1) * dScale ;
|
||||
CovMat(2,2) = CovMat(2,2) * dScale ;
|
||||
CovMat(0,1) = CovMat(0,1) * dScale ;
|
||||
CovMat(0,2) = CovMat(0,2) * dScale ;
|
||||
CovMat(1,2) = CovMat(1,2) * dScale ;
|
||||
CovMat(1,0) = CovMat(0,1) ;
|
||||
CovMat(2,0) = CovMat(0,2) ;
|
||||
CovMat(2,1) = CovMat(1,2) ;
|
||||
|
||||
// calcolo gli autovalori e autovettori (essendo matrice 3x3 uso metodo diretto)
|
||||
// calcolo gli autovalori e autovettori
|
||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es ;
|
||||
es.compute( m_CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
|
||||
es.compute( CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
|
||||
if ( es.info() == Eigen::NoConvergence)
|
||||
return false ;
|
||||
|
||||
|
||||
+3
-4
@@ -13,8 +13,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class PointsPCA
|
||||
@@ -33,9 +32,9 @@ class PointsPCA
|
||||
static const int MAX_RANK = 3 ;
|
||||
|
||||
private :
|
||||
double m_dTotW ; // peso totale (se pesi tutti unitari, allora è numero punti)
|
||||
PNTUVECTOR m_vPntW ; // vettore dei punti con i loro pesi
|
||||
Point3d m_ptCen ; // baricentro
|
||||
Eigen::Matrix3d m_CovMat ; // matrice di covarianza
|
||||
double m_dTotW ; // peso totale
|
||||
int m_nRank ; // numero delle componenti principali (MAX_RANK = 3)
|
||||
Vector3d m_vtPC[MAX_RANK] ; // direzioni delle componenti principali
|
||||
} ;
|
||||
+3
-3
@@ -62,7 +62,7 @@ bool
|
||||
PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
|
||||
{
|
||||
// se il punto è uguale al precedente (ignoro parametro e bulge), non lo inserisco ma ok
|
||||
if ( m_lUPointBs.size() > 0 && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
|
||||
if ( ! m_lUPointBs.empty() && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
|
||||
// assegno parametro e bulge
|
||||
m_lUPointBs.back().dU = dPar ;
|
||||
m_lUPointBs.back().dB = dBulge ;
|
||||
@@ -285,10 +285,10 @@ bool
|
||||
PolyArc::Join( PolyArc& PA, double dOffsetPar)
|
||||
{
|
||||
// se l'altro poliarco non contiene alcunchè, esco con ok
|
||||
if ( PA.m_lUPointBs.size() == 0)
|
||||
if ( PA.m_lUPointBs.empty())
|
||||
return true ;
|
||||
// verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro
|
||||
if ( m_lUPointBs.size() > 0 && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
|
||||
if ( ! m_lUPointBs.empty() && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
|
||||
return false ;
|
||||
// cancello l'ultimo di questo
|
||||
EraseLastUPoint() ;
|
||||
|
||||
+404
-34
@@ -18,6 +18,8 @@
|
||||
#include "PolygonPlane.h"
|
||||
#include "PointsPCA.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
@@ -54,7 +56,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
||||
// se da aggiungere in coda
|
||||
if ( bEndOrStart) {
|
||||
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
|
||||
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
@@ -69,7 +71,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
||||
// altrimenti si aggiunge in testa
|
||||
else {
|
||||
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
|
||||
if ( ! m_lUPoints.empty() && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
}
|
||||
@@ -234,10 +236,10 @@ bool
|
||||
PolyLine::Join( PolyLine& PL, double dOffsetPar)
|
||||
{
|
||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||
if ( PL.m_lUPoints.size() == 0)
|
||||
if ( PL.m_lUPoints.empty())
|
||||
return true ;
|
||||
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
|
||||
if ( m_lUPoints.size() > 0 && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
|
||||
if ( ! m_lUPoints.empty() && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
|
||||
return false ;
|
||||
// cancello l'ultimo di questa
|
||||
EraseLastUPoint() ;
|
||||
@@ -587,18 +589,29 @@ PolyLine::IsClosedAndFlat( Plane3d& plPlane, double& dArea, double dToler) const
|
||||
// Test if closed
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
// Compute a representative plane for the polygon
|
||||
Point3d ptP ;
|
||||
// Calcolo il centro (per minimizzare gli errori nelle successive operazioni)
|
||||
Point3d ptCen = ORIG ;
|
||||
int nCount = 0 ;
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
|
||||
ptCen += ptP ;
|
||||
++ nCount ;
|
||||
}
|
||||
ptCen /= nCount ;
|
||||
Vector3d vtMove = ptCen - ORIG ;
|
||||
// Compute a representative plane for the polygon (faccio il calcolo nel centro e poi traslo al contrario il piano)
|
||||
PolygonPlane PolyPlane ;
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP))
|
||||
PolyPlane.AddPoint( ptP) ;
|
||||
PolyPlane.AddPoint( ptP - vtMove) ;
|
||||
if ( ! PolyPlane.GetPlane( plPlane) || ! PolyPlane.GetArea( dArea)) {
|
||||
dArea = 0 ;
|
||||
return IsFlat( plPlane, dToler) ;
|
||||
}
|
||||
plPlane.Translate( vtMove) ;
|
||||
// Sistemo il piano per l'offset utilizzato
|
||||
// Test each vertex to see if it is farther from plane than allowed max distance
|
||||
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
|
||||
double dDist = ( ( ptP - ORIG) * plPlane.GetVersN()) - plPlane.GetDist() ;
|
||||
double dDist = DistPointPlane( ptP, plPlane) ;
|
||||
if ( abs( dDist) > dToler)
|
||||
return false ;
|
||||
}
|
||||
@@ -762,7 +775,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::RemoveAlignedPoints( double dToler)
|
||||
PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd)
|
||||
{
|
||||
// se non ci sono almeno 3 punti, esco subito
|
||||
if ( m_lUPoints.size() < 3)
|
||||
@@ -785,7 +798,7 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
vInd.push_back( 0) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
vInd.push_back( int( vPtU.size()) - 1) ;
|
||||
}
|
||||
// altrimenti chiusa
|
||||
else {
|
||||
@@ -806,15 +819,15 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
vInd.push_back( nMaxInd) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
vInd.push_back( int( vPtU.size()) - 1) ;
|
||||
}
|
||||
|
||||
// ordino in senso crescente
|
||||
sort( vInd.begin(), vInd.end()) ;
|
||||
|
||||
// se chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
|
||||
if ( IsClosed() && vInd.size() >= 4) {
|
||||
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[vInd.size()-2]].first).IsEpsilon( dToler)) {
|
||||
// se richiesto e chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
|
||||
if ( bStartEnd && IsClosed() && vInd.size() >= 4) {
|
||||
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[int(vInd.size())-2]].first).IsEpsilon( dToler)) {
|
||||
vInd.erase( vInd.begin()) ;
|
||||
vInd.back() = vInd.front() ;
|
||||
}
|
||||
@@ -1074,15 +1087,8 @@ PolyLine::Invert( bool bInvertU)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::Flatten( double dZ)
|
||||
PolyLine::MyRemoveSamePoints( double dToler)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// ciclo su tutti gli elementi per portarli alla Z indicata
|
||||
for ( auto& UPoint : m_lUPoints) {
|
||||
UPoint.first.z = dZ ;
|
||||
}
|
||||
// elimino i punti consecutivi diventati coincidenti (almeno 2)
|
||||
if ( m_lUPoints.size() < 2)
|
||||
return true ;
|
||||
@@ -1093,7 +1099,7 @@ PolyLine::Flatten( double dZ)
|
||||
// mentre esiste un corrente
|
||||
while ( currP != m_lUPoints.end()) {
|
||||
// se coincidono
|
||||
if ( AreSamePointApprox( precP->first, currP->first)) {
|
||||
if ( AreSamePointEpsilon( precP->first, currP->first, dToler)) {
|
||||
// elimino il punto corrente
|
||||
currP = m_lUPoints.erase( currP) ;
|
||||
// il precedente rimane inalterato
|
||||
@@ -1108,6 +1114,50 @@ PolyLine::Flatten( double dZ)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::Flatten( double dZ)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// ciclo su tutti gli elementi per portarli alla Z indicata
|
||||
for ( auto& UPoint : m_lUPoints)
|
||||
UPoint.first.z = dZ ;
|
||||
// elimino i punti consecutivi diventati coincidenti
|
||||
MyRemoveSamePoints() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::FlattenInAutoPlane( double dToler)
|
||||
{
|
||||
// verifico non sia vuota
|
||||
if ( m_lUPoints.empty())
|
||||
return true ;
|
||||
// recupero dati sulla planarità della polilinea
|
||||
int nRank ;
|
||||
Point3d ptCen ;
|
||||
Vector3d vtDir ;
|
||||
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
|
||||
// se non planare entro la tolleranza, esco
|
||||
if ( ! bFlat)
|
||||
return false ;
|
||||
// se punto o linea, non devo fare alcunché
|
||||
if ( nRank == 0 || nRank == 1)
|
||||
return true ;
|
||||
// assegno il piano medio
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptCen, vtDir) ;
|
||||
// proietto i punti su questo piano
|
||||
for ( auto& UPoint : m_lUPoints)
|
||||
UPoint.first = ProjectPointOnPlane( UPoint.first, plPlane) ;
|
||||
// elimino i punti consecutivi diventati coincidenti
|
||||
MyRemoveSamePoints() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
PolyLine::GetConvexHullXY( PNTVECTOR& vConvHull) const
|
||||
@@ -1278,7 +1328,7 @@ bool
|
||||
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
||||
{
|
||||
// se vuota non faccio alcunché
|
||||
if ( m_lUPoints.size() == 0)
|
||||
if ( m_lUPoints.empty())
|
||||
return false ;
|
||||
|
||||
// determino le intersezioni dei lati con il piano
|
||||
@@ -1397,7 +1447,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
}
|
||||
// Determino tangente di riferimento
|
||||
Vector3d vtTang ;
|
||||
// se minima distanza nell'estremo iniziale del segmento
|
||||
// se minima distanza nell'estremo iniziale del segmento
|
||||
if ( AreSamePointApprox( ptMinDist, prev( itMinDistEnd)->first)) {
|
||||
// direzione del segmento
|
||||
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
|
||||
@@ -1413,7 +1463,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
vtTang = vtPrevTg + vtCurrTg ;
|
||||
vtTang.Normalize() ;
|
||||
}
|
||||
// se altrimenti minima distanza nell'estremo finale del segmento
|
||||
// se altrimenti minima distanza nell'estremo finale del segmento
|
||||
else if ( AreSamePointApprox( ptMinDist, itMinDistEnd->first)) {
|
||||
// direzione del segmento
|
||||
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
|
||||
@@ -1429,7 +1479,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
vtTang = vtCurrTg + vtNextTg ;
|
||||
vtTang.Normalize() ;
|
||||
}
|
||||
// altrimenti minima distanza con l'interno
|
||||
// altrimenti minima distanza con l'interno
|
||||
else {
|
||||
vtTang = itMinDistEnd->first - prev( itMinDistEnd)->first ;
|
||||
}
|
||||
@@ -1481,6 +1531,10 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Se il punto inziale è già quello, non faccio nulla
|
||||
if ( AreSamePointEpsilon( LoopList.begin()->first, ptNewStart, dToler))
|
||||
return true ;
|
||||
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
auto itMinDistEnd = LoopList.end() ;
|
||||
@@ -1564,8 +1618,9 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
int nPnt2 = PL2.GetPointNbr() ;
|
||||
if ( nPnt1 == 0 || nPnt2 == 0)
|
||||
return false ;
|
||||
|
||||
bCommonInternalPoints = false ; // indica la presenza di punti interni in comune tra le due polylines
|
||||
|
||||
// indica la presenza di punti interni in comune tra le due polylines
|
||||
bCommonInternalPoints = false ;
|
||||
|
||||
vPnt1.reserve( PL1.GetPointNbr()) ;
|
||||
Point3d ptP1 ;
|
||||
@@ -1597,7 +1652,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
// distanza del punto dal segmento della polilinea
|
||||
DistPointLine PointLineDistCalc( vPnt1[i].first, vPnt2[j-1].first, vPnt2[j].first) ;
|
||||
double dPlDist ;
|
||||
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist) {
|
||||
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += j - 1 ;
|
||||
@@ -1609,7 +1664,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
nMinJ = nLastJ ;
|
||||
|
||||
// verifica se è un punto interno in comune con l'altra polyline
|
||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
vPnt1[i].second = nMinJ ;
|
||||
@@ -1628,8 +1683,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
// distanza del punto dal segmento della polilinea
|
||||
DistPointLine PointLineDistCalc( vPnt2[j].first, vPnt1[i-1].first, vPnt1[i].first) ;
|
||||
double dPlDist ;
|
||||
PointLineDistCalc.GetDist( dPlDist) ;
|
||||
if ( dPlDist < dDist) {
|
||||
if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) {
|
||||
dDist = dPlDist ;
|
||||
PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ;
|
||||
dMinDistPar += i - 1 ;
|
||||
@@ -1640,12 +1694,328 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
if ( nMinI < nLastI)
|
||||
nMinI = nLastI ;
|
||||
|
||||
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
if ( j < nTotP2 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
vPnt2[j].second = nMinI ;
|
||||
nLastI = nMinI ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType, PNTIVECTOR& vPnt1, PNTIVECTOR& vPnt2)
|
||||
{
|
||||
// prima trovo le associazioni senza aggiunte di punti
|
||||
Point3d ptP2 ;
|
||||
CurveComposite cc1, cc2 ;
|
||||
cc1.FromPolyLine( PL1) ;
|
||||
cc2.FromPolyLine( PL2) ;
|
||||
int nPnt1 = PL1.GetPointNbr() ;
|
||||
int nPnt2 = PL2.GetPointNbr() ;
|
||||
vector<POINTU> vMatch2 ;
|
||||
PL2.GetFirstPoint( ptP2) ;
|
||||
while ( PL2.GetNextPoint( ptP2, true)) {
|
||||
DistPointCurve dpc( ptP2, cc1, false) ;
|
||||
int nFlag = 0 ;
|
||||
double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
|
||||
Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
|
||||
vMatch2.emplace_back( ptJoint, dParam) ;
|
||||
}
|
||||
|
||||
int nAtStart2 = 0 ; // match ripetuti dalla curva U0 allo start della curva U1
|
||||
int nAtEnd2 = 0 ;
|
||||
Point3d ptP1 ; PL1.GetFirstPoint( ptP1) ;
|
||||
int c = 0 ;
|
||||
int nRep1 = 0 ; // match interni consecutivi uguali di punti della curva U0 con punti della curva U1
|
||||
int nRep2 = 0 ;
|
||||
double dLastParamMatch = 0 ;
|
||||
Point3d ptLastPointMatch = ptP1 ;
|
||||
BOOLVECTOR vbRep1( nPnt1) ;
|
||||
INTVECTOR vnAddedOrNextIsRep1 ; // 0 non Rep, 1 Rep, 2 Next is Rep ;
|
||||
DBLVECTOR vdSplit1 ;
|
||||
DBLVECTOR vdMatch1 ;
|
||||
fill( vbRep1.begin(), vbRep1.end(), false) ;
|
||||
while ( PL1.GetNextPoint( ptP1, true)) {
|
||||
// devo salvarmi se matcho più punti con lo start o l'end della curva totale
|
||||
DistPointCurve dpc( ptP1, cc2, false) ;
|
||||
int nFlag = 0 ;
|
||||
double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
|
||||
Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
|
||||
vdMatch1.push_back( dParam) ;
|
||||
if ( dParam < EPS_SMALL ) {
|
||||
++nAtStart2 ;
|
||||
vbRep1[c] = true ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else if ( dParam > nPnt2 - EPS_SMALL ) {
|
||||
vbRep1[c] = nAtEnd2 == 0 ? false : true ;
|
||||
vbRep1.back() = true ;
|
||||
++ nAtEnd2 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) {
|
||||
dParam = dLastParamMatch ;
|
||||
vbRep1[c] = true ;
|
||||
++ nRep1 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else {
|
||||
dLastParamMatch = dParam ;
|
||||
ptLastPointMatch = ptJoint ;
|
||||
// se sono già troppo vicino ad un split esistente allora non faccio nulla
|
||||
if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM) {
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
vdSplit1.push_back( dParam) ;
|
||||
// verifico se ho un match per questo punto
|
||||
// in tal caso vuol dire che sto creando una ripetizione nRep1
|
||||
int nCase = 0 ;
|
||||
for ( int j = 0 ; j < int( vMatch2.size()) ; ++j) {
|
||||
if ( abs(vMatch2[j].second - (c + 1)) < EPS_SMALL) {
|
||||
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
|
||||
bool bFoundMatch = false ;
|
||||
for ( int z = int( vMatch2[j].second) ; z < int( vdMatch1.size()) ; ++z) {
|
||||
if ( abs( vdMatch1[z] - ( j + 1 )) < EPS_SMALL ) {
|
||||
bFoundMatch = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bFoundMatch) {
|
||||
++ nRep2 ;
|
||||
// capisco se il punto è rep o se lo è il suo successivo
|
||||
if ( j + 1 < dParam)
|
||||
nCase = 1 ;
|
||||
else
|
||||
nCase = 2 ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
vnAddedOrNextIsRep1.push_back( nCase) ;
|
||||
}
|
||||
++c ;
|
||||
}
|
||||
int nAtStart1 = 0 ;
|
||||
int nAtEnd1 = 0 ;
|
||||
PL2.GetFirstPoint( ptP2) ;
|
||||
c = 0 ;
|
||||
dLastParamMatch = 0 ;
|
||||
ptLastPointMatch = ptP2 ;
|
||||
INTVECTOR vnAddedOrNextIsRep2 ; // 0 non Rep, 1 Rep, 2 Next is Rep ;
|
||||
DBLVECTOR vdSplit2 ;
|
||||
BOOLVECTOR vbRep2( nPnt2) ;
|
||||
fill( vbRep2.begin(), vbRep2.end(), false) ;
|
||||
while ( PL2.GetNextPoint( ptP2, true)) {
|
||||
DistPointCurve dpc( ptP2, cc1, false) ;
|
||||
int nFlag = 0 ;
|
||||
double dParam ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
|
||||
Point3d ptJoint ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
|
||||
if ( dParam < EPS_SMALL ) {
|
||||
++nAtStart1 ;
|
||||
vbRep2[c] = true ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else if ( dParam > nPnt1 - EPS_SMALL ) {
|
||||
vbRep2[c] = ( nAtEnd1 == 0 ? false : true) ;
|
||||
vbRep2.back() = true ;
|
||||
++ nAtEnd1 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) {
|
||||
dParam = dLastParamMatch ;
|
||||
vbRep2[c] = true ;
|
||||
++ nRep2 ;
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
else {
|
||||
dLastParamMatch = dParam ;
|
||||
ptLastPointMatch = ptJoint ;
|
||||
// se sono troppo vicino ad uno split esistente allora non faccio nulla
|
||||
if ( abs( dParam - round( dParam)) < 100 * EPS_PARAM) {
|
||||
++c ;
|
||||
continue ;
|
||||
}
|
||||
vdSplit2.push_back( dParam) ;
|
||||
// verifico se ho un match per questo punto
|
||||
// in tal caso vuol dire che sto creando una ripetizione nRep0
|
||||
int nCase = 0 ;
|
||||
for ( int j = 0 ; j < int( vdMatch1.size()) ; ++j) {
|
||||
if ( abs( vdMatch1[j] - (c + 1)) < EPS_SMALL) {
|
||||
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
|
||||
bool bFoundMatch = false ;
|
||||
for ( int z = int( vdMatch1[j]) ; z < int( vMatch2.size()) ; ++z) {
|
||||
if ( abs( vMatch2[z].second - ( j + 1 )) < EPS_SMALL) {
|
||||
bFoundMatch = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bFoundMatch) {
|
||||
++nRep1 ;
|
||||
// capisco se il punto è rep o se lo è il suo successivo
|
||||
if ( j + 1 < dParam)
|
||||
nCase = 1 ;
|
||||
else
|
||||
nCase = 2 ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
vnAddedOrNextIsRep2.push_back( nCase) ;
|
||||
}
|
||||
++c ;
|
||||
}
|
||||
|
||||
// applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep
|
||||
int nUnit = 0 ;
|
||||
if ( ! vdSplit1.empty())
|
||||
nUnit = int( vdSplit1.back()) ;
|
||||
for ( int z = int( vdSplit1.size()) - 1 ; z >= 0 ; --z) {
|
||||
double dSplit = vdSplit1[z] ;
|
||||
int nSplit = int( dSplit) ;
|
||||
// se sto cercando di fare uno split sulla stessa curva che ho già splittato al passaggio precedente allora devo
|
||||
// riscalare
|
||||
if ( nSplit == nUnit && z < int( vdSplit1.size()) - 1) {
|
||||
dSplit = nSplit + ( dSplit - nSplit) / ( vdSplit1[z+1] - nSplit) ;
|
||||
}
|
||||
nUnit = nSplit ;
|
||||
cc2.AddJoint( dSplit) ;
|
||||
switch ( vnAddedOrNextIsRep1[z]) {
|
||||
case 0 :
|
||||
if ( vbRep2[nSplit])
|
||||
++ nRep2 ;
|
||||
// di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo
|
||||
vbRep2.insert( vbRep2.begin() + nSplit, vbRep2[nSplit]) ;
|
||||
break ;
|
||||
case 1 :
|
||||
vbRep2.insert( vbRep2.begin() + nSplit, true) ;
|
||||
break ;
|
||||
case 2 :
|
||||
if ( vbRep2[nSplit])
|
||||
--nRep2 ;
|
||||
else
|
||||
vbRep2[nSplit] = true ;
|
||||
vbRep2.insert( vbRep2.begin() + nSplit, false) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( ! vdSplit2.empty())
|
||||
nUnit = int( vdSplit2.back()) ;
|
||||
for ( int z = int( vdSplit2.size()) - 1 ; z >= 0 ; --z) {
|
||||
double dSplit = vdSplit2[z] ;
|
||||
int nSplit = int( dSplit) ;
|
||||
// se sto cercando di fare uno split sulla stessa curva che ho già splittato al passaggio precedente allora devo
|
||||
// riscalare
|
||||
if ( nSplit == nUnit && z < int( vdSplit2.size()) - 1) {
|
||||
dSplit = nSplit + ( dSplit - nSplit) / (vdSplit2[z+1] - nSplit) ;
|
||||
}
|
||||
nUnit = nSplit ;
|
||||
cc1.AddJoint( dSplit) ;
|
||||
switch ( vnAddedOrNextIsRep2[z]) {
|
||||
case 0 :
|
||||
if ( vbRep1[nSplit])
|
||||
++ nRep1 ;
|
||||
// di default aggiungerei false, ma se il successivo è già un Rep allora anche questo deve esserlo
|
||||
vbRep1.insert( vbRep1.begin() + nSplit, vbRep1[nSplit]) ;
|
||||
break ;
|
||||
case 1 :
|
||||
vbRep1.insert( vbRep1.begin() + nSplit, true) ;
|
||||
break ;
|
||||
case 2 :
|
||||
if ( vbRep1[nSplit])
|
||||
-- nRep1 ;
|
||||
else
|
||||
vbRep1[nSplit] = true ;
|
||||
vbRep1.insert( vbRep1.begin() + nSplit, false) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
nPnt1 = cc1.GetCurveCount() ;
|
||||
nPnt2 = cc2.GetCurveCount() ;
|
||||
//aggiusto i vettori delle ripetizioni in modo in modo che non arrivino mai ad essere contemporaneamente true
|
||||
int nAddedSpan = 0 ;
|
||||
int nCrv1 = 0 ;
|
||||
int nCrv2 = 0 ;
|
||||
while ( nAddedSpan < nPnt1 + nAtStart1 + nAtEnd1 + nRep2) {
|
||||
if ( nCrv1 >= nPnt1)
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
if ( nCrv2 >= nPnt2)
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
bool bRep1 = vbRep1[nCrv1] ;
|
||||
bool bRep2 = vbRep2[nCrv2] ;
|
||||
if ( bRep1 && bRep2) {
|
||||
vbRep1[nCrv1] = false ;
|
||||
bRep1 = false ;
|
||||
vbRep2[nCrv2] = false ;
|
||||
bRep2 = false ;
|
||||
-- nRep1 ;
|
||||
-- nRep2 ;
|
||||
}
|
||||
if ( ! bRep1 || nCrv2 == nPnt2 - 1)
|
||||
++ nCrv2 ;
|
||||
if ( ! bRep2 || nCrv1 == nPnt1 - 1)
|
||||
++ nCrv1 ;
|
||||
++ nAddedSpan ;
|
||||
}
|
||||
// se non sono arrivato all'ultima curva su U0 o U1 vuol dire che ho creato delle ripetizioni che non ho contato prima
|
||||
if ( nCrv2 < nPnt2) {
|
||||
nRep2 += nPnt2 - nCrv2 ;
|
||||
for ( int z = int( vbRep2.size()) - 1 ; z >= nCrv2 ; --z)
|
||||
vbRep2[z] = true ;
|
||||
}
|
||||
if ( nCrv1 < nPnt1) {
|
||||
nRep1 += nPnt1 - nCrv1 ;
|
||||
for ( int z = int( vbRep1.size()) - 1 ; z >= nCrv1 ; --z)
|
||||
vbRep1[z] = true ;
|
||||
}
|
||||
|
||||
// trovo il numero di span che dovrà avere la superficie
|
||||
// ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0)
|
||||
int nPnt = nPnt1 + nAtStart1 + nAtEnd1 + nRep2 ;
|
||||
|
||||
if ( nPnt != nPnt2 + nAtStart2 + nAtEnd2 + nRep1)
|
||||
LOG_DBG_ERR( GetEGkLogger(), "There could be an error in the creation of a ruled surface in mode RLT_B_MINDIST_PLUS") ;
|
||||
|
||||
// aggiungo i punti di controllo scorrendo in contemporanea le due curve
|
||||
nAddedSpan = 0 ;
|
||||
nCrv1 = 0 ;
|
||||
nCrv2 = 0 ;
|
||||
bool bLast1 = false ;
|
||||
bool bLast2 = false ;
|
||||
while ( nAddedSpan < nPnt) {
|
||||
if ( nCrv1 >= nPnt1) {
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
bLast1 = true ;
|
||||
}
|
||||
if ( nCrv2 >= nPnt2) {
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
bLast2 = true ;
|
||||
}
|
||||
bool bRep1 = vbRep1[nCrv1] ;
|
||||
bool bRep2 = vbRep2[nCrv2] ;
|
||||
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
|
||||
Point3d ptStart1 ; pSubCrv1->GetStartPoint( ptStart1) ;
|
||||
vPnt1.emplace_back( ptStart1, nAddedSpan) ;
|
||||
const ICurve* pSubCrv2 = cc2.GetCurve( nCrv2) ;
|
||||
Point3d ptStart2 ; pSubCrv2->GetStartPoint( ptStart2) ;
|
||||
vPnt2.emplace_back( ptStart2, nAddedSpan) ;
|
||||
if ( ! bRep2)
|
||||
++ nCrv1 ;
|
||||
if ( ! bRep1)
|
||||
++ nCrv2 ;
|
||||
++ nAddedSpan ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-16
@@ -150,12 +150,18 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
Vector3d vtN = pgFacet.GetVersN() ;
|
||||
PolyLine PL = pgFacet.GetPolyLine() ;
|
||||
|
||||
// calcolo elevazione massima del contorno della faccia
|
||||
// calcolo elevazione massima del contorno della faccia e nel suo centro
|
||||
const double RAY_LEN = 100000 ;
|
||||
dElev = 0 ;
|
||||
PNTVECTOR vptP ; vptP.reserve( PL.GetPointNbr()) ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstPoint( ptP) ;
|
||||
while ( bFound) {
|
||||
vptP.push_back( ptP) ;
|
||||
bFound = PL.GetNextPoint( ptP, true) ;
|
||||
}
|
||||
vptP.push_back( ptCen) ;
|
||||
for ( const Point3d& ptP : vptP) {
|
||||
ILSIVECTOR vInters ;
|
||||
IntersLineSurfTm( ptP, vtN, RAY_LEN, CldStm, vInters, true) ;
|
||||
for ( int i = 0 ; i < int( vInters.size()) ; ++ i) {
|
||||
@@ -166,12 +172,11 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
|
||||
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
|
||||
dElev = max( dElev, Inters.dU) ;
|
||||
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
dElev = max( dElev, Inters.dU2) ;
|
||||
}
|
||||
bFound = PL.GetNextPoint( ptP, true) ;
|
||||
}
|
||||
// calcolo elevazione massima degli eventuali spigoli (e vertici) della superficie chiusa dalla parte positiva della faccia e che cadono in essa
|
||||
int nEdgeCnt = CldStm.GetEdgeCount() ;
|
||||
@@ -201,22 +206,30 @@ PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& Cl
|
||||
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
|
||||
continue ;
|
||||
// calcolo il segmento di linea
|
||||
CurveLine clLine ;
|
||||
CurveLine clLine ;
|
||||
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
|
||||
return false ;
|
||||
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
|
||||
IntersCurveCurve intLL( clLine, ccLoop) ;
|
||||
IntCrvCrvInfo aInfo ;
|
||||
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
||||
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
||||
if ( aInfo.bOverlap)
|
||||
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
|
||||
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
|
||||
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].first.z) ;
|
||||
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
|
||||
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].second.z) ;
|
||||
if ( intLL.GetIntersCount() == 0) {
|
||||
Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ;
|
||||
ptM.z = 0 ;
|
||||
if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL))
|
||||
dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.z)) ;
|
||||
}
|
||||
else {
|
||||
IntCrvCrvInfo aInfo ;
|
||||
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
||||
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
||||
if ( aInfo.bOverlap)
|
||||
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
|
||||
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
|
||||
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].first.z) ;
|
||||
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
|
||||
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
|
||||
dElev = max( dElev, vEdges[i].second.z) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -19,10 +19,10 @@
|
||||
void
|
||||
PolygonPlane::AddPoint( const Point3d& ptP)
|
||||
{
|
||||
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
|
||||
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
|
||||
if ( m_nPntNbr == -1) {
|
||||
// inizializzazioni
|
||||
m_dLenN = 0 ;
|
||||
m_dLenN = -1 ;
|
||||
m_vtN = V_NULL ;
|
||||
m_ptMid = ORIG ;
|
||||
m_dSXy = 0 ; m_dSXz = 0 ;
|
||||
@@ -60,16 +60,16 @@ PolygonPlane::AddPoint( const Point3d& ptP)
|
||||
bool
|
||||
PolygonPlane::Finalize( void)
|
||||
{
|
||||
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
|
||||
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
|
||||
if ( m_nPntNbr + 1 < 3)
|
||||
return false ;
|
||||
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
|
||||
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
|
||||
if ( ! AreSamePointExact( m_ptFirst, m_ptLast)) {
|
||||
// aggiungo il primo punto per far eseguire i conti sul lato di chiusura
|
||||
AddPoint( m_ptFirst) ;
|
||||
}
|
||||
// se non effettuato, eseguo il calcolo finale
|
||||
if ( m_dLenN < EPS_SMALL) {
|
||||
if ( m_dLenN < 0) {
|
||||
// lunghezza della normale (doppio dell'area del poligono)
|
||||
m_dLenN = m_vtN.Len() ;
|
||||
if ( m_dLenN < SQ_EPS_SMALL)
|
||||
|
||||
@@ -0,0 +1,953 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2023-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ProjectCurveSurfTm.cpp Data : 03.01.26 Versione : 3.1a1
|
||||
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 31.08.23 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurf.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
|
||||
const double COS_ANG_LIM = 0.0175 ;
|
||||
// Angolo massimo tra normali per effettuare bisezione su spigolo
|
||||
const double COS_ANG_MAX_CORNER = 0.8660 ;
|
||||
// Tipologia di punto
|
||||
const int P5AX_TO_DELETE = -1 ; // da cancellare
|
||||
const int P5AX_OUT = 0 ; // aggiunto prima di inizio o dopo fine
|
||||
const int P5AX_STD = 1 ; // standard
|
||||
const int P5AX_CVEX = 2 ; // su angolo convesso
|
||||
const int P5AX_CONC = 3 ; // in angolo concavo
|
||||
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
|
||||
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static double
|
||||
GetSurfBezierTol( double dLinTol)
|
||||
{
|
||||
return max( dLinTol / 10, EPS_SMALL) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
|
||||
{
|
||||
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
|
||||
double dSqDist ;
|
||||
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
|
||||
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
|
||||
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
|
||||
// intersezione tra le due facce
|
||||
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
|
||||
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
|
||||
Point3d ptEdge ; Vector3d vtEdge ;
|
||||
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
|
||||
Plane3d plPlane3 ; plPlane3.Set(vPt5ax[i].ptP, (vPt5ax[i].ptP - vPt5ax[j].ptP) ^ ( vPt5ax[i].vtDir1 + vPt5ax[j].vtDir1)) ;
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
else
|
||||
vPt5ax[j].nFlag = P5AX_CVEX ;
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CVEX ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
else
|
||||
vPt5ax[i].nFlag = P5AX_CVEX ;
|
||||
}
|
||||
// altrimenti concavo, aggiungo un solo punto con la direzione media
|
||||
else {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ;
|
||||
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ;
|
||||
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
|
||||
Pt5ax.nFlag = P5AX_CONC ;
|
||||
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
|
||||
++ i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir)
|
||||
{
|
||||
// Parametri di riferimento
|
||||
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
|
||||
double dSqTol = dLinTol * dLinTol ;
|
||||
const double LENREF = 200 ;
|
||||
double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ;
|
||||
// Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo
|
||||
int nInd = 0 ;
|
||||
while ( nInd < ssize( vPt5ax)) {
|
||||
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
|
||||
// analizzo i punti appena precedenti
|
||||
int nIpv = nInd - 1 ;
|
||||
while ( nIpv >= 0) {
|
||||
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nIpv].ptP) ;
|
||||
if ( dSqLen < dSqMaxLen)
|
||||
vPt5ax[nIpv].nFlag = P5AX_TO_DELETE ;
|
||||
else {
|
||||
vPt5ax[nIpv].nFlag = P5AX_BEFORE_CONC ;
|
||||
break ;
|
||||
}
|
||||
-- nIpv ;
|
||||
}
|
||||
// analizzo i punti appena successivi
|
||||
int nInx = nInd + 1 ;
|
||||
while ( nInx < ssize( vPt5ax)) {
|
||||
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
|
||||
if ( dSqLen < dSqMaxLen)
|
||||
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
|
||||
else {
|
||||
vPt5ax[nInx].nFlag = P5AX_AFTER_CONC ;
|
||||
break ;
|
||||
}
|
||||
++ nInx ;
|
||||
}
|
||||
}
|
||||
++ nInd ;
|
||||
}
|
||||
// Rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
int nCnt = 0 ;
|
||||
int nPrec = 0 ;
|
||||
int nCurr = 1 ;
|
||||
int nNext = 2 ;
|
||||
while ( nNext < ssize( vPt5ax)) {
|
||||
bool bRemove = false ;
|
||||
// lunghezza del segmento che unisce gli adiacenti
|
||||
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
|
||||
// se rimovibile (Flag standard) e lunghezza inferiore al massimo, passo agli altri controlli
|
||||
if ( vPt5ax[nCurr].nFlag == P5AX_STD && dSqLen <= dSqMaxLen) {
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( vPt5ax[nCurr].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
|
||||
double dSqDist ;
|
||||
// se distanza inferiore a tolleranza lineare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vPt5ax, nPrec, nCurr, nNext, dSqTol)) {
|
||||
// verifico se errore angolare inferiore a limite
|
||||
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
|
||||
if ( bTestDir) {
|
||||
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir1, vPt5ax[nNext].vtDir1, dPar) ;
|
||||
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir1 > dCosAngLim)
|
||||
bRemove = true ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir2, vPt5ax[nNext].vtDir2, dPar) ;
|
||||
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir2 > dCosAngLim)
|
||||
bRemove = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se da eliminare
|
||||
if ( bRemove) {
|
||||
// dichiaro da eliminare il punto
|
||||
vPt5ax[nCurr].nFlag = P5AX_TO_DELETE ;
|
||||
// avanzo con corrente e successivo
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// avanzo il terzetto di uno step
|
||||
nPrec = nCurr ;
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
// incremento contatore dei punti conservati
|
||||
++ nCnt ;
|
||||
}
|
||||
}
|
||||
|
||||
// Copio i punti da conservare in un vettore temporaneo
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( nCnt) ;
|
||||
for ( const auto& Pt5ax : vPt5ax) {
|
||||
if ( Pt5ax.nFlag != P5AX_TO_DELETE)
|
||||
vMyPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
// scambio i due vettori
|
||||
vPt5ax.swap( vMyPt5ax) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulle supefici a minima distanza
|
||||
int nSurfMin = -1 ;
|
||||
int nTriaMin ;
|
||||
Point3d ptMin ;
|
||||
double dMinDist ;
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
// punto sulla superficie a minima distanza
|
||||
DistPointSurfTm dPS( ptP, *vpStm[i]) ;
|
||||
double dDist ;
|
||||
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
|
||||
nSurfMin = i ;
|
||||
dPS.GetMinDistPoint( ptMin) ;
|
||||
dPS.GetMinDistTriaIndex ( nTriaMin) ;
|
||||
dMinDist = dDist ;
|
||||
}
|
||||
}
|
||||
|
||||
// se trovato
|
||||
if ( nSurfMin >= 0) {
|
||||
// assegno il punto
|
||||
Point3d ptInt = ptMin ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptMin, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtN ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// --- vettore di oggetti intersezione massiva rette parallele SurfTM --------
|
||||
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
|
||||
double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptInt, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = frRefLine.VersZ() ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Oggetti per calcolo massivo intersezioni tra linee di proiezione e superfici
|
||||
Frame3d frRefLine ;
|
||||
if ( ! frRefLine.Set( ORIG, vtDir))
|
||||
return false ;
|
||||
INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
|
||||
for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) {
|
||||
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
|
||||
if ( pIntPLSTM == nullptr) {
|
||||
for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j)
|
||||
delete vpIntPLSTM[j] ;
|
||||
return false ;
|
||||
}
|
||||
vpIntPLSTM.emplace_back( pIntPLSTM) ;
|
||||
}
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// Libero oggetti per calcolo massivo
|
||||
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i)
|
||||
delete vpIntPLSTM[i] ;
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto di riferimento
|
||||
Point3d ptMin = gpRef.GetPoint() ;
|
||||
// intersezione della retta di minima distanza con le superfici
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
// conservo l'intersezione più alta
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptInt, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto a minima distanza
|
||||
DistPointCurve dPC( ptP, crRef) ;
|
||||
Point3d ptMin ;
|
||||
int nFlag ;
|
||||
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
|
||||
// intersezione della retta di minima distanza con le superfici
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
// conservo l'intersezione più alta
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// assegno il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptInt, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// Sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// Controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// Approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulla superficie guida a minima distanza
|
||||
DistPointSurfTm dPS( ptP, stmRef) ;
|
||||
Point3d ptMin ;
|
||||
int nTriaMin ;
|
||||
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
|
||||
// recupero direzione della retta di minima distanza, altrimenti normale alla superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL)
|
||||
vtLine /= dLineLen ;
|
||||
else {
|
||||
// calcolo la normale della superficie guida
|
||||
Triangle3dEx trGuide ;
|
||||
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
|
||||
return false ;
|
||||
if ( ! CalcNormal( ptMin, trGuide, vtLine))
|
||||
vtLine = trGuide.GetN() ;
|
||||
dLineLen = 100 ;
|
||||
}
|
||||
// intersezione della retta con le superfici (conservo l'intersezione più alta)
|
||||
int nInd = -1 ;
|
||||
IntLinStmInfo IntRes ;
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se trovata
|
||||
if ( nInd >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = IntRes.ptI2 ;
|
||||
else
|
||||
ptInt = IntRes.ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcNormal( ptMin, trTria, vtN))
|
||||
vtN = trTria.GetN() ;
|
||||
// calcolo la normale della superficie guida
|
||||
Triangle3dEx trGuide ;
|
||||
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
|
||||
return false ;
|
||||
Vector3d vtN2 ;
|
||||
if ( ! CalcNormal( ptMin, trGuide, vtN2))
|
||||
vtN2 = trGuide.GetN() ;
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtN2 ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
Pt5ax.nFlag = P5AX_STD ;
|
||||
// ritorno con successo
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
|
||||
const SurfTriMesh* pSurfTm = nullptr ;
|
||||
switch ( vpSurf[i]->GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pSurfTm == nullptr)
|
||||
return false ;
|
||||
vpSurfTm.emplace_back( pSurfTm) ;
|
||||
}
|
||||
|
||||
// sistemazioni per tipo di superficie di riferimento
|
||||
const SurfTriMesh* pRefTm = nullptr ;
|
||||
switch ( sfRef.GetType()) {
|
||||
case SRF_TRIMESH :
|
||||
pRefTm = GetBasicSurfTriMesh( &sfRef) ;
|
||||
break ;
|
||||
case SRF_BEZIER :
|
||||
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
|
||||
pRefTm = GetBasicSurfBezier( &sfRef)->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
|
||||
} break ;
|
||||
case SRF_FLATRGN :
|
||||
pRefTm = GetBasicSurfFlatRegion( &sfRef)->GetAuxSurf() ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
if ( pRefTm == nullptr)
|
||||
return false ;
|
||||
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.RemoveAlignedPoints( dLinTol, false) )
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Pulisco e riservo spazio nel vettore dei punti risultanti
|
||||
vPt5ax.clear() ;
|
||||
vPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1,414 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2023-2023
|
||||
//----------------------------------------------------------------------------
|
||||
// File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3
|
||||
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 31.08.23 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
|
||||
const double COS_ANG_LIM = 0.0175 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
|
||||
{
|
||||
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
|
||||
double dSqDist ;
|
||||
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, double dLinTol, double dMaxSegmLen)
|
||||
{
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
|
||||
double dSqTol = dLinTol * dLinTol ;
|
||||
int nPrec = 0 ;
|
||||
int nCurr = 1 ;
|
||||
int nNext = 2 ;
|
||||
while ( nNext < int( vMyPt5ax.size())) {
|
||||
bool bRemove = false ;
|
||||
// lunghezza del segmento che unisce gli adiacenti
|
||||
double dSqLen = SqDist( vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
|
||||
// se lunghezza inferiore al massimo, passo agli altri controlli
|
||||
if ( dSqLen <= dSqMaxLen) {
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( vMyPt5ax[nCurr].ptP, vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
|
||||
double dSqDist ;
|
||||
// se distanza inferiore a tolleranza lineare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vMyPt5ax, nPrec, nCurr, nNext, dSqTol)) {
|
||||
// verifico se errore angolare inferiore a limite
|
||||
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
|
||||
Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ;
|
||||
if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > cos( 2 * DEGTORAD))
|
||||
bRemove = true ;
|
||||
}
|
||||
}
|
||||
// se da eliminare
|
||||
if ( bRemove) {
|
||||
// dichiaro da eliminare il punto
|
||||
vMyPt5ax[nCurr].nFlag = -1 ;
|
||||
// avanzo con corrente e successivo
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// avanzo il terzetto di uno step
|
||||
nPrec = nCurr ;
|
||||
nCurr = nNext ;
|
||||
++ nNext ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
|
||||
PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
// approssimo la curva con una polilinea alla massima risoluzione
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
|
||||
Frame3d frRefLine ;
|
||||
if ( ! frRefLine.Set( ORIG, vtDir))
|
||||
return false ;
|
||||
IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// intersezione retta di proiezione con superficie
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, dPar, 1) ;
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// punto di riferimento
|
||||
Point3d ptMin = gpRef.GetPoint() ;
|
||||
// intersezione della retta di minima distanza con la superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea alla massima risoluzione
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// punto sulla curva a minima distanza
|
||||
DistPointCurve dPC( ptP, crRef) ;
|
||||
Point3d ptMin ;
|
||||
int nFlag ;
|
||||
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
|
||||
// intersezione della retta di minima distanza con la superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ISurfTriMesh& tmRef,
|
||||
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// controllo le tolleranze
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
|
||||
|
||||
// approssimo la curva con una polilinea entro la metà della tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
|
||||
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
|
||||
return false ;
|
||||
|
||||
// Vettore locale dei punti risultanti
|
||||
PNT5AXVECTOR vMyPt5ax ;
|
||||
vMyPt5ax.reserve( PL.GetPointNbr()) ;
|
||||
|
||||
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
|
||||
double dPar ;
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
|
||||
while ( bFound) {
|
||||
// punto sulla superficie guida a minima distanza
|
||||
DistPointSurfTm dPS( ptP, tmRef) ;
|
||||
Point3d ptMin ;
|
||||
int nTriaMin ;
|
||||
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
|
||||
// intersezione della retta di minima distanza con la superficie
|
||||
Vector3d vtLine = ptP - ptMin ;
|
||||
double dLineLen = vtLine.Len() ;
|
||||
if ( dLineLen > EPS_SMALL) {
|
||||
vtLine /= dLineLen ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
Point3d ptInt ;
|
||||
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
|
||||
ptInt = vIntRes[nI].ptI2 ;
|
||||
else
|
||||
ptInt = vIntRes[nI].ptI ;
|
||||
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
|
||||
Triangle3dEx trTria ;
|
||||
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
|
||||
return false ;
|
||||
Vector3d vtN ;
|
||||
double dU, dV, dW ;
|
||||
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
|
||||
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
|
||||
if ( ! vtN.Normalize())
|
||||
vtN = trTria.GetN() ;
|
||||
// calcolo la normale della superficie guida
|
||||
Triangle3dEx trGuide ;
|
||||
if ( ! tmRef.GetTriangle( nTriaMin, trGuide))
|
||||
return false ;
|
||||
Vector3d vtN2 ;
|
||||
double dU2, dV2, dW2 ;
|
||||
if ( BarycentricCoord( ptMin, trGuide, dU2, dV2, dW2))
|
||||
vtN2 = dU2 * trGuide.GetVertexNorm( 0) + dV2 * trGuide.GetVertexNorm( 1) + dW2 * trGuide.GetVertexNorm( 2) ;
|
||||
if ( ! vtN2.Normalize())
|
||||
vtN2 = trGuide.GetN() ;
|
||||
// aggiungo al vettore dei proiettati
|
||||
vMyPt5ax.emplace_back( ptInt, vtN, vtN2, dPar, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
}
|
||||
|
||||
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
|
||||
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
|
||||
|
||||
// copio i punti rimasti nel vettore di ritorno
|
||||
vPt5ax.clear() ;
|
||||
for ( const auto& Pt5ax : vMyPt5ax) {
|
||||
if ( Pt5ax.nFlag != -1)
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -0,0 +1,808 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 20024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SbzFromCurves.cpp Data : 07.05.24 Versione : 2.6e2
|
||||
// Contenuto : Implementazione di funzioni per creazione di superfici Sbz
|
||||
// a partire da curve, con diversi metodi.
|
||||
//
|
||||
//
|
||||
// Modifiche : 07.05.24 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
|
||||
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkSbzFromCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <future>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByFlatContour( const ICurve* pCurve, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr)
|
||||
return nullptr ;
|
||||
// calcolo la polilinea che approssima la curva
|
||||
PolyLine PL ;
|
||||
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return nullptr ;
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( &vpCurve == nullptr || vpCurve.empty())
|
||||
return nullptr ;
|
||||
// calcolo le polilinee che approssimano le curve della regione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return nullptr ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat,vbInvert))
|
||||
return nullptr ;
|
||||
POLYLINEVECTOR vPLOrd ;
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
||||
vPLOrd.push_back(vPL[vnPLIndMat[i][j]]) ;
|
||||
if ( vbInvert[vnPLIndMat[i][j]])
|
||||
vPLOrd.back().Invert() ;
|
||||
}
|
||||
}
|
||||
// creo e setto la superficie di bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByRegion( vPLOrd))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
|
||||
bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &vtExtr == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
PtrOwner<const ICurve> pBezierForm( CurveToBezierCurve( pCurve)) ;
|
||||
// creo e setto la superficie di Bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfCompo*
|
||||
//GetSurfBezierByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) ///// RICHIEDE LE SURF COMPO/////////////////
|
||||
//{
|
||||
// // verifica parametri
|
||||
// if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr)
|
||||
// return nullptr ;
|
||||
// // se una sola curva, uso la funzione precedente
|
||||
// if ( vpCurve.size() == 1 )
|
||||
// return GetSurfBezierByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
|
||||
// // calcolo le polilinee che approssimano le curve della regione
|
||||
// POLYLINEVECTOR vPL ;
|
||||
// Vector3d vtN ;
|
||||
// if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
|
||||
// return nullptr ;
|
||||
// // verifico la direzione di estrusione
|
||||
// double dOrthoExtr = vtN * vtExtr ;
|
||||
// if ( ( abs( dOrthoExtr) < EPS_SMALL))
|
||||
// return nullptr ;
|
||||
// // se componente estrusione negativa, inverto tutti i percorsi
|
||||
// if ( dOrthoExtr < 0) {
|
||||
// for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
|
||||
// vPL[i].Invert() ;
|
||||
// }
|
||||
// // creo la prima superficie di estremità
|
||||
// PtrOwner<SurfBezier> pSbz1( CreateBasicSurfBezier()) ;
|
||||
// if ( IsNull( pSbz1) || ! pSbz1->CreateByRegion( vPL))
|
||||
// return nullptr ;
|
||||
// // creo la seconda superficie come copia della prima e poi inverto la prima
|
||||
// PtrOwner<ISurfBezier> pSbz2( pSbz1->Clone()) ;
|
||||
// pSbz1->Invert() ;
|
||||
//
|
||||
// // creo e unisco le diverse superfici di estrusione
|
||||
// for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// // estrusione
|
||||
// SurfBezier SbzLat ;
|
||||
// if ( ! SbzLat.CreateByExtrusion( vPL[i], vtExtr)) // qui mi serve la curva e non la polyline della curva. vuol dire che dalla CalcRegionPolyLines devo farmi restituire anche le curve ordinate
|
||||
// return nullptr ;
|
||||
// }
|
||||
// // restituisco la superficie
|
||||
// return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica
|
||||
//}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
|
||||
bool bCapEnds, double dLinTol) // con l'aggiunta delle SURFCOMPO posso gestire anche i cap e curve che attraversano l'asse
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
|
||||
return nullptr ;
|
||||
// limite minimo su tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, ANG_FULL, 0))
|
||||
return nullptr ;
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSbz->GetVolume( dVol) && dVol < 0)
|
||||
pSbz->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
|
||||
double dAngRotDeg, double dMove, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
|
||||
return nullptr ;
|
||||
// limite minimo su tolleranza
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
|
||||
// creo e setto la superficie bezier
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByScrewing( pCurve, ptAx, vtAx, dAngRotDeg, dMove))
|
||||
return nullptr ;
|
||||
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSbz->GetVolume( dVol) && dVol < 0)
|
||||
pSbz->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// riferimento all'inizio della linea guida
|
||||
Frame3d frStart ;
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
bool bGuideIsPolyLine = false ;
|
||||
switch ( pGuide->GetType()) {
|
||||
case CRV_COMPO : {
|
||||
bGuideIsPolyLine = true ;
|
||||
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
|
||||
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
|
||||
const ICurve* pCrv = pCC->GetCurve( i) ;
|
||||
if ( pCrv->GetType() != CRV_LINE) {
|
||||
if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
}
|
||||
else
|
||||
bGuideIsPolyLine = false ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
}
|
||||
case CRV_LINE :
|
||||
bGuideIsPolyLine = true ;
|
||||
break ;
|
||||
case CRV_BEZIER : {
|
||||
// controllo se i punti di controllo sono allineati
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
break ;
|
||||
}
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
||||
bool bRat = false ;
|
||||
int nSpanV = 0 ;
|
||||
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
if ( bGuideIsPolyLine ) {
|
||||
if ( pGuide->GetType() == CRV_LINE)
|
||||
nSpanV = 1 ;
|
||||
else if ( pGuide->GetType() == CRV_COMPO)
|
||||
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
|
||||
}
|
||||
else {
|
||||
//converto in bezier la guida ( grado 3, non razionale)
|
||||
if ( pGuide->GetType() != CRV_BEZIER)
|
||||
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
|
||||
if ( ! pGuideBez->IsRational())
|
||||
pCrvV->AddCurve( pGuide->Clone()) ;
|
||||
else
|
||||
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvV) || ! pCrvV->IsValid())
|
||||
return nullptr ;
|
||||
nSpanV = pCrvV->GetCurveCount() ;
|
||||
}
|
||||
|
||||
// converto in bezier la sezione ( grado 3, non razionale)
|
||||
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
|
||||
if ( pSect->GetType() != CRV_BEZIER)
|
||||
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
|
||||
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
|
||||
return nullptr ;
|
||||
int nSpanU = int( pCrvU->GetCurveCount()) ;
|
||||
|
||||
int nDegV = 3 ;
|
||||
if ( bGuideIsPolyLine)
|
||||
nDegV = 1 ;
|
||||
|
||||
int nDegU = 3 ;
|
||||
// superficie swept
|
||||
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
// la guida è una linea spezzata, quindi posso lavorare con gli offset
|
||||
ICRVCOMPOPOVECTOR vCC ;
|
||||
INTMATRIX mRep ; mRep.resize( nSpanU * nDegU + 1) ;
|
||||
int nMaxSpanV = nSpanV ;
|
||||
for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
|
||||
for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
|
||||
// faccio l'offset della guida nel punto di controllo della sezione
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
vCC.emplace_back() ;
|
||||
vCC.back()->AddCurve(OffsCrv.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrvV))
|
||||
return nullptr ;
|
||||
vCC.back()->Translate( ptCtrl.y * frStart.VersY()) ;
|
||||
//mRep[ i * nDegU + j].resize(vCC.back()->GetCurveCount()) ;
|
||||
nMaxSpanV = max ( nMaxSpanV, vCC.back()->GetCurveCount()) ;
|
||||
}
|
||||
}
|
||||
|
||||
// devo capire quante span in V devo creare e a quale span appartengono i tratti degli offset
|
||||
for ( int k = 0 ; k < int( vCC.size()) ; ++k) {
|
||||
const ICurveComposite* pCC = vCC[k] ;
|
||||
mRep[k].resize( nMaxSpanV) ;
|
||||
for ( int z = 0 ; z < int( mRep[k].size()) ; ++z) {
|
||||
int nProp = - 1 ; pCC->GetCurveTempProp( z, nProp) ;
|
||||
if ( nProp == 0) {
|
||||
// ho trovato almeno una curva di offset che ha un tratto non derivante direttamente dalla curva originale
|
||||
// tutte le altre curve che hanno curve di offeset che non hanno questo tratto bonus dovranno ripetere il punto di controllo
|
||||
for ( int w = 0 ; w < int( vCC.size()) ; ++w) {
|
||||
const ICurveComposite* pCCOther = vCC[w] ;
|
||||
int nPropCheck = -1 ; pCCOther->GetCurveTempProp( z, nPropCheck) ;
|
||||
if ( nPropCheck != 0)
|
||||
mRep[w][z] = 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// conto in quante colonne di mRep la somma degli elementi è != 0
|
||||
// questo numero va aggiunto all'attuale nSpanV
|
||||
int nSpanPlus = 0 ;
|
||||
for ( int z = 0 ; z < nMaxSpanV ; ++z) {
|
||||
int nPosTot = 0 ;
|
||||
for ( int k = 0 ; k < int( mRep.size()) ; ++k )
|
||||
nPosTot += mRep[k][z] ;
|
||||
if ( nPosTot != 0)
|
||||
nSpanPlus += 1 ;
|
||||
}
|
||||
nMaxSpanV = max( nMaxSpanV, nSpanV + nSpanPlus) ;
|
||||
nSpanV = nMaxSpanV ;
|
||||
|
||||
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
|
||||
//// aggiungo i punti di controllo alla superficie
|
||||
//for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
// const ICurveComposite* pOffsetCrv = vCC[i*nDegU + j] ;
|
||||
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
|
||||
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
|
||||
// if ( pCL == nullptr)
|
||||
// return nullptr ;
|
||||
// if ( z == 0) {
|
||||
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
|
||||
// }
|
||||
// Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//// aggiungo i punti di controllo alla superficie /// DA CORREGGERE L'AGGIUNTA DEI PUNTI DI CONTROLLO
|
||||
//for ( int i = 0 ; i < int( vCC.size()) ; ++i) {
|
||||
// const ICurveComposite* pOffsetCrv = vCC[i] ;
|
||||
// for ( int z = 0 ; z < pOffsetCrv->GetCurveCount() ; ++z) {
|
||||
// const ICurveLine* pCL = GetCurveLine( pOffsetCrv->GetCurve( z)) ;
|
||||
// if ( pCL == nullptr)
|
||||
// return nullptr ;
|
||||
// if ( z == 0) {
|
||||
// Point3d ptSubStart ; pCL->GetStartPoint( ptSubStart) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, 0, ptSubStart) ;
|
||||
// }
|
||||
// Point3d ptSubEnd ; pCL->GetEndPoint( ptSubEnd) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, z + 1, ptSubEnd) ;
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
else {
|
||||
pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ;
|
||||
|
||||
// VERSIONE con le copie della sezione ( superficie skinned)
|
||||
|
||||
// creo delle copie della curva e faccio la skinned
|
||||
// per ogni sottocurva della guida ( che sarà composta da curve di bezier di grado 3)
|
||||
// posiziono una copia della curva di sezione per ogni punto di controllo
|
||||
frStart.Set( ptStart, vtStart) ;
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
ICURVEPOVECTOR vCrvSet ;
|
||||
CICURVEPVECTOR vpCrv ;
|
||||
RotationMinimizingFrame rmfGuide ; rmfGuide.Set( pCrvV, frStart) ;
|
||||
//double dStep = 0.25 ;
|
||||
FRAME3DVECTOR vFrame ;
|
||||
int nSpanV = pCrvV->GetCurveCount() ;
|
||||
int nSplit = 8 * nSpanV ;
|
||||
rmfGuide.GetFramesBySplit( nSplit, vFrame) ;
|
||||
|
||||
for ( int i = 0 ; i < nSpanV ; ++i) {
|
||||
for ( int j = i==0 ? 0 : 1 ; j < nSplit + 1 ; ++j) {
|
||||
ICurve* pNewSect = pCrvU->Clone() ;
|
||||
pNewSect->ToGlob( vFrame[j]) ; // da sistemare se ho più curve ( la pGuide è una compo) e in base allo step di divisione!!!!!!!!! ///////
|
||||
vpCrv.push_back( pNewSect) ;
|
||||
vCrvSet.emplace_back( pNewSect) ;
|
||||
}
|
||||
}
|
||||
|
||||
return GetSurfBezierSkinned( vpCrv, dLinTol) ;
|
||||
|
||||
|
||||
|
||||
//////VERSIONE con l'offset dei punti di controllo // richiede l'interpolazione dei punti
|
||||
//
|
||||
//// faccio l'offset della guida e poi riconverto i risultati in curve di bezier tramite interpolazione
|
||||
//
|
||||
//frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
//// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
//pCrvU->ToLoc( frStart) ;
|
||||
//for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
// const ICurveBezier* pSubCrv = GetCurveBezier( pCrvU->GetCurve( i)) ;
|
||||
// for ( int j = i==0 ? 0 : 1 ; j < nDegU + 1 ; ++j ) {
|
||||
// Point3d ptCtrl = pSubCrv->GetControlPoint( j) ;
|
||||
// // faccio l'offset della guida nel punto di controllo della sezione
|
||||
// OffsetCurve OffsCrv ;
|
||||
// if ( ! OffsCrv.Make( pGuide, ptCtrl.x, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0)
|
||||
// return nullptr ;
|
||||
// PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
// pCrvV->AddCurve( OffsCrv.GetLongerCurve()) ;
|
||||
// if ( IsNull( pCrvV))
|
||||
// return nullptr ;
|
||||
// pCrvV->Translate( ptCtrl.y * frStart.VersY()) ;
|
||||
// PNTVECTOR vPnt ;
|
||||
// int nOffCrvs = pCrvV->GetCurveCount() ;
|
||||
// for ( int z = 0 ; z < nOffCrvs ; ++z) {
|
||||
// Point3d ptCtrl ;
|
||||
// if ( z == 0) {
|
||||
// pCrvV->GetCurve(z)->GetStartPoint( ptCtrl) ;
|
||||
// vPnt.push_back( ptCtrl) ;
|
||||
// }
|
||||
// pCrvV->GetCurve(z)->GetEndPoint( ptCtrl) ;
|
||||
// vPnt.push_back( ptCtrl) ;
|
||||
// }
|
||||
// pCrvV.Set( CreateCurveComposite()) ;
|
||||
// pCrvV->AddCurve( InterpolatePointSetWithBezier( vPnt, dLinTol)) ;
|
||||
//
|
||||
//
|
||||
// nSpanV = pCrvV->GetCurveCount() ;
|
||||
// pSurfBez->Init( nDegU,nDegV, nSpanU, nSpanV, bRat) ; /// NON POSSO REINIZIALIZZARE LA SURF QUI!
|
||||
// /// QUANDO INIZIO A INSERIRE I PUNTI DI CONTROLLO DEVO AVER DEFINITO nSpanV
|
||||
//
|
||||
//
|
||||
// // aggiungo i punti di controllo alla superficie
|
||||
// for ( int z = 0 ; z < nSpanV ; ++z) {
|
||||
// const ICurveBezier* pCrvBez = GetCurveBezier( pCrvV->GetCurve( z)) ;
|
||||
// if ( pCrvBez == nullptr)
|
||||
// return nullptr ;
|
||||
// for ( int k = z == 0 ? 0 : 1 ; k < nDegV ; ++k) {
|
||||
// Point3d ptCtrl = pCrvBez->GetControlPoint( k) ;
|
||||
// pSurfBez->SetControlPoint( i * nDegU + j, z * nDegV + k, ptCtrl) ;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////// se richiesti caps e sezione chiusa e guida aperta /// in attesa della SurfCompo, al momento viene fatto nell'executor
|
||||
//if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
// // verifico che le due estremità siano chiuse e piatte
|
||||
|
||||
//}
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSurfBez) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione//////////////////////
|
||||
{
|
||||
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
|
||||
bool bRMF = vtAx.IsSmall() ;
|
||||
|
||||
// riferimento all'inizio della linea guida
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
Frame3d frStart ;
|
||||
if ( bRMF) {
|
||||
if ( ! frStart.Set( ptStart, vtStart))
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
Vector3d vtAxX = vtAx ^ vtStart ;
|
||||
if ( vtAxX.IsSmall()) {
|
||||
vtAxX = FromUprightOrtho( vtAx) ;
|
||||
vtAxX.Rotate( vtAx, 0, 1) ;
|
||||
}
|
||||
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// capisco se la guida è una linea spezzata o una curva
|
||||
bool bGuideIsPolyLine = false ;
|
||||
switch( pGuide->GetType()) {
|
||||
case CRV_COMPO : {
|
||||
bGuideIsPolyLine = true ;
|
||||
const ICurveComposite* pCC = GetCurveComposite( pGuide) ;
|
||||
for ( int i = 0 ; i < pCC->GetCurveCount() && bGuideIsPolyLine ; ++i) {
|
||||
const ICurve* pCrv = pCC->GetCurve( i) ;
|
||||
if ( pCrv->GetType() != CRV_LINE) {
|
||||
if ( pCrv->GetType() == CRV_BEZIER) {
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pCrv) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
}
|
||||
else
|
||||
bGuideIsPolyLine = false ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
}
|
||||
case CRV_LINE :
|
||||
bGuideIsPolyLine = true ;
|
||||
break ;
|
||||
case CRV_BEZIER : {
|
||||
// controllo se i punti di controllo sono allineati
|
||||
const ICurveBezier* pCrvBez = GetCurveBezier( pGuide) ;
|
||||
bGuideIsPolyLine = pCrvBez->IsALine() ;
|
||||
break ;
|
||||
}
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
|
||||
bool bRat = false ;
|
||||
int nSpanV = 0 ;
|
||||
PtrOwner<ICurveComposite> pCrvV( CreateCurveComposite()) ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( pGuide->GetType() == CRV_LINE)
|
||||
nSpanV = 1 ;
|
||||
else if ( pGuide->GetType() == CRV_COMPO)
|
||||
nSpanV = GetCurveComposite( pGuide)->GetCurveCount() ;
|
||||
}
|
||||
else {
|
||||
// converto in bezier la guida ( grado 3, non razionale)
|
||||
if ( pGuide->GetType() != CRV_BEZIER)
|
||||
pCrvV->AddCurve( CurveToBezierCurve( pGuide, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pGuideBez = GetCurveBezier( pGuide) ;
|
||||
if ( ! pGuideBez->IsRational())
|
||||
pCrvV->AddCurve( pGuide->Clone()) ;
|
||||
else
|
||||
pCrvV->AddCurve( EditBezierCurve( pGuideBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvV) || ! pCrvV->IsValid())
|
||||
return nullptr ;
|
||||
nSpanV = pCrvV->GetCurveCount() ;
|
||||
}
|
||||
|
||||
// converto in bezier la sezione ( grado 3, non razionale)
|
||||
PtrOwner<ICurveComposite> pCrvU( CreateCurveComposite()) ;
|
||||
if ( pSect->GetType() != CRV_BEZIER)
|
||||
pCrvU->AddCurve( CurveToBezierCurve( pSect, 3, false)) ;
|
||||
else {
|
||||
const ICurveBezier* pSectBez = GetCurveBezier( pSect) ;
|
||||
if ( ! pSectBez->IsRational())
|
||||
pCrvU->AddCurve( pSect->Clone()) ; ///// questa curva potrebbe non essere di grado 3!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
else
|
||||
pCrvU->AddCurve( EditBezierCurve( pSectBez, 3, false)) ;
|
||||
}
|
||||
if ( IsNull( pCrvU) || ! pCrvU->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
FRAME3DVECTOR vFrames ;
|
||||
if ( bRMF) {
|
||||
RotationMinimizingFrame RMF ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
if ( ! RMF.Set( pGuide, frStart) ||
|
||||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RotationXplaneFrame RXF ;
|
||||
if ( bGuideIsPolyLine) {
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesBySplit( nSpanV, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
|
||||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
|
||||
int nSpanU = int( pCrvU->GetCurveCount()) ;
|
||||
int nDegU = 9 ; // debug
|
||||
int nDegV = 3 ;
|
||||
if ( bGuideIsPolyLine){
|
||||
nDegV = 1 ;
|
||||
// superficie swept
|
||||
PtrOwner<ISurfBezier> pSurfBez( CreateSurfBezier()) ;
|
||||
pSurfBez->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
|
||||
PtrOwner<ICurveComposite> pNewSect( pCrvU->Clone()) ;
|
||||
pNewSect->ToGlob( vFrames[f]) ;
|
||||
for ( int i = 0 ; i < nSpanU ; ++i) {
|
||||
const ICurveBezier* pSubCrvBez = GetCurveBezier( pNewSect->GetCurve( i)) ;
|
||||
for ( int j = 0 ; j < nDegU + 1 ; ++j) {
|
||||
Point3d ptCtrl = pSubCrvBez->GetControlPoint( j) ;
|
||||
pSurfBez->SetControlPoint( i * nDegU + j, f, ptCtrl) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Release( pSurfBez) ;
|
||||
}
|
||||
else {
|
||||
// porto la sezione nel sistema di riferimento del piano in cui giace
|
||||
pCrvU->ToLoc( frStart) ;
|
||||
ICURVEPOVECTOR vCrvSet ;
|
||||
CICURVEPVECTOR vpCrv ;
|
||||
for ( int f = 0 ; f < int( vFrames.size()) ; ++f) {
|
||||
ICurve* pNewSect = pCrvU->Clone() ;
|
||||
// porto la curva nel frame corrente
|
||||
pNewSect->ToGlob( vFrames[f]) ;
|
||||
vpCrv.push_back( pNewSect) ;
|
||||
vCrvSet.emplace_back( pNewSect) ;
|
||||
}
|
||||
|
||||
return GetSurfBezierSkinned( vpCrv, dLinTol) ;
|
||||
}
|
||||
|
||||
//// se richiesti caps e sezione chiusa e guida aperta
|
||||
//if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
|
||||
// // aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida )
|
||||
// PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// pSci->ToGlob( vFrames.front()) ;
|
||||
// // aggiungo
|
||||
// StmFts.AddSurfTriMesh( *pSci) ;
|
||||
|
||||
// // aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida )
|
||||
// PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
// if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
// return nullptr ;
|
||||
// pSce->ToGlob( vFrames.back()) ;
|
||||
// // inverto
|
||||
// pSce->Invert() ;
|
||||
// // aggiungo
|
||||
// StmFts.AddSurfTriMesh( *pSce) ;
|
||||
//}
|
||||
|
||||
//// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
//double dVol ;
|
||||
//if ( pSTM->GetVolume( dVol) && dVol < 0)
|
||||
// pSTM->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( &ptP == nullptr || pCurve == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByPointCurve( ptP, pCurve))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
if ( pCurve1->GetType() != CRV_BEZIER)
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
|
||||
else
|
||||
pCC1->AddCurve( pCurve1->Clone()) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
if ( pCurve2->GetType() != CRV_BEZIER)
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
|
||||
else
|
||||
pCC2->AddCurve( pCurve2->Clone()) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByTwoCurves( pCC1, pCC2, nType))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
if ( pCurve1->GetType() != CRV_BEZIER)
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
|
||||
else
|
||||
pCC1->AddCurve( pCurve1->Clone()) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
if ( pCurve2->GetType() != CRV_BEZIER)
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
|
||||
else
|
||||
pCC2->AddCurve( pCurve2->Clone()) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateByIsoParamSet( pCC1, pCC2, vCrv))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol)
|
||||
{
|
||||
// verifico che le curve siano valide
|
||||
for ( int i = 0 ; i < int( vCrv.size()) ; ++i) {
|
||||
if ( vCrv[i] == nullptr || ! vCrv[i]->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// se ho solo due curve allora faccio la rigata
|
||||
if ( vCrv.size() == 2)
|
||||
return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ;
|
||||
|
||||
//trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
ICURVEPOVECTOR vCrvBez ;
|
||||
for ( int c = 0 ; c < int( vCrv.size()) ; ++c){
|
||||
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
|
||||
if ( vCrv[c]->GetType() != CRV_BEZIER )
|
||||
pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ;
|
||||
else
|
||||
pCC->AddCurve( vCrv[c]->Clone()) ;
|
||||
if ( IsNull( pCC) || ! pCC->IsValid())
|
||||
return nullptr ;
|
||||
vCrvBez.emplace_back( Release( pCC)) ;
|
||||
}
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateBySetOfCurves( vCrvBez, true))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
+34
-1
@@ -17,12 +17,13 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkSbzStandard.h"
|
||||
#include "/EgtDev/Include/EGkSbzFromCurves.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
CreateBezierSphere( const Point3d& ptCenter, double dR)
|
||||
GetSurfBezierSphere( const Point3d& ptCenter, double dR)
|
||||
{
|
||||
// creo una superficie di Bezier di grado 2 con 45 punti di controllo
|
||||
PtrOwner<ISurfBezier> pSrfBez( CreateSurfBezier()) ;
|
||||
@@ -78,3 +79,35 @@ CreateBezierSphere( const Point3d& ptCenter, double dR)
|
||||
|
||||
return Release( pSrfBez) ;
|
||||
}
|
||||
|
||||
////-------------------------------------------------------------------------------
|
||||
//ISurfBezier*
|
||||
//GetSurfBezierCone( const Point3d& ptCenter, double dRadius, const Vector3d& dHeight)
|
||||
//{
|
||||
// // le dimensioni devono essere significative
|
||||
// if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL)
|
||||
// return nullptr ;
|
||||
// // creo la circonferenza di base
|
||||
// CurveArc cArc ;
|
||||
// cArc.Set( ORIG, Z_AX, dRadius) ;
|
||||
// if ( dHeight < 0)
|
||||
// cArc.Invert() ;
|
||||
// // punto di vertice
|
||||
// Point3d ptTip( 0, 0, dHeight) ;
|
||||
// // creo la superficie laterale del cono
|
||||
// PtrOwner<ISurfBezier> pSbz( GetSurfBezierRuled( ptTip, &cArc)) ;
|
||||
// if ( IsNull( pSbz))
|
||||
// return nullptr ;
|
||||
//
|
||||
// //// creo la superficie di base e la inverto
|
||||
// //PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc, dLinTol)) ;
|
||||
// //if ( IsNull( pSTM1))
|
||||
// // return nullptr ;
|
||||
// //pSTM1->Invert() ;
|
||||
// //// la unisco alla superficie del fianco
|
||||
// //if ( ! pSTM->DoSewing( *pSTM1))
|
||||
// // return nullptr ;
|
||||
//
|
||||
// // restituisco la superficie
|
||||
// return Release( pSbz) ;
|
||||
//}
|
||||
|
||||
+3
-1
@@ -88,6 +88,8 @@ SelfIntersCurve::SelfIntersCurve( const ICurve& Curve)
|
||||
}
|
||||
}
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
// per curva approssimata, sistemo...
|
||||
AdjustIntersParams( ( pCalcCrv != m_pCurve), pCalcCrv, vTmpPar) ;
|
||||
@@ -133,7 +135,7 @@ bool
|
||||
SelfIntersCurve::AdjustIntersParams( bool bAdjCrv, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar)
|
||||
{
|
||||
// se la curva originale non è stata approssimata o non ci sono auto-intersezioni, non va fatto alcunché
|
||||
if ( ! bAdjCrv || m_Info.size() == 0)
|
||||
if ( ! bAdjCrv || m_Info.empty())
|
||||
return true ;
|
||||
// procedo ad aggiustare
|
||||
for ( auto& aInfo : m_Info) {
|
||||
|
||||
+144
-32
@@ -115,7 +115,8 @@ GetSurfFlatRegionDisk( double dRadius)
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfFlatRegion*
|
||||
GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, double dOffsLinTol)
|
||||
GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, double dOffsLinTol,
|
||||
bool bMergeOnlySameProps)
|
||||
{
|
||||
// metodo di calcolo impostato da USE_VORONOI
|
||||
|
||||
@@ -330,7 +331,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
|
||||
else {
|
||||
// calcolo la fat curve con Voronoi
|
||||
ICURVEPOVECTOR vFatCurves ;
|
||||
if ( ! CalcCurveFatCurve( *pCurve, vFatCurves, dRadius, bSquareEnds, bSquareMids))
|
||||
if ( ! CalcCurveFatCurve( *pCurve, vFatCurves, dRadius, bSquareEnds, bSquareMids, bMergeOnlySameProps))
|
||||
return nullptr ;
|
||||
|
||||
// costruisco la superficie a partire dalle curve
|
||||
@@ -367,25 +368,14 @@ GetSurfFlatRegionFromTriangle( const Triangle3d& Tria)
|
||||
ISurfFlatRegion*
|
||||
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
|
||||
{
|
||||
// Creo la regione.
|
||||
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfr))
|
||||
return nullptr ;
|
||||
// Creo curva composita.
|
||||
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pLoop))
|
||||
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( ContourPolyLine))
|
||||
return nullptr ;
|
||||
// Creo la regione.
|
||||
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pLoop)))
|
||||
return nullptr ;
|
||||
Point3d ptSt, ptEn ;
|
||||
bool bContinue = ContourPolyLine.GetFirstPoint( ptSt) &&
|
||||
ContourPolyLine.GetNextPoint( ptEn) ;
|
||||
while ( bContinue) {
|
||||
CurveLine cvLine ;
|
||||
cvLine.Set( ptSt, ptEn) ;
|
||||
pLoop->AddCurve( cvLine) ;
|
||||
ptSt = ptEn ;
|
||||
bContinue = ContourPolyLine.GetNextPoint( ptEn) ;
|
||||
}
|
||||
pSfr->AddExtLoop( Release( pLoop)) ;
|
||||
return Release( pSfr) ;
|
||||
}
|
||||
|
||||
@@ -401,25 +391,17 @@ GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
|
||||
for ( int nL = 0 ; nL < int( vContoursPolyLineVec.size()) ; ++ nL) {
|
||||
// Creo curva composita.
|
||||
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pLoop))
|
||||
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( vContoursPolyLineVec[nL]))
|
||||
return nullptr ;
|
||||
Point3d ptSt, ptEn ;
|
||||
bool bContinue = vContoursPolyLineVec[nL].GetFirstPoint( ptSt) &&
|
||||
vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
|
||||
while ( bContinue) {
|
||||
CurveLine cvLine ;
|
||||
cvLine.Set( ptSt, ptEn) ;
|
||||
pLoop->AddCurve( cvLine) ;
|
||||
ptSt = ptEn ;
|
||||
bContinue = vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
|
||||
}
|
||||
// Loop esterno
|
||||
if ( nL == 0) {
|
||||
pSfr->AddExtLoop( Release( pLoop)) ;
|
||||
if ( ! pSfr->AddExtLoop( Release( pLoop)))
|
||||
return nullptr ;
|
||||
}
|
||||
// Loop interno
|
||||
else {
|
||||
pSfr->AddIntLoop( Release( pLoop)) ;
|
||||
if ( ! pSfr->AddIntLoop( Release( pLoop)))
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
return Release( pSfr) ;
|
||||
@@ -590,4 +572,134 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
|
||||
vId.push_back( pCrv->GetTempProp()) ;
|
||||
}
|
||||
return ( ! vId.empty()) ;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool
|
||||
CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert)
|
||||
{
|
||||
// vnPLIndMat : ogni riga corrisponde ad un chunk, in posizione 0 c'è il loop esterno e nelle successive i loop interni
|
||||
// vbInvert : riferito al vettore delle polyline, riporta true se la polyline è stata invertita
|
||||
|
||||
// ricavo versore normale
|
||||
Plane3d plPlane ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
|
||||
return false ;
|
||||
vtN = plPlane.GetVersN() ;
|
||||
|
||||
typedef std::pair<int,double> INDAREA ;
|
||||
std::vector<INDAREA> m_vArea ;
|
||||
// calcolo piano medio e area delle curve
|
||||
m_vArea.reserve( vPL.size()) ;
|
||||
VCT3DVECTOR vvtN ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// calcolo piano medio e area
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
// verifico che le normali siano molto vicine
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
|
||||
return false ;
|
||||
// salvo la normale
|
||||
vvtN.push_back( plPlane.GetVersN()) ;
|
||||
// assegno il segno all'area secondo il verso della normale
|
||||
if ( ( plPlane.GetVersN() * vtN) > 0)
|
||||
m_vArea.emplace_back( i, dArea) ;
|
||||
else
|
||||
m_vArea.emplace_back( i, - dArea) ;
|
||||
}
|
||||
// ordino in senso decrescente sull'area
|
||||
sort( m_vArea.begin(), m_vArea.end(),
|
||||
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
|
||||
|
||||
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
|
||||
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
|
||||
if ( ! frRef.IsValid())
|
||||
return false ;
|
||||
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vCrvCompo[i].Set( CreateCurveComposite()) ;
|
||||
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
|
||||
vCrvCompo[i]->ToLoc( frRef) ;
|
||||
}
|
||||
|
||||
// restituisco la normale del loop più grande
|
||||
bool bInvertAll = vvtN[m_vArea[0].first] * vtN < 0 ;
|
||||
vtN = vvtN[m_vArea[0].first] ;
|
||||
|
||||
//// vettore di indici per ordinare le PolyLine
|
||||
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
|
||||
vPL_IndOrder[i] = m_vArea[i].first ;
|
||||
|
||||
// aggiungo le diverse curve
|
||||
bool bFirstCrv ;
|
||||
Plane3d plExtLoop ;
|
||||
double dAreaExtLoop = 0. ;
|
||||
vbInvert.resize( vPL.size()) ;
|
||||
fill( vbInvert.begin(), vbInvert.end(), false) ;
|
||||
do {
|
||||
bFirstCrv = true ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
|
||||
// recupero indice di percorso e verifico sia valido
|
||||
int j = m_vArea[i].first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstCrv) {
|
||||
vnPLIndMat.push_back({ j}) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
dAreaExtLoop = m_vArea[i].second ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second < EPS_SMALL) {
|
||||
vCrvCompo[j]->Invert() ;
|
||||
dAreaExtLoop *= -1 ;
|
||||
vbInvert[j] = true ;
|
||||
}
|
||||
bFirstCrv = false ;
|
||||
}
|
||||
// ... altrimenti verifico se il loop è interno o no
|
||||
else {
|
||||
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
|
||||
// esterno a tutti i loop già inseriti nella riga attuale.
|
||||
// verifica rispetto loop esterno
|
||||
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
|
||||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
||||
continue ;
|
||||
// verifica rispetto ai loop interni
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
|
||||
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass2 ;
|
||||
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
|
||||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnPLIndMat.back().push_back( j) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
|
||||
vCrvCompo[j]->Invert() ;
|
||||
vbInvert[j] = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstCrv) ;
|
||||
|
||||
if ( bInvertAll) {
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
|
||||
vbInvert[i] = ! vbInvert[i] ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+35
-147
@@ -31,10 +31,6 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
|
||||
POLYLINEVECTOR& vPL, Vector3d& vtN) ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol)
|
||||
@@ -65,12 +61,25 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
return nullptr ;
|
||||
// calcolo le polilinee che approssimano le curve della regione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return nullptr ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++i) {
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++j){
|
||||
if ( vbInvert[vnPLIndMat[i][j]])
|
||||
vPL[vnPLIndMat[i][j]].Invert() ;
|
||||
}
|
||||
}
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL, vnPLIndMat))
|
||||
return nullptr ;
|
||||
// salvo tolleranza lineare usata
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
@@ -145,9 +154,20 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
return GetSurfTriMeshByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
|
||||
// calcolo le polilinee che approssimano le curve della regione
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return nullptr ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
|
||||
INTMATRIX vnPLIndMat ;
|
||||
BOOLVECTOR vbInvert ;
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
|
||||
if ( vbInvert[i])
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
// verifico la direzione di estrusione
|
||||
double dOrthoExtr = vtN * vtExtr ;
|
||||
if ( ( abs( dOrthoExtr) < EPS_SMALL))
|
||||
@@ -159,7 +179,8 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
}
|
||||
// creo la prima superficie di estremità
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
|
||||
// alla funzione CreateByRegion passo anche la matrice che contiene la struttura dei chunk. Le polyline hanno già il verso giusto
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL, vnPLIndMat))
|
||||
return nullptr ;
|
||||
// creo la seconda superficie e la unisco alla prima
|
||||
{ // copio la prima superficie
|
||||
@@ -1279,8 +1300,9 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
|
||||
}
|
||||
}
|
||||
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
|
||||
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
|
||||
if ( ! pSci->CreateByRegion( vPLi))
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
INTMATRIX vnPLIndMat ;
|
||||
if ( ! pSci->CreateByRegion( vPLi, vnPLIndMat))
|
||||
return nullptr ;
|
||||
pStmSwept->DoSewing( *pSci) ;
|
||||
// recupero i loops alla fine
|
||||
@@ -1288,8 +1310,9 @@ GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, cons
|
||||
if ( ! pStmSwept->GetLoops( vPLe))
|
||||
return nullptr ;
|
||||
// creo la superficie alla fine e la attacco
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( ! pSce->CreateByRegion( vPLe))
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
vnPLIndMat.clear() ;
|
||||
if ( ! pSce->CreateByRegion( vPLe, vnPLIndMat))
|
||||
return nullptr ;
|
||||
// attacco la superficie finale alla swept
|
||||
pSce->Invert() ;
|
||||
@@ -1433,138 +1456,3 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool
|
||||
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
|
||||
POLYLINEVECTOR& vPL, Vector3d& vtN)
|
||||
{
|
||||
// se non ho curve, non faccio nulla
|
||||
if ( int( vpCurve.size()) == 0)
|
||||
return true ;
|
||||
|
||||
// calcolo le polilinee che approssimano le curve
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// ricavo versore normale
|
||||
Plane3d plPlane ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
|
||||
return false ;
|
||||
vtN = plPlane.GetVersN() ;
|
||||
|
||||
typedef std::pair<int,double> INDAREA ;
|
||||
std::vector<INDAREA> m_vArea ;
|
||||
// calcolo piano medio e area delle curve
|
||||
m_vArea.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// calcolo piano medio e area
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
// verifico che le normali siano molto vicine
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
|
||||
return false ;
|
||||
// assegno il segno all'area secondo il verso della normale
|
||||
if ( ( plPlane.GetVersN() * vtN) > 0)
|
||||
m_vArea.emplace_back( i, dArea) ;
|
||||
else
|
||||
m_vArea.emplace_back( i, - dArea) ;
|
||||
}
|
||||
// ordino in senso decrescente sull'area
|
||||
sort( m_vArea.begin(), m_vArea.end(),
|
||||
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
|
||||
|
||||
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
|
||||
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
|
||||
if ( ! frRef.IsValid())
|
||||
return false ;
|
||||
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vCrvCompo[i].Set( CreateCurveComposite()) ;
|
||||
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
|
||||
vCrvCompo[i]->ToLoc( frRef) ;
|
||||
}
|
||||
|
||||
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
|
||||
// successive i loop interni
|
||||
INTMATRIX vnPLIndMat ;
|
||||
|
||||
// vettore di indici per ordinare le PolyLine
|
||||
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
|
||||
vPL_IndOrder[i] = m_vArea[i].first ;
|
||||
|
||||
// aggiungo le diverse curve
|
||||
bool bFirstCrv ;
|
||||
Plane3d plExtLoop ;
|
||||
double dAreaExtLoop = 0. ;
|
||||
do {
|
||||
bFirstCrv = true ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
|
||||
// recupero indice di percorso e verifico sia valido
|
||||
int j = m_vArea[i].first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstCrv) {
|
||||
vnPLIndMat.push_back({ j}) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
dAreaExtLoop = m_vArea[i].second ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second < EPS_SMALL) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
dAreaExtLoop *= -1 ;
|
||||
}
|
||||
bFirstCrv = false ;
|
||||
}
|
||||
// ... altrimenti verifico se il loop è interno o no
|
||||
else {
|
||||
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
|
||||
// esterno a tutti i loop già inseriti nella riga attuale.
|
||||
// verifica rispetto loop esterno
|
||||
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
|
||||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
||||
continue ;
|
||||
// verifica rispetto ai loop interni
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
|
||||
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass2 ;
|
||||
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
|
||||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnPLIndMat.back().push_back( j) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstCrv) ;
|
||||
|
||||
// ordino le PolyLine per area
|
||||
POLYLINEVECTOR vPL_tmp ;
|
||||
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
|
||||
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
|
||||
swap( vPL, vPL_tmp) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+123
-6
@@ -22,6 +22,18 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshEmpty( void)
|
||||
{
|
||||
// creo oggetto con superficie vuota
|
||||
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pStm) || ! pStm->AdjustTopology())
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pStm) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
static SurfTriMesh*
|
||||
GetStandardSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
||||
@@ -160,15 +172,15 @@ GetSurfTriMeshPyramid( double dDimX, double dDimY, double dHeight)
|
||||
return nullptr ;
|
||||
// creo la polilinea del contorno della base
|
||||
PolyLine PL ;
|
||||
PL.AddUPoint( 0, ORIG) ;
|
||||
PL.AddUPoint( 1, Point3d( dDimX, 0, 0)) ;
|
||||
PL.AddUPoint( 2, Point3d( dDimX, dDimY, 0)) ;
|
||||
PL.AddUPoint( 3, Point3d( 0, dDimY, 0)) ;
|
||||
PL.AddUPoint( 4, ORIG) ;
|
||||
PL.AddUPoint( 0, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 1, Point3d( dDimX / 2, -dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 2, Point3d( dDimX / 2, dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 3, Point3d( -dDimX / 2, dDimY / 2, 0)) ;
|
||||
PL.AddUPoint( 4, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
||||
if ( dHeight < 0)
|
||||
PL.Invert() ;
|
||||
// punto di vertice
|
||||
Point3d ptTip( 0.5 * dDimX, 0.5 * dDimY, dHeight) ;
|
||||
Point3d ptTip( 0, 0, dHeight) ;
|
||||
// creo e setto la superficie trimesh laterale
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL))
|
||||
@@ -245,6 +257,111 @@ GetSurfTriMeshSphere( double dRadius, double dLinTol)
|
||||
return GetSurfTriMeshByRevolve( &cArc, ORIG, Z_AX, true, dLinTol) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshPyramidFrustum( double dBaseDimX, double dBaseDimY, double dTopDimX, double dTopDimY, double dHeight)
|
||||
{
|
||||
// le dimensioni devono essere significative
|
||||
if ( ( min( dBaseDimX, dBaseDimY) < EPS_SMALL && min( dTopDimX, dTopDimY) < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
|
||||
return nullptr ;
|
||||
// se piramide
|
||||
if ( min( dTopDimX, dTopDimY) < EPS_SMALL)
|
||||
return GetSurfTriMeshPyramid( dBaseDimX, dBaseDimY, dHeight) ;
|
||||
// se piramide inversa
|
||||
if ( min( dBaseDimX, dBaseDimY) < EPS_SMALL)
|
||||
return GetSurfTriMeshPyramid( dTopDimX, dTopDimY, -dHeight) ;
|
||||
// se parallelepipedo
|
||||
// continuo qui per avere l'origine in centro e non sullo spigolo in basso a sinistra
|
||||
// creo la polilinea del contorno della base
|
||||
PolyLine PL1 ;
|
||||
PL1.AddUPoint( 0, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 1, Point3d( dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 2, Point3d( dBaseDimX / 2 , dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 3, Point3d( -dBaseDimX / 2, dBaseDimY / 2, 0)) ;
|
||||
PL1.AddUPoint( 4, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
||||
if ( dHeight < 0)
|
||||
PL1.Invert() ;
|
||||
// creo la polilinea del contorno di sopra
|
||||
PolyLine PL2 ;
|
||||
PL2.AddUPoint( 0, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 1, Point3d( dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 2, Point3d( dTopDimX / 2, dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 3, Point3d( -dTopDimX / 2, dTopDimY / 2, dHeight)) ;
|
||||
PL2.AddUPoint( 4, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
||||
if ( dHeight < 0)
|
||||
PL2.Invert() ;
|
||||
// creo e setto la superficie trimesh laterale
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR_SMOOTH))
|
||||
return nullptr ;
|
||||
// creo la superficie di base e ne inverto la normale
|
||||
SurfTriMesh STM1 ;
|
||||
if ( ! STM1.CreateByFlatContour( PL1))
|
||||
return nullptr ;
|
||||
STM1.Invert() ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( STM1))
|
||||
return nullptr ;
|
||||
// creo la superficie sopra
|
||||
SurfTriMesh STM2 ;
|
||||
if ( ! STM2.CreateByFlatContour( PL2))
|
||||
return nullptr ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( STM2))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshConeFrustum( double dBaseRad, double dTopRad, double dHeight, double dLinTol)
|
||||
{
|
||||
// le dimensioni devono essere significative
|
||||
if ( ( dBaseRad < EPS_SMALL && dTopRad < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
|
||||
return nullptr ;
|
||||
// se cono
|
||||
if ( dTopRad < EPS_SMALL)
|
||||
return GetSurfTriMeshCone( dBaseRad, dHeight, dLinTol) ;
|
||||
// se cono rovescio
|
||||
if ( dBaseRad < EPS_SMALL)
|
||||
return GetSurfTriMeshCone( dTopRad, -dHeight, dLinTol) ;
|
||||
// se cilindro
|
||||
if ( abs( dTopRad - dBaseRad) < EPS_SMALL)
|
||||
return GetSurfTriMeshCylinder( dBaseRad, dHeight, dLinTol) ;
|
||||
// creo la circonferenza sotto
|
||||
CurveArc cArc1 ;
|
||||
cArc1.Set( ORIG, Z_AX, dBaseRad) ;
|
||||
if ( dHeight < 0)
|
||||
cArc1.Invert() ;
|
||||
// creo la circonferenza sopra
|
||||
CurveArc cArc2 ;
|
||||
cArc2.Set( Point3d( 0, 0, dHeight), Z_AX, dTopRad) ;
|
||||
if ( dHeight < 0)
|
||||
cArc2.Invert() ;
|
||||
// creo la superficie laterale del cono
|
||||
PtrOwner<ISurfTriMesh> pSTM( GetSurfTriMeshRuled( &cArc1, &cArc2, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
|
||||
if ( IsNull( pSTM))
|
||||
return nullptr ;
|
||||
// creo la superficie sotto e la inverto
|
||||
PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc1, dLinTol)) ;
|
||||
if ( IsNull( pSTM1))
|
||||
return nullptr ;
|
||||
pSTM1->Invert() ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( *pSTM1))
|
||||
return nullptr ;
|
||||
// creo la superficie sopra
|
||||
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMeshByFlatContour( &cArc2, dLinTol)) ;
|
||||
if ( IsNull( pSTM2))
|
||||
return nullptr ;
|
||||
// la unisco alla superficie del fianco
|
||||
if ( ! pSTM->DoSewing( *pSTM2))
|
||||
return nullptr ;
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt)
|
||||
|
||||
@@ -302,7 +302,7 @@ SetTmpPropByOverlap( ICurveComposite* pCrvCheck, const int nInd, const ICurveCom
|
||||
// ultimo tratto di curva della Composita iniziale
|
||||
PtrOwner<CurveComposite> pCrvB( GetBasicCurveComposite( pCrvCheck->CopyParamRange( nInd + 1, pCrvCheck->GetCurveCount()))) ;
|
||||
if ( ! IsNull( pCrvB) && pCrvB->GetCurveCount() > 0 && pCrvB->IsValid())
|
||||
if( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
|
||||
if ( ! pCrvToReturn->AddCurve( Release( pCrvB))) {
|
||||
nStat = 2 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+36
-7
@@ -37,14 +37,15 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
bool bIsRational = snData.bRat ;
|
||||
// vettore dei nodi
|
||||
DBLVECTOR vU ;
|
||||
int nKnot = (int) snData.vU.size() ;
|
||||
int nKnot = ssize( snData.vU) ;
|
||||
for ( int k = 0 ; k < nKnot ; ++k ) {
|
||||
double dKnot = snData.vU[k] ;
|
||||
vU.push_back( dKnot) ;
|
||||
}
|
||||
for( int j = 0 ; j < snData.nCPV ; ++j) {
|
||||
for ( int j = 0 ; j < snData.nCPV ; ++j) {
|
||||
CNurbsData nuCurve ;
|
||||
nuCurve.bPeriodic = true ;
|
||||
nuCurve.bRat = snData.bRat ;
|
||||
nuCurve.nDeg = snData.nDegU ;
|
||||
nuCurve.vU = vU ;
|
||||
// vettore dei punti di controllo
|
||||
@@ -63,26 +64,41 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
nuCurve.vW = vWeCtrl ;
|
||||
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
|
||||
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
if ( snData.mCP.size() != nuCurve.vCP.size() ) {
|
||||
snData.mCP.resize( nuCurve.vCP.size()) ;
|
||||
if ( snData.bRat)
|
||||
snData.mW.resize( nuCurve.vW.size()) ;
|
||||
}
|
||||
for ( int i = 0 ; i < ssize( nuCurve.vCP) ; ++i) {
|
||||
if ( snData.mCP[i].empty())
|
||||
snData.mCP[i].resize( snData.nCPV) ;
|
||||
snData.mCP[i][j] = nuCurve.vCP[i] ;
|
||||
if ( snData.bRat) {
|
||||
if ( snData.mW[i].empty())
|
||||
snData.mW[i].resize( snData.nCPV) ;
|
||||
snData.mW[i][j] = nuCurve.vW[i] ;
|
||||
snData.mCP[i][j] *= nuCurve.vW[i] ;
|
||||
}
|
||||
}
|
||||
snData.vU = nuCurve.vU ;
|
||||
}
|
||||
}
|
||||
snData.bPeriodicU = false ;
|
||||
snData.nCPU = ssize( snData.mCP) ;
|
||||
}
|
||||
if ( snData.bPeriodicV || ! snData.bClampedV) {
|
||||
bool bIsRational = snData.bRat ;
|
||||
// vettore dei nodi
|
||||
DBLVECTOR vV ;
|
||||
int nKnot = (int) snData.vV.size() ;
|
||||
int nKnot = ssize( snData.vV) ;
|
||||
for ( int k = 0 ; k < nKnot ; ++k ) {
|
||||
double dKnot = snData.vV[k] ;
|
||||
vV.push_back( dKnot) ;
|
||||
}
|
||||
for( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
CNurbsData nuCurve ;
|
||||
nuCurve.bPeriodic = true ;
|
||||
nuCurve.bRat = snData.bRat ;
|
||||
nuCurve.nDeg = snData.nDegV ;
|
||||
nuCurve.vU = vV ;
|
||||
// vettore dei punti di controllo
|
||||
@@ -101,15 +117,28 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
nuCurve.vW = vWeCtrl ;
|
||||
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
|
||||
if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
|
||||
for ( int j = 0 ; j < snData.nCPV ; ++j ) {
|
||||
if ( snData.mCP[i].size() != nuCurve.vCP.size()){
|
||||
snData.mCP[i].clear() ;
|
||||
snData.mCP[i].resize( nuCurve.vCP.size()) ;
|
||||
if ( snData.bRat ) {
|
||||
snData.mW[i].clear() ;
|
||||
snData.mW[i].resize( nuCurve.vW.size()) ;
|
||||
}
|
||||
}
|
||||
for ( int j = 0 ; j < int( nuCurve.vCP.size()) ; ++j ) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[j] ;
|
||||
if ( snData.bRat ) {
|
||||
snData.mW[i][j] = nuCurve.vW[j] ;
|
||||
snData.mCP[i][j] *= nuCurve.vW[j] ;
|
||||
}
|
||||
}
|
||||
snData.vV = nuCurve.vU ;
|
||||
}
|
||||
}
|
||||
snData.bPeriodicV = false ;
|
||||
snData.nCPV = ssize( snData.mCP[0]) ;
|
||||
}
|
||||
return true;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+3793
-599
File diff suppressed because it is too large
Load Diff
+66
-39
@@ -20,11 +20,9 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
using namespace std ;
|
||||
class Tree ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
{
|
||||
@@ -69,13 +67,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
public : // ISurf
|
||||
bool IsSimple( void) const override
|
||||
{ return true ; }
|
||||
bool IsClosed( void) const override
|
||||
{ return false ; }
|
||||
bool IsClosed( void) const override ;
|
||||
bool GetArea( double& dArea) const override ;
|
||||
bool GetVolume( double& dVolume) const override
|
||||
{ if ( &dVolume == nullptr)
|
||||
return false ;
|
||||
if ( m_pSTM == nullptr)
|
||||
GetAuxSurf() ;
|
||||
dVolume = 0 ;
|
||||
if ( m_pSTM != nullptr)
|
||||
m_pSTM->GetVolume( dVolume) ;
|
||||
return true ; }
|
||||
bool GetCentroid( Point3d& ptCen) const override ;
|
||||
bool Invert( void) override ;
|
||||
@@ -99,6 +100,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
{ return GetControlWeight( GetInd( nIndU, nIndV), pbOk) ; }
|
||||
double GetControlWeight( int nInd, bool* pbOk) const override ;
|
||||
bool IsAPoint( void) const override ;
|
||||
bool GetPoint( double dU, double dV, Side nUs, Side nVs, Point3d& ptPos) const override ;
|
||||
bool GetPointD1D2( double dU, double dV, Side nUs, Side nVs,
|
||||
Point3d& ptPos,
|
||||
Vector3d* pvtDerU = nullptr, Vector3d* pvtDerV = nullptr,
|
||||
@@ -109,23 +111,23 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
Vector3d* pvtDerUU = nullptr, Vector3d* pvtDerVV = nullptr, Vector3d* pvtDerUV = nullptr) const override ;
|
||||
CurveComposite* GetCurveOnU( double dV) const override ;
|
||||
CurveComposite* GetCurveOnV( double dU) const override ;
|
||||
CurveComposite* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni)
|
||||
CurveComposite* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni)
|
||||
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
|
||||
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL) const override ;
|
||||
const SurfTriMesh* GetAuxSurfRefined( void) const override ;
|
||||
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) const override ;
|
||||
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
|
||||
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
|
||||
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
|
||||
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
|
||||
// a nIL si può passare 5 come valore di default
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = IntLineTriaType::ILTT_IN) const override ;
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ;
|
||||
// restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie
|
||||
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
|
||||
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
|
||||
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
|
||||
// pPlCut è il piano di taglio su cui giace la curva
|
||||
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
|
||||
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
|
||||
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev = P_INVALID, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
|
||||
// pPlCut è il piano di taglio su cui giace la curva
|
||||
bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ;
|
||||
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
|
||||
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
|
||||
@@ -134,9 +136,23 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
|
||||
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
|
||||
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
|
||||
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
|
||||
// restituisce un vettore con i loop della superficie ( più di uno solo se è trimmata con un parametrico con buchi o più di un chunk)
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier) const override ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const override ;
|
||||
bool IsPlanar( void) const override ;
|
||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr) override ;
|
||||
bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ;
|
||||
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
|
||||
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
|
||||
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ;
|
||||
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
|
||||
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
|
||||
bool RemoveCollapsedSpans() override ;
|
||||
bool SwapParameters() ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -148,7 +164,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
|
||||
public :
|
||||
SurfBezier( void) ;
|
||||
SurfBezier( const SurfBezier& sbSrc)
|
||||
SurfBezier( const SurfBezier& sbSrc) : m_pSTM( nullptr), m_pSTMRefined( nullptr), m_pTrimReg(nullptr)
|
||||
{ if ( ! CopyFrom( sbSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "SurfBezier : copy constructor error") }
|
||||
SurfBezier& operator =( const SurfBezier& sbSrc)
|
||||
@@ -189,32 +205,43 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
double GetCurveOnVApproxLen( double dU) const ;
|
||||
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
|
||||
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
||||
bool UpdateEdgesFromTree( Tree& tr) const ;
|
||||
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
|
||||
// funzione che calcola se gli edge sono collassati in poli
|
||||
bool CalcPoles( void) ;
|
||||
bool CalcPoles( void) const ;
|
||||
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ;
|
||||
bool ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ;
|
||||
bool ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ;
|
||||
bool GetBernstein( double dU, int nDegU, DBLVECTOR& vBernU) const ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria
|
||||
Status m_nStatus ; // stato
|
||||
int m_nDegU ; // grado in U
|
||||
int m_nDegV ; // grado in V
|
||||
int m_nSpanU ; // numero di pezze in U
|
||||
int m_nSpanV ; // numero di pezze in V
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
|
||||
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable vector<ICRVCOMPOPOVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
|
||||
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria per la visualizzazione
|
||||
mutable SurfTriMesh* m_pSTMRefined ; // superficie trimesh ausiliaria raffinata per i calcoli
|
||||
Status m_nStatus ; // stato
|
||||
int m_nDegU ; // grado in U
|
||||
int m_nDegV ; // grado in V
|
||||
int m_nSpanU ; // numero di pezze in U
|
||||
int m_nSpanV ; // numero di pezze in V
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U ( gli edge a V=0 e V=1 coincidono)
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V ( gli edge a U=0 e U=1 coincidono)
|
||||
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable std::vector<ICRVCOMPOPOVECTOR> m_mCCEdge ; // vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
|
||||
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
|
||||
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
|
||||
mutable DBLVECTOR m_vBernU ;
|
||||
mutable PNTVECTOR m_ptTemp ;
|
||||
mutable DBLVECTOR m_vBernV ;
|
||||
mutable PNTVECTOR m_ptTempW ;
|
||||
mutable DBLVECTOR m_dTempW ;
|
||||
mutable PNTVECTOR m_vPtWCtrlLoc ;
|
||||
mutable DBLVECTOR m_vWeCtrlLoc ;
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+300
-29
@@ -56,6 +56,7 @@ SurfFlatRegion::Clear( void)
|
||||
for ( auto& pLoop : m_vpLoop)
|
||||
delete pLoop ;
|
||||
m_vpLoop.clear() ;
|
||||
m_vExtInd.clear() ;
|
||||
|
||||
m_nTempProp[0] = 0 ;
|
||||
m_nTempProp[1] = 0 ;
|
||||
@@ -109,18 +110,25 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
|
||||
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
||||
return false ;
|
||||
// aggiungo le singole curve
|
||||
int nExtAdded = 0 ;
|
||||
bool bOk = true ;
|
||||
for ( auto& pSingCrv : CrvLst) {
|
||||
if ( ! AddSimpleExtLoop( pSingCrv))
|
||||
bool bAdded = false ;
|
||||
if ( AddSimpleExtLoop( pSingCrv, bAdded))
|
||||
++ nExtAdded ;
|
||||
else
|
||||
bOk = false ;
|
||||
|
||||
}
|
||||
return bOk ;
|
||||
return ( bOk && nExtAdded > 0) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
{
|
||||
// default
|
||||
bAdded = false ;
|
||||
// acquisisco la curva
|
||||
PtrOwner<ICurve> pMyCrv( pCrv) ;
|
||||
if ( IsNull( pMyCrv))
|
||||
@@ -133,8 +141,10 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
Plane3d plPlane ;
|
||||
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
||||
return false ;
|
||||
if ( dArea < SQ_EPS_SMALL)
|
||||
return true ;
|
||||
// se sto costruendo il primo chunk
|
||||
if ( m_vExtInd.size() == 0) {
|
||||
if ( m_vExtInd.empty()) {
|
||||
// assegno il riferimento intrinseco
|
||||
if ( ! m_frF.Set( ORIG + plPlane.GetVersN() * plPlane.GetDist(), plPlane.GetVersN()))
|
||||
return false ;
|
||||
@@ -198,6 +208,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
bAdded = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -547,7 +558,7 @@ SurfFlatRegion::Load( NgeReader& ngeIn)
|
||||
string sName ;
|
||||
int j ;
|
||||
bool bOk = ngeIn.ReadString( sName, ";") &&
|
||||
FromString( sName.substr(2), j) && i == j ;
|
||||
FromString( sName.substr( 2), j) && i == j ;
|
||||
int nChunk = 0, nLoop = 0 ;
|
||||
bOk = ngeIn.ReadInt( nChunk, ",") &&
|
||||
ngeIn.ReadInt( nLoop, ";", true) ;
|
||||
@@ -817,7 +828,7 @@ SurfFlatRegion::ConvertArcsToBezierCurves( void)
|
||||
// ciclo sui loop
|
||||
for ( auto& pLoop : m_vpLoop) {
|
||||
if ( pLoop->GetType() == CRV_ARC) {
|
||||
ICurve* pCrvNew = ArcToBezierCurve( pLoop) ;
|
||||
ICurve* pCrvNew = ArcToBezierCurve( GetCurveArc(pLoop)) ;
|
||||
if ( pCrvNew == nullptr)
|
||||
return false ;
|
||||
delete pLoop ;
|
||||
@@ -912,9 +923,6 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
bool
|
||||
SurfFlatRegion::GetArea( double& dArea) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// inizio con area nulla
|
||||
dArea = 0 ;
|
||||
// la regione deve essere validata
|
||||
@@ -937,9 +945,6 @@ SurfFlatRegion::GetArea( double& dArea) const
|
||||
bool
|
||||
SurfFlatRegion::GetGrossArea( double& dArea) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &dArea == nullptr)
|
||||
return false ;
|
||||
// inizio con area nulla
|
||||
dArea = 0 ;
|
||||
// la regione deve essere validata
|
||||
@@ -963,9 +968,6 @@ SurfFlatRegion::GetGrossArea( double& dArea) const
|
||||
bool
|
||||
SurfFlatRegion::GetCentroid( Point3d& ptCen) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &ptCen == nullptr)
|
||||
return false ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
@@ -991,13 +993,20 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfFlatRegion::GetChunkCount( void) const
|
||||
{
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return 0 ;
|
||||
return int( m_vExtInd.size()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
|
||||
{
|
||||
// controllo parametro di ritorno
|
||||
if ( &ptCen == nullptr)
|
||||
return false ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
@@ -1011,13 +1020,53 @@ SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfFlatRegion::GetChunkCount( void) const
|
||||
bool
|
||||
SurfFlatRegion::GetChunkArea( int nChunk, double& dArea) const
|
||||
{
|
||||
// default, area nulla
|
||||
dArea = 0 ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return 0 ;
|
||||
return int( m_vExtInd.size()) ;
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// il chunk deve esistere
|
||||
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// calcolo l'area
|
||||
bool bOk = true ;
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
|
||||
double dLoopArea ;
|
||||
if ( pLoop != nullptr && pLoop->GetAreaXY( dLoopArea))
|
||||
dArea += dLoopArea ;
|
||||
else
|
||||
bOk = false ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetChunkPerimeter( int nChunk, double& dLen) const
|
||||
{
|
||||
// default, perimetro nullo
|
||||
dLen = 0 ;
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// il chunk deve esistere
|
||||
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// calcolo il perimetro
|
||||
bool bOk = true ;
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nL) ;
|
||||
double dLoopLen ;
|
||||
if ( pLoop != nullptr && pLoop->GetLength( dLoopLen))
|
||||
dLen += dLoopLen ;
|
||||
else
|
||||
bOk = false ;
|
||||
}
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1118,6 +1167,19 @@ SurfFlatRegion::GetLoop( int nChunk, int nLoop) const
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfFlatRegion::GetLoopCurveCount( int nChunk, int nLoop) const
|
||||
{
|
||||
// recupero il loop nel riferimento intrinseco
|
||||
const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pMyCrv == nullptr)
|
||||
return 0 ;
|
||||
// restituisco il numero di curve di cui è composto
|
||||
const ICurveComposite* pMyCompo = GetCurveComposite( pMyCrv) ;
|
||||
return ( pMyCompo == nullptr ? 1 : pMyCompo->GetCurveCount()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const
|
||||
@@ -1149,21 +1211,26 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
|
||||
for ( int i = 0 ; i < GetChunkCount() ; ++ i) {
|
||||
// calcolo le polilinee che approssimano i loop
|
||||
POLYLINEVECTOR vPL ;
|
||||
vPL.resize( GetLoopCount( i)) ;
|
||||
vPL.reserve( GetLoopCount( i)) ;
|
||||
int j = 0 ;
|
||||
ICurve* pLoop = GetMyLoop( i, j) ;
|
||||
ICurve* pLoop = GetMyLoop( i, j) ;
|
||||
while ( pLoop != nullptr) {
|
||||
// approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
|
||||
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL[j]))
|
||||
vPL.emplace_back( PolyLine()) ;
|
||||
if ( ! pLoop->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_RIGHT, vPL.back()))
|
||||
return nullptr ;
|
||||
double dLoopArea ;
|
||||
if ( ! vPL.back().GetAreaXY( dLoopArea) || abs( dLoopArea) <= 25 * SQ_EPS_SMALL)
|
||||
vPL.pop_back() ;
|
||||
pLoop = GetMyLoop( i, ++j) ;
|
||||
}
|
||||
// se chunk abbastanza grande, creo la superficie trimesh relativa
|
||||
double dArea ;
|
||||
if ( vPL[0].GetAreaXY( dArea) && dArea > 100 * SQ_EPS_SMALL) {
|
||||
if ( ! vPL.empty() && vPL[0].GetAreaXY( dArea) && dArea > 25 * SQ_EPS_SMALL) {
|
||||
// creo, setto la superficie trimesh ed elimino punti ripetuti
|
||||
PtrOwner<SurfTriMesh> pChSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL) || ! pChSTM->DoCompacting())
|
||||
INTMATRIX vnPLIndMat ;
|
||||
if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL, vnPLIndMat) || ! pChSTM->DoCompacting())
|
||||
return nullptr ;
|
||||
// porto la trimesh in globale al riferimento intrinseco
|
||||
pChSTM->ToGlob( m_frF) ;
|
||||
@@ -1171,7 +1238,10 @@ SurfFlatRegion::CalcAuxSurf( double dLinTol, double dAngTolDeg) const
|
||||
pSTM->DoSewing( *pChSTM) ;
|
||||
}
|
||||
}
|
||||
// la restituisco
|
||||
// se vuota
|
||||
if ( pSTM->IsEmpty())
|
||||
pSTM->AdjustTopology() ;
|
||||
// la restituisco
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
@@ -1226,6 +1296,56 @@ SurfFlatRegion::CloneChunk( int nChunk) const
|
||||
return Release( pSfr) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::EraseChunk(int nChunk)
|
||||
{
|
||||
// la regione deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// il chunk deve esistere
|
||||
if ( nChunk < 0 || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// se un solo chunk, resetto la regione
|
||||
if ( GetChunkCount() == 1) {
|
||||
Clear() ;
|
||||
return true ;
|
||||
}
|
||||
// se ultimo chunk
|
||||
if ( nChunk == m_vExtInd.size() - 1) {
|
||||
// elimino i loop
|
||||
for ( int i = m_vExtInd[nChunk] ; i < int( m_vpLoop.size()) ; ++ i) {
|
||||
delete m_vpLoop[i] ;
|
||||
m_vpLoop[i] = nullptr ;
|
||||
}
|
||||
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.end()) ;
|
||||
// elimino indice di loop esterno
|
||||
m_vExtInd.pop_back() ;
|
||||
}
|
||||
// altrimenti
|
||||
else {
|
||||
// numero di loop da eliminare
|
||||
int nLoopCnt = m_vExtInd[nChunk+1] - m_vExtInd[nChunk] ;
|
||||
// elimino i loop
|
||||
for ( int i = m_vExtInd[nChunk] ; i < m_vExtInd[nChunk+1] ; ++ i) {
|
||||
delete m_vpLoop[i] ;
|
||||
m_vpLoop[i] = nullptr ;
|
||||
}
|
||||
m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.begin() + m_vExtInd[nChunk+1]) ;
|
||||
// elimino indice di loop esterno
|
||||
m_vExtInd.erase( m_vExtInd.begin() + nChunk) ;
|
||||
// aggiorno indice inizio chunk successivi
|
||||
for ( int i = nChunk ; i < int( m_vExtInd.size()) ; ++i)
|
||||
m_vExtInd[i] -= nLoopCnt ;
|
||||
}
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetAuxSurf() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
|
||||
@@ -1480,3 +1600,154 @@ SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const
|
||||
|
||||
return m_pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetChunkMaxOffset( int nChunk, double& dOffs) const
|
||||
{
|
||||
// verifico se è stato calcolato Voronoi
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
if ( ! CalcVoronoiObject())
|
||||
return false ;
|
||||
|
||||
// il massimo offset per il chunk è il massimo offset del suo loop esterno
|
||||
// ( il diagramma di Voronoi tiene già conto della limitazione con i loop interni)
|
||||
int nInd = GetIndFromChunkLoop( nChunk, 0) ;
|
||||
return m_pVoronoiObj->CalcLimitOffset( nInd, true, dOffs) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetMaxOffset( double& dOffs) const
|
||||
{
|
||||
int nChunks = GetChunkCount() ;
|
||||
if ( nChunks == 0)
|
||||
return false ;
|
||||
|
||||
// calcolo il massimo fra gli offset limite di tutti i suoi chunks
|
||||
if ( ! GetChunkMaxOffset( 0, dOffs))
|
||||
return false ;
|
||||
for ( int i = 1 ; i < nChunks ; i++) {
|
||||
double dCurrOffs ;
|
||||
if ( ! GetChunkMaxOffset( i, dCurrOffs))
|
||||
return false ;
|
||||
if ( dCurrOffs > dOffs)
|
||||
dOffs = dCurrOffs ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd)
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
pLoop->SetTempProp( nProp, nPropInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->SetCurveTempProp( nCrv, nProp, nPropInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd) const
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
nProp = pLoop->GetTempProp( nPropInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->GetCurveTempProp( nCrv, nProp, nPropInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::ResetAllCurveTempProps( void)
|
||||
{
|
||||
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
|
||||
ICurve* pLoop = GetMyLoop( nC, nL) ;
|
||||
if ( pLoop != nullptr) {
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
pLoop->SetTempProp( 0, 0) ;
|
||||
pLoop->SetTempProp( 0, 1) ;
|
||||
}
|
||||
else {
|
||||
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
|
||||
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
|
||||
pCompoLoop->SetCurveTempProp( nI, 0, 0) ;
|
||||
pCompoLoop->SetCurveTempProp( nI, 0, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd)
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
pLoop->SetTempParam( dParam, nParamInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->SetCurveTempParam( nCrv, dParam, nParamInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd) const
|
||||
{
|
||||
ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
if ( pLoop == nullptr)
|
||||
return false ;
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
if ( nCrv != 0)
|
||||
return false ;
|
||||
dParam = pLoop->GetTempParam( nParamInd) ;
|
||||
return true ;
|
||||
}
|
||||
return GetBasicCurveComposite( pLoop)->GetCurveTempParam( nCrv, dParam, nParamInd) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::ResetAllCurveTempParams( void)
|
||||
{
|
||||
for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) {
|
||||
ICurve* pLoop = GetMyLoop( nC, nL) ;
|
||||
if ( pLoop != nullptr) {
|
||||
if ( pLoop->GetType() != CRV_COMPO) {
|
||||
pLoop->SetTempParam( 0, 0) ;
|
||||
pLoop->SetTempParam( 0, 1) ;
|
||||
}
|
||||
else {
|
||||
CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ;
|
||||
for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) {
|
||||
pCompoLoop->SetCurveTempParam( nI, 0, 0) ;
|
||||
pCompoLoop->SetCurveTempParam( nI, 0, 1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+21
-9
@@ -94,18 +94,30 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
{ return m_frF.Orig() ; }
|
||||
const Vector3d& GetNormVersor( void) const override
|
||||
{ return m_frF.VersZ() ; }
|
||||
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
|
||||
void ResetVoronoiObject( void) const override ;
|
||||
bool GetMaxOffset( double& dOffs) const override ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
|
||||
int GetChunkCount( void) const override ;
|
||||
SurfFlatRegion* CloneChunk( int nChunk) const override ;
|
||||
bool EraseChunk(int nChunk) override ;
|
||||
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
|
||||
bool GetChunkArea( int nChunk, double& dArea) const override ;
|
||||
bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
|
||||
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
|
||||
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
|
||||
int GetLoopCount( int nChunk) const override ;
|
||||
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
|
||||
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
|
||||
bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
SurfFlatRegion* CloneChunk( int nChunk) const override ;
|
||||
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
|
||||
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
|
||||
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
|
||||
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
|
||||
void ResetVoronoiObject( void) const override ;
|
||||
bool SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd = 0) override ;
|
||||
bool GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd = 0) const override ;
|
||||
bool ResetAllCurveTempProps( void) override ;
|
||||
bool SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool ResetAllCurveTempParams( void) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -136,7 +148,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
|
||||
private :
|
||||
bool CopyFrom( const SurfFlatRegion& clSrc) ;
|
||||
bool AddSimpleExtLoop( ICurve* pCrv) ;
|
||||
bool AddSimpleExtLoop( ICurve* pCrv, bool& bAdded) ;
|
||||
bool MyAddExtLoop( ICurve* pCrv) ;
|
||||
bool AddSimpleIntLoop( ICurve* pCrv) ;
|
||||
bool MyAddIntLoop( ICurve* pCrv, int nChunk) ;
|
||||
|
||||
@@ -168,7 +168,7 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
|
||||
|
||||
// creo una nuova regione a partire da questi loop
|
||||
PtrOwner<SurfFlatRegion> pSfr ;
|
||||
if ( vpLoop.size() == 0)
|
||||
if ( vpLoop.empty())
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||
@@ -258,7 +258,7 @@ SurfFlatRegion::Intersect( const ISurfFlatRegion& Other)
|
||||
|
||||
// creo una nuova regione a partire da questi loop
|
||||
PtrOwner<SurfFlatRegion> pSfr ;
|
||||
if ( vpLoop.size() == 0)
|
||||
if ( vpLoop.empty())
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||
|
||||
@@ -148,7 +148,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
return nullptr ;
|
||||
|
||||
// costruisco la superficie
|
||||
if ( vOffs.size() > 0) {
|
||||
if ( ! vOffs.empty()) {
|
||||
PCRV_DEQUE vLoops ;
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
|
||||
vOffs[i]->ToLoc( m_frF) ;
|
||||
@@ -162,7 +162,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
}
|
||||
|
||||
// verifico di avere ancora dei loops
|
||||
if ( vLoops.size() > 0) {
|
||||
if ( ! vLoops.empty()) {
|
||||
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
|
||||
if ( IsNull( pSfr)) {
|
||||
MyTestAndDelete( vLoops) ;
|
||||
|
||||
+800
-276
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user