Compare commits
536 Commits
FasterBezier
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 37aaa98df6 | |||
| 2dcaa57aa3 | |||
| ba7379e752 | |||
| 6646aee01c | |||
| 7f8382f1b8 | |||
| 4bcdb03598 | |||
| 68e9be7901 | |||
| 9e3bac4a68 | |||
| 1fee7b8e49 | |||
| f668d7ac11 | |||
| 4a1c13154f | |||
| 68a9848748 | |||
| f5059166ed | |||
| ad7f209fc9 | |||
| 8b5bfb6e19 | |||
| 1efd17f6ee | |||
| b8caeb49e0 | |||
| a9fc259745 | |||
| bbc98fe282 | |||
| a445ddd89b | |||
| e874b2eb36 | |||
| a45faa4793 | |||
| 344f0da7ff | |||
| cea869c6ee | |||
| 8ad2887c38 | |||
| 2b1d2a512d | |||
| a55770d702 | |||
| 2e4b1cdd40 | |||
| 3ffc0b40d8 | |||
| cd2cde40da | |||
| efc656a72c | |||
| e1eb139aee | |||
| e7d25b2d0e | |||
| ce05ce577c | |||
| ae2cac48d1 | |||
| 37e9a05347 | |||
| 02cb8a0d3c | |||
| 6942f5fc23 | |||
| 6c4bf3f05a | |||
| 4bc8590ce9 | |||
| 5b68e33d1f | |||
| a70f7ee9c9 | |||
| 95a070413a | |||
| 223489e80d | |||
| f6a535d94c | |||
| dbc3e7d2bf | |||
| a3d44261bb | |||
| 9220fd568f | |||
| 17346e1b42 | |||
| c95ef6764d | |||
| d0f2d56bdb | |||
| fb037f2f2a | |||
| 2d94dddccb | |||
| d2d025a594 | |||
| 64abf640f6 | |||
| cb2b63320a | |||
| 951d3781d6 | |||
| 27bd0e579e | |||
| ff7d564de8 | |||
| a27b9e871a | |||
| eb497cbd39 | |||
| dd3091fc13 | |||
| 69d463713c | |||
| 5e918ff3aa | |||
| b4522c712d | |||
| fa9a9e89cb | |||
| d51a0d2258 | |||
| 580230b38b | |||
| 4b24906d2e | |||
| 2094a1cc0d | |||
| b8b639699a | |||
| 0b86c4f72b | |||
| 5c93384690 | |||
| b77db4a5bc | |||
| c704d94829 | |||
| 0373021b7a | |||
| 6de856b3e1 | |||
| a231d8f26c | |||
| 745a7eb38c | |||
| 78c40ebca7 | |||
| a39af1c3a3 | |||
| c2a0f9dff1 | |||
| 6be67258d2 | |||
| 6c76943bf4 | |||
| 9306f5be9d | |||
| 944ce79776 | |||
| 313c735956 | |||
| 007ed1701c | |||
| 7385709bb4 | |||
| da4cd4c482 | |||
| dee744725c | |||
| 2aca943de4 | |||
| 25f6bae120 | |||
| c92d841011 | |||
| 398c8c430a | |||
| 79dc8f8fc2 | |||
| 1545bc07cd | |||
| 44edef378a | |||
| 679efc22e8 | |||
| 1076dc54dc | |||
| e091f253d0 | |||
| 3206961b88 | |||
| 48b2029d19 | |||
| a2ca0ac6f7 | |||
| 4155dd3e5a | |||
| 5a3b7e311c | |||
| 991586a880 | |||
| de4165889a | |||
| 42c5ffb014 | |||
| e394615f84 | |||
| 1008ba4229 | |||
| f4328430b9 | |||
| 1d6bc847da | |||
| d76beb09ee | |||
| 026436b914 | |||
| ebc5fd7ee7 | |||
| 82a211753e | |||
| a258e9cb31 | |||
| 157885f71a | |||
| f227a9cba7 | |||
| 39360eefd7 | |||
| 6b5fb15c9b | |||
| 4e698d4049 | |||
| e20bd7fd0c | |||
| 7e62acf351 | |||
| 421bc2eb3b | |||
| db98fa5d5a | |||
| 5f28258d16 | |||
| 8f06488b33 | |||
| ac7ba1b12c | |||
| 67131a1482 | |||
| a92cba8697 | |||
| 52cca7233e | |||
| b2beed0fe0 | |||
| 1f301b6100 | |||
| c74ca4932f | |||
| fafcd67a2c | |||
| 390cc3bd8b | |||
| b2ccda1b34 | |||
| 69916e7756 | |||
| 3a7b6f1343 | |||
| 71a054749c | |||
| 06d87d5c52 | |||
| 98c576afe0 | |||
| 6d544f93f4 | |||
| 3c1a7ff1bb | |||
| ae8f80d6e9 | |||
| 9b933bd26d | |||
| baa8736276 | |||
| 73bedf4f55 | |||
| bae8d4651d | |||
| c75a7e9514 | |||
| 233f64e68f | |||
| f9127ce64d | |||
| 86338db67d | |||
| da7ebd6f61 | |||
| 8db1765505 | |||
| 2438d1d23a | |||
| f790736fd7 | |||
| 985b69ae33 | |||
| 6faf5ccde2 | |||
| 2e129d7b06 | |||
| 5d2e1ff608 | |||
| a9f8ef2ff3 | |||
| 2b7070e408 | |||
| 571a24b419 | |||
| 5f132ae3d3 | |||
| fe5a09281e | |||
| b66522de33 | |||
| e87ef178c2 | |||
| 0987496caf | |||
| 5ad9c48285 | |||
| ec6eb3e645 | |||
| 64c3363426 | |||
| 2023ba3f7d | |||
| 27c1823a54 | |||
| f111827545 | |||
| 7cdc1ba5a3 | |||
| 1d68a1ee8e | |||
| b426ccc04d | |||
| a1c448d8dd | |||
| 25d53338c2 | |||
| 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 | |||
| b3ebb35d01 | |||
| a508da8b18 | |||
| 91ca84f77a | |||
| d27fdb9904 | |||
| 3b816e2a45 | |||
| 1ad96ce8ca | |||
| 36422c43b3 | |||
| 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 | |||
| 851c053f7c | |||
| 71276a8de3 | |||
| b2e799e1d6 | |||
| eb9aaef53a | |||
| 0b9c9f375c | |||
| cd56f80790 | |||
| 9d34df708d | |||
| 72947f1e36 | |||
| 1cdae73b24 |
+2
-2
@@ -151,11 +151,11 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
else {
|
||||
double dParA = vIccInfo[i].IciA[0].dU ;
|
||||
double dParB = vIccInfo[i].IciB[0].dU ;
|
||||
if ( abs( dParA - dEnd) < EPS_SMALL)
|
||||
if ( dParA > dParB)
|
||||
swap( dParA, dParB) ;
|
||||
// verifico se uno dei due intervalli dà origine ad un tratto trascurabile
|
||||
PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ;
|
||||
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
|
||||
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
|
||||
double dArea1 = 0, dArea2 = 0 ;
|
||||
if ( ! IsNull( pCrv1))
|
||||
pCrv1->GetAreaXY( dArea1) ;
|
||||
|
||||
+152
-109
@@ -311,7 +311,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol,
|
||||
bool bAdvCorners)
|
||||
{
|
||||
|
||||
// se non ho polylinee, allora esco
|
||||
if ( vPL.empty())
|
||||
return true ;
|
||||
@@ -341,10 +340,45 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, mIndMat, vbInv))
|
||||
return false ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
|
||||
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
|
||||
// ombra del tool
|
||||
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
|
||||
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
|
||||
// 1° gruppo, griglia di punti
|
||||
for ( int j = 0 ; j <= nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= nStepX ; ++ i) {
|
||||
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
|
||||
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
|
||||
myPtGrid->Set( ptP) ;
|
||||
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
|
||||
vvCol[0].emplace_back( BLUE) ;
|
||||
}
|
||||
}
|
||||
// 2° gruppo, superfici
|
||||
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
|
||||
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
|
||||
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
|
||||
if ( ! IsNull( pMyStm)) {
|
||||
pMyStm->ToLoc( frGrid) ;
|
||||
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
|
||||
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// vettore delle polyline visitate ( viste però come curve composite)
|
||||
ICRVCOMPOPOVECTOR vPL_AsCompo ; vPL_AsCompo.reserve( vPL.size()) ;
|
||||
|
||||
// scorro i Chunk della matrice di interi, quindi le righe
|
||||
for ( int nChunk = 0 ; nChunk < int( mIndMat.size()) ; ++ nChunk) {
|
||||
// scorro le PolyLinee presenti nel Chunk
|
||||
for ( int nPol = 0 ; nPol < int( vPL.size()) ; ++ nPol) {
|
||||
for ( int nLoop = 0 ; nLoop < int( mIndMat[nChunk].size()) ; ++ nLoop) {
|
||||
// recupero l'indice della PolyLine di riferimento
|
||||
int nPol = mIndMat[nChunk][nLoop] ;
|
||||
if ( nPol < 0 || nPol >= int( vPL.size()))
|
||||
return false ;
|
||||
// essendo chiusa, se presenti meno di 4 punti, non faccio nulla
|
||||
int nPts = vPL[nPol].GetPointNbr() ;
|
||||
if ( nPts < 4)
|
||||
@@ -380,33 +414,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
|
||||
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
|
||||
// ombra del tool
|
||||
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
|
||||
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
|
||||
// 1° gruppo, griglia di punti
|
||||
for ( int j = 0 ; j <= nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= nStepX ; ++ i) {
|
||||
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
|
||||
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
|
||||
myPtGrid->Set( ptP) ;
|
||||
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
|
||||
vvCol[0].emplace_back( BLUE) ;
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
// 2° gruppo, superfici
|
||||
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
|
||||
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
|
||||
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
|
||||
if ( ! IsNull( pMyStm)) {
|
||||
pMyStm->ToLoc( frGrid) ;
|
||||
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
|
||||
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
|
||||
}
|
||||
}
|
||||
// 3° gruppo, punti della PolyLine
|
||||
for ( int i = 0 ; i < int( vAdvPt.size()) ; ++ i) {
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
@@ -416,23 +423,23 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
}
|
||||
#endif
|
||||
|
||||
// modifico la posizione dei punti
|
||||
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
|
||||
return false ;
|
||||
// modifico la posizione dei punti
|
||||
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
|
||||
return false ;
|
||||
|
||||
// ricostrusico la polyLine
|
||||
vPL[nPol].Clear() ;
|
||||
// ricostrusico la polyLine a partire da una vuota
|
||||
PolyLine PL_New ;
|
||||
double dPar = -1 ;
|
||||
for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) {
|
||||
// se punto valido o sharped di angolo interno, lo aggiungo
|
||||
if ( j == 0 || j == int( vAdvPt.size() - 1) ||
|
||||
vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT)
|
||||
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
// se è un punto sharped di un angolo esterno
|
||||
else if ( vAdvPt[j].second == PointType::SHARPED_EXT) {
|
||||
// se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto
|
||||
if ( ! bAdvCorners)
|
||||
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
else {
|
||||
// ricavo il punto a minima distanza dal materiale mediante metodo di bisezione
|
||||
Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ;
|
||||
@@ -463,51 +470,29 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ;
|
||||
distPtLPrev.GetMinDistPoint( ptMinDistA) ;
|
||||
distPtLSucc.GetMinDistPoint( ptMinDistB) ;
|
||||
vPL[nPol].AddUPoint( ++ dPar, ptMinDistA) ;
|
||||
vPL[nPol].AddUPoint( ++ dPar, ptTest) ;
|
||||
vPL[nPol].AddUPoint( ++ dPar, ptMinDistB) ;
|
||||
}
|
||||
PL_New.AddUPoint( ++ dPar, ptMinDistA) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptTest) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptMinDistB) ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 5° gruppo, punti minDist A e B e ptMid
|
||||
/*PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
|
||||
myPtA->Set( ptMinDistA) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
|
||||
myPtB->Set( ptMinDistB) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
|
||||
myPtMid->Set( ptTest) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;*/
|
||||
#endif
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 5° gruppo, punti minDist A e B e ptMid
|
||||
PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
|
||||
myPtA->Set( ptMinDistA) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
|
||||
myPtB->Set( ptMinDistB) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
|
||||
myPtMid->Set( ptTest) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// riposiziono la polyLine
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 6° gruppo, curve composita derivante dalla polyline
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( vPL[nPol]) ;
|
||||
//pCrvCompoPoly->SetExtrusion( frGrid.VersZ()) ;
|
||||
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
|
||||
vvCol[5].emplace_back( RED) ;
|
||||
// 7° gruppo, controOffset
|
||||
OffsetCurve offsCrv ;
|
||||
offsCrv.Make( pCrvCompoPoly, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
|
||||
pCrvCompoPoly.Set( ConvertCurveToComposite( offsCrv.GetLongerCurve())) ;
|
||||
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( Release( pCrvCompoPoly))) ;
|
||||
vvCol[6].emplace_back( WHITE) ;
|
||||
string myName = Sharped_Edges_Debug_File_Name +
|
||||
to_string( nChunk) + "_" +
|
||||
to_string( nPol) + "_" +
|
||||
to_string( dLevel) + "_" +
|
||||
to_string( dAngTol) + ".nge" ;
|
||||
SaveGeoObj( vvpGObj, vvCol, myName) ;
|
||||
#endif
|
||||
|
||||
// se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla
|
||||
// trimesh rischio di evere Chunk distinti uniti in un unico Chunk
|
||||
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
||||
@@ -515,11 +500,53 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
return false ;
|
||||
pCompo->FromPolyLine( vPL[nPol]) ;
|
||||
SelfIntersCurve SIC( *pCompo) ;
|
||||
if ( SIC.GetCrossOrOverlapIntersCount() > 0)
|
||||
continue ;
|
||||
bool bDiscard = ( SIC.GetCrossOrOverlapIntersCount() > 0) ;
|
||||
if ( ! bDiscard) {
|
||||
// se la polyLine interseca una delle PolyLine precedenti, non la modifico
|
||||
for ( auto& pCompoPL_Prev : vPL_AsCompo) {
|
||||
IntersCurveCurve ICC( *pCompo, *pCompoPL_Prev) ;
|
||||
if ( ICC.GetCrossOrOverlapIntersCount() > 0) {
|
||||
bDiscard = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se nuova approssimazione da conservare, memorizzo i risultati
|
||||
if ( ! bDiscard) {
|
||||
vPL[nPol] = PL_New ;
|
||||
vPL_AsCompo.emplace_back( Release( pCompo)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
|
||||
for ( const auto& PL : vPL) {
|
||||
// 6° gruppo, curve composita derivante dalla polyline
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( PL) ;
|
||||
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
|
||||
vvCol[5].emplace_back( RED) ;
|
||||
vpCrv.emplace_back( Release( pCrvCompoPoly)) ;
|
||||
}
|
||||
// 7° gruppo, controOffset
|
||||
ICURVEPOVECTOR vCrvCompoOffs ;
|
||||
if ( ! CalcOffsetCurves( vpCrv, vCrvCompoOffs, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND)) {
|
||||
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
|
||||
return false ;
|
||||
}
|
||||
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
|
||||
for ( const auto& pCvrOffs : vCrvCompoOffs) {
|
||||
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCvrOffs))) ;
|
||||
vvCol[6].emplace_back( WHITE) ;
|
||||
}
|
||||
string myName = Sharped_Edges_Debug_File_Name +
|
||||
to_string( dLevel) + "_" +
|
||||
to_string( dAngTol) + ".nge" ;
|
||||
SaveGeoObj( vvpGObj, vvCol, myName) ;
|
||||
#endif
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -785,21 +812,31 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false))
|
||||
swap( vPL_Sharped, vPL) ;
|
||||
|
||||
// se vettore di PolyLine vuoto, non faccio nulla
|
||||
if ( vPL.empty())
|
||||
return true ;
|
||||
|
||||
// se non ho impostato un utensile, devo effettuare un contro-offset
|
||||
if ( ! bTool) {
|
||||
POLYLINEVECTOR vPL_Offs ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
CurveComposite crvCompo ;
|
||||
if ( ! crvCompo.FromPolyLine( vPL[i]))
|
||||
return false ;
|
||||
OffsetCurve offsCompo ;
|
||||
offsCompo.Make( &crvCompo, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
|
||||
PtrOwner<ICurve> pCrvOffset( offsCompo.GetLongerCurve()) ;
|
||||
while ( ! IsNull( pCrvOffset)) {
|
||||
ICURVEPOVECTOR vpOwCrv ; vpOwCrv.reserve( vPL.size()) ;
|
||||
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
|
||||
for ( const auto& PL : vPL) {
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( PL) ;
|
||||
vpOwCrv.emplace_back( Release( pCrvCompoPoly)) ;
|
||||
vpCrv.emplace_back( vpOwCrv.back()) ;
|
||||
}
|
||||
// calcolo l'Offset
|
||||
ICURVEPOVECTOR vpCrvOffs ;
|
||||
if ( ! CalcOffsetCurves( vpCrv, vpCrvOffs, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
// resituisco le PolyLine
|
||||
POLYLINEVECTOR vPL_Offs ; vPL_Offs.reserve( vpCrvOffs.size()) ;
|
||||
for ( auto& pCrv : vpCrvOffs) {
|
||||
if ( pCrv != nullptr && pCrv->IsValid()) {
|
||||
PolyLine myPolyLine ;
|
||||
pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
|
||||
pCrv->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
|
||||
vPL_Offs.emplace_back( myPolyLine) ;
|
||||
pCrvOffset.Set( offsCompo.GetLongerCurve()) ;
|
||||
}
|
||||
}
|
||||
swap( vPL_Offs, vPL) ;
|
||||
@@ -976,28 +1013,13 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
return false ;
|
||||
b3All.Add( b3Surf) ;
|
||||
}
|
||||
|
||||
// calcolo dati della griglia
|
||||
const double EXTRA_XY = ( m_bTool ? m_dRad + 2 : 1.5 * m_dTol) ;
|
||||
// espansione in Z del Box
|
||||
const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ;
|
||||
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ;
|
||||
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
||||
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
||||
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
|
||||
b3All.Expand( 0., 0., EXTRA_Z) ;
|
||||
m_dDimZ = b3All.GetDimZ() ;
|
||||
m_dLevelOffs = - b3All.GetMin().z ;
|
||||
|
||||
// calcolo dei punti della griglia (sul top del cilindro)
|
||||
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
|
||||
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
|
||||
int nInd = i + j * ( m_nStepX + 1) ;
|
||||
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
|
||||
vPntM[nInd] = { ptP, 0.} ;
|
||||
}
|
||||
}
|
||||
|
||||
// esecuzione della verifica
|
||||
// set utensile corrente per calcolo delle collisioni
|
||||
double dExtraXY = m_dRad + m_dOffsR ;
|
||||
if ( m_dSideAng < EPS_ANG_SMALL)
|
||||
m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||
else {
|
||||
@@ -1015,8 +1037,29 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
|
||||
double dStemRad = m_dRad + dDeltaRad ;
|
||||
double dTipRad = m_dRad ;
|
||||
dExtraXY = dStemRad + m_dOffsR ;
|
||||
m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||
}
|
||||
|
||||
// calcolo dati della griglia
|
||||
const double EXTRA_XY = ( m_bTool ? dExtraXY + 2. : 1.5 * m_dTol) ;
|
||||
b3All.Expand( EXTRA_XY, EXTRA_XY, 0.) ;
|
||||
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
|
||||
m_dLevelOffs = - b3All.GetMin().z ;
|
||||
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
||||
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
||||
|
||||
// calcolo dei punti della griglia (sul top del cilindro)
|
||||
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
|
||||
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
|
||||
int nInd = i + j * ( m_nStepX + 1) ;
|
||||
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
|
||||
vPntM[nInd] = { ptP, 0.} ;
|
||||
}
|
||||
}
|
||||
|
||||
// esecuzione verifica della collisione
|
||||
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
|
||||
return false ;
|
||||
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
|
||||
|
||||
@@ -140,16 +140,20 @@ MyCAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) {
|
||||
m_SCollInfo = scInfoCurr ;
|
||||
m_SCollInfo.nChunkM = j ;
|
||||
m_SCollInfo.nLoopM = 0 ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = i ;
|
||||
m_SCollInfo.nLoopF = 0 ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
}
|
||||
else if ( dNewLenXY < dPrevLenXY) {
|
||||
m_SCollInfo = scInfoCurr ;
|
||||
m_SCollInfo.nChunkM = j ;
|
||||
m_SCollInfo.nLoopM = 0 ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = i ;
|
||||
m_SCollInfo.nLoopF = 0 ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
|
||||
@@ -30,7 +30,7 @@ class MyCAvSimpleSurfFrMove
|
||||
const SCollInfo& GetSCollInfo()
|
||||
{ return m_SCollInfo ;}
|
||||
|
||||
private :
|
||||
protected :
|
||||
bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2,
|
||||
const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ;
|
||||
bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
|
||||
@@ -40,7 +40,7 @@ class MyCAvSimpleSurfFrMove
|
||||
bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
|
||||
const Point3d& ptCen, double& dAng) ;
|
||||
|
||||
private :
|
||||
protected :
|
||||
const SurfFlatRegion* m_pRegM ;
|
||||
const SurfFlatRegion* m_pRegF ;
|
||||
SCollInfo m_SCollInfo ;
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2026-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CASurfFrMove.cpp Data : 26.03.2026 Versione : 3.1c7
|
||||
// Contenuto : Implementazione delle funzioni di movimento per SurfFlatRegion
|
||||
// senza collisione con altri oggetti dello stesso tipo e nello
|
||||
// stesso piano o in piani paralleli.
|
||||
//
|
||||
//
|
||||
// Modifiche : 26.03.2026 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CAvSurfFrMove.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "IntersLineArc.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkCAvSurfFrMove.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CASurfFrMove
|
||||
//----------------------------------------------------------------------------
|
||||
CAvSurfFrMove::CAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF)
|
||||
{
|
||||
// salvo puntatori alle regioni
|
||||
m_pRegM = &SfrM ;
|
||||
m_pRegF = &SfrF ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
{
|
||||
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
|
||||
m_CollInfo.nType = SCI_NONE ;
|
||||
if ( ! ScdMove.Translate( vtDir, dLen))
|
||||
return false ;
|
||||
m_CollInfo = ScdMove.GetCollInfo() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
|
||||
{
|
||||
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
|
||||
m_CollInfo.nType = SCI_NONE ;
|
||||
return ScdMove.Rotate( ptCen, dAng) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MyCAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
{
|
||||
// verifico validità regioni
|
||||
if ( m_pRegM == nullptr || m_pRegF == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico che le due regioni giacciano in piani paralleli
|
||||
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
|
||||
return false ;
|
||||
|
||||
// reset info di collisione
|
||||
m_SCollInfo.nType = SCI_NONE ;
|
||||
|
||||
// porto il vettore di movimento nel riferimento intrinseco e ne annullo la componente Z
|
||||
Vector3d vtDirL = vtDir ;
|
||||
vtDirL.ToLoc( m_pRegM->m_frF) ;
|
||||
vtDirL.z = 0 ;
|
||||
double dLenXY = vtDirL.Len() ;
|
||||
if ( dLenXY < EPS_SMALL)
|
||||
return true ;
|
||||
vtDirL /= dLenXY ;
|
||||
dLenXY *= dLen ;
|
||||
double dNewLenXY = dLenXY ;
|
||||
|
||||
// ciclo sui chunk della seconda superficie
|
||||
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
|
||||
// ciclo sui bordi dei chunk
|
||||
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
|
||||
|
||||
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
|
||||
const ICurve* pCrv2Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
|
||||
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
|
||||
else {
|
||||
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
|
||||
pCrv2Loc = pCopyCrv ;
|
||||
}
|
||||
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
|
||||
|
||||
// ciclo sui chunk della prima superficie
|
||||
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
|
||||
// ciclo sui bordi del chunk
|
||||
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
|
||||
|
||||
// per CAv non ha senso confrontare due loop interni tra di loro.
|
||||
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
|
||||
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
|
||||
if ( nLF > 0 && nLM > 0)
|
||||
continue ;
|
||||
|
||||
// curva corrente del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
|
||||
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
|
||||
|
||||
// verifico la collisione tra le entità dei loop esterni dei due chunk
|
||||
int k = 0 ;
|
||||
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
|
||||
while ( pCrv1 != nullptr) {
|
||||
int l = 0 ;
|
||||
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
|
||||
while ( pCrv2 != nullptr) {
|
||||
SCollInfo cInfoCurr ;
|
||||
double dPrevLenXY = dNewLenXY ;
|
||||
if ( ! TranslateCurveNoCollisionCurve( pCrv1, pCrv2, vtDirL, dNewLenXY, cInfoCurr))
|
||||
return false ;
|
||||
if ( abs( dNewLenXY - dPrevLenXY) < EPS_SMALL) {
|
||||
if ( cInfoCurr.nType == SCI_LINE_LINE || cInfoCurr.nType == SCI_PNT_LINE) {
|
||||
m_SCollInfo = cInfoCurr ;
|
||||
m_SCollInfo.nChunkM = nCM ;
|
||||
m_SCollInfo.nLoopM = nLM ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = nCF ;
|
||||
m_SCollInfo.nLoopF = nLF ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
}
|
||||
else if ( dNewLenXY < dPrevLenXY) {
|
||||
m_SCollInfo = cInfoCurr ;
|
||||
m_SCollInfo.nChunkM = nCM ;
|
||||
m_SCollInfo.nLoopM = nLM ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = nCF ;
|
||||
m_SCollInfo.nLoopF = nLF ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
++ l ;
|
||||
}
|
||||
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
|
||||
++ k ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se da limitare il movimento
|
||||
if ( dNewLenXY < dLenXY - EPS_SMALL)
|
||||
dLen *= dNewLenXY / dLenXY ;
|
||||
|
||||
// porto i punti e le direzioni di SCollInfo da intrinseco a locale della prima regione
|
||||
if ( m_SCollInfo.nType != SCI_NONE) {
|
||||
m_SCollInfo.ptP1.ToGlob( m_pRegM->m_frF) ;
|
||||
m_SCollInfo.vtDirM.ToGlob( m_pRegM->m_frF) ;
|
||||
m_SCollInfo.vtDirF.ToGlob( m_pRegM->m_frF) ;
|
||||
}
|
||||
if ( m_SCollInfo.nType == SCI_LINE_LINE)
|
||||
m_SCollInfo.ptP2.ToGlob( m_pRegM->m_frF) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MyCAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
|
||||
{
|
||||
// verifico validità regioni
|
||||
if ( m_pRegM == nullptr || m_pRegF == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico che le due regioni giacciano in piani paralleli
|
||||
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
|
||||
return false ;
|
||||
|
||||
// reset info di collisione
|
||||
m_SCollInfo.nType = SCI_NONE ;
|
||||
|
||||
// porto il centro di rotazione nel riferimento intrinseco e ne annullo la componente Z
|
||||
Point3d ptCenL = ptCen ;
|
||||
ptCenL.ToLoc( m_pRegM->m_frF) ;
|
||||
ptCenL.z = 0 ;
|
||||
if ( abs( dAng) < EPS_ANG_SMALL)
|
||||
return true ;
|
||||
double dNewAng = dAng ;
|
||||
|
||||
// ciclo sui chunk della seconda superficie
|
||||
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
|
||||
// ciclo sui bordi del Chunk
|
||||
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
|
||||
|
||||
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
|
||||
const ICurve* pCrv2Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
|
||||
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
|
||||
else {
|
||||
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
|
||||
pCrv2Loc = pCopyCrv ;
|
||||
}
|
||||
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
|
||||
|
||||
// ciclo sui chunk della prima superficie
|
||||
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
|
||||
// ciclo sui bordi del chunk
|
||||
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
|
||||
|
||||
// per CAv non ha senso confrontare due loop interni tra di loro.
|
||||
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
|
||||
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
|
||||
if ( nLF > 0 && nLM > 0)
|
||||
continue ;
|
||||
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
|
||||
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
|
||||
|
||||
// verifico la collisione tra le entità dei loop esterni dei due chunk
|
||||
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
|
||||
while ( pCrv1 != nullptr) {
|
||||
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
|
||||
while ( pCrv2 != nullptr) {
|
||||
if ( ! RotateCurveNoCollisionCurve( pCrv1, pCrv2, ptCenL, dNewAng))
|
||||
return false ;
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
}
|
||||
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se da limitare il movimento
|
||||
if ( ( dAng > 0 && dNewAng < dAng - EPS_ANG_SMALL) ||
|
||||
( dAng < 0 && dNewAng > dAng + EPS_ANG_SMALL))
|
||||
dAng = dNewAng ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2018
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CAvSurfFrMove.h Data : 27.04.18 Versione : 3.1c7
|
||||
// Contenuto : Dich.ne classe privata per movimento di superfici flat region
|
||||
// nel loro piano evitando collisioni
|
||||
//
|
||||
// Modifiche : 26.03.2026 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CAvSimpleSurfFrMove.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class MyCAvSurfFrMove : public MyCAvSimpleSurfFrMove
|
||||
{
|
||||
public :
|
||||
MyCAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) :
|
||||
MyCAvSimpleSurfFrMove( SfrM, SfrF) {} ;
|
||||
|
||||
public :
|
||||
bool Translate( const Vector3d& vtDir, double& dLen) ;
|
||||
bool Rotate( const Point3d& ptCen, double& dAng) ;
|
||||
const SCollInfo& GetCollInfo()
|
||||
{ return m_SCollInfo ; }
|
||||
} ;
|
||||
+2
-4
@@ -2440,12 +2440,10 @@ CAvDiskTriangle( const Point3d& ptDiskCen, const Vector3d& vtDiskAx, double dDis
|
||||
// Allontanamento dall'interno
|
||||
double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ;
|
||||
// Allontanamento dalla frontiera
|
||||
Vector3d vtMoveOrt = vtMove - vtMove * vtDiskAx * vtDiskAx ;
|
||||
Vector3d vtMoveOrt = OrthoCompo( vtMove, vtDiskAx) ;
|
||||
vtMoveOrt.Normalize() ;
|
||||
Frame3d DiskFrame ;
|
||||
Vector3d vtJ = vtDiskAx ^ vtMoveOrt ;
|
||||
vtJ.Normalize() ;
|
||||
DiskFrame.Set( ptDiskCen, vtMoveOrt, vtJ, vtDiskAx) ;
|
||||
DiskFrame.Set( ptDiskCen, vtDiskAx, vtMoveOrt) ;
|
||||
Triangle3d trTriaLoc = trTria ;
|
||||
Vector3d vtMoveLoc = vtMove ;
|
||||
trTriaLoc.ToLoc( DiskFrame) ;
|
||||
|
||||
@@ -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) ;
|
||||
+2838
-1529
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -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 ;
|
||||
@@ -168,7 +169,7 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
|
||||
ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
|
||||
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
|
||||
// verifico se sono arrivato al punto di chiusura
|
||||
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
|
||||
if ( AreSamePointEpsilon( ptCurr, ptStop, 0.5 * EPS_SMALL)) {
|
||||
bStopped = true ;
|
||||
break ;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ static const NamedColor StdColor[] = {
|
||||
{ "FUCHSIA", FUCHSIA},
|
||||
{ "PURPLE", PURPLE},
|
||||
{ "ORANGE", ORANGE},
|
||||
{ "BROWN", BROWN}
|
||||
{ "BROWN", BROWN},
|
||||
{ "INVISIBLE", INVISIBLE}
|
||||
} ;
|
||||
static const int NUM_STDCOLOR = ( sizeof(StdColor) / sizeof(StdColor[0]) ) ;
|
||||
|
||||
@@ -127,7 +128,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 ;
|
||||
|
||||
+2
-2
@@ -1294,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)
|
||||
@@ -1329,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 ;
|
||||
|
||||
+868
-161
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -33,5 +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 ICurveBezier* pCrvBez) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
+136
-47
@@ -93,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
|
||||
@@ -123,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
|
||||
@@ -151,7 +157,7 @@ CurveBezier::SetControlWeight( int nInd, double dW)
|
||||
return false ;
|
||||
|
||||
// verifico che il peso non sia nullo o negativo
|
||||
if ( dW < EPS_SMALL)
|
||||
if ( dW < EPS_SMALL || ! isfinite( dW) || dW > INFINITO)
|
||||
return false ;
|
||||
|
||||
// assegno il valore e il peso
|
||||
@@ -267,22 +273,21 @@ 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 ;
|
||||
Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
|
||||
SetControlPoint( nCount, ptStart, dWeight) ;
|
||||
SetControlPoint( nCount, ptStart) ;
|
||||
++nCount ;
|
||||
double dPart = 1. / m_nDeg ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
double dU = i * dPart ;
|
||||
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
|
||||
SetControlPoint( nCount, ptMid, dWeight) ;
|
||||
SetControlPoint( nCount, ptMid) ;
|
||||
++nCount ;
|
||||
}
|
||||
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
|
||||
SetControlPoint( nCount, ptEnd, dWeight) ;
|
||||
SetControlPoint( nCount, ptEnd) ;
|
||||
++nCount ;
|
||||
return true ;
|
||||
}
|
||||
@@ -367,8 +372,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 ;
|
||||
@@ -516,21 +524,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) ;
|
||||
|
||||
@@ -1657,6 +1665,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)
|
||||
@@ -1799,6 +1811,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)
|
||||
@@ -1808,19 +1824,19 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
return false ;
|
||||
// se razionale devo trovare il punto di trim iniziale per ricalcolare il parametro di trim
|
||||
Point3d ptStart ;
|
||||
if( m_bRat)
|
||||
if ( m_bRat)
|
||||
GetPointD1D2( dUStartTrim, ptStart) ;
|
||||
// trim finale
|
||||
if ( ! TrimEndAtParam( dUEndTrim))
|
||||
return false ;
|
||||
// trim iniziale con il parametro opportunamente ricalcolato
|
||||
double dNewUStartTrim ;
|
||||
if( m_bRat)
|
||||
if ( m_bRat)
|
||||
GetParamAtPoint( ptStart, dNewUStartTrim) ;
|
||||
else
|
||||
dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
||||
//trim iniziale
|
||||
if( ! TrimStartAtParam( dNewUStartTrim))
|
||||
if ( ! TrimStartAtParam( dNewUStartTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
@@ -1830,6 +1846,10 @@ CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
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.) ;
|
||||
|
||||
@@ -1839,7 +1859,7 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
if( ! TrimStartAtParam( dUTrim))
|
||||
if ( ! TrimStartAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
@@ -1849,6 +1869,10 @@ CurveBezier::TrimStartAtLen( double dLenTrim)
|
||||
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.) ;
|
||||
|
||||
@@ -1858,7 +1882,7 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
return false ;
|
||||
|
||||
// utilizzo il trim sui parametri
|
||||
if( ! TrimEndAtParam( dUTrim))
|
||||
if ( ! TrimEndAtParam( dUTrim))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
@@ -1868,6 +1892,10 @@ CurveBezier::TrimEndAtLen( double dLenTrim)
|
||||
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 ;
|
||||
@@ -1919,6 +1947,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 ;
|
||||
@@ -2258,6 +2290,10 @@ CurveBezier::ResetVoronoiObject() const
|
||||
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
|
||||
@@ -2272,19 +2308,23 @@ CurveBezier::MakeRational( void)
|
||||
bool
|
||||
CurveBezier::MakeRationalStandardForm( void)
|
||||
{
|
||||
// la curva deve essere valida
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
if ( ! m_bRat)
|
||||
return false ;
|
||||
double dW0 = m_vWeCtrl[0] ;
|
||||
double dW0 = m_vWeCtrl.front() ;
|
||||
double dWn = m_vWeCtrl.back() ;
|
||||
if( dW0 > 1- EPS_ZERO && dWn > 1 - EPS_ZERO)
|
||||
if ( dW0 > 1 - EPS_ZERO && dWn > 1 - EPS_ZERO)
|
||||
return true ;
|
||||
if( dW0 < EPS_ZERO || dWn < EPS_ZERO)
|
||||
if ( dW0 < EPS_ZERO || dWn < EPS_ZERO)
|
||||
return false ;
|
||||
|
||||
// formula del Farin
|
||||
// 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 ;
|
||||
m_vWeCtrl[i] *= Pow( dCoeff, i) / dW0 ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -2293,13 +2333,17 @@ CurveBezier::MakeRationalStandardForm( void)
|
||||
bool
|
||||
CurveBezier::MakeNonRational( double dTol)
|
||||
{
|
||||
if( ! m_bRat)
|
||||
// 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) {
|
||||
if ( abs( m_vWeCtrl[i] - 1) > EPS_SMALL) {
|
||||
bIsActualRat = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -2307,15 +2351,44 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
|
||||
bool bOk = true ;
|
||||
if ( ! bIsActualRat) {
|
||||
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
|
||||
for ( int p = 0 ; p < m_nDeg ; ++p) {
|
||||
Point3d pt = GetControlPoint( p) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
}
|
||||
// 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 ;
|
||||
@@ -2323,8 +2396,8 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
pNewBez->Init( nDeg, false) ;
|
||||
PNTVECTOR vPntCtrl ;
|
||||
PNTVECTOR vPntSampling ;
|
||||
for ( int p = 0 ; p < nDeg + 1; ++p) {
|
||||
Point3d pt ; GetPointD1D2( double(p) / nDeg, pt) ;
|
||||
for ( int p = 0 ; p < nDeg + 1 ; ++p) {
|
||||
Point3d pt ; GetPointD1D2( double( p) / nDeg, pt) ;
|
||||
pNewBez->SetControlPoint( p, pt) ;
|
||||
vPntCtrl.push_back( pt) ;
|
||||
}
|
||||
@@ -2334,11 +2407,11 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
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) ;
|
||||
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)
|
||||
if ( dErrLoc > dErrMax)
|
||||
dErrMax = dErrLoc ;
|
||||
// aggiorno il vettore dei punti di controllo della nuova curva
|
||||
vPntCtrl[p] += vDiff ;
|
||||
@@ -2351,17 +2424,17 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
}
|
||||
|
||||
// calcolo l'errore di approssimazione sulla curva
|
||||
CalcBezierApproxError( this, pNewBez, dErr) ;
|
||||
CalcApproxError( this, pNewBez, dErr) ;
|
||||
bOk = dErr < dTol ;
|
||||
if( bOk) {
|
||||
if ( bOk) {
|
||||
// aggiorno la curva di bezier originale con quella approssimata
|
||||
Init( nDeg, false) ;
|
||||
for( int i = 0 ; i < nDeg + 1 ; ++i) {
|
||||
for ( int i = 0 ; i < nDeg + 1 ; ++i) {
|
||||
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
|
||||
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
|
||||
}
|
||||
}
|
||||
else if( nDeg < m_nDeg + 4)
|
||||
else if ( nDeg < m_nDeg + 4)
|
||||
goto retry ;
|
||||
}
|
||||
|
||||
@@ -2372,14 +2445,30 @@ CurveBezier::MakeNonRational( double dTol)
|
||||
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)
|
||||
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 ;
|
||||
}
|
||||
+2
-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 ;
|
||||
@@ -153,6 +153,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
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 ;
|
||||
|
||||
+7
-203
@@ -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) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -502,8 +303,9 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng
|
||||
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, dLinTol)) ;
|
||||
// forzo la spezzatura della curva
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
dMaxDist = 2 * dLinTol ;
|
||||
}
|
||||
// se la polilinea è formata da 2 punti
|
||||
else if ( PL.GetPointNbr() == 2) {
|
||||
@@ -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 ;
|
||||
|
||||
+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) ;
|
||||
}
|
||||
+245
-40
@@ -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)
|
||||
@@ -375,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 ;
|
||||
@@ -388,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 ;
|
||||
}
|
||||
|
||||
@@ -878,14 +889,21 @@ 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
|
||||
@@ -1696,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)
|
||||
@@ -1718,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)
|
||||
@@ -1778,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 ;
|
||||
}
|
||||
@@ -1825,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()) ;
|
||||
@@ -1948,7 +1967,120 @@ CurveComposite::AddJoint( double dU)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol)
|
||||
{
|
||||
int nCrvCount = GetCurveCount() ;
|
||||
// verifico l'indice della giunzione
|
||||
if ( nU < 0 || nU > nCrvCount)
|
||||
return false ;
|
||||
// salvo le vecchie curve e nel caso le ripristino
|
||||
int nPrevCrv = -1 ;
|
||||
// recupero l'indice e il puntatore alla curva precedente (se esiste)
|
||||
if ( nU >= 0)
|
||||
nPrevCrv = nU - 1 ;
|
||||
else if ( IsClosed())
|
||||
nPrevCrv = nCrvCount - 1 ;
|
||||
PtrOwner<CurveComposite> pOrigCrv( CreateBasicCurveComposite()) ;
|
||||
if ( nPrevCrv >= 0)
|
||||
pOrigCrv->AddCurve( m_CrvSmplS[ nPrevCrv]->Clone()) ;
|
||||
// recupero il puntatore alla curva successiva (se esiste)
|
||||
int nNextCrv = -1 ;
|
||||
if ( nU < nCrvCount)
|
||||
nNextCrv = nU ;
|
||||
else if ( IsClosed())
|
||||
nNextCrv = 0 ;
|
||||
else
|
||||
nNextCrv = - 1 ;
|
||||
if ( nNextCrv >= 0)
|
||||
pOrigCrv->AddCurve( m_CrvSmplS[ nNextCrv]->Clone()) ;
|
||||
|
||||
int nCrvNmbr = GetCurveCount() ;
|
||||
int nFlagDel = DeletedCurve::NONE ;
|
||||
if ( ! ModifyJoint( nU, ptNewJoint, &nFlagDel))
|
||||
return false ;
|
||||
|
||||
bool bErasedSomeCrv = nCrvCount > GetCurveCount() ;
|
||||
bool bErasedPrev = ( nFlagDel == DeletedCurve::PREV) ;
|
||||
bool bErasedNext = ( nFlagDel == DeletedCurve::NEXT) ;
|
||||
if ( ( bErasedPrev && nNextCrv == -1) || ( bErasedNext && nPrevCrv == -1)) {
|
||||
// se sono su un estremo di una curva aperta e ho cancellato la sottocurva di estremità devo verificare che fosse più piccola della tolleranza
|
||||
if ( bErasedPrev && nNextCrv == -1) {
|
||||
Point3d ptOrigEnd ; pOrigCrv->GetEndPoint( ptOrigEnd) ;
|
||||
Point3d ptNewEnd ; GetEndPoint( ptNewEnd) ;
|
||||
if ( Dist( ptOrigEnd, ptNewEnd) > dTol)
|
||||
m_CrvSmplS.push_back( Release( pOrigCrv)) ;
|
||||
return true ;
|
||||
}
|
||||
if ( bErasedNext && nPrevCrv == -1) {
|
||||
Point3d ptOrigStart ; pOrigCrv->GetStartPoint( ptOrigStart) ;
|
||||
Point3d ptNewStart ; GetStartPoint( ptNewStart) ;
|
||||
if ( Dist( ptOrigStart, ptNewStart) > dTol)
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin(), Release( pOrigCrv)) ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
double dStart ;
|
||||
double dEnd ;
|
||||
if ( bErasedPrev) {
|
||||
dStart = nU ;
|
||||
dEnd = nNextCrv + 1 ;
|
||||
}
|
||||
else if ( bErasedNext) {
|
||||
dStart = nPrevCrv ;
|
||||
dEnd = nU ;
|
||||
if ( nU == 0)
|
||||
dStart -= 1 ;
|
||||
}
|
||||
else { // ! bErasedSomeCrv
|
||||
dStart = ( nPrevCrv != -1 ? nPrevCrv : 0) ;
|
||||
dEnd = ( nNextCrv != -1 ? nNextCrv + 1 : nCrvNmbr) ;
|
||||
}
|
||||
PtrOwner<ICurve> pNewCurve( CopyParamRange( dStart, dEnd)) ;
|
||||
double dErr = 0 ;
|
||||
if ( ! CalcApproxError( pOrigCrv, pNewCurve, dErr, 6) || dErr > dTol) {
|
||||
// se ho fallito il check o la variazione è superiore alla tolleranza richiesta, ripristino le curve originali
|
||||
if ( ! bErasedSomeCrv) {
|
||||
if ( nNextCrv != -1) {
|
||||
delete m_CrvSmplS[nNextCrv] ;
|
||||
m_CrvSmplS[nNextCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
}
|
||||
if ( nPrevCrv != -1) {
|
||||
delete m_CrvSmplS[nPrevCrv] ;
|
||||
m_CrvSmplS[nPrevCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( bErasedNext) {
|
||||
int nPos = nU == 0 ? nPrevCrv - 1 : nU ;
|
||||
delete m_CrvSmplS[nPos] ;
|
||||
if ( nU == 0) {
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( false) ;
|
||||
nPos = 0 ;
|
||||
}
|
||||
else
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
|
||||
}
|
||||
else {
|
||||
int nPos = nU == 0 ? nU : nPrevCrv ;
|
||||
delete m_CrvSmplS[nPos] ;
|
||||
if ( nU == 0) {
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
nPos = nCrvNmbr - 1 ;
|
||||
}
|
||||
else
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1958,6 +2090,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
// verifico l'indice della giunzione
|
||||
if ( nU < 0 || nU > nCrvCount)
|
||||
return false ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::NONE ;
|
||||
// recupero l'indice e il puntatore alla curva precedente (se esiste)
|
||||
int nPrevCrv = -1 ;
|
||||
if ( nU > 0)
|
||||
@@ -1986,6 +2120,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
|
||||
delete pPrevCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::PREV ;
|
||||
}
|
||||
// altrimenti diventa un segmento di retta
|
||||
else {
|
||||
@@ -2005,6 +2141,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
|
||||
delete pNextCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::NEXT ;
|
||||
}
|
||||
// altrimenti diventa un segmento di retta
|
||||
else {
|
||||
@@ -3034,7 +3172,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
|
||||
@@ -3168,11 +3306,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
|
||||
@@ -3181,10 +3334,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
|
||||
@@ -3264,11 +3431,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)
|
||||
@@ -3277,6 +3445,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() ;
|
||||
@@ -3794,19 +3966,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
|
||||
@@ -3818,3 +3977,49 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
|
||||
ptStart = m_ptStart ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurveToAdd, double dTolStartEnd, double dTolAlong)
|
||||
{
|
||||
// prendo il possesso e verifico la curva
|
||||
PtrOwner<ICurve> pNewCurve( pNewCurveToAdd) ;
|
||||
if ( IsNull( pNewCurve) || ! pNewCurve->IsValid())
|
||||
return false ;
|
||||
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico l'indice sia sensato
|
||||
if ( nSubCrv < 0 || nSubCrv > GetCurveCount())
|
||||
return false ;
|
||||
|
||||
// verifico che start e end coincidano entro la tolleranza
|
||||
Point3d ptStart ; m_CrvSmplS[nSubCrv]->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; m_CrvSmplS[nSubCrv]->GetEndPoint( ptEnd) ;
|
||||
Point3d ptNewStart ; pNewCurve->GetStartPoint( ptNewStart) ;
|
||||
Point3d ptNewEnd ; pNewCurve->GetEndPoint( ptNewEnd) ;
|
||||
if ( ! AreSamePointApprox( ptStart, ptNewStart) || ! AreSamePointApprox( ptEnd, ptNewEnd)) {
|
||||
// se i punti di inizio e fine non sono entro EPS_SMALL ma sono entro la tolleranza passata allora modifico la curva da aggiungere
|
||||
if ( AreSamePointEpsilon( ptStart, ptNewStart, dTolStartEnd) && AreSamePointEpsilon( ptEnd, ptNewEnd, dTolStartEnd)) {
|
||||
if ( ! pNewCurve->ModifyStart( ptStart) || ! pNewCurve->ModifyEnd( ptEnd))
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se presente una tolleranza lungo la curva controllo che sia rispettata
|
||||
if ( dTolAlong < INFINITO) {
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( m_CrvSmplS[nSubCrv], pNewCurve, dErr, 20) ;
|
||||
if ( dErr > dTolAlong)
|
||||
return false ;
|
||||
}
|
||||
|
||||
delete m_CrvSmplS[nSubCrv] ;
|
||||
m_CrvSmplS[nSubCrv] = Release( pNewCurve) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
+12
-6
@@ -26,6 +26,9 @@ class Voronoi ;
|
||||
//----------------------------------------------------------------------------
|
||||
class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
{
|
||||
public :
|
||||
enum DeletedCurve { NONE = 0, PREV = 1, NEXT = 2 } ;
|
||||
|
||||
public : // IGeoObj
|
||||
~CurveComposite( void) override ;
|
||||
CurveComposite* Clone( void) const override ;
|
||||
@@ -113,7 +116,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
|
||||
@@ -156,7 +159,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddJoint( double dU) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override
|
||||
{ return ModifyJoint( nU, ptNewJoint, nullptr) ; }
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) override ; // verifico se le curve interessate sono in tolleranza con la versione prima della modifica
|
||||
bool RemoveJoint( int nU) override ;
|
||||
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
|
||||
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ;
|
||||
@@ -177,8 +182,8 @@ 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 ;
|
||||
bool ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -199,19 +204,20 @@ 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 ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel) ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
|
||||
|
||||
+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
|
||||
|
||||
+15
-2
@@ -116,6 +116,7 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
|
||||
vtDiff = ptQ - ptP ;
|
||||
// angolo tra vettore e tangente
|
||||
dTemp = vtDer1 * vtDiff ;
|
||||
bool bEquiverse = dTemp > 0 ;
|
||||
if ( abs( dTemp) > EPS_ZERO)
|
||||
dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ;
|
||||
else
|
||||
@@ -123,8 +124,20 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
|
||||
// stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U))
|
||||
dPrevPar = dPar ;
|
||||
dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ;
|
||||
if ( abs( dTemp) > EPS_ZERO)
|
||||
dPar = dPrevPar - ( vtDer1 * vtDiff) / dTemp ;
|
||||
|
||||
// se il coseno tra questi due vettori è troppo grande potrei aver avuto una cattiva stima iniziale
|
||||
// provo quindi ad aggiustare a mano, anziché usare il segno suggerito da newton, che con queste premesse potrebbe divergere
|
||||
double dCos75 = 0.2588 ;
|
||||
if ( abs( dTemp) > EPS_ZERO) {
|
||||
double dDelta = ( vtDer1 * vtDiff) / dTemp ;
|
||||
if ( dSqCosA > dCos75) {
|
||||
if ( ( bEquiverse && dDelta > 0) || ( ! bEquiverse && dDelta < 0))
|
||||
dDelta *= -1 ;
|
||||
dPar = dPrevPar + dDelta ;
|
||||
}
|
||||
else
|
||||
dPar = dPrevPar - dDelta ;
|
||||
}
|
||||
// clipping parametro
|
||||
if ( dPar < approxMin.dParMin) {
|
||||
if ( approxMin.bParMinSing && ! bClampedFromSing) {
|
||||
|
||||
+12
-1
@@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
|
||||
// distanza non calcolata
|
||||
m_dDist = - 1 ;
|
||||
|
||||
if ( &CrvBez == nullptr || ! CrvBez.IsValid())
|
||||
if ( ! CrvBez.IsValid())
|
||||
return ;
|
||||
|
||||
// determino tolleranza di approssimazione in base a ingombro curva
|
||||
@@ -42,6 +42,17 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
|
||||
if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
|
||||
return ;
|
||||
|
||||
int nDeg = CrvBez.GetDegree() ;
|
||||
if ( PL.GetPointNbr() < nDeg + 1) {
|
||||
// costruisco una polilinea con un numero di curve scelto in base al grado della curva
|
||||
PL.Clear() ;
|
||||
for ( int i = 0 ; i <= nDeg + 1 ; ++i) {
|
||||
double dU = double(i) / (nDeg + 1) ;
|
||||
Point3d ptBez ;
|
||||
CrvBez.GetPointD1D2( dU, ICurve::Side::FROM_MINUS, ptBez) ;
|
||||
PL.AddUPoint( dU, ptBez) ;
|
||||
}
|
||||
}
|
||||
// cerco la minima distanza per la polilinea
|
||||
MDCVECTOR vApproxMin ;
|
||||
if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin))
|
||||
|
||||
+22
-11
@@ -152,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 ||
|
||||
@@ -197,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)) {
|
||||
@@ -211,13 +211,13 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int&
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide) const
|
||||
DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide, double dTol) const
|
||||
{
|
||||
if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size())
|
||||
return false ;
|
||||
|
||||
// se distanza nulla, il punto giace sulla curva
|
||||
if ( m_dDist <= EPS_SMALL) {
|
||||
if ( m_dDist <= dTol) {
|
||||
nSide = MDS_ON ;
|
||||
return true ;
|
||||
}
|
||||
@@ -232,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))
|
||||
@@ -248,7 +259,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
|
||||
|
||||
// determino il lato di giacitura del punto
|
||||
double dSide = vtRef * ( m_ptP - ptQ) ;
|
||||
if ( abs( dSide) < EPS_SMALL)
|
||||
if ( abs( dSide) < dTol)
|
||||
nSide = MDS_ON ;
|
||||
else if ( dSide > 0)
|
||||
nSide = MDS_LEFT ;
|
||||
@@ -259,12 +270,12 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide) const
|
||||
DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide, double dTol) const
|
||||
{
|
||||
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) {
|
||||
@@ -275,7 +286,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i
|
||||
}
|
||||
}
|
||||
// mi sono ricondotto al caso precedente
|
||||
return GetSideAtMinDistPoint( nInd, vtN, nSide) ;
|
||||
return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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), m_bIsSurfClosed( false)
|
||||
{
|
||||
// Bezier non valida
|
||||
if ( ! 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::GetParamsAtMinDistPoint( double& dU, double& dV) const
|
||||
{
|
||||
// Distanza non valida
|
||||
if ( m_dDist < -EPS_ZERO)
|
||||
return false ;
|
||||
// Distanza valida
|
||||
dU = m_ptParam.x ;
|
||||
dV = m_ptParam.y ;
|
||||
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 ;
|
||||
}
|
||||
@@ -94,6 +94,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
// Vettore di indici dei triangoli più vicini inizialmente vuoto
|
||||
m_vnMinDistTriaIndex.clear() ;
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = tmSurf.IsClosed() ;
|
||||
|
||||
@@ -184,6 +186,10 @@ 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 = dMinDist ;
|
||||
// salvo il punto a distanza minima
|
||||
@@ -279,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)
|
||||
|
||||
+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.
+15
-4
@@ -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,8 +281,10 @@ 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="CAvSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvToolSurfTm.cpp" />
|
||||
<ClCompile Include="CAvToolTriangle.cpp" />
|
||||
<ClCompile Include="CDeBoxClosedSurfTm.cpp" />
|
||||
@@ -310,7 +312,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>
|
||||
@@ -320,6 +324,10 @@ 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" />
|
||||
@@ -338,12 +346,15 @@ 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="CAvSurfFrMove.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
<ClInclude Include="CDeConeFrustumTria.h" />
|
||||
|
||||
@@ -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">
|
||||
@@ -546,6 +549,33 @@
|
||||
<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>
|
||||
<ClCompile Include="CAvSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1226,6 +1256,15 @@
|
||||
<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>
|
||||
<ClInclude Include="CAvSurfFrMove.h">
|
||||
<Filter>File di intestazione</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
|
||||
|
||||
+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
@@ -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
|
||||
|
||||
+14
@@ -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)
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
|
||||
+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 ; }
|
||||
} ;
|
||||
|
||||
+13
-11
@@ -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() ;
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
+510
-137
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,9 @@ class IntersCrvCompoCrvCompo
|
||||
bool bAutoInters, bool bClosed, int nCurvesNbr) ;
|
||||
bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ;
|
||||
bool EraseOtherInfo( int& nIndCurr, int& nIndOther) ;
|
||||
bool EraseBothInfo( int& nIndCurr, int& nIndOther) ;
|
||||
bool CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ;
|
||||
bool MergeNewOverlap( int i, bool bCrvAOrB) ;
|
||||
|
||||
private :
|
||||
bool m_bOverlaps ;
|
||||
|
||||
+104
-18
@@ -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
|
||||
@@ -127,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) ;
|
||||
}
|
||||
@@ -252,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é
|
||||
// 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
|
||||
@@ -291,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)
|
||||
@@ -340,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)
|
||||
@@ -347,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) ;
|
||||
@@ -416,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) ;
|
||||
}
|
||||
@@ -433,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) ;
|
||||
}
|
||||
@@ -498,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 ;
|
||||
@@ -517,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 ;
|
||||
@@ -534,9 +576,25 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
}
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
|
||||
/*int j = i < nNumInters - 1 ? i + 1 : -1 ;
|
||||
if ( pCurve->IsClosed() && j == - 1)
|
||||
j = 0 ;*/
|
||||
int j = i == 0 ? -1 : i - 1 ;
|
||||
if ( pCurve->IsClosed() && j == - 1)
|
||||
j = nNumInters - 1 ;
|
||||
bool bSpike = false ;
|
||||
if ( j != -1) {
|
||||
bSpike = InfoCorr[i].bOverlap && InfoCorr[j].bOverlap && InfoCorr[i].bCBOverEq != InfoCorr[j].bCBOverEq ;
|
||||
if ( bSpike) {
|
||||
bSpike = abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ||
|
||||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ;
|
||||
}
|
||||
}
|
||||
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
|
||||
@@ -557,7 +615,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 ;
|
||||
@@ -568,7 +626,11 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
// salvo dati correnti
|
||||
dCurrPar = InfoCorr[i].IciA[1].dU ;
|
||||
dCurrLen = dLenU ;
|
||||
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
|
||||
// se sono in un caso di spike devo trattare l'overlap in modo diverso
|
||||
if ( ! bSpike)
|
||||
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
|
||||
else
|
||||
nLastTy = InfoCorr[i].IciA[0].nPrevTy ;
|
||||
}
|
||||
}
|
||||
// eventuale tratto finale rimasto
|
||||
@@ -597,7 +659,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))
|
||||
@@ -640,13 +702,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 {
|
||||
@@ -670,7 +756,7 @@ IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
|
||||
double dArea ;
|
||||
if ( ! pCurve->GetAreaXY( dArea))
|
||||
return false ;
|
||||
nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ;
|
||||
nClass = (( dArea >= 0) ? CRVC_OUT : CRVC_IN) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,459 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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()
|
||||
{
|
||||
// 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::GetIntCrvPlnInfo( int nInd, IntCrvPlnInfo& aInfo)
|
||||
{
|
||||
if ( nInd < 0 || nInd >= m_nIntersCount)
|
||||
return false ;
|
||||
aInfo = m_Info[nInd] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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 ;
|
||||
}
|
||||
+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 ;
|
||||
|
||||
@@ -159,6 +159,36 @@ IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line
|
||||
// flag per segmenti che si allontanano significativamente
|
||||
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) {
|
||||
// posizioni parametriche dell'intersezione sulle linee
|
||||
|
||||
+623
-28
@@ -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,14 +72,28 @@ 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) {
|
||||
int nType = LSBT_NONE ;
|
||||
if ( dCos > EPS_ZERO)
|
||||
nType = LSBT_IN ;
|
||||
else if ( dCos < EPS_ZERO)
|
||||
nType = LSBT_OUT ;
|
||||
else
|
||||
nType = LSBT_TOUCH ;
|
||||
|
||||
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) ;
|
||||
vInfo.emplace_back( nType, 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) ;
|
||||
int nType2 = LSBT_NONE ;
|
||||
if ( dCos2 > EPS_ZERO)
|
||||
nType2 = LSBT_IN ;
|
||||
else if ( dCos2 < EPS_ZERO)
|
||||
nType2 = LSBT_OUT ;
|
||||
vInfo.emplace_back( nType, dU, 0, nT, dCos, ptIBz, P_INVALID, ptSP, P_INVALID) ;
|
||||
vInfo.emplace_back( nType2, dU2, 0, nT, dCos2, ptIBz2, P_INVALID, ptSP2, P_INVALID) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +107,7 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||
// 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) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
{ return ( a.dU < b.dU) ; }) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -137,16 +154,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 +174,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,19 +193,9 @@ 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) {
|
||||
int nFlag = LSBT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LSBT_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LSBT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
vInters.emplace_back( Info.nILSB, Info.dU) ;
|
||||
// se intersezione sovrapposta
|
||||
// da sviluppare
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
@@ -232,3 +239,591 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier di grado 3x1 monopatch
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineSurfBzCubicLinear( 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 di grado 3x1
|
||||
if ( nDegU != 3 || nDegV != 1 || nSpanU > 1 || nSpanV > 1 || bRat)
|
||||
return false ;
|
||||
|
||||
int nInters = int( vInfo.size()) ;
|
||||
|
||||
Point3d r = ptL ;
|
||||
Vector3d q = vtL ;
|
||||
bool bNeedToRotX = AreSameVectorApprox( q, X_AX) ;
|
||||
bool bNeedToRotY = AreSameVectorApprox( q, Y_AX) ;
|
||||
bool bNeedToRot = bNeedToRotX || bNeedToRotY ;
|
||||
Frame3d frRot ;
|
||||
if ( bNeedToRotX)
|
||||
frRot.Set( ORIG, X_AX) ;
|
||||
if ( bNeedToRotY)
|
||||
frRot.Set( ORIG, Y_AX) ;
|
||||
if ( bNeedToRot) {
|
||||
r.ToLoc( frRot) ;
|
||||
q.ToLoc( frRot) ;
|
||||
}
|
||||
|
||||
PNTVECTOR vPntCtrl = pSurfBz->GetAllControlPoints() ;
|
||||
|
||||
if ( bNeedToRot) {
|
||||
for ( Point3d& pt: vPntCtrl)
|
||||
pt.ToLoc( frRot) ;
|
||||
}
|
||||
|
||||
Vector3d A = vPntCtrl[4] - vPntCtrl[0] ;
|
||||
Vector3d B = vPntCtrl[5] - vPntCtrl[1] ;
|
||||
Vector3d C = vPntCtrl[6] - vPntCtrl[2] ;
|
||||
Vector3d D = vPntCtrl[7] - vPntCtrl[3] ;
|
||||
Vector3d E = vPntCtrl[0] - ORIG ;
|
||||
Vector3d F = vPntCtrl[1] - ORIG ;
|
||||
Vector3d G = vPntCtrl[2] - ORIG ;
|
||||
Vector3d H = vPntCtrl[3] - ORIG ;
|
||||
|
||||
Vector3d a3 = -A + 3 * B - 3 * C + D ;
|
||||
Vector3d a2 = 3 * A - 6 * B + 3 * C ;
|
||||
Vector3d a1 = -3 * A + 3 * B ;
|
||||
Vector3d a0 = A ;
|
||||
|
||||
Vector3d b3 = -E + 3 * F - 3 * G + H ;
|
||||
Vector3d b2 = 3 * E - 6 * F + 3 * G ;
|
||||
Vector3d b1 = -3 * E + 3 * F ;
|
||||
Vector3d b0 = E ;
|
||||
|
||||
|
||||
|
||||
DBLVECTOR vdCoeff, vdRoots ;
|
||||
// coefficienti dal grado più basso al grado più alto
|
||||
vdCoeff = { // c0
|
||||
q.x*q.z*a0.y*b0.z - q.x*q.y*a0.z*b0.z // 3
|
||||
- r.z*q.x*q.z*a0.y + r.z*q.x*q.y*a0.z + // 3
|
||||
q.y*q.z*a0.z*b0.z - q.z*q.z*a0.y*b0.x // 4
|
||||
- r.x*q.y*q.z*a0.z + r.x*q.z*q.z*a0.y + // 4
|
||||
q.z*q.z*a0.x*b0.y - q.y*q.z*a0.x*b0.z - q.x*q.z*a0.z*b0.y + q.x*q.y*a0.z*b0.z // 5
|
||||
- r.y*q.z*q.z*a0.x + r.z*q.y*q.z*a0.x + r.y*q.x*q.z*a0.z - r.z*q.x*q.y*a0.z, // 5
|
||||
|
||||
// c1
|
||||
q.x*q.z*(a1.y*b0.z + a0.y*b1.z) - q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 3
|
||||
- r.z*q.x*q.z*a1.y + r.z*q.x*q.y*a1.z + // 3
|
||||
q.y*q.z*(a1.z*b0.x + a0.z*b1.x) - q.z*q.z*(a1.y*b0.x + a0.y*b1.x) // 4
|
||||
- r.x*q.y*q.z*a1.z + r.x*q.z*q.z*a1.y + // 4
|
||||
q.z*q.z*(a1.x*b0.y + a0.x*b1.y) - q.y*q.z*(a1.x*b0.z + a0.x*b1.z) // 5
|
||||
- q.x*q.z*(a1.z*b0.y + a0.z*b1.y) + q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 5
|
||||
- r.y*q.z*q.z*a1.x + r.z*q.y*q.z*a1.x + r.y*q.x*q.z*a1.z - r.z*q.x*q.y*a1.z, // 5
|
||||
|
||||
// c2
|
||||
q.x*q.z*(a2.y*b0.z + a1.y*b1.z + a0.y*b2.z) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z) // 3
|
||||
- r.z*q.x*q.z*a2.y + r.z*q.x*q.y*a2.z + // 3
|
||||
q.y*q.z*(a2.z*b0.x + a1.z*b1.x + a0.z*b2.x) - q.z*q.z*(a2.y*b0.x + a1.y*b1.x + a0.y*b2.x) // 4
|
||||
- r.x*q.y*q.z*a2.z + r.x*q.z*q.z*a2.y + // 4
|
||||
q.z*q.z*(a2.x*b0.y + a1.x*b1.y + a0.x*b2.y) - q.y*q.z*(a2.x*b0.z + a1.x*b1.z + a0.x*b2.z) // 5
|
||||
- q.x*q.z*(a2.z*b0.y + a1.z*b1.y + a0.z*b2.y) + q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z)// 5
|
||||
- r.y*q.z*q.z*a2.x + r.z*q.y*q.z*a2.x + r.y*q.x*q.z*a2.z - r.z*q.x*q.y*a2.z, // 5
|
||||
|
||||
// c3
|
||||
q.x*q.z*(a3.y*b0.z + a2.y*b1.z + a1.y*b2.z + a0.y*b3.z) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z) // 3
|
||||
- r.z*q.x*q.z*a3.y + r.z*q.x*q.y*a3.z + // 3
|
||||
q.y*q.z*(a3.z*b0.x + a2.z*b1.x + a1.z*b2.x + a0.z*b3.x) - q.z*q.z*(a3.y*b0.x + a2.y*b1.x + a1.y*b2.x + a0.y*b3.x) // 4
|
||||
- r.x*q.y*q.z*a3.z + r.x*q.z*q.z*a3.y + // 4
|
||||
q.z*q.z*(a3.x*b0.y + a2.x*b1.y + a1.x*b2.y + a0.x*b3.y) - q.y*q.z*(a3.x*b0.z + a2.x*b1.z + a1.x*b2.z + a0.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b0.y + a2.z*b1.y + a1.z*b2.y + a0.z*b3.y) + q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z)// 5
|
||||
- r.y*q.z*q.z*a3.x + r.z*q.y*q.z*a3.x + r.y*q.x*q.z*a3.z - r.z*q.x*q.y*a3.z, // 5
|
||||
|
||||
// c4
|
||||
q.x*q.z*(a3.y*b1.z + a2.y*b2.z + a1.y*b3.z) - q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z) + // 3
|
||||
q.y*q.z*(a3.z*b1.x + a2.z*b2.x + a1.z*b3.x) - q.z*q.z*(a3.y*b1.x + a2.y*b2.x + a1.y*b3.x) + // 4
|
||||
q.z*q.z*(a3.x*b1.y + a2.x*b2.y + a1.x*b3.y) - q.y*q.z*(a3.x*b1.z + a2.x*b2.z + a1.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b1.y + a2.z*b2.y + a1.z*b3.y) + q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z), // 5
|
||||
|
||||
// c5
|
||||
q.x*q.z*(a3.y*b2.z + a2.y*b3.z) - q.x*q.y*(a3.z*b2.z + a2.z*b3.z) + // 3
|
||||
q.y*q.z*(a3.z*b2.x + a2.z*b3.x) - q.z*q.z*(a3.y*b2.x + a2.y*b3.x) + // 4
|
||||
q.z*q.z*(a3.x*b2.y + a2.x*b3.y) - q.y*q.z*(a3.x*b2.z + a2.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b2.y + a2.z*b3.y) + q.x*q.y*(a3.z*b2.z + a2.z*b3.z), // 5
|
||||
|
||||
// c6
|
||||
q.x*q.z*a3.y*b3.z - q.x*q.y*a3.z*b3.z + // 3
|
||||
q.y*q.z*a3.z*b3.x - q.z*q.z*a3.y*b3.x + // 4
|
||||
q.z*q.z*a3.x*b3.y - q.y*q.z*a3.x*b3.z - q.x*q.z*a3.z*b3.y + q.x*q.y*a3.z*b3.z} ; // 5
|
||||
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
|
||||
bool bFound = false ;
|
||||
for ( int w = 0 ; w < nRoots ; ++w) {
|
||||
double dU = 0, dV = 0 ;
|
||||
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
|
||||
dU = 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( dU - vdRoots[k]) < EPS_PARAM) ;
|
||||
if ( ! bAlreadyFound) {
|
||||
Vector3d vAlpha = a3 * pow(dU, 3) + a2 * pow( dU, 2) + a1 * dU + a0 ;
|
||||
Vector3d vBeta = b3 * pow(dU, 3) + b2 * pow( dU, 2) + b1 * dU + b0 ;
|
||||
double dDen = ( vAlpha.x * q.z - vAlpha.z * q.x) ;
|
||||
if ( abs( dDen) > EPS_ZERO)
|
||||
dV = ( ( vBeta.z - r.z) * q.x - ( vBeta.x - r.x ) * q.z) / dDen ;
|
||||
else {
|
||||
// se la prima equazione risulta un x/0 allora uso la seconda equazione per trovare il secondo parametro
|
||||
double dDen2 = ( vAlpha.y * q.z - vAlpha.z * q.y) ;
|
||||
dV = ( ( vBeta.z - r.z) * q.y - ( vBeta.y - r.y ) * q.z) / dDen2 ;
|
||||
}
|
||||
if ( dV > - EPS_ZERO && dV < 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 ;
|
||||
int nType = ILTA_NO_TRIA ;
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, nType, -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 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier bilineare monopatch
|
||||
//----------------------------------------------------------------------------
|
||||
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]) ;
|
||||
}
|
||||
}
|
||||
|
||||
+106
-21
@@ -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) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||
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) ||
|
||||
|
||||
@@ -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 ;
|
||||
} ;
|
||||
|
||||
+149
-25
@@ -16,9 +16,17 @@
|
||||
#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)
|
||||
@@ -52,36 +60,76 @@ IsFillet( const 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 ;
|
||||
}
|
||||
@@ -175,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 ;
|
||||
}
|
||||
|
||||
+1
-3
@@ -16,6 +16,4 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ;
|
||||
bool IsFillet( const 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) ;
|
||||
+56
-9
@@ -60,6 +60,8 @@ OffsetCurve::Reset( void)
|
||||
}
|
||||
}
|
||||
m_CrvLst.clear() ;
|
||||
m_ptOffs = P_INVALID ;
|
||||
m_vtOut = V_INVALID ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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])) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,6 +714,18 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
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 ++)
|
||||
@@ -733,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
|
||||
@@ -814,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)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "PointsPCA.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
|
||||
|
||||
+331
-14
@@ -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"
|
||||
@@ -773,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)
|
||||
@@ -796,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 {
|
||||
@@ -817,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() ;
|
||||
}
|
||||
@@ -1445,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 ;
|
||||
@@ -1461,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 ;
|
||||
@@ -1477,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 ;
|
||||
}
|
||||
@@ -1529,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() ;
|
||||
@@ -1612,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 ;
|
||||
@@ -1657,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 ;
|
||||
@@ -1687,12 +1694,322 @@ 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 ;
|
||||
while ( nAddedSpan < nPnt) {
|
||||
if ( nCrv1 >= nPnt1)
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
if ( nCrv2 >= nPnt2)
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -173,7 +173,7 @@ Polygon3d::FromPlaneTrimmedWithBox( const Point3d& ptOn, const Vector3d& vtN,
|
||||
{
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptOn, vtN) ;
|
||||
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt) ;
|
||||
return FromPlaneTrimmedWithBox( plPlane, ptMin, ptMax, bOnEq, bOnCt, dToler) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+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)
|
||||
|
||||
+689
-370
File diff suppressed because it is too large
Load Diff
@@ -92,11 +92,18 @@ RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dPa
|
||||
Vector3d vtCurrR = frAct.VersX() ;
|
||||
Vector3d vtCurrT = frAct.VersZ() ;
|
||||
|
||||
// punto i-esimo sulla curva e suo vettore tangente
|
||||
// punto i-esimo sulla curva e suo vettore tangente medio
|
||||
Point3d ptNextM, ptNextP ;
|
||||
Vector3d vtNextM, vtNextP ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNextM, &vtNextM) ||
|
||||
! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_PLUS, ptNextP, &vtNextP) ||
|
||||
! vtNextM.Normalize() || ! vtNextP.Normalize())
|
||||
return false ;
|
||||
Point3d ptNext ;
|
||||
Vector3d vtNextT ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) ||
|
||||
! vtNextT.Normalize())
|
||||
ptNext = Media( ptNextM, ptNextP) ;
|
||||
vtNextT = Media( vtNextM, vtNextP) ;
|
||||
if ( ! vtNextT.Normalize())
|
||||
return false ;
|
||||
|
||||
// controllo per casi degeneri
|
||||
|
||||
+126
-689
File diff suppressed because it is too large
Load Diff
+5
-6
@@ -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
|
||||
@@ -577,10 +578,8 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
|
||||
bool
|
||||
CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert)
|
||||
{
|
||||
// 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 bool : riferito al vettore originale delle polyline, riporta true se la polyline è stata invertita
|
||||
// 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 ;
|
||||
|
||||
+5
-5
@@ -73,7 +73,7 @@ GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol)
|
||||
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]])
|
||||
if ( vbInvert[vnPLIndMat[i][j]])
|
||||
vPL[vnPLIndMat[i][j]].Invert() ;
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, vnPLIndMat, vbInvert))
|
||||
return nullptr ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
|
||||
if( vbInvert[i])
|
||||
if ( vbInvert[i])
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
// verifico la direzione di estrusione
|
||||
@@ -1095,7 +1095,7 @@ GetSurfTriMeshSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
|
||||
bool bRMF = vtAx.IsSmall() ;
|
||||
bool bRMF = ( ! vtAx.IsValid() || vtAx.IsSmall()) ;
|
||||
|
||||
// riferimento all'inizio della linea guida
|
||||
Point3d ptStart ;
|
||||
@@ -1242,9 +1242,9 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, const Vector3d&
|
||||
if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
|
||||
bIsLine = true ;
|
||||
}
|
||||
// se la guida è piana
|
||||
// se la guida è piana e il vettore di riferimento è non definito oppure non nullo
|
||||
Plane3d plGuide ;
|
||||
if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL))
|
||||
if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL) && ( ! vtAx.IsValid() || ! vtAx.IsSmall()))
|
||||
return GetSurfTriMeshSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ;
|
||||
|
||||
// altrimenti swept 3d
|
||||
|
||||
+14
-7
@@ -76,11 +76,18 @@ FromString( const string& sVal, Frame3d& frFrame)
|
||||
bool
|
||||
FromString( const string& sVal, Color& cCol)
|
||||
{
|
||||
// devono essere 4 parametri : Red, Green, Blue, Alpha
|
||||
int vnVal[4] ;
|
||||
if ( ! FromString( sVal, vnVal))
|
||||
return false ;
|
||||
// assegno il colore
|
||||
cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[3]) ;
|
||||
return true ;
|
||||
// dovrebbero essere 4 parametri : Red, Green, Blue, Alpha
|
||||
int vnRGBA[4] ;
|
||||
if ( FromString( sVal, vnRGBA)) {
|
||||
cCol.Set( vnRGBA[0], vnRGBA[1], vnRGBA[2], vnRGBA[3]) ;
|
||||
return true ;
|
||||
}
|
||||
// riprovo con 3 parametri : Red, Green, Blue
|
||||
int vnRGB[3] ;
|
||||
if ( FromString( sVal, vnRGB)) {
|
||||
cCol.Set( vnRGB[0], vnRGB[1], vnRGB[2]) ;
|
||||
return true ;
|
||||
}
|
||||
// altrimenti errore
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
+324
-78
@@ -24,6 +24,14 @@
|
||||
#include "/EgtDev/Include/EGkSurfAux.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
|
||||
|
||||
#define SAVEMKUNIF_CRVS 0
|
||||
#if SAVEMKUNIF_CRVS
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -37,12 +45,12 @@ 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 ;
|
||||
@@ -66,12 +74,16 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
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
|
||||
if ( snData.mCP.size() != nuCurve.vCP.size() ) {
|
||||
snData.mCP.resize( nuCurve.vCP.size()) ;
|
||||
if( snData.bRat)
|
||||
if ( snData.bRat)
|
||||
snData.mW.resize( nuCurve.vW.size()) ;
|
||||
}
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
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.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] ;
|
||||
}
|
||||
@@ -80,18 +92,18 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
}
|
||||
}
|
||||
snData.bPeriodicU = false ;
|
||||
snData.nCPU = int( snData.mCP.size()) ;
|
||||
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 ;
|
||||
@@ -132,7 +144,7 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
}
|
||||
}
|
||||
snData.bPeriodicV = false ;
|
||||
snData.nCPV = int( snData.mCP[0].size()) ;
|
||||
snData.nCPV = ssize( snData.mCP[0]) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@@ -526,6 +538,25 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
return Release( pSrfBz) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveComposite*
|
||||
GetRectangleCurve( const Point3d& ptStart, double dWidth, double dHeight)
|
||||
{
|
||||
PolyLine PL ;
|
||||
PL.AddUPoint( 0, ptStart) ;
|
||||
PL.AddUPoint( 1, Point3d( ptStart.x + dWidth, ptStart.y)) ;
|
||||
PL.AddUPoint( 2, Point3d( ptStart.x + dWidth, ptStart.y + dHeight, 0)) ;
|
||||
PL.AddUPoint( 3, Point3d( ptStart.x , ptStart.y + dHeight, 0)) ;
|
||||
PL.AddUPoint( 4, ptStart) ;
|
||||
// creo la curva e la inserisco nel GDB
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
bool bOk = true ;
|
||||
bOk = bOk && ! IsNull( pCrvCompo) ;
|
||||
// inserisco i segmenti che uniscono i punti
|
||||
bOk = bOk && pCrvCompo->FromPolyLine( PL) ;
|
||||
return Release( pCrvCompo) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
|
||||
@@ -535,36 +566,33 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
bool bRescaledU = false ;
|
||||
bool bRescaledV = false ;
|
||||
int nSpanU = 1, nSpanV = 1 ;
|
||||
PtrOwner<ISurfFlatRegion> pRescaledSfr( CreateSurfFlatRegion()) ;
|
||||
ICRVCOMPOPOVECTOR vUniformedCurves ;
|
||||
BOOLVECTOR vbUniform(2) ;
|
||||
fill( vbUniform.begin(), vbUniform.end(), true) ;
|
||||
DBLMATRIX mKnots(2) ;
|
||||
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
|
||||
// vettore dei nodi
|
||||
DBLVECTOR vU ;
|
||||
DBLVECTOR& vU = mKnots[nDir] ;
|
||||
int nExtraKnots = 0 ;
|
||||
// controllo in U
|
||||
if ( nDir == 0) {
|
||||
if ( nDegU > 1) {
|
||||
nExtraKnots = nDegU - 1 ;
|
||||
}
|
||||
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
|
||||
for ( int i = nExtraKnots ; i < ssize( vU0) - nExtraKnots ; ++i ) {
|
||||
double dKnot = vU0[i] * SBZ_TREG_COEFF ;
|
||||
// lo aggiungo solo se è diverso dal precedente
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
|
||||
vU.push_back( dKnot) ;
|
||||
}
|
||||
nSpanU = (int)vU.size() - 1 ;
|
||||
nSpanU = ssize( vU) - 1 ;
|
||||
}
|
||||
// controllo in V
|
||||
else if ( nDir == 1 ) {
|
||||
if ( nDegV > 1) {
|
||||
nExtraKnots = nDegV - 1 ;
|
||||
}
|
||||
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
|
||||
for ( int i = nExtraKnots ; i < ssize( vV0) - nExtraKnots ; ++i ) {
|
||||
double dKnot = vV0[i] * SBZ_TREG_COEFF ;
|
||||
// lo aggiungo solo se è diverso dal precedente
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
|
||||
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
|
||||
vU.push_back( dKnot) ;
|
||||
}
|
||||
nSpanV = (int)vU.size() - 1 ;
|
||||
nSpanV = ssize( vU) - 1 ;
|
||||
}
|
||||
|
||||
// controllo se il vettore dei nodi è uniforme
|
||||
@@ -577,76 +605,268 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
if ( b < (int)vU.size())
|
||||
d1 = abs( vU[b] - vU[a]) ;
|
||||
}
|
||||
if ( b != (int)vU.size()) {
|
||||
if ( b != (int)vU.size())
|
||||
vbUniform[nDir] = false ;
|
||||
}
|
||||
// vettore delle curve di loop della regione di trim
|
||||
ICRVCOMPOPOVECTOR vLoop ;
|
||||
if ( ! vbUniform[0] || ! vbUniform[1]) {
|
||||
for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++c) {
|
||||
for ( int l = 0 ; l < pSfr->GetLoopCount( c); ++l)
|
||||
vLoop.emplace_back( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ;
|
||||
}
|
||||
}
|
||||
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vLoop); ++i){
|
||||
vGeo.push_back(vLoop[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_loops.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
|
||||
DBLVECTOR& vU = mKnots[nDir] ;
|
||||
if ( ! vbUniform[nDir]) {
|
||||
nDir == 0 ? bRescaledU = true : bRescaledV = true ;
|
||||
pRescaledSfr.Set( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pRescaledSfr))
|
||||
return false ;
|
||||
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
|
||||
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
|
||||
if ( IsNull( pSfr_copy))
|
||||
return false ;
|
||||
// creo il vettore delle curve all'interno di una striscia
|
||||
ICRVCOMPOPOVECTOR vCrvStrip ;
|
||||
for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) {
|
||||
double dLenStrip = abs( vU[p+1] - vU[p]) ;
|
||||
if ( dLenStrip < EPS_SMALL)
|
||||
continue ;
|
||||
// creo la maschera per tagliare la superficie originale e ottenere una striscia
|
||||
PtrOwner<ISurfFlatRegion> pSfrTrim( CreateSurfFlatRegion()) ;
|
||||
PtrOwner<ICurveComposite> pTrimMask ;
|
||||
|
||||
// ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
|
||||
Vector3d vtTrim ;
|
||||
if ( nDir == 0) {
|
||||
pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ;
|
||||
vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ;
|
||||
Point3d ptStart( abs(vU[p] - vU.front()), - 1, 0) ;
|
||||
pTrimMask.Set( GetRectangleCurve( ptStart, dLenStrip, dScaleV + 2)) ;
|
||||
}
|
||||
else{
|
||||
pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ;
|
||||
vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ;
|
||||
Point3d ptStart( - 1, abs(vU[p] - vU.front()), 0) ;
|
||||
pTrimMask.Set( GetRectangleCurve( ptStart, dScaleU + 2, dLenStrip)) ;
|
||||
}
|
||||
pSfrTrim->Translate( vtTrim) ;
|
||||
|
||||
if ( ! pSfr_copy->Intersect( *pSfrTrim))
|
||||
return false ;
|
||||
// qui potrei decidere di eliminare tutti i tratti dei loop paralleli alla direzione del parametro che sto analizzando ( e di valore coincidente a quello di un nodo)
|
||||
|
||||
// aggiungo la nuova striscia solo se è valida
|
||||
if ( pSfr_copy->IsValid() ) {
|
||||
for ( int l = 0 ; l < ssize( vLoop); ++l) {
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
vGeo.push_back(pTrimMask->Clone()) ;
|
||||
vGeo.push_back(vLoop[l]->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
IntersCurveCurve icc( *vLoop[l], *pTrimMask) ;
|
||||
int nInters = icc.GetIntersCount() ;
|
||||
ICCIVECTOR vICCI ;
|
||||
for ( int i = 0 ; i < nInters ; ++i) {
|
||||
IntCrvCrvInfo icci ; icc.GetIntCrvCrvInfo( i, icci) ;
|
||||
vICCI.push_back( std::move( icci)) ;
|
||||
}
|
||||
CRVCVECTOR vCrvClass, vMaskClass ;
|
||||
icc.GetCurveClassification( 0, EPS_SMALL, vCrvClass) ;
|
||||
icc.GetCurveClassification( 1, EPS_SMALL, vMaskClass) ;
|
||||
// se dei pezzi di trim risultano esterni allo spazio parametrico tengo il bordo della maschera di trim
|
||||
double dLastParam1 = 0 ;
|
||||
double dStartA = 0, dEndA = 0 ; vLoop[l]->GetDomain( dStartA, dEndA) ;
|
||||
double dEndB = 4 ;
|
||||
for ( int i = 0 ; i < ssize( vCrvClass); ++i) {
|
||||
if ( vCrvClass[i].nClass == CRVC_IN || vCrvClass[i].nClass == CRVC_ON_P) {
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE))) ;
|
||||
|
||||
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
|
||||
int k = vICCI[j].bOverlap ? 1 : 0 ;
|
||||
if ( abs( vICCI[j].IciA[k].dU - vCrvClass[i].dParE) < EPS_PARAM) {
|
||||
dLastParam1 = vICCI[j].IciB[k].dU ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( vCrvClass[i].nClass == CRVC_OUT && ( p == 0 || p == ssize(vU) - 2)){
|
||||
double dMin, dMax ;
|
||||
if ( p == 0) {
|
||||
dMin = nDir == 0 ? 3 : 0 ;
|
||||
dMax = nDir == 0 ? 4 : 1 ;
|
||||
}
|
||||
else {
|
||||
dMin = nDir == 0 ? 1 : 2 ;
|
||||
dMax = nDir == 0 ? 2 : 3 ;
|
||||
}
|
||||
// aggiungo la parte di curva di edge al posto della parte di curva che esce dal parametrico
|
||||
// se non ho ancora aggiunto un tratto parto dal primo punto di intersezione
|
||||
if ( ssize( vCrvStrip) == 0) {
|
||||
double dPar0 = vCrvClass[i].dParS ;
|
||||
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
|
||||
int k = vICCI[j].bOverlap ? 1 : 0 ;
|
||||
if ( abs(vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM ||
|
||||
( abs( dEndA - vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM)) {
|
||||
if ( abs( dEndB - vICCI[j].IciB[k].dU) < EPS_PARAM)
|
||||
dLastParam1 = 0 ;
|
||||
else
|
||||
dLastParam1 = vICCI[j].IciB[k].dU ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
int c = 0 ;
|
||||
while ( c < ssize( vMaskClass) - 1 && abs( vMaskClass[c].dParS - dLastParam1) > EPS_PARAM)
|
||||
++c ;
|
||||
|
||||
if ( vMaskClass[c].nClass == CRVC_IN && vMaskClass[c].dParS < dMax && vMaskClass[c].dParS >= dMin) {
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
|
||||
dLastParam1 = vMaskClass[c].dParE ;
|
||||
// se sono alla fine curva verifico se devo aggiungere anche un pezzo di inizio
|
||||
if ( dLastParam1 == dEndB && vMaskClass[0].nClass == CRVC_IN) {
|
||||
c = 0 ;
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
|
||||
dLastParam1 = vMaskClass[c].dParE ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
|
||||
vGeo.push_back(vCrvStrip[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
// riscalo le curve nella striscia
|
||||
if ( ! vCrvStrip.empty()) {
|
||||
double dCoeffX = 1, dCoeffY = 1 ;
|
||||
|
||||
if ( nDir == 0)
|
||||
pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
|
||||
else
|
||||
pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
|
||||
|
||||
// prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo
|
||||
|
||||
Point3d pt ;
|
||||
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
|
||||
if ( nDir == 0)
|
||||
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
|
||||
else
|
||||
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
|
||||
|
||||
Vector3d vtJoin ;
|
||||
if ( nDir == 0)
|
||||
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
|
||||
else
|
||||
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
|
||||
pSfr_copy->Translate( vtJoin) ;
|
||||
// se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET
|
||||
if ( bRetry)
|
||||
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // OFFSET
|
||||
if ( pRescaledSfr->IsValid()) {
|
||||
if ( ! pRescaledSfr->Add( *pSfr_copy))
|
||||
dCoeffX = SBZ_TREG_COEFF / dLenStrip ;
|
||||
else
|
||||
dCoeffY = SBZ_TREG_COEFF / dLenStrip ;
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i) {
|
||||
if( ! IsNull( vCrvStrip[i]))
|
||||
vCrvStrip[i]->Scale( GLOB_FRM, dCoeffX, dCoeffY, 1) ;
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
pRescaledSfr.Set( pSfr_copy) ;
|
||||
|
||||
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo (nDir == 0)
|
||||
// oppure sul bordo superiore ( nDir == 1)
|
||||
Point3d pt ;
|
||||
Vector3d vtJoin ;
|
||||
if ( nDir == 0) {
|
||||
pt.Set( abs( vU[p] - vU.front()), 0, 0) ;
|
||||
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
|
||||
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
|
||||
}
|
||||
else {
|
||||
pt.Set( 0, abs(vU[p] - vU.front()), 0) ;
|
||||
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
|
||||
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
|
||||
}
|
||||
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i)
|
||||
vCrvStrip[i]->Translate( vtJoin) ;
|
||||
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
|
||||
vGeo.push_back(vCrvStrip[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
// faccio la chain con le curve delle striscie precedenti
|
||||
|
||||
if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) {
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
|
||||
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
ChainCurves chainCrv ;
|
||||
double dChainTol = 5 * EPS_SMALL ;
|
||||
chainCrv.Init( false, dChainTol, max(ssize( vUniformedCurves), ssize(vCrvStrip))) ;
|
||||
for ( int c = 0 ; c < ssize( vUniformedCurves) ; ++c) {
|
||||
Point3d ptStart, ptEnd ;
|
||||
Vector3d vtStart, vtEnd ;
|
||||
vUniformedCurves[c]->GetStartPoint( ptStart) ;
|
||||
vUniformedCurves[c]->GetEndPoint( ptEnd) ;
|
||||
vUniformedCurves[c]->GetStartDir( vtStart) ;
|
||||
vUniformedCurves[c]->GetEndDir( vtEnd) ;
|
||||
chainCrv.AddCurve( 1 + c, ptStart, vtStart, ptEnd, vtEnd) ;
|
||||
}
|
||||
for ( int c = 0 ; c < ssize( vCrvStrip); ++c) {
|
||||
Point3d ptStart, ptEnd ;
|
||||
Vector3d vtStart, vtEnd ;
|
||||
vCrvStrip[c]->GetStartPoint( ptStart) ;
|
||||
vCrvStrip[c]->GetEndPoint( ptEnd) ;
|
||||
vCrvStrip[c]->GetStartDir( vtStart) ;
|
||||
vCrvStrip[c]->GetEndDir( vtEnd) ;
|
||||
chainCrv.AddCurve( 1 + ssize( vUniformedCurves) + c, ptStart, vtStart, ptEnd, vtEnd) ;
|
||||
}
|
||||
INTVECTOR vIds ;
|
||||
ICRVCOMPOPOVECTOR vNewCrv ;
|
||||
int nCrvPrec = ssize( vUniformedCurves) ;
|
||||
while ( chainCrv.GetChainFromNear( ORIG, false, vIds)) {
|
||||
// se ho una solo curva piccola allora la salto
|
||||
if ( ssize(vIds) == 1) {
|
||||
double dLen = 0 ;
|
||||
int nId = vIds[0] - 1 ;
|
||||
bool bSkip = false ;
|
||||
if ( nId < nCrvPrec)
|
||||
bSkip = vUniformedCurves[nId]->GetLength( dLen) && dLen < dChainTol ;
|
||||
else
|
||||
bSkip = vCrvStrip[nId - ssize(vUniformedCurves)]->GetLength(dLen) && dLen < dChainTol ;
|
||||
|
||||
if ( bSkip)
|
||||
continue ;
|
||||
}
|
||||
|
||||
vNewCrv.emplace_back( CreateBasicCurveComposite()) ;
|
||||
for ( int nId : vIds) {
|
||||
nId -= 1 ;
|
||||
if ( nId < nCrvPrec)
|
||||
vNewCrv.back()->AddCurve( Release( vUniformedCurves[nId]), true, dChainTol) ;
|
||||
else
|
||||
vNewCrv.back()->AddCurve( Release( vCrvStrip[nId - ssize( vUniformedCurves)]), true, dChainTol) ;
|
||||
}
|
||||
}
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vNewCrv); ++i){
|
||||
vGeo.push_back(vNewCrv[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\trim_crv_unif_AFTERchain.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
// aggiorno le curve
|
||||
vUniformedCurves.clear() ;
|
||||
vUniformedCurves.swap( vNewCrv) ;
|
||||
}
|
||||
}
|
||||
vCrvStrip.clear() ;
|
||||
}
|
||||
if ( nDir == 0) {
|
||||
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
|
||||
if ( pRescaledSfr->IsValid()) {
|
||||
if ( bRetry)
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
if( ! vbUniform[1]) {
|
||||
vLoop.swap( vUniformedCurves) ;
|
||||
vUniformedCurves.clear() ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -654,12 +874,38 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
|
||||
if ( bRetry)
|
||||
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
if ( ! vUniformedCurves.empty()) {
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
|
||||
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
// controllo che tutte le curve siano chiuse, sennò vuol dire che ho perso qualche pezzo durante le intersezioni
|
||||
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i) {
|
||||
if ( ! vUniformedCurves[i]->IsClosed() && ! vUniformedCurves[i]->Close())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// creo una regione dalle curve riscalate
|
||||
SurfFlatRegionByContours sfrRescaled ;
|
||||
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i)
|
||||
sfrRescaled.AddCurve( Release( vUniformedCurves[i])) ;
|
||||
|
||||
PtrOwner<ISurfFlatRegion> pRescaledSfr( sfrRescaled.GetSurf()) ;
|
||||
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
|
||||
delete pSfr ;
|
||||
pSfr = Release( pRescaledSfr) ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
else if( ! vbUniform[0] || ! vbUniform[1])
|
||||
return false ;
|
||||
|
||||
if ( ! bRescaledU && ! bRescaledV)
|
||||
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
|
||||
|
||||
+3343
-766
File diff suppressed because it is too large
Load Diff
+57
-43
@@ -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,16 +67,15 @@ 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)
|
||||
if ( m_pSTM == nullptr)
|
||||
GetAuxSurf() ;
|
||||
dVolume = 0 ;
|
||||
if( m_pSTM != nullptr)
|
||||
if ( m_pSTM != nullptr)
|
||||
m_pSTM->GetVolume( dVolume) ;
|
||||
return true ; }
|
||||
bool GetCentroid( Point3d& ptCen) const override ;
|
||||
@@ -103,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,
|
||||
@@ -113,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 = 10 * 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 GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined = false) 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
|
||||
@@ -138,16 +136,26 @@ 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 ; // se la superficie non è trimmata restituisce un vettore di 4 elementi. Se la superficie è chiusa lungo un parametro i lati algi estremi di quel parametro saranno null.
|
||||
// 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, bool bDeg3OrDeg2 = false) 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 override ;
|
||||
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
|
||||
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
|
||||
bool RemoveCollapsedSpans( void) override ;
|
||||
bool SwapParameters( void) ;
|
||||
bool LimitSurfToTrimmedRegion( void) override ;
|
||||
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
|
||||
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -159,7 +167,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)
|
||||
@@ -201,36 +209,42 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
// 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 ;
|
||||
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
||||
bool UpdateEdgesFromTree( Tree& tr) const ;
|
||||
// funzione che calcola se gli edge sono collassati in poli
|
||||
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
|
||||
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
|
||||
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 ;
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+190
-36
@@ -28,6 +28,13 @@
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
#define SAVECLASSCRV 0
|
||||
#define SAVEADJUSTCRV 0
|
||||
#if SAVECLASSCRV || SAVEADJUSTCRV
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -56,6 +63,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 ;
|
||||
@@ -106,8 +114,20 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
|
||||
pMyCrv->SetThickness( 0) ;
|
||||
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
|
||||
ICURVEPLIST CrvLst ;
|
||||
|
||||
#if SAVEADJUSTCRV
|
||||
SaveGeoObj( pMyCrv->Clone(), "D:\\Temp\\inters\\CrvCrvInters\\before_adjust.nge") ;
|
||||
#endif
|
||||
|
||||
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
||||
return false ;
|
||||
|
||||
#if SAVEADJUSTCRV
|
||||
for ( auto& pSingCrv : CrvLst)
|
||||
vGeo.push_back( pSingCrv->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\after_adjust.nge") ;
|
||||
#endif
|
||||
|
||||
// aggiungo le singole curve
|
||||
int nExtAdded = 0 ;
|
||||
bool bOk = true ;
|
||||
@@ -168,14 +188,18 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
Vector3d vtExtr ;
|
||||
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
|
||||
pMyCrv->SetExtrusion( Z_AX) ;
|
||||
// verifico non abbia auto-intersezioni che si attraversano o si sovrappongano
|
||||
SelfIntersCurve sInt( *pMyCrv) ;
|
||||
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
||||
return false ;
|
||||
|
||||
// verifico che sia esterna alle curve esterne degli altri chunk
|
||||
bool bOk = true ;
|
||||
CRVCVECTOR ccClass ;
|
||||
for ( auto i : m_vExtInd) {
|
||||
#if SAVEADJUSTCRV
|
||||
vGeo.clear() ;
|
||||
vGeo.push_back( pMyCrv->Clone()) ;
|
||||
vGeo.push_back( m_vpLoop[i]->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\during_add_simpleExt.nge") ;
|
||||
#endif
|
||||
|
||||
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
|
||||
@@ -215,14 +239,9 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
bool
|
||||
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
|
||||
{
|
||||
try {
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
||||
m_nStatus = OK ;
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
}
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
||||
m_nStatus = OK ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -303,10 +322,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
// sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0)
|
||||
if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
|
||||
pMyCrv->Invert() ;
|
||||
// verifico non abbia auto-intersezioni
|
||||
SelfIntersCurve sInt( *pMyCrv) ;
|
||||
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
||||
return false ;
|
||||
|
||||
// ricerca del chunk in cui andrebbe inserito
|
||||
int nChunk = -1 ;
|
||||
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
|
||||
@@ -353,23 +369,18 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
bool
|
||||
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
|
||||
{
|
||||
try {
|
||||
// se da aggiungere all'ultimo chunk
|
||||
if ( nChunk == -1)
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
// altrimenti aggiungo al chunck indicato
|
||||
else {
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
if ( nLoopCnt == 0)
|
||||
return false ;
|
||||
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
||||
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
||||
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
||||
++ m_vExtInd[i] ;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
//se da aggiungere all'ultimo chunk
|
||||
if ( nChunk == -1)
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
//altrimenti aggiungo al chunck indicato
|
||||
else {
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
if ( nLoopCnt == 0)
|
||||
return false ;
|
||||
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
||||
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
||||
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
||||
++ m_vExtInd[i] ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -827,7 +838,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 ;
|
||||
@@ -1373,6 +1384,15 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
|
||||
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
|
||||
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
|
||||
// intersezione
|
||||
|
||||
#if SAVECLASSCRV
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.push_back( Crv.Clone()) ;
|
||||
vGeo.push_back( pLoop->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\crv_and_loop.nge") ;
|
||||
#endif
|
||||
|
||||
IntersCurveCurve ccInt( Crv, *pLoop) ;
|
||||
// classificazione
|
||||
CRVCVECTOR ccPart ;
|
||||
@@ -1536,7 +1556,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
|
||||
int nClass = ccInt.GetRegionCurveClassification() ;
|
||||
switch ( nClass){
|
||||
switch ( nClass) {
|
||||
default : // CCREGC_NULL
|
||||
return REGC_NULL ;
|
||||
case CCREGC_IN1 :
|
||||
@@ -1549,7 +1569,141 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
return REGC_OUT ;
|
||||
case CCREGC_INTERS :
|
||||
return REGC_INTERS ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const
|
||||
{
|
||||
bInterference = false ;
|
||||
// verifico lo stato e il numero di chunk
|
||||
if ( m_nStatus != OK || m_vpLoop.empty() || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// recupero rappresentazione base dell'altra regione
|
||||
const SurfFlatRegion& Reg2 = *GetBasicSurfFlatRegion( &Other) ;
|
||||
// verifico lo stato e il numero di chunk dell'altra regione
|
||||
if ( Reg2.m_nStatus != OK || Reg2.m_vpLoop.empty() || nOthChunk >= Reg2.GetChunkCount())
|
||||
return false ;
|
||||
|
||||
// verifico che le due regioni giacciano in piani paralleli
|
||||
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
|
||||
return false ;
|
||||
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
int nClass = GetChunkSimpleClassification( nChunk, Other, nOthChunk) ;
|
||||
if ( nClass == REGC_NULL)
|
||||
return false ;
|
||||
// se le regioni non hanno isole, allora ho già identificato se i Chunks fanno interferenza
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
int nOtherLoopCnt = Other.GetLoopCount( nOthChunk) ;
|
||||
if ( nLoopCnt == 1 && nOtherLoopCnt == 1) {
|
||||
bInterference = ( nClass != REGC_OUT) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// --- a prescindere dalle isole presenti nei 2 Chunks in esame :
|
||||
// se i due loop esterni si intersecano tra loro o sono gli stessi, allora fanno per forza interferenza
|
||||
if ( nClass == REGC_INTERS || nClass == CCREGC_SAME) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// se invece sono esterni tra loro, allora non c'è interferenza
|
||||
else if ( nClass == REGC_OUT)
|
||||
return true ;
|
||||
// --- Analisi del loop interni :
|
||||
// se la curva esterna corrente è interna alla curva esterna dell'altro chunk
|
||||
else if ( nClass == REGC_IN1) {
|
||||
// se l'altro chunk non ha isole, c'è interferenza (a prescinere da numero di loop interni del primo chunk)
|
||||
if ( nOtherLoopCnt == 1) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
|
||||
// per ogni loop interno (isole)
|
||||
for ( int i = 1 ; i < nOtherLoopCnt ; ++ i) {
|
||||
const ICurve* pCrv2Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( m_frF, Reg2.m_frF))
|
||||
pCrv2Loc = Reg2.GetMyLoop( nOthChunk, i) ;
|
||||
else {
|
||||
pCopyCrv.Set( Reg2.GetMyLoop( nOthChunk, i)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( Reg2.m_frF, m_frF) ;
|
||||
pCrv2Loc = pCopyCrv ;
|
||||
}
|
||||
// classifico il loop esterno del chunk della prima regione rispetto all'interno corrente del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
|
||||
int nInternalClass = ccInt.GetRegionCurveClassification() ;
|
||||
// se le curve non sono classificabili, errore
|
||||
if ( nInternalClass == REGC_NULL)
|
||||
return false ;
|
||||
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
|
||||
else if ( nInternalClass == REGC_IN1)
|
||||
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
|
||||
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
|
||||
else if ( nInternalClass == REGC_OUT)
|
||||
return true ;
|
||||
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
|
||||
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// negli altri casi ho un orientamento errato dei loop o delle regioni
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se la curva esterna dell'altro chunk è interna alla curva esterna corrente
|
||||
else if ( nClass == REGC_IN2) {
|
||||
// se l'altro chunk non ha isole, c'è interferenza
|
||||
if ( nLoopCnt == 1) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv2Loc = Reg2.GetMyLoop( nChunk, 0) ;
|
||||
// per ogni loop interno (isole)
|
||||
for ( int i = 1 ; i < nLoopCnt ; ++ i) {
|
||||
const ICurve* pCrv1Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( Reg2.m_frF, m_frF))
|
||||
pCrv1Loc = GetMyLoop( nOthChunk, i) ;
|
||||
else {
|
||||
pCopyCrv.Set( GetMyLoop( nOthChunk, i)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( m_frF, Reg2.m_frF) ;
|
||||
pCrv1Loc = pCopyCrv ;
|
||||
}
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv2Loc, *pCrv1Loc) ;
|
||||
int nInternalClass = ccInt.GetRegionCurveClassification() ;
|
||||
// se le curve non sono classificabili, errore
|
||||
if ( nInternalClass == REGC_NULL)
|
||||
return false ;
|
||||
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
|
||||
else if ( nInternalClass == REGC_IN1)
|
||||
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
|
||||
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
|
||||
else if ( nInternalClass == REGC_OUT)
|
||||
return true ;
|
||||
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
|
||||
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// negli altri casi ho un orientamento errato dei loop o delle regioni
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// in questo la curva di bordo è interna ad ogni isola ma interna anche al loop esterno, quindi esiste interferenza
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -107,6 +107,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
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 CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const override ; // compare alls
|
||||
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
|
||||
int GetLoopCount( int nChunk) const override ;
|
||||
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
|
||||
@@ -139,6 +140,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ;
|
||||
|
||||
friend class MyCAvSimpleSurfFrMove ;
|
||||
friend class MyCAvSurfFrMove ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
#define SAVELOOPS 0
|
||||
#if SAVELOOPS
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -172,6 +178,13 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||
|
||||
#if SAVELOOPS
|
||||
for (int i = 0 ; i < ssize( vpLoop) ; ++i)
|
||||
vGeo.push_back( vpLoop[i]) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\NewLoops.nge") ;
|
||||
#endif
|
||||
|
||||
if ( IsNull( pSfr)) {
|
||||
MyTestAndDelete( vpCurve) ;
|
||||
MyTestAndDelete( vpLoop) ;
|
||||
|
||||
+322
-45
@@ -234,9 +234,13 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
|
||||
m_vPart.clear() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
if ( ! vtN.Normalize( EPS_ZERO))
|
||||
return SVT_DEL ;
|
||||
// inserisco il triangolo
|
||||
try { m_vTria.emplace_back( nIdVert, nTFlag) ;}
|
||||
catch(...) { return SVT_NULL ;}
|
||||
// aggiorno la sua normale
|
||||
m_vTria.back().vtN = vtN ;
|
||||
// aggiorno massimo TFlag
|
||||
m_nMaxTFlag = max( m_nMaxTFlag, nTFlag) ;
|
||||
// ne determino l'indice
|
||||
@@ -513,9 +517,9 @@ SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const
|
||||
// verifico esistenza del vertice
|
||||
if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL)
|
||||
return false ;
|
||||
// recupero i dati
|
||||
dU = m_vVert[nId].dU ;
|
||||
dV = m_vVert[nId].dV ;
|
||||
// recupero i dati (verso l'esterno sempre in 0..1..2..3..)
|
||||
dU = m_vVert[nId].dU / PREC_SCALE_COEFF ;
|
||||
dV = m_vVert[nId].dV / PREC_SCALE_COEFF ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -866,15 +870,21 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
if ( nPos == -1)
|
||||
return false ;
|
||||
|
||||
// medio le normali, finch� non incontro degli spigoli
|
||||
vtN = m_vTria[nT].vtN ;
|
||||
// medio le normali, finchè non incontro degli spigoli
|
||||
double dAngW = 1 ;
|
||||
GetTriangleVertexAngle( nT, nV, dAngW) ;
|
||||
vtN = dAngW * m_vTria[nT].vtN ;
|
||||
// parto dal triangolo e vado in direzione positiva
|
||||
int nLim = nPos ;
|
||||
for ( int i = NextIndAroundVertex( nPos, nTria, bCirc) ;
|
||||
i != nPos && i < int( vT.size()) ;
|
||||
i = NextIndAroundVertex( i, nTria, bCirc)) {
|
||||
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng)
|
||||
vtN += m_vTria[vT[i]].vtN ;
|
||||
if ( m_vTria[nT].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) {
|
||||
int nK ; double dAngW = 1 ;
|
||||
if ( FindVertexInTria( m_vTria[nT].nIdVert[nV], vT[i], nK) &&
|
||||
GetTriangleVertexAngle( vT[i], nK, dAngW))
|
||||
vtN += dAngW * m_vTria[vT[i]].vtN ;
|
||||
}
|
||||
else
|
||||
break ;
|
||||
nLim = i ;
|
||||
@@ -883,8 +893,12 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
for ( int i = PrevIndAroundVertex( nPos, nTria, bCirc) ;
|
||||
i != nLim && i >= 0 ;
|
||||
i = PrevIndAroundVertex( i, nTria, bCirc)) {
|
||||
if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng)
|
||||
vtN += m_vTria[vT[i]].vtN ;
|
||||
if ( m_vTria[nT].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) {
|
||||
int nK ; double dAngW = 1 ;
|
||||
if ( FindVertexInTria( m_vTria[nT].nIdVert[nV], vT[i], nK) &&
|
||||
GetTriangleVertexAngle( vT[i], nK, dAngW))
|
||||
vtN += dAngW * m_vTria[vT[i]].vtN ;
|
||||
}
|
||||
else
|
||||
break ;
|
||||
}
|
||||
@@ -893,6 +907,23 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetTriangleVertexAngle( int nT, int nV, double& dAng) const
|
||||
{
|
||||
// verifico esistenza del triangolo e validità vertice
|
||||
if ( nT < 0 || nT >= GetTriangleSize() || m_vTria[nT].nIdVert[0] == SVT_DEL || nV < 0 || nV > 2)
|
||||
return false ;
|
||||
// determino i vettori dei due lati che partono dal vertice
|
||||
Point3d ptVert = m_vVert[ m_vTria[nT].nIdVert[nV]].ptP ;
|
||||
Point3d ptPrev = m_vVert[ m_vTria[nT].nIdVert[Prev( nV)]].ptP ;
|
||||
Point3d ptNext = m_vVert[ m_vTria[nT].nIdVert[Next( nV)]].ptP ;
|
||||
Vector3d vtPrev = ptPrev - ptVert ;
|
||||
Vector3d vtNext = ptNext - ptVert ;
|
||||
// determino l'angolo tra i due lati
|
||||
return vtPrev.GetAngle( vtNext, dAng) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneTriangle( int nT) const
|
||||
@@ -1220,16 +1251,17 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
// se rimasto qualcosa
|
||||
if ( pgTria.GetSideCount() > 0) {
|
||||
// lo proietto sul piano e creo la regione
|
||||
pgTria.Scale( frOCS, 1, 1, 0) ;
|
||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
if ( pgTria.Scale( frOCS, 1, 1, 0)) {
|
||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1335,6 +1367,8 @@ SurfTriMesh::GetTitle( void) const
|
||||
bool
|
||||
SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
{
|
||||
// visualizzazione spigoli
|
||||
sOut += "ShowEdges=" + ToString( GetShowEdges()) + szNewLine ;
|
||||
// area
|
||||
double dArea ;
|
||||
GetArea( dArea) ;
|
||||
@@ -1687,11 +1721,13 @@ SurfTriMesh::AdjustVertices( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustAdjacencies( void)
|
||||
SurfTriMesh::AdjustAdjacencies( bool AdjustVert)
|
||||
{
|
||||
// sistemo le relazioni tra triangoli e vertici
|
||||
if ( ! AdjustVertices())
|
||||
return false ;
|
||||
if ( AdjustVert) {
|
||||
if ( ! AdjustVertices())
|
||||
return false ;
|
||||
}
|
||||
// matrice di incidenza vertici-triangoli
|
||||
INTMATRIX mVertTria( GetVertexSize()) ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
@@ -1874,7 +1910,7 @@ SurfTriMesh::TestSealing( void)
|
||||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
|
||||
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
|
||||
bClosed = false ;
|
||||
break ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1936,7 +1972,7 @@ SurfTriMesh::PackVertices( void)
|
||||
++ nFirstFree ;
|
||||
}
|
||||
else
|
||||
vVId.push_back( nId) ;
|
||||
vVId.push_back( nId) ;
|
||||
}
|
||||
else {
|
||||
if ( nFirstFree == SVT_NULL)
|
||||
@@ -2091,6 +2127,17 @@ SurfTriMesh::CreateByFlatContour( const PolyLine& PL)
|
||||
return AdjustTopology() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL)
|
||||
{
|
||||
INTMATRIX vnPLIndMat ;
|
||||
vnPLIndMat.push_back( { 0}) ;
|
||||
for ( int i = 1 ; i < int( vPL.size()) ; ++ i)
|
||||
vnPLIndMat[0].push_back( i) ;
|
||||
return CreateByRegion( vPL, vnPLIndMat) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat)
|
||||
@@ -3032,7 +3079,7 @@ SurfTriMesh::AddBiTriangle( const int nIdVert[4])
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::DoCompacting( double dTol)
|
||||
{
|
||||
{
|
||||
// imposto ricalcolo
|
||||
m_nStatus = ERR ;
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -3073,6 +3120,7 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
int nVIdSize = int( vVId.size()) ;
|
||||
|
||||
// sistemo gli indici dei vertici nei triangoli
|
||||
INTVECTOR vInvalidIds ;
|
||||
for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) {
|
||||
// salto i triangoli cancellati
|
||||
if ( m_vTria[nId].nIdVert[0] == SVT_DEL)
|
||||
@@ -3089,15 +3137,51 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
// aggiorno il triangolo
|
||||
m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ;
|
||||
m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
// se due vertici coincidono o la normale non è calcolabile, cancello il triangolo
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] ||
|
||||
m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] ||
|
||||
m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] ||
|
||||
! CalcTriangleNormal( nId))
|
||||
RemoveTriangle( nId) ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
|
||||
// verifico se triangolo da rimuovere per vertici coincidenti
|
||||
bool bRemove = false ;
|
||||
int nTAdj1 = SVT_NULL, nTAdj2 = SVT_NULL ;
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[1] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
else if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[1] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
else if ( m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
if ( bRemove) {
|
||||
// sistemo le contro adiacenze
|
||||
if ( nTAdj1 != SVT_NULL) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
if ( m_vTria[nTAdj1].nIdAdjac[j] == nId)
|
||||
m_vTria[nTAdj1].nIdAdjac[j] = nTAdj2 ;
|
||||
}
|
||||
if ( nTAdj2 != SVT_NULL) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
if ( m_vTria[nTAdj2].nIdAdjac[j] == nId)
|
||||
m_vTria[nTAdj2].nIdAdjac[j] = nTAdj1 ;
|
||||
}
|
||||
// rimuovo il triangolo
|
||||
RemoveTriangle( nId) ;
|
||||
}
|
||||
|
||||
// verifico se il triangolo va rimosso per normale non calcolabile
|
||||
else if ( ! CalcTriangleNormal( nId))
|
||||
vInvalidIds.emplace_back( nId) ;
|
||||
}
|
||||
|
||||
// elimino triangoli invalidi ( con gestione speciale per evitare T-junctions)
|
||||
if ( ! vInvalidIds.empty())
|
||||
RemoveInvalidTriangles( vInvalidIds) ;
|
||||
|
||||
// compatto il vettore dei vertici
|
||||
if ( ! PackVertices())
|
||||
return false ;
|
||||
@@ -3334,22 +3418,23 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
|
||||
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
|
||||
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
|
||||
|
||||
// aggiorno le facce
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL) {
|
||||
// se c'è mirror, devo invertire la faccia
|
||||
if ( bMirror)
|
||||
InvertTriangle( i) ;
|
||||
// aggiorno la normale
|
||||
if ( ! CalcTriangleNormal( i)) {
|
||||
// elimino il triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
// se c'è mirror, devo invertire le facce
|
||||
if ( bMirror) {
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i)
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL)
|
||||
InvertTriangle( i) ;
|
||||
}
|
||||
|
||||
// rimuovo i triangoli resi invalidi dalla scalatura
|
||||
bool bOk = DoCompacting() ;
|
||||
|
||||
return DoCompacting() ;
|
||||
// rimuovo i triangoli doppi
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -3581,6 +3666,18 @@ SurfTriMesh::Invert( void)
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i)
|
||||
InvertTriangle( i) ;
|
||||
|
||||
// se bordi della sfaccettatura validi
|
||||
if ( m_bFacEdged) {
|
||||
for ( int nE = 0 ; nE < GetEdgeCount() ; ++ nE) {
|
||||
// inversione dei vertici nel vettore delle sfaccettature
|
||||
swap( m_vFacEdge[nE].nIdVert[0], m_vFacEdge[nE].nIdVert[1]) ;
|
||||
// inversione delle adiacenze nel vettore delle sfaccettature
|
||||
swap( m_vFacEdge[nE].nIdFacAdj[0], m_vFacEdge[nE].nIdFacAdj[1]) ;
|
||||
// inversione dell'angolo interno
|
||||
m_vFacEdge[nE].dIntAng *= -1. ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -3973,6 +4070,56 @@ SurfTriMesh::CloneShell( int nShell) const
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartLocalBBox( int nP, BBox3d& b3Loc) const
|
||||
{
|
||||
// verifico esistenza della parte
|
||||
if ( nP < 0 || nP >= GetPartCount())
|
||||
return false ;
|
||||
|
||||
// assegno il box in locale
|
||||
b3Loc.Reset() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// recupero il vettore delle Shell della parte corrente
|
||||
const auto& vShell = m_vPart[nP].vShell ;
|
||||
// scorro i triangoli validi contenuti nella Shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
// ciclo sui tre vertici
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
b3Loc.Add( m_vVert[m_vTria[i].nIdVert[j]].ptP) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const
|
||||
{
|
||||
// verifico esistenza della parte
|
||||
if ( nP < 0 || nP >= GetPartCount())
|
||||
return false ;
|
||||
|
||||
// assegno il box in locale
|
||||
b3Ref.Reset() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// recupero il vettore delle Shell della parte corrente
|
||||
const auto& vShell = m_vPart[nP].vShell ;
|
||||
// scorro i triangoli validi contenuti nella Shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
// ciclo sui tre vertici
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
b3Ref.Add( GetToGlob( m_vVert[m_vTria[i].nIdVert[j]].ptP, frRef)) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetPartCount( void) const
|
||||
@@ -4268,6 +4415,35 @@ SurfTriMesh::ClonePart( int nPart) const
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const
|
||||
{
|
||||
// l'indice della faccia deve essere nei limiti
|
||||
if ( nFacet < 0 || nFacet >= int( m_vFacet.size()))
|
||||
return false ;
|
||||
|
||||
// mi assicuro che siano calcolate il numero di parti e di shell
|
||||
int nParts = GetPartCount() ;
|
||||
|
||||
int nTria = m_vFacet[nFacet] ;
|
||||
nShell = m_vTria[nTria].nShell ;
|
||||
|
||||
// scopro in quale part è la shell
|
||||
int nPartTemp = 0 ;
|
||||
nPart = - 1 ;
|
||||
while ( nPartTemp < nParts && nPart == - 1) {
|
||||
for ( int i : m_vPart[nPartTemp].vShell) {
|
||||
if ( i == nShell) {
|
||||
nPart = nPartTemp ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
++nPartTemp ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::ResetTFlags( void)
|
||||
@@ -4311,3 +4487,104 @@ SurfTriMesh::SetTempInt( int nId, int nTempInt) const
|
||||
m_vTria[nId].nTemp = nTempInt ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol)
|
||||
{
|
||||
// scorro i triangoli
|
||||
for ( const Triangle3dEx& Tria : vTria) {
|
||||
// ciclo sui tre vertici
|
||||
int nIdV[3]{} ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
||||
// verifico se vertice già presente
|
||||
int nId ;
|
||||
if ( ! VertGrid.Find( Tria.GetP( nV), dVertexTol, nId)) {
|
||||
// se non presente, lo aggiugo
|
||||
nIdV[nV] = AddVertex( Tria.GetP( nV)) ;
|
||||
if ( nIdV[nV] == SVT_NULL)
|
||||
return false ;
|
||||
VertGrid.InsertPoint( Tria.GetP( nV), nIdV[nV]) ;
|
||||
}
|
||||
else
|
||||
nIdV[nV] = nId ;
|
||||
}
|
||||
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
|
||||
if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) {
|
||||
int nT = AddTriangle( nIdV, Tria.GetGrade()) ;
|
||||
if ( nT != SVT_NULL && nT != SVT_DEL) {
|
||||
// associo relazione vertice-triangolo
|
||||
for ( int i = 0 ; i < 3 ; ++ i)
|
||||
m_vVert[nIdV[i]].nIdTria = nT ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustTopologyFromZMap( void)
|
||||
{
|
||||
// cancello tutti i vertici che puntano a triangoli cancellati
|
||||
bool bPack = false ;
|
||||
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
|
||||
if ( m_vVert[i].nIdTria == SVT_NULL) {
|
||||
m_vVert[i].nIdTria = SVT_DEL ;
|
||||
bPack = true ;
|
||||
}
|
||||
}
|
||||
if ( bPack)
|
||||
PackVertices() ;
|
||||
m_nStatus = SurfTriMesh::OK ;
|
||||
|
||||
// calcolo le adiacenze
|
||||
if ( ! AdjustAdjacencies())
|
||||
return false ;
|
||||
|
||||
// verifico l'orientamento ( TODO -- Da migliorare...)
|
||||
// Ora per funzionare è necessario che il ciclo sui triangoli parta da un triangolo orientato
|
||||
// correttamente e che i triangoli invertiti siano "circondati" da triangoli tutti orientati correttamente
|
||||
if ( ! AdjustOrientations())
|
||||
return false ;
|
||||
|
||||
// calcolo le facce
|
||||
if ( ! VerifyFaceting())
|
||||
return false ;
|
||||
|
||||
// rimozione delle TJunction
|
||||
bool bModified = false ;
|
||||
if ( ! RemoveTJunctions( bModified, SQ_EPS_SMALL))
|
||||
return false ;
|
||||
if ( bModified) {
|
||||
if ( ! AdjustVertices() || ! DoCompacting())
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
TestSealing() ;
|
||||
|
||||
// semplifico le facce ( anche più piccola)
|
||||
if ( ! SimplifyFacets( MAX_EDGE_LEN_STD, false, 5. * EPS_SMALL))
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::AdjustTopologyFromZMap")
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetTriaFromFace( int nF, int& nT) const
|
||||
{
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico stato sfaccettatura
|
||||
if ( ! VerifyFaceting())
|
||||
return false ;
|
||||
// l'indice della faccia deve essere nei limiti
|
||||
if ( nF < 0 || nF >= int( m_vFacet.size()))
|
||||
return false ;
|
||||
// recupero la normale di un triangolo della faccetta
|
||||
nT = m_vFacet[nF] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+27
-7
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2023
|
||||
// EgalTech 2014-2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMesh.h Data : 09.12.23 Versione : 2.5l2
|
||||
// File : SurfTriMesh.h Data : 28.03.25 Versione : 2.7c4
|
||||
// Contenuto : Dichiarazione della classe Superficie TriMesh.
|
||||
//
|
||||
//
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GeoObjRW.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkHashGrids3d.h"
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
#include <deque>
|
||||
#include <set>
|
||||
|
||||
@@ -251,6 +252,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool RemoveTriangle( int nId) override ;
|
||||
bool AdjustTopology( void) override ;
|
||||
bool CreateByFlatContour( const PolyLine& PL) override ;
|
||||
bool CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL) override ;
|
||||
bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) override ;
|
||||
bool CreateByPointCurve( const Point3d& ptP, const PolyLine& PL) override ;
|
||||
bool CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nRuledType) override ;
|
||||
@@ -320,13 +322,15 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetEdge( int nInd, int& nV1, int& nV2, int& nFl, int& nFr, double& dAng) const override ;
|
||||
bool GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) const override ;
|
||||
bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ;
|
||||
bool GetCurvature( int nV,
|
||||
double& dMinK, Vector3d& vtMinK, double& dMaxK, Vector3d& vtMaxK, bool& bPlanar, Vector3d& vtNorm) const override ;
|
||||
bool Cut( const Plane3d& plPlane, bool bSaveOnEq) override ;
|
||||
bool GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) override ;
|
||||
bool Add( const ISurfTriMesh& Other) override ;
|
||||
bool Intersect( const ISurfTriMesh& Other) override ;
|
||||
bool Subtract( const ISurfTriMesh& Other) override ;
|
||||
bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
|
||||
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
|
||||
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
|
||||
bool CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bool bSaveOnEq) override ;
|
||||
bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ;
|
||||
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
|
||||
@@ -335,12 +339,15 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetShellArea( int nShell, double& dArea) const override ;
|
||||
bool RemoveShell( int nShell) override ;
|
||||
SurfTriMesh* CloneShell( int nShell) const override ;
|
||||
bool GetPartLocalBBox( int nP, BBox3d& b3Loc) const override ;
|
||||
bool GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const override ;
|
||||
int GetPartCount( void) const override ;
|
||||
bool RemovePart( int nPart) override ;
|
||||
bool GetPartArea( int nPart, double& dArea) const override ;
|
||||
bool GetPartVolume( int nPart, double& dVolume) const override ;
|
||||
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
|
||||
SurfTriMesh* ClonePart( int nPart) const override ;
|
||||
bool GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const override ;
|
||||
bool SetTFlag( int nId, int nTFlag) override ;
|
||||
bool GetTFlag( int nId, int& nFlag) const override ;
|
||||
int GetMaxTFlag( void) const override
|
||||
@@ -372,6 +379,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetTempInt( int nId, int& nTempInt) const ;
|
||||
bool ResetTempInts( void) const ;
|
||||
bool SetTempInt( int nId, int nTempInt) const ;
|
||||
bool AddTriaFromZMap( const TRIA3DEXVECTOR& vTria, PointGrid3d& VertGrid, double dVertexTol = 2 * EPS_SMALL) ;
|
||||
bool AdjustTopologyFromZMap( void) ;
|
||||
bool GetTriaFromFace( int nF, int& nT) const ;
|
||||
|
||||
private :
|
||||
typedef std::vector<StmVert> VERTVECTOR ;
|
||||
@@ -387,7 +397,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool CopyFrom( const SurfTriMesh& clSrc) ;
|
||||
bool Validate( bool bCorrect = false) ;
|
||||
bool AdjustVertices( void) ;
|
||||
bool AdjustAdjacencies( void) ;
|
||||
bool AdjustAdjacencies( bool AdjustVert = true) ;
|
||||
bool AdjustOrientations( void) ;
|
||||
bool AdjustTriaOrientation( TRINTDEQUE& S3iQ) ;
|
||||
bool TestSealing( void) ;
|
||||
@@ -405,6 +415,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
int NextIndAroundVertex( int nInd, int nSize, bool bCirc) const ;
|
||||
int PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const ;
|
||||
bool GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const ;
|
||||
bool GetTriangleVertexAngle( int nT, int nV, double& dAng) const ;
|
||||
bool MarchAlongLoop( int nT, int nV, int nTimeStamp, PolyLine& PL) const ;
|
||||
bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
|
||||
bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ;
|
||||
@@ -432,14 +443,16 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
|
||||
bool IdentifyShells( void) const ;
|
||||
bool RemoveDoubleTriangles( bool& bModified) ;
|
||||
bool RemoveTJunctions( bool& bModified) ;
|
||||
bool RemoveTJunctions( bool& bModified, double dMinSqDist = SQ_EPS_TRIA_H) ;
|
||||
bool FlipTriangles( int nTA, int nTB) ;
|
||||
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ;
|
||||
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true, double dTolAlign = 50 * EPS_SMALL) ;
|
||||
bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ;
|
||||
bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ;
|
||||
bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ;
|
||||
bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ;
|
||||
|
||||
bool AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, double dTolAlign, bool& bModif) const ;
|
||||
bool RemoveInvalidTriangles( const INTVECTOR& vIds) ;
|
||||
bool FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const ;
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
Status m_nStatus ; // stato
|
||||
@@ -482,3 +495,10 @@ inline SurfTriMesh* GetBasicSurfTriMesh( IGeoObj* pGObj)
|
||||
{ if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH)
|
||||
return nullptr ;
|
||||
return ( static_cast<SurfTriMesh*>( pGObj)) ; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Raccolte di puntatori a SurfTriMesh
|
||||
typedef std::vector<const SurfTriMesh*> CISRFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh
|
||||
typedef std::vector<SurfTriMesh*> ISRFTMPVECTOR ; // vettore di puntatori a SurfTriMesh
|
||||
typedef std::list<SurfTriMesh*> ISRFTMPLIST ; // lista di puntatori a SurfTriMesh
|
||||
typedef std::vector<PtrOwner<SurfTriMesh>> ISRFTMPOVECTOR ; // vettore di puntatori esclusivi a SurfTriMesh
|
||||
|
||||
+43
-84
@@ -41,7 +41,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const double BOOLEAN_SCALE = 1024 ;
|
||||
const double BOOLEAN_SCALE = PREC_SCALE_COEFF ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
@@ -502,9 +502,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. Questo viene diviso in sotto-loop
|
||||
// chiusi mediante quelli aperti. I loop chiusi trovati precedentemente sono interni a uno dei
|
||||
// sotto-loop chiusi di cui è formato il perimetro.
|
||||
@@ -704,16 +702,18 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
// Elimino loop interni non validi
|
||||
bool bDouble = true ;
|
||||
// Verifico se i loop interni sono validi
|
||||
bool bAllInvalid = true ;
|
||||
for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) {
|
||||
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 2) {
|
||||
bDouble = false ;
|
||||
// se chain formata da tre segmenti significa che si tratta di due linee sovrapposte ( il terzo tratto è quello aggiunto
|
||||
// per forzare la chiusura)
|
||||
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 3) {
|
||||
bAllInvalid = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vInnerLoop.empty() || bDouble) {
|
||||
if ( vInnerLoop.empty() || bAllInvalid) {
|
||||
// Eseguo triangolazione
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
@@ -753,63 +753,20 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vPolygons.emplace_back( CurLoop) ;
|
||||
}
|
||||
|
||||
// poligono
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine( vPolygons[1]) ;
|
||||
|
||||
// controllo direzioni delle normali
|
||||
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
|
||||
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
|
||||
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
|
||||
// Ciclo sui segmenti del loop esterno
|
||||
auto itSt = ExternLoopList.begin() ;
|
||||
auto itEn = itSt ;
|
||||
++ itEn ;
|
||||
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
|
||||
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
|
||||
Point3d ptSt = itSt->first ;
|
||||
Point3d ptEn = itEn->first ;
|
||||
Vector3d vtSeg = ptEn - ptSt ;
|
||||
double dSegLen = vtSeg.Len() ;
|
||||
vtSeg /= dSegLen ;
|
||||
// Vettore dei punti dei loop interni che stanno sul segmento del loop esterno
|
||||
PNTUVECTOR vPointWithOrder ;
|
||||
// Ciclo sui loop interni
|
||||
for ( int nInnPoly = 1 ; nInnPoly < int( vPolygons.size()) ; ++ nInnPoly) {
|
||||
// Ciclo sui punti dei loop interni
|
||||
Point3d ptInnPoint ;
|
||||
bool bIsFirst = true ;
|
||||
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
|
||||
while ( bContinue) {
|
||||
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
double dLongPos = ( ptInnPoint - ptSt) * vtSeg ;
|
||||
if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) {
|
||||
POINTU NewPointU ;
|
||||
NewPointU.first = ptInnPoint ;
|
||||
NewPointU.second = dLongPos ;
|
||||
if ( ! bIsFirst)
|
||||
vPointWithOrder.emplace_back( NewPointU) ;
|
||||
}
|
||||
bIsFirst = false ;
|
||||
bContinue = vPolygons[nInnPoly].GetNextPoint( ptInnPoint) ;
|
||||
}
|
||||
}
|
||||
// Riordino i punti interni sul segmento esterno in funzione della distanza dall'origine di esso
|
||||
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) - 1 ; ++ nPi) {
|
||||
for ( int nPj = nPi + 1 ; nPj < int( vPointWithOrder.size()) ; ++ nPj) {
|
||||
if ( vPointWithOrder[nPi].second > vPointWithOrder[nPj].second) {
|
||||
swap( vPointWithOrder[nPi], vPointWithOrder[nPj]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Aggiungo i punti al loop esterno
|
||||
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
|
||||
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
|
||||
}
|
||||
// controllo la direzione della normale del triangolo con quella del poligono di area maggiore
|
||||
// ( per gestire eventuali inscatolamenti)
|
||||
Vector3d vtPoly = V_NULL ;
|
||||
double dMaxArea = -1 ;
|
||||
for ( int i = 1 ; i < int( vPolygons.size()) ; i ++) {
|
||||
Plane3d plPoly ;
|
||||
double dAreaPoly ;
|
||||
vPolygons[i].IsClosedAndFlat( plPoly, dAreaPoly) ;
|
||||
if ( dAreaPoly > dMaxArea) {
|
||||
vtPoly = plPoly.GetVersN() ;
|
||||
dMaxArea = dAreaPoly ;
|
||||
}
|
||||
}
|
||||
bool bCodirectedNormals = trTria.GetN() * vtPoly > 0. ;
|
||||
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
@@ -836,6 +793,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
|
||||
// Divido i loop che si autointercettano
|
||||
// TO DO : da verificare. Questa porzione di codice non dovrebbe andare prima della triangolazione?
|
||||
int nInitialLoopNum = int( vPolygons.size()) ;
|
||||
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
@@ -883,11 +841,11 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
itSt2 = LoopPointList.emplace( itEn2, vAddingPointWithOrder[nPi]) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Spezzo i loop autointersecantesi
|
||||
POLYLINEVECTOR vAuxPolygons ;
|
||||
vAuxPolygons.emplace_back( vPolygons[nL]) ;
|
||||
|
||||
|
||||
bool bSplitted = true ;
|
||||
while ( bSplitted) {
|
||||
bSplitted = false ;
|
||||
@@ -956,16 +914,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vPolygons.erase( vPolygons.begin() + i) ;
|
||||
else
|
||||
++ i ;
|
||||
|
||||
}
|
||||
|
||||
bool bCordirectedNormals_intLoop = bCodirectedNormals ;
|
||||
// eventuale inversione della prima curva ( che determina il verso della triangolazione) per averla orientata
|
||||
// come il triangolo
|
||||
if ( ! vPolygons.empty()) {
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine( vPolygons[0]) ;
|
||||
// controllo direzioni delle normali
|
||||
bCordirectedNormals_intLoop = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
if ( ! bCordirectedNormals_intLoop)
|
||||
if ( trTria.GetN() * pgPol.GetVersN() < 0.)
|
||||
vPolygons[0].Invert() ;
|
||||
}
|
||||
|
||||
@@ -981,7 +936,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCordirectedNormals_intLoop)
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = -1 ;
|
||||
@@ -1123,7 +1078,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
{
|
||||
{
|
||||
bool bModif = false ;
|
||||
SurfTriMesh& SurfB = Other ;
|
||||
|
||||
@@ -1176,7 +1131,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
INTVECTOR vNearTria ;
|
||||
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
|
||||
// I scorro tutti i triangoli di B che intersecano il box di A
|
||||
// Scorro tutti i triangoli di B che intersecano il box di A
|
||||
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
|
||||
|
||||
// Se il triangolo B non è valido, continuo
|
||||
@@ -1365,7 +1320,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Triangoli sovrapposti
|
||||
if ( bContinue) {
|
||||
int nTriaNum2A = GetTriangleSize() ;
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
SurfB.ResetHashGrids3d() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) {
|
||||
// Se il triangolo A non è valido, continuo
|
||||
@@ -1375,15 +1330,19 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Box del triangolo A
|
||||
BBox3d b3dTriaA ;
|
||||
trTriaA.GetLocalBBox( b3dTriaA) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ;
|
||||
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
|
||||
// Se il triangolo B non è valido, continuo
|
||||
// Se il triangolo B non è valido, continuo
|
||||
Triangle3d trTriaB ;
|
||||
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
|
||||
continue ;
|
||||
// Se i triangoli sono sovrapposti
|
||||
// Se sono già stati classificati entrambi come sovrapposti continuo
|
||||
if ( abs( m_vTria[nTA].nTempShell) == 2 && abs( SurfB.m_vTria[vNearTria[nTB]].nTempShell) == 2)
|
||||
continue ;
|
||||
|
||||
// Se i triangoli sono sovrapposti
|
||||
TRIA3DVECTOR vTriaAB ;
|
||||
Point3d ptTempA, ptTempB ;
|
||||
int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ;
|
||||
@@ -1475,7 +1434,7 @@ SurfTriMesh::Add( const ISurfTriMesh& Other)
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfA_cl ;
|
||||
SurfA_cl.CopyFrom( this) ;
|
||||
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
@@ -1625,12 +1584,12 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
AddTriangle( nNewVert, m_nMaxTFlag) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sistemazioni varie
|
||||
bool bOk = ( AdjustVertices() && DoCompacting()) ;
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
bOk = bOk && RemoveTJunctions( bModified) ;
|
||||
if ( bModified)
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const double CUT_SCALE = 1024 ;
|
||||
const double CUT_SCALE = PREC_SCALE_COEFF ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
|
||||
+167
-19
@@ -21,6 +21,8 @@
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -54,7 +56,7 @@ SurfTriMesh::UpdateFaceting( void)
|
||||
bool bOk = true ;
|
||||
for ( int j = 0 ; j < int( vOldFacet.size()) ; ++ j) {
|
||||
int i = vOldFacet[j] ;
|
||||
// salto triangoli inesistenti o già assegnati
|
||||
// salto triangoli inesistenti o già assegnati
|
||||
if ( i >= int( m_vTria.size()) ||
|
||||
m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nIdFacet != SVT_NULL)
|
||||
@@ -69,7 +71,7 @@ SurfTriMesh::UpdateFaceting( void)
|
||||
|
||||
// ricostruisco le altre sfaccettature
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o già assegnati
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nIdFacet != SVT_NULL)
|
||||
continue ;
|
||||
@@ -103,7 +105,7 @@ SurfTriMesh::UpdateOneFace( int nFacet, int nT)
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( nT) ;
|
||||
// finchè set non vuoto
|
||||
// finchè set non vuoto
|
||||
bool bOk = true ;
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
@@ -421,7 +423,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 0 è di contorno
|
||||
// se il lato 0 è di contorno
|
||||
else if ( nAdjF[0] != nF) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -433,7 +435,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 1 è di contorno
|
||||
// se il lato 1 è di contorno
|
||||
else if ( nAdjF[1] != nF) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -445,7 +447,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 2, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 2 è di contorno
|
||||
// se il lato 2 è di contorno
|
||||
else if ( nAdjF[2] != nF) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -457,7 +459,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongFacetLoop( nF, nT, 0, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti non c'è contorno
|
||||
// altrimenti non c'è contorno
|
||||
else {
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
@@ -476,7 +478,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
|
||||
return false ;
|
||||
// se loop esterno
|
||||
if ( vtN * plPlane.GetVersN() > 0) {
|
||||
// se non c'è ancora loop esterno in prima posizione
|
||||
// se non c'è ancora loop esterno in prima posizione
|
||||
if ( ! bOutFirst) {
|
||||
// lo sposto in prima posizione
|
||||
if ( i != 0)
|
||||
@@ -517,7 +519,7 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
|
||||
// verifico appartenga alla stessa faccia
|
||||
if ( m_vTria[nAdjT].nIdFacet != nF)
|
||||
return false ;
|
||||
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
|
||||
// recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza)
|
||||
int nAdjS = SVT_NULL ;
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( m_vTria[nAdjT].nIdAdjac[i] == nT) {
|
||||
@@ -531,11 +533,11 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp,
|
||||
return false ;
|
||||
// vertice di fine adiacenza e indice del successivo lato
|
||||
int nAdjV = Next( nAdjS) ;
|
||||
// verifico se il lato successivo è un bordo
|
||||
// verifico se il lato successivo è un bordo
|
||||
int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
|
||||
int nNextF = ( nNextT != SVT_NULL ? m_vTria[nNextT].nIdFacet : SVT_NULL) ;
|
||||
if ( nNextF != nF) {
|
||||
// se già recuperato
|
||||
// se già recuperato
|
||||
if ( m_vTria[nAdjT].nTemp == nTimeStamp) {
|
||||
bEnd = true ;
|
||||
return true ;
|
||||
@@ -593,7 +595,7 @@ SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Po
|
||||
// verifico esistenza seconda faccia
|
||||
if ( nF2 < 0 || nF2 >= int( m_vFacet.size()))
|
||||
return false ;
|
||||
// verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto
|
||||
// verifico se c'è un contatto con la seconda faccia e recupero i punti estremi della eventuale linea di contatto
|
||||
bAdjac = false ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
double dUs, dUe ;
|
||||
@@ -606,7 +608,7 @@ SurfTriMesh::GetFacetsContact( int nF1, int nF2, bool& bAdjac, Point3d& ptP1, Po
|
||||
ptP2 = ptPe ;
|
||||
}
|
||||
else {
|
||||
// parametri del segmento già definito
|
||||
// parametri del segmento già definito
|
||||
Vector3d vtT ;
|
||||
double dLen ;
|
||||
DirDist( ptP1, ptP2, vtT, dLen) ;
|
||||
@@ -646,7 +648,7 @@ SurfTriMesh::GetFacetCenter( int nF, Point3d& ptCen, Vector3d& vtN) const
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! GetFacetLoops( nF, vPL) || vPL.empty())
|
||||
return false ;
|
||||
// calcolo il centro del loop esterno (è il primo)
|
||||
// calcolo il centro del loop esterno (è il primo)
|
||||
PolygonPlane PolyPlane ;
|
||||
Point3d ptP ;
|
||||
for ( bool bFound = vPL[0].GetFirstPoint( ptP) ; bFound ; bFound = vPL[0].GetNextPoint( ptP))
|
||||
@@ -730,7 +732,7 @@ SurfTriMesh::CloneFacet( int nF) const
|
||||
// ciclo sui tre vertici
|
||||
int nIdV[3] ;
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
// verifico se vertice già presente
|
||||
// verifico se vertice già presente
|
||||
const auto it = PntMap.find( m_vTria[nT].nIdVert[j]) ;
|
||||
if ( it == PntMap.end()) {
|
||||
// aggiungo il vertice
|
||||
@@ -773,7 +775,7 @@ SurfTriMesh::RemoveFacet( int nF)
|
||||
if ( ! DoCompacting())
|
||||
return false ;
|
||||
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
@@ -878,7 +880,7 @@ SurfTriMesh::UpdateFacetEdging( void)
|
||||
m_bFacEdged = false ;
|
||||
m_vFacEdge.clear() ;
|
||||
|
||||
// verifico validità sfaccettatura
|
||||
// verifico validità sfaccettatura
|
||||
if ( ! VerifyFaceting())
|
||||
return false ;
|
||||
|
||||
@@ -957,7 +959,7 @@ SurfTriMesh::GetEdge( int nInd, int& nV1, int& nV2, int& nFl, int& nFr, double&
|
||||
// verifico stato bordi sfaccettatura
|
||||
if ( ! VerifyFacetEdging())
|
||||
return false ;
|
||||
// verifico la validità dell'indice
|
||||
// verifico la validità dell'indice
|
||||
if ( nInd < 0 || nInd > int( m_vFacEdge.size()))
|
||||
return SVT_NULL ;
|
||||
// recupero i dati
|
||||
@@ -980,7 +982,7 @@ SurfTriMesh::GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) cons
|
||||
// verifico stato bordi sfaccettatura
|
||||
if ( ! VerifyFacetEdging())
|
||||
return false ;
|
||||
// verifico la validità dell'indice
|
||||
// verifico la validità dell'indice
|
||||
if ( nInd < 0 || nInd > int( m_vFacEdge.size()))
|
||||
return SVT_NULL ;
|
||||
// recupero i dati
|
||||
@@ -1015,3 +1017,149 @@ SurfTriMesh::GetEdges( ICURVEPOVECTOR& vpCurve) const
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Funzione per il calcolo della curvatura massima e minima in un vertice della superficie TriMesh
|
||||
// dMinK : curvatura minima
|
||||
// vtMinK : versore direzione curvatura minima
|
||||
// dMaxK : curvatura massima
|
||||
// vtMaxK : versore direzione curvatura massima
|
||||
// bPlanar : Flag per indicare le superficie localmente piana
|
||||
// vtNorm : versore normale del piano tangente alla supericie nel vertice
|
||||
bool
|
||||
SurfTriMesh::GetCurvature( int nV,
|
||||
double& dMinK, Vector3d& vtMinK, double& dMaxK, Vector3d& vtMaxK, bool& bPlanar, Vector3d& vtNorm) const
|
||||
{
|
||||
// Controllo la validità della TriMesh e del Vertice
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
Point3d ptCurr ;
|
||||
if ( ! GetVertex( nV, ptCurr))
|
||||
return false ;
|
||||
bPlanar = false ;
|
||||
|
||||
// Recupero tutti i vertici attorno al vertice corrente ( se presenza di lato libero, allora errore)
|
||||
INTVECTOR vT ;
|
||||
bool bCirc ;
|
||||
if ( ! GetAllTriaAroundVertex( nV, vT, bCirc) || ! bCirc)
|
||||
return false ;
|
||||
|
||||
// Calcolo la normale del vertice pesata mediante angolo sotteso e distanza baricentrica
|
||||
// ["Estimation Normal Vector of Triangular Mesh Vertex by Angle and Centroid Weights"]
|
||||
// Controllo anche di non essere in presenza di uno spigolo vivo
|
||||
INTSET setIndTriaNeightbors ;
|
||||
bool bFirstTria = true ;
|
||||
Vector3d vtNFirstTria = V_NULL ;
|
||||
for ( const int& nT : vT) {
|
||||
// Recupero il triangolo corrente
|
||||
Triangle3d Tria ;
|
||||
int nIdVert[3] ;
|
||||
if ( ! GetTriangle( nT, Tria) || ! GetTriangle( nT, nIdVert))
|
||||
return false ;
|
||||
// Se il triangolo ha area troppo piccola, lo scarto
|
||||
if ( Tria.GetArea() < EPS_SMALL)
|
||||
continue ;
|
||||
// Se primo triangolo salvo la sua normale di riferimento per successivi confronti
|
||||
if ( bFirstTria) {
|
||||
vtNFirstTria = Tria.GetN() ;
|
||||
bFirstTria = false ;
|
||||
}
|
||||
else {
|
||||
// Se spigolo vivo, la curvatura non può esistere
|
||||
if ( Tria.GetN() * vtNFirstTria < m_dCosSmAng - EPS_SMALL)
|
||||
return false ;
|
||||
}
|
||||
// Recupero le direzioni delle semirette per l'angolo al vertice corrente
|
||||
Vector3d vtDir0 = V_NULL, vtDir1 = V_NULL ;
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( AreSamePointApprox( Tria.GetP( i), ptCurr)) {
|
||||
vtDir0 = Tria.GetP( ( i + 1) % 3) - Tria.GetP( i) ;
|
||||
vtDir0.Normalize() ;
|
||||
vtDir1 = Tria.GetP( ( i + 2) % 3) - Tria.GetP( i) ;
|
||||
vtDir1.Normalize() ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( nV == nIdVert[i]) {
|
||||
setIndTriaNeightbors.insert( nIdVert[( i + 1) % 3]) ;
|
||||
setIndTriaNeightbors.insert( nIdVert[( i + 2) % 3]) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// Calcolo l'angolo sotteso
|
||||
double dCosTheta = max( -1., min( 1., ( vtDir0 * vtDir1))) ;
|
||||
double dTheta = acos( dCosTheta) ;
|
||||
// Calcolo la distanza baricentrica
|
||||
double dSqBarDist = max( EPS_SMALL, ( ptCurr - Tria.GetCentroid()).SqLen()) ;
|
||||
// Aggiorno il contributo della normale al vertice
|
||||
vtNorm += ( ( dTheta / dSqBarDist) * Tria.GetN()) ;
|
||||
}
|
||||
vtNorm.Normalize() ;
|
||||
|
||||
// [ESTIMATING CURVATURE ON TRIANGULAR MESHES, cap. 2.1. Fitting Methods,
|
||||
// par. 2.1.2. Quadric Fitting]
|
||||
// [https://people.eecs.berkeley.edu/~jrs/meshpapers/GatzkeGrimm.pdf]
|
||||
|
||||
// Definisco il piano tangente al vertice corrente
|
||||
Plane3d plTan ;
|
||||
if ( ! plTan.Set( ptCurr, vtNorm))
|
||||
return false ;
|
||||
|
||||
// Proietto i punti Neightbors(1) sul piano tangete ( senza ripeterli)
|
||||
BIPNTVECTOR vPtPtProj ; vPtPtProj.reserve( setIndTriaNeightbors.size()) ;
|
||||
for ( auto nIter = setIndTriaNeightbors.begin() ; nIter != setIndTriaNeightbors.end() ; ++ nIter) {
|
||||
Point3d ptNeightbors ;
|
||||
if ( ! GetVertex( *nIter, ptNeightbors))
|
||||
return false ;
|
||||
vPtPtProj.emplace_back( make_pair( ptNeightbors, ProjectPointOnPlane( ptNeightbors, plTan))) ;
|
||||
}
|
||||
|
||||
// Recupero due versori perpendicolari nel piano definito
|
||||
Vector3d vtTan1 = V_NULL ;
|
||||
if ( abs( vtNorm.x) < 1./64. && abs( vtNorm.y) < 1./64.)
|
||||
vtTan1 = Y_AX ^ vtNorm ;
|
||||
else
|
||||
vtTan1 = Z_AX ^ vtNorm ;
|
||||
vtTan1.Normalize() ;
|
||||
Vector3d vtTan2 = vtNorm ^ vtTan1 ;
|
||||
vtTan2.Normalize() ;
|
||||
|
||||
// Sistema da risolvere mediante minimi quadrati : z(u,v) = Au^2 + Buv + Cv^2
|
||||
// Questo sistema è molto più semplice e robusto rispetto a z(u,v) = Au^2 + Buv + Cv^2 + Du + Ev + F
|
||||
// per il fatto che ora le coordinate sono in locale al piano tangente alla superficie ( mettendo
|
||||
// quindi a 0 i coefficienti del primo ordine e il termine noto F)
|
||||
// Definizione della matrice A(Nx3)
|
||||
const int nPts = int( vPtPtProj.size()) ;
|
||||
Eigen::MatrixXd mat_A( nPts, 3) ;
|
||||
Eigen::VectorXd vec_b( nPts) ;
|
||||
for ( int i = 0 ; i < nPts ; ++ i) {
|
||||
Vector3d vtEdgeProj = vPtPtProj[i].second - ptCurr ;
|
||||
Vector3d vtEdge = ( vPtPtProj[i].first - vPtPtProj[i].second) ;
|
||||
double dU = vtEdgeProj * vtTan1 ;
|
||||
double dV = vtEdgeProj * vtTan2 ;
|
||||
double dW = vtEdge * vtNorm ;
|
||||
mat_A( i, 0) = dU * dU ;
|
||||
mat_A( i, 1) = dU * dV ;
|
||||
mat_A( i, 2) = dV * dV ;
|
||||
vec_b( i) = dW ;
|
||||
}
|
||||
// Risoluzione del sistema
|
||||
Eigen::VectorXd vec_x = mat_A.colPivHouseholderQr().solve( vec_b) ;
|
||||
|
||||
// Costruzione della matrice hessiana
|
||||
Eigen::Matrix2d mat_H {{ 2. * vec_x( 0), vec_x( 1)},
|
||||
{ vec_x( 1), 2. * vec_x( 2)}} ;
|
||||
|
||||
// Calcolo gli autovalori ( quindi le curvature principali) e restituisco i risultati
|
||||
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> Solver( mat_H) ;
|
||||
dMinK = Solver.eigenvalues()( 0) ;
|
||||
dMaxK = Solver.eigenvalues()( 1) ;
|
||||
Eigen::Vector2d dir_Min = Solver.eigenvectors().col( 0) ;
|
||||
Eigen::Vector2d dir_Max = Solver.eigenvectors().col( 1) ;
|
||||
vtMinK = dir_Min( 0) * vtTan1 + dir_Min( 1) * vtTan2 ;
|
||||
vtMaxK = dir_Max( 0) * vtTan1 + dir_Max( 1) * vtTan2 ;
|
||||
bPlanar = ( abs( dMinK) < EPS_SMALL && abs( dMaxK) < EPS_SMALL) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,791 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMeshOffset.cpp Data : 07.07.25 Versione : 2.7g1
|
||||
// Contenuto : Implementazione funzione per Offset di Superfici TriMesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 10.06.25 RE Creazione modulo.
|
||||
// 10.06.25 RE Offset di superfici chiuse.
|
||||
// 04.07.25 RE Thickening Offset di superfici generiche.
|
||||
// 10.12.25 RE Creazione superfici Shell.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include <future>
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
||||
#include "/EgtDev/Include/EGkStmStandard.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
std::vector<IGeoObj*> VT ;
|
||||
std::vector<Color> VC ;
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static ISurfTriMesh*
|
||||
SumStm( const CISURFTMPVECTOR& vStm)
|
||||
{
|
||||
// se vettore vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// definisco la superficie somma tra tutte ( la prima deve essere valida)
|
||||
PtrOwner<ISurfTriMesh> pStmAdd( CreateSurfTriMesh()) ;
|
||||
if ( IsNull( pStmAdd))
|
||||
return nullptr ;
|
||||
// scorro le superfici
|
||||
for ( const ISurfTriMesh* pStm : vStm) {
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || pStm->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
if ( ! pStmAdd->IsValid() || pStmAdd->GetTriangleCount() == 0) {
|
||||
if ( ! pStmAdd->CopyFrom( pStm))
|
||||
return nullptr ;
|
||||
}
|
||||
else
|
||||
pStmAdd->Add( *pStm) ;
|
||||
}
|
||||
// restituisco la superficie ottenuta
|
||||
return ( Release( pStmAdd)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzioni per la distanza tra punto e superficie TriMesh in parallelo
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff)
|
||||
{
|
||||
// svuoto il risultato
|
||||
vBoxDiff.clear() ;
|
||||
// se box A vuoto, risultato vuoto
|
||||
if ( boxA.IsEmpty())
|
||||
return false ;
|
||||
// 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) ;
|
||||
return true ;
|
||||
}
|
||||
// recupero i punti estremi dei box A e Intersezione
|
||||
Point3d ptMinA, ptMaxA ; boxA.GetMinMax( ptMinA, ptMaxA) ;
|
||||
Point3d ptMinInt, ptMaxInt ; boxInt.GetMinMax( ptMinInt, ptMaxInt) ;
|
||||
// sotto
|
||||
if ( ptMinInt.z - ptMinA.z > EPS_SMALL) {
|
||||
BBox3d boxD( ptMinA, Point3d( ptMaxA.x, ptMaxA.y, ptMinInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// sopra
|
||||
if ( ptMaxA.z - ptMaxInt.z > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMaxInt.z), ptMaxA) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// davanti
|
||||
if ( ptMinInt.y - ptMinA.y > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMinA.y, ptMinInt.z), Point3d( ptMaxA.x, ptMinInt.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// dietro
|
||||
if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMaxInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxA.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// sinistra
|
||||
if ( ptMinInt.x - ptMinA.x > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMinA.x, ptMinInt.y, ptMinInt.z), Point3d( ptMinInt.x, ptMaxInt.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// destra
|
||||
if ( ptMaxA.y - ptMaxInt.y > EPS_SMALL) {
|
||||
BBox3d boxD( Point3d( ptMaxInt.x, ptMinInt.y, ptMinInt.z), Point3d( ptMaxA.x, ptMaxInt.y, ptMaxInt.z)) ;
|
||||
vBoxDiff.emplace_back( boxD) ;
|
||||
}
|
||||
// risultato
|
||||
return ( ! vBoxDiff.empty()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
DistPointSurfTmMultiThread( const Point3d& ptP, const SurfTriMesh& SurfTm, double& dDist,
|
||||
bool& bIsInside, INTVECTOR& vIndClosestTria)
|
||||
{
|
||||
// verifico che la supercicie sia valida
|
||||
if ( ! SurfTm.IsValid())
|
||||
return false ;
|
||||
|
||||
// inizializzo distanza non calcolata
|
||||
dDist = - 1. ;
|
||||
// vettore di indici dei triangoli più vicini inizialmente vuoto
|
||||
vIndClosestTria.clear() ;
|
||||
// vettore dei flag temporanei inizialmente tutto a 0
|
||||
INTVECTOR vIntFlags( SurfTm.GetTriangleCount(), 0) ;
|
||||
|
||||
// recupero e verifico il box locale della superficie
|
||||
BBox3d b3Stm = SurfTm.GetAllTriaBox() ;
|
||||
if ( b3Stm.IsEmpty())
|
||||
return false ;
|
||||
|
||||
// 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 ;
|
||||
double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ;
|
||||
double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ;
|
||||
// considero anche il box precedente per poter analizzare solo il volume differenza tra i due
|
||||
BBox3d boxPPrev( ptP) ;
|
||||
BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ;
|
||||
// variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima
|
||||
double dMinDist = DBL_MAX ;
|
||||
int nMinDistTriaIndex = SVT_NULL ;
|
||||
Point3d ptMinDistPoint ;
|
||||
// finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
bool bContinue = true ;
|
||||
|
||||
// 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
|
||||
BOXVECTOR vBox ;
|
||||
BoundingBoxDifference( boxP, boxPPrev, vBox) ;
|
||||
// Ciclo sui box differenza
|
||||
bool bCollide = false ;
|
||||
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.DistFromPoint( ptP) > dMinDist)
|
||||
continue ;
|
||||
// ricerca sui triangoli nel box
|
||||
bCollide = true ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( SurfTm.GetAllTriaOverlapBox( b3Int, vnIds)) {
|
||||
// ciclo sui triangoli del sotto-box corrente
|
||||
for ( auto nT : vnIds) {
|
||||
Triangle3d trCurTria ;
|
||||
if ( vIntFlags[nT] == 0 && SurfTm.GetTriangle( nT, trCurTria)) {
|
||||
vIntFlags[nT] = 1 ;
|
||||
DistPointTriangle distPT( ptP, trCurTria) ;
|
||||
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) ;
|
||||
// aggiungo il triangolo
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
|
||||
if ( ! bCollide || dMinDist < EPS_SMALL)
|
||||
bContinue = false ;
|
||||
else {
|
||||
boxPPrev = boxP ;
|
||||
boxP.Expand( dDeltaLen) ;
|
||||
}
|
||||
}
|
||||
// se non ho trovato nessun triangolo, errore
|
||||
if ( nMinDistTriaIndex == SVT_NULL)
|
||||
return false ;
|
||||
|
||||
// riempio il vettore dei triangoli a minima distanza
|
||||
for ( auto& Tria : vTria)
|
||||
vIndClosestTria.emplace_back( Tria.first) ;
|
||||
// salvo la distanza
|
||||
dDist = dMinDist ;
|
||||
|
||||
// determino il Side
|
||||
if ( dDist < EPS_SMALL) {
|
||||
bIsInside = false ;
|
||||
return true ;
|
||||
}
|
||||
// se ho solo un triangolo
|
||||
else if ( int( vTria.size()) == 1) {
|
||||
bIsInside = ( ( ptP - ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// controllo se tutti i triangoli a minima distanza forniscono la stessa informazione
|
||||
// ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito )
|
||||
bool bInside = false ;
|
||||
bool bOutside = false ;
|
||||
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) {
|
||||
if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL)
|
||||
bInside = true ;
|
||||
else
|
||||
bOutside = true ;
|
||||
}
|
||||
|
||||
bIsInside = false ;
|
||||
if ( bOutside == bInside) {
|
||||
Point3d ptBar_tot ;
|
||||
for ( const auto& Tria : vTria)
|
||||
ptBar_tot += Tria.second.GetCentroid() ;
|
||||
for ( const auto& Tria : vTria) {
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ;
|
||||
if ( nType == ILTT_IN) {
|
||||
DistPointTriangle( ptP, Tria.second).GetMinDistPoint( ptMinDistPoint) ;
|
||||
bIsInside = ( ( ptP - ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ;
|
||||
nMinDistTriaIndex = Tria.first ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
bIsInside = bInside ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ClassifyTrianglesMultiThread( const TRIA3DEXVECTOR& vTria, int nIndS, int nIndE,
|
||||
const SurfTriMesh& SurfTm, double dOffs, double dPrec,
|
||||
bool bSaveInside, BOOLVECTOR& vbSafe)
|
||||
{
|
||||
// verifico che la superficie sia valida
|
||||
if ( ! SurfTm.IsValid())
|
||||
return false ;
|
||||
// verifico la validità degli indici
|
||||
if ( nIndS < 0 || nIndE >= int( vTria.size()))
|
||||
return false ;
|
||||
// verifico la dimensione dei vettori
|
||||
if ( vTria.size() != vbSafe.size())
|
||||
return false ;
|
||||
|
||||
// scorro gli indici dei triangoli da classificare
|
||||
for ( int k = nIndS ; k <= nIndE ; ++ k) {
|
||||
// recupero il triangolo corrente
|
||||
const Triangle3dEx& Tria = vTria[k] ;
|
||||
// preparo gli elementi di classificazione
|
||||
DBLVECTOR vDists ; vDists.resize( 3) ;
|
||||
INTMATRIX matIndClosestTria ; matIndClosestTria.resize( 3) ;
|
||||
// verifico che i suoi punti siano distanti almeno |dOffs| - dTol dalla superficie
|
||||
vbSafe[k] = true ;
|
||||
for ( int i = 0 ; vbSafe[k] && i < 3 ; ++ i) {
|
||||
bool bIsInside = false ;
|
||||
DistPointSurfTmMultiThread( Tria.GetP( i), SurfTm, vDists[i], bIsInside, matIndClosestTria[i]) ;
|
||||
vbSafe[k] = ( ( vDists[i] > abs( dOffs) - 0.25 * dPrec) &&
|
||||
( vDists[i] < abs( dOffs) + 0.25 * dPrec) &&
|
||||
( bIsInside == bSaveInside)) ;
|
||||
}
|
||||
// se tutti sufficientemente distanti
|
||||
if ( vbSafe[k]) {
|
||||
// i triangoli a minima distanza devono avere normale simile
|
||||
bool bPerp = true ;
|
||||
for ( int i = 0 ; bPerp && i < 3 ; ++ i) {
|
||||
for ( int j = 0 ; bPerp && j < int( matIndClosestTria[i].size()) ; ++ j) {
|
||||
Triangle3d TriaCloser ;
|
||||
SurfTm.GetTriangle( matIndClosestTria[i][j], TriaCloser) ;
|
||||
bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < cos( 30. * DEGTORAD)) ;
|
||||
}
|
||||
}
|
||||
vbSafe[k] = ( ! bPerp) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea l'Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dPrec, nType)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea il Fat Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dPrec, nType)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea l'Offset di un insieme di superfici
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
// se vettore delle superfici vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyPrec = max( dPrec, 100. * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10. * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
VolZmap myVolZmap ;
|
||||
if ( ! myVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
if ( ! myVolZmap.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// recupero le superfici aperte
|
||||
CISURFTMPVECTOR vStmOpen ;
|
||||
for ( const ISurfTriMesh* pStm : vStm) {
|
||||
if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed())
|
||||
vStmOpen.emplace_back( pStm) ;
|
||||
}
|
||||
|
||||
// --- se non ho superfici aperte
|
||||
if ( vStmOpen.empty()) {
|
||||
// restituisco la superficie TriMesh di Offset
|
||||
return ( myVolZmap.GetSurfTriMesh()) ;
|
||||
}
|
||||
|
||||
// --- se ho delle superfici chiuse
|
||||
TRIA3DEXVECTOR vAllTria, vTriaOffs ;
|
||||
for ( int nB = 0 ; nB < myVolZmap.GetBlockCount() ; ++ nB) {
|
||||
TRIA3DEXVECTOR vTria, vTriaSafe ;
|
||||
myVolZmap.GetBlockTriangles( nB, vTria) ;
|
||||
#if DEBUG
|
||||
TRIA3DVECTOR vTriaUnsafe ;
|
||||
#endif
|
||||
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
|
||||
Triangle3dEx& Tria = vTria[nT] ;
|
||||
BBox3d BBoxTria ;
|
||||
Tria.GetLocalBBox( BBoxTria) ;
|
||||
// azzero flag di colore
|
||||
vAllTria.push_back( Tria) ;
|
||||
}
|
||||
}
|
||||
// classifico i triangoli
|
||||
PtrOwner<const SurfTriMesh> pStmBasic( nullptr) ;
|
||||
if ( int( vStmOpen.size() == 1))
|
||||
pStmBasic.Set( GetBasicSurfTriMesh( CloneSurfTriMesh( vStmOpen[0]))) ;
|
||||
else {
|
||||
StmFromTriangleSoup AllOpenStmSoup ; AllOpenStmSoup.Start() ;
|
||||
for ( const ISurfTriMesh* pStmOpen : vStmOpen) {
|
||||
if ( pStmOpen != nullptr && pStmOpen->IsValid()) {
|
||||
for ( int nT = 0 ; nT < pStmOpen->GetTriangleCount() ; ++ nT) {
|
||||
Triangle3d Tria ;
|
||||
if ( pStmOpen->GetTriangle( nT, Tria))
|
||||
AllOpenStmSoup.AddTriangle( Tria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
AllOpenStmSoup.End() ;
|
||||
pStmBasic.Set( GetBasicSurfTriMesh( AllOpenStmSoup.GetSurf())) ;
|
||||
}
|
||||
if ( pStmBasic == nullptr)
|
||||
return nullptr ;
|
||||
BBox3d b3Stm = pStmBasic->GetAllTriaBox() ;
|
||||
if ( b3Stm.IsEmpty())
|
||||
return nullptr ;
|
||||
// numero di triangoli da analizzare
|
||||
int nTriaCnt = int( vAllTria.size()) ;
|
||||
// definisco un vettore di Flag per i triangoli già visitati
|
||||
INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ;
|
||||
// numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
BOOLVECTOR vbSafeTria( vAllTria.size(), true) ;
|
||||
if ( nThreadMax <= 1 || nTriaCnt < 50)
|
||||
ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, abs( dOffs), dPrec, ( dOffs < 0.), vbSafeTria) ;
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = nTriaCnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first,
|
||||
vFstLst[i].second, cref( *pStmBasic), abs( dOffs), dPrec, ( dOffs < 0.), ref( vbSafeTria)) ;
|
||||
}
|
||||
// attendo i risultati
|
||||
int nFin = 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 ( ! bOk)
|
||||
return nullptr ;
|
||||
TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ;
|
||||
#if DEBUG
|
||||
TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ;
|
||||
#endif
|
||||
for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) {
|
||||
if ( vbSafeTria[i])
|
||||
vTriaSafe.emplace_back( vAllTria[i]) ;
|
||||
#if DEBUG
|
||||
if ( ! vbSafeTria[i])
|
||||
vTriaUnSafe.emplace_back( vAllTria[i]) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
// definisco la superficie con i soli triangoli validi
|
||||
StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ;
|
||||
for ( const Triangle3d& SafeTria : vTriaSafe)
|
||||
TriaSoup.AddTriangle( SafeTria) ;
|
||||
TriaSoup.End() ;
|
||||
PtrOwner<ISurfTriMesh> pStmOffs( TriaSoup.GetSurf()) ;
|
||||
if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0)
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG
|
||||
StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ;
|
||||
for ( const Triangle3d& _unsafeTria : vTriaUnSafe)
|
||||
_invalidSoup.AddTriangle( _unsafeTria) ;
|
||||
_invalidSoup.End() ;
|
||||
VT.emplace_back( pStmOffs->Clone()) ;
|
||||
VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( _invalidSoup.GetSurf()) ;
|
||||
VC.emplace_back( RED) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
|
||||
#endif
|
||||
|
||||
return ( Release( pStmOffs)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//* Funzione che crea il Fat Offset di un insieme di superfici
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
// se vettore delle superfici vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
VolZmap OneVolZmap ;
|
||||
if ( ! OneVolZmap.CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
if ( ! OneVolZmap.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( OneVolZmap.GetSurfTriMesh()) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per creare la Superficie TriMesh Shell da una Trimesh aperta
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshShell( const ISurfTriMesh* pStm, double dThick, double dPrec)
|
||||
{
|
||||
// verifico che la superficie sia valida ed aperta
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || pStm->IsClosed())
|
||||
return nullptr ;
|
||||
// lo spessore deve essere sempre positivo, il verso è sempre dato dalla normale dei triangoli
|
||||
dThick = - max( 10. * EPS_SMALL, abs( dThick)) ;
|
||||
|
||||
// creo il suo Offset ( salvandomi lo Zmap per l'orientamento)
|
||||
#if DEBUG
|
||||
PerformanceCounter PC ; PC.Start() ;
|
||||
#endif
|
||||
VolZmap myVolZMap ;
|
||||
if ( ! myVolZMap.CreateFromTriMeshOffset( { pStm}, dThick, dPrec))
|
||||
return nullptr ;
|
||||
if ( ! myVolZMap.IsValid())
|
||||
return nullptr ;
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Tria Time : "} + ToString( PC.Stop())).c_str()) ;
|
||||
VT.clear() ; VC.clear() ;
|
||||
VT.emplace_back( myVolZMap.Clone()) ;
|
||||
VC.emplace_back( BLACK) ;
|
||||
VT.emplace_back( pStm->Clone()) ;
|
||||
VC.emplace_back( YELLOW) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\VolZMapOffs.nge") ;
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
VT.clear() ; VC.clear() ;
|
||||
PC.Start() ;
|
||||
#endif
|
||||
|
||||
// recupero i triangoli dallo ZMap creato
|
||||
TRIA3DEXVECTOR vAllTria, vTriaOffs ;
|
||||
for ( int nB = 0 ; nB < myVolZMap.GetBlockCount() ; ++ nB) {
|
||||
TRIA3DEXVECTOR vTria, vTriaSafe ;
|
||||
myVolZMap.GetBlockTriangles( nB, vTria) ;
|
||||
#if DEBUG
|
||||
TRIA3DVECTOR vTriaUnsafe ;
|
||||
#endif
|
||||
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
|
||||
Triangle3dEx& Tria = vTria[nT] ;
|
||||
BBox3d BBoxTria ;
|
||||
Tria.GetLocalBBox( BBoxTria) ;
|
||||
// azzero flag di colore
|
||||
vAllTria.push_back( Tria) ;
|
||||
}
|
||||
}
|
||||
// classifico i triangoli
|
||||
const SurfTriMesh* pStmBasic = GetBasicSurfTriMesh( pStm) ;
|
||||
if ( pStmBasic == nullptr)
|
||||
return nullptr ;
|
||||
BBox3d b3Stm = pStmBasic->GetAllTriaBox() ;
|
||||
if ( b3Stm.IsEmpty())
|
||||
return nullptr ;
|
||||
// numero di triangoli da analizzare
|
||||
int nTriaCnt = int( vAllTria.size()) ;
|
||||
// definisco un vettore di Flag per i triangoli già visitati
|
||||
INTVECTOR vIntFlags( pStmBasic->GetTriangleCount()) ;
|
||||
// numero massimo di thread concorrenti
|
||||
int nThreadMax = thread::hardware_concurrency() ;
|
||||
bool bOk = true ;
|
||||
BOOLVECTOR vbSafeTria( vAllTria.size(), true) ;
|
||||
if ( nThreadMax <= 1 || nTriaCnt < 50)
|
||||
ClassifyTrianglesMultiThread( vAllTria, 0, nTriaCnt - 1, *pStmBasic, dThick, dPrec, true, vbSafeTria) ;
|
||||
else {
|
||||
const int MAX_PARTS = 32 ;
|
||||
INTINTVECTOR vFstLst( MAX_PARTS) ;
|
||||
// calcolo le parti del vettore
|
||||
int nPartCnt = min( nThreadMax, MAX_PARTS) ;
|
||||
int nPartDim = nTriaCnt / nPartCnt + 1 ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vFstLst[i].first = i * nPartDim ;
|
||||
vFstLst[i].second = min( ( i + 1) * nPartDim, nTriaCnt) - 1 ;
|
||||
}
|
||||
// processo le parti
|
||||
future<bool> vRes[MAX_PARTS] ;
|
||||
for ( int i = 0 ; i < nPartCnt ; ++ i) {
|
||||
vRes[i] = async( launch::async, &ClassifyTrianglesMultiThread, cref( vAllTria), vFstLst[i].first,
|
||||
vFstLst[i].second, cref( *pStmBasic), dThick, dPrec, true, ref( vbSafeTria)) ;
|
||||
}
|
||||
// attendo i risultati
|
||||
int nFin = 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 ( ! bOk)
|
||||
return nullptr ;
|
||||
TRIA3DEXVECTOR vTriaSafe ; vTriaSafe.reserve( vAllTria.size()) ;
|
||||
#if DEBUG
|
||||
TRIA3DEXVECTOR vTriaUnSafe ; vTriaUnSafe.reserve( vAllTria.size()) ;
|
||||
#endif
|
||||
for ( int i = 0 ; i < int( vAllTria.size()) ; ++ i) {
|
||||
if ( vbSafeTria[i])
|
||||
vTriaSafe.emplace_back( vAllTria[i]) ;
|
||||
#if DEBUG
|
||||
if ( ! vbSafeTria[i])
|
||||
vTriaUnSafe.emplace_back( vAllTria[i]) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
// definisco la superficie con i soli triangoli validi
|
||||
StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ;
|
||||
for ( const Triangle3d& SafeTria : vTriaSafe)
|
||||
TriaSoup.AddTriangle( SafeTria) ;
|
||||
TriaSoup.End() ;
|
||||
PtrOwner<ISurfTriMesh> pStmOffs( TriaSoup.GetSurf()) ;
|
||||
if ( IsNull( pStmOffs) || ! pStmOffs->IsValid() || pStmOffs->GetTriangleCount() == 0)
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Tria Time ( exceed Approx) : "} + ToString( PC.Stop())).c_str()) ;
|
||||
StmFromTriangleSoup _invalidSoup ; _invalidSoup.Start() ;
|
||||
for ( const Triangle3d& _unsafeTria : vTriaUnSafe)
|
||||
_invalidSoup.AddTriangle( _unsafeTria) ;
|
||||
_invalidSoup.End() ;
|
||||
VT.emplace_back( pStmOffs->Clone()) ;
|
||||
VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( _invalidSoup.GetSurf()) ;
|
||||
VC.emplace_back( RED) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
|
||||
VT.clear() ; VC.clear() ;
|
||||
PC.Start() ;
|
||||
#endif
|
||||
|
||||
// recupero i loops della superficie originaria e del suo Offset orientato ( non devono essere diminuiti)
|
||||
POLYLINEVECTOR vPL, vPLOffs ;
|
||||
if ( ! pStm->GetLoops( vPL) || ! pStmOffs->GetLoops( vPLOffs))
|
||||
return nullptr ;
|
||||
|
||||
// trasformo ogni loop in curve composite ( devono essere chiuse)
|
||||
ICRVCOMPOPOVECTOR vCompoLoops ; vCompoLoops.reserve( vPL.size()) ;
|
||||
for ( const PolyLine& PL : vPL) {
|
||||
if ( PL.IsClosed()) {
|
||||
if ( ! vCompoLoops.emplace_back( CreateCurveComposite()) ||
|
||||
! vCompoLoops.back()->FromPolyLine( PL) ||
|
||||
! vCompoLoops.back()->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
ICRVCOMPOPOVECTOR vCompoOffsLoops ; vCompoOffsLoops.reserve( vPLOffs.size()) ;
|
||||
for ( const PolyLine& PLOffs : vPLOffs) {
|
||||
if ( PLOffs.IsClosed()) {
|
||||
if ( ! vCompoOffsLoops.emplace_back( CreateCurveComposite()) ||
|
||||
! vCompoOffsLoops.back()->FromPolyLine( PLOffs) ||
|
||||
! vCompoOffsLoops.back()->IsValid())
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
VT.emplace_back( pStmOffs->Clone()) ;
|
||||
VC.emplace_back( YELLOW) ;
|
||||
for ( ICurveComposite* pCompo : vCompoLoops) {
|
||||
VT.emplace_back( pCompo->Clone()) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
}
|
||||
for ( ICurveComposite* pCompoOffs : vCompoOffsLoops) {
|
||||
VT.emplace_back( pCompoOffs->Clone()) ;
|
||||
VC.emplace_back( ORANGE) ;
|
||||
}
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\myCurve.nge") ;
|
||||
VT.clear() ; VC.clear() ;
|
||||
#endif
|
||||
|
||||
// per ogni curva della superficie originale cerco la sua associata
|
||||
// NB. per la creazione della superficie ruled la prima curva è quellla che determina il verso
|
||||
// dei triangoli associati. Per un corretto ed automatico orientamento della superficie
|
||||
// la prima curva deve essere sempre definita dalla superficie originale ed invertita ( le
|
||||
// curve nella rigata devono seguire lo stesso orientamento
|
||||
ISURFTMPOVECTOR vStmRuled ; vStmRuled.reserve( vCompoLoops.size()) ;
|
||||
BOOLVECTOR vIndMatched( vCompoOffsLoops.size(), false) ;
|
||||
for ( ICurveComposite* pCompoLoop : vCompoLoops) {
|
||||
// sposto il punto iniziale della curva nel tratto più lungo
|
||||
double dMaxLen = - INFINITO ;
|
||||
int nIndCrv = 0 ;
|
||||
for ( int nCrv = 0 ; nCrv < pCompoLoop->GetCurveCount() ; ++ nCrv) {
|
||||
const ICurve* pCurve = pCompoLoop->GetCurve( nCrv) ;
|
||||
if ( pCurve != nullptr && pCurve->IsValid()) {
|
||||
double dCurrLen = 0. ;
|
||||
pCurve->GetLength( dCurrLen) ;
|
||||
if ( dCurrLen > dMaxLen) {
|
||||
dMaxLen = dCurrLen ;
|
||||
nIndCrv = nCrv ;
|
||||
}
|
||||
}
|
||||
}
|
||||
pCompoLoop->ChangeStartPoint( nIndCrv + 0.5) ;
|
||||
Point3d ptStart ; pCompoLoop->GetStartPoint( ptStart) ;
|
||||
// dalle altre curve derivanti dalla superficie di Offset cerco quella più vicina al punto inziale
|
||||
double dMinSqDist = INFINITO ;
|
||||
int nIndOffsCrv = -1 ;
|
||||
Point3d ptMinDist ;
|
||||
for ( int nOffsCrv = 0 ; nOffsCrv < int( vCompoOffsLoops.size()) ; ++ nOffsCrv) {
|
||||
if ( vIndMatched[nOffsCrv])
|
||||
continue ;
|
||||
// recupero la curva e calcolo la distanza
|
||||
const ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nOffsCrv] ;
|
||||
int nFlag = 0 ;
|
||||
Point3d ptCurrMinDist ;
|
||||
if ( DistPointCurve( ptStart, *pCompoOffsLoop).GetMinDistPoint( 0., ptCurrMinDist, nFlag)) {
|
||||
double dCurrSqDist = SqDist( ptStart, ptCurrMinDist) ;
|
||||
if ( dCurrSqDist < dMinSqDist) {
|
||||
dMinSqDist = dCurrSqDist ;
|
||||
nIndOffsCrv = nOffsCrv ;
|
||||
ptMinDist = ptCurrMinDist ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nIndOffsCrv == -1)
|
||||
return nullptr ;
|
||||
vIndMatched[ nIndOffsCrv] = true ;
|
||||
// associo le due curve
|
||||
ICurveComposite* pCompoOffsLoop = vCompoOffsLoops[nIndOffsCrv] ;
|
||||
double dParMinDist = 0. ;
|
||||
pCompoOffsLoop->GetParamAtPoint( ptMinDist, dParMinDist, 10. * EPS_SMALL) ;
|
||||
pCompoOffsLoop->ChangeStartPoint( dParMinDist) ;
|
||||
|
||||
#if DEBUG
|
||||
Color _cCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ;
|
||||
VT.emplace_back( pCompoLoop->Clone()) ;
|
||||
VC.emplace_back( _cCol) ;
|
||||
VT.emplace_back( pCompoOffsLoop->Clone()) ;
|
||||
VC.emplace_back( _cCol) ;
|
||||
#endif
|
||||
|
||||
// creo la superficie tra queste due curve e la oriento in modo da definire un volume
|
||||
pCompoLoop->Invert() ;
|
||||
PtrOwner<ISurfTriMesh> pStmRuled( GetSurfTriMeshRuled( pCompoLoop, pCompoOffsLoop, ISurfTriMesh::RuledType::RLT_MINDIST)) ;
|
||||
if ( IsNull( pStmRuled) || ! pStmRuled->IsValid() ||
|
||||
! vStmRuled.emplace_back( Release( pStmRuled)))
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Strip generation : "} + ToString( PC.Stop())).c_str()) ;
|
||||
VT.emplace_back( vStmRuled.back()->Clone()) ;
|
||||
VC.emplace_back( _cCol) ;
|
||||
_cCol.SetAlpha( .5) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\Strips.nge") ;
|
||||
PC.Start() ;
|
||||
#endif
|
||||
|
||||
// compongo la superficie finale
|
||||
PtrOwner<ISurfTriMesh> pStmOrig( CloneSurfTriMesh( pStm)) ;
|
||||
if ( IsNull( pStmOrig) || ! pStmOrig->IsValid())
|
||||
return nullptr ;
|
||||
PtrOwner<ISurfTriMesh> pStmRef( Release( pStmOrig)) ;
|
||||
if ( IsNull( pStmRef) || ! pStmRef->IsValid())
|
||||
return nullptr ;
|
||||
for ( int nStrip = 0 ; nStrip < int( vStmRuled.size()) ; ++ nStrip) {
|
||||
if ( ! pStmRef->DoSewing( *vStmRuled[nStrip]))
|
||||
return nullptr ;
|
||||
}
|
||||
if ( ! pStmRef->DoSewing( *pStmOffs))
|
||||
return nullptr ;
|
||||
pStmRef->Repair() ;
|
||||
|
||||
#if DEBUG
|
||||
LOG_INFO( GetEGkLogger(), ( string{ "Sewing : "} + ToString( PC.Stop())).c_str()) ;
|
||||
#endif
|
||||
|
||||
return ( ( ! IsNull( pStmRef) && pStmRef->IsValid()) ? Release( pStmRef) : nullptr) ;
|
||||
}
|
||||
+204
-31
@@ -17,7 +17,6 @@
|
||||
#include "Triangulate.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -35,6 +34,7 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
// recupero i vertici dei triangoli
|
||||
int nIdV[3] ;
|
||||
GetTriangle( nT, nIdV) ;
|
||||
bool bToRemove = false ;
|
||||
// ciclo sui triangoli adiacenti
|
||||
for ( int nE = 0 ; nE < 3 ; ++ nE) {
|
||||
// recupero triangolo adiacente, se non esiste passo al successivo
|
||||
@@ -53,10 +53,14 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
}
|
||||
}
|
||||
if ( nCoinc == 3) {
|
||||
RemoveTriangle( nAdjT) ;
|
||||
// se i vertici coincidono rimuovo entrambi i triangoli
|
||||
bToRemove = true ;
|
||||
bModified = true ;
|
||||
RemoveTriangle( nAdjT) ;
|
||||
}
|
||||
}
|
||||
if ( bToRemove)
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -86,8 +90,8 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
// Recupero i vertici del triangolo A
|
||||
Point3d ptSegSt, ptSegEn, ptVertA ;
|
||||
if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) ||
|
||||
! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA))
|
||||
return false ;
|
||||
// Recupero il vertice opposto del triangolo B
|
||||
Point3d ptVertB ;
|
||||
@@ -98,23 +102,43 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
if ( ! DiagDist.IsSmall())
|
||||
return false ;
|
||||
double dPos1, dPos2 ;
|
||||
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2) ||
|
||||
dPos1 < EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() - EPS_SMALL ||
|
||||
dPos2 < EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() - EPS_SMALL)
|
||||
return false ;
|
||||
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2))
|
||||
return false ;
|
||||
if ( dPos1 < - EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() + EPS_SMALL ||
|
||||
dPos2 < - EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() + EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// Eseguo il flipping
|
||||
m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ;
|
||||
m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
|
||||
m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ;
|
||||
m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
|
||||
m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ;
|
||||
|
||||
// sistemo anche le contro-adiacenze
|
||||
int nTC = m_vTria[nTA].nIdAdjac[nEdgeA] ;
|
||||
if ( nTC != SVT_NULL) {
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
if ( m_vTria[nTC].nIdAdjac[i] == nTB) {
|
||||
m_vTria[nTC].nIdAdjac[i] = nTA ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
int nTD = m_vTria[nTB].nIdAdjac[nEdgeB] ;
|
||||
if ( nTD != SVT_NULL) {
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
if ( m_vTria[nTD].nIdAdjac[i] == nTA) {
|
||||
m_vTria[nTD].nIdAdjac[i] = nTB ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
SurfTriMesh::RemoveTJunctions( bool& bModified, double dMinSqDist)
|
||||
{
|
||||
bModified = false ;
|
||||
|
||||
@@ -123,6 +147,11 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
|
||||
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
|
||||
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
|
||||
// se adiacenze tutte valide, passo al successivo
|
||||
if ( m_vTria[nT].nIdAdjac[0] != SVT_DEL && m_vTria[nT].nIdAdjac[0] != SVT_NULL &&
|
||||
m_vTria[nT].nIdAdjac[1] != SVT_DEL && m_vTria[nT].nIdAdjac[1] != SVT_NULL &&
|
||||
m_vTria[nT].nIdAdjac[2] != SVT_DEL && m_vTria[nT].nIdAdjac[2] != SVT_NULL)
|
||||
continue ;
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
|
||||
@@ -150,6 +179,8 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
if ( dSegLen < EPS_SMALL)
|
||||
continue ;
|
||||
vtSeg /= dSegLen ;
|
||||
int nV1 = m_vTria[nT].nIdVert[nSeg] ;
|
||||
int nV2 = m_vTria[nT].nIdVert[Next( nSeg)] ;
|
||||
// Ciclo sui triangoli vicini
|
||||
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
|
||||
// Salto il triangolo se è quello di riferimento
|
||||
@@ -157,13 +188,16 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
continue ;
|
||||
// Cerco i vertici che stanno sul lato del triangolo
|
||||
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
|
||||
int nCurrVert = m_vTria[vNearTria[nI]].nIdVert[nVert] ;
|
||||
if ( nCurrVert == nV1 || nCurrVert == nV2)
|
||||
continue ;
|
||||
Point3d ptVert ;
|
||||
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
|
||||
continue ;
|
||||
double dProj = ( ptVert - ptSegSt) * vtSeg ;
|
||||
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
|
||||
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H)
|
||||
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
|
||||
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
|
||||
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < dMinSqDist)
|
||||
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
|
||||
}
|
||||
}
|
||||
// Riordino i vertici sul segmento
|
||||
@@ -307,16 +341,42 @@ ChooseGoodStartPoint( PNTULIST& PointList)
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
// -------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, double dTolAlign, bool& bModif) const
|
||||
{
|
||||
// vettore dei loop della faccia adiacente
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
// Ciclo sui punti del loop
|
||||
auto itLast = PointList.begin() ;
|
||||
for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) {
|
||||
|
||||
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia
|
||||
if ( itLast->second != it->second) {
|
||||
|
||||
// bisogna fermarsi per analizzare il tratto corrente alla ricerca di punti allineati se dal punto corrente
|
||||
// inizia un tratto adiacente ad un'altra faccia oppure se il punto corrente non verrà eliminato dal loop
|
||||
// della faccia adiacente
|
||||
|
||||
bool bAnalyze = ( itLast->second != it->second) ;
|
||||
if ( bAnalyze)
|
||||
LoopVec.clear() ;
|
||||
if ( ! bAnalyze && itLast->second != - 1) {
|
||||
if ( LoopVec.empty())
|
||||
GetFacetLoops( int( itLast->second), LoopVec) ;
|
||||
for ( int i = 0 ; i < int( LoopVec.size()) && ! bAnalyze ; i ++) {
|
||||
const PNTULIST& PointListAdj = LoopVec[i].GetUPointList() ;
|
||||
int nSamePoints = 0 ;
|
||||
for ( auto itAdj = PointListAdj.begin() ; itAdj != prev( PointListAdj.end()) ; ++ itAdj) {
|
||||
// cerco il punto corrente sul loop della faccia adiacente
|
||||
if ( AreSamePointApprox( it->first, itAdj->first))
|
||||
++ nSamePoints ;
|
||||
if ( ( nSamePoints == 1 && int( PointListAdj.size()) <= 4) || nSamePoints > 1) {
|
||||
bAnalyze = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bAnalyze) {
|
||||
// Raccolgo i punti in una polyline
|
||||
PolyLine PL ;
|
||||
int nPar = -1 ;
|
||||
@@ -326,7 +386,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
}
|
||||
PL.AddUPoint( ++nPar, it->first) ;
|
||||
// Provo ad eliminare i punti allineati
|
||||
PL.RemoveAlignedPoints( 50 * EPS_SMALL) ;
|
||||
PL.RemoveAlignedPoints( dTolAlign) ;
|
||||
if ( PL.GetPointNbr() < nPar + 1) {
|
||||
// rimuovo dalla lista dei punti gli eliminati (salto gli estremi)
|
||||
int nUCurr = 1 ;
|
||||
@@ -418,7 +478,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced, double dTolAlign)
|
||||
{
|
||||
// La trimesh deve essere valida
|
||||
if ( ! IsValid())
|
||||
@@ -433,8 +493,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare
|
||||
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
|
||||
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
|
||||
|
||||
// Recupero i loop della faccia (il parametro indica la faccia adiacente)
|
||||
|
||||
// Recupero i loop della faccia ( il parametro indica la faccia adiacente)
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
GetFacetLoops( nF, LoopVec) ;
|
||||
|
||||
@@ -445,13 +505,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Lista dei punti del loop
|
||||
PNTULIST& PointList = LoopVec[nL].GetUPointList() ;
|
||||
|
||||
// Se il loop è un triangolo, non va modificato
|
||||
if ( int( PointList.size()) <= 4)
|
||||
continue ;
|
||||
|
||||
// Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento
|
||||
if ( ! ChooseGoodStartPoint( PointList))
|
||||
continue ;
|
||||
|
||||
// Sistemo il loop
|
||||
bool bModif = false ;
|
||||
if ( ! AdjustLoop( PointList, dMaxEdgeLen, bModif))
|
||||
if ( ! AdjustLoop( PointList, dMaxEdgeLen, dTolAlign, bModif))
|
||||
return false ;
|
||||
if ( bModif)
|
||||
bToRetriangulate = true ;
|
||||
@@ -479,9 +543,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Eseguo la ritriangolazione della faccia
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( LoopVec, vPt, vTr)) {
|
||||
if ( Triangulate().Make( LoopVec, vPt, vTr) && ! vTr.empty())
|
||||
FacetMap.emplace( nF, make_pair( vPt, vTr)) ;
|
||||
}
|
||||
// Se non riesco a triangolare anche solo questa faccia, interrompo tutto
|
||||
else
|
||||
return false ;
|
||||
@@ -502,17 +565,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Cancello i triangoli
|
||||
for ( int nT : vDelTria)
|
||||
RemoveTriangle( nT) ;
|
||||
|
||||
|
||||
// Applico le nuove triangolazioni delle facce
|
||||
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
|
||||
const PNTVECTOR& vPt = itF->second.first ;
|
||||
const INTVECTOR& vTr = itF->second.second ;
|
||||
// Inserisco i nuovi triangoli
|
||||
// Inserisco i nuovi triangoli
|
||||
bool bFirstTria = true ;
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewId[3] = { AddVertex( vPt[vTr[n]]),
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
auto itCol = ColorMap.find( itF->first) ;
|
||||
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
|
||||
int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
|
||||
@@ -525,7 +588,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
@@ -722,3 +785,113 @@ SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECT
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const
|
||||
{
|
||||
// recupero il lato più lungo del triangolo
|
||||
double dLen0 = SqDist( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
double dLen1 = SqDist( m_vVert[m_vTria[nT].nIdVert[1]].ptP, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
double dLen2 = SqDist( m_vVert[m_vTria[nT].nIdVert[2]].ptP, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
nEdge = -1 ;
|
||||
if ( dLen0 > dLen1 && dLen0 > dLen2)
|
||||
nEdge = 0 ;
|
||||
else if ( dLen1 > dLen2)
|
||||
nEdge = 1 ;
|
||||
else
|
||||
nEdge = 2 ;
|
||||
|
||||
// recupero il triangolo adiacente sul lato più lungo
|
||||
nAdjTrg = m_vTria[nT].nIdAdjac[nEdge] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveInvalidTriangles( const INTVECTOR& vIds)
|
||||
{
|
||||
// al momento gestito solo per trimesh con adiacenze definite, eventualmente da estendere.
|
||||
// Analoga a RemoveFistInvalidTrg in Triangulate.cpp
|
||||
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
|
||||
|
||||
unordered_map<int, bool> InvalidMap ;
|
||||
for ( auto nId : vIds)
|
||||
InvalidMap[nId] = true ;
|
||||
|
||||
for ( int i = 0 ; i < int( vIds.size()) ; i++) {
|
||||
|
||||
int nTA = vIds[i] ;
|
||||
if ( ! InvalidMap[nTA])
|
||||
continue ;
|
||||
|
||||
// recupero il triangolo adiacente sul suo lato più lungo
|
||||
int nTB, nEdgeA ;
|
||||
FindAdjacentOnLongerEdge( nTA, nEdgeA, nTB) ;
|
||||
|
||||
// se adiacente è nullo posso rimuovere tranquillamente il triangolo senza creare TJunctions
|
||||
if ( nTB == SVT_NULL) {
|
||||
RemoveTriangle( nTA) ;
|
||||
continue ;
|
||||
}
|
||||
// se adiacente è valido posso fare il flip per rendere valido nTA
|
||||
else if ( ! InvalidMap[nTB]) {
|
||||
FlipTriangles( nTA, nTB) ;
|
||||
InvalidMap[nTA] = false ;
|
||||
}
|
||||
// se adiacente è invalido creo una catena da risolvere non appena si trova un triangolo valido
|
||||
else {
|
||||
INTVECTOR vChain = {nTA} ;
|
||||
INTVECTOR vChainEdges = {nEdgeA} ;
|
||||
int nTCurr = nTB ;
|
||||
|
||||
while ( nTCurr != SVT_NULL && InvalidMap[nTCurr]) {
|
||||
|
||||
// calcolo il successivo
|
||||
int nTOther, nEdgeCurr ;
|
||||
FindAdjacentOnLongerEdge( nTCurr, nEdgeCurr, nTOther) ;
|
||||
|
||||
if ( nTOther == vChain.back()) {
|
||||
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||
FlipTriangles( nTCurr, nTOther) ;
|
||||
if ( vChain.size() > 1) {
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
// individuo il nuovo adiacente all'ultimo triangolo della catena dopo aver fatto flip
|
||||
nTOther = m_vTria[vChain.back()].nIdAdjac[vChainEdges.back()] ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vChain.emplace_back( nTCurr) ;
|
||||
vChainEdges.emplace_back( nEdgeCurr) ;
|
||||
}
|
||||
// aggiorno per iterazione successiva
|
||||
nTCurr = nTOther ;
|
||||
}
|
||||
|
||||
// se la catena termina su triangolo nullo, posso rimuovere tutti i triangoli della catena
|
||||
if ( nTCurr == SVT_NULL) {
|
||||
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||
RemoveTriangle( vChain[k]) ;
|
||||
InvalidMap[vChain[k]] = false ;
|
||||
}
|
||||
}
|
||||
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido trovato
|
||||
else {
|
||||
FlipTriangles( vChain.back(), nTCurr) ;
|
||||
InvalidMap[vChain.back()] = false ;
|
||||
for ( int i = int( vChain.size()) - 2 ; i >= 0 ; i--) {
|
||||
int nTA = vChain[i] ;
|
||||
if ( ! InvalidMap[nTA])
|
||||
continue ;
|
||||
// eseguo il flip con il triangolo adiacente sul suo lato più lungo
|
||||
int nTOther = m_vTria[nTA].nIdAdjac[vChainEdges[i]] ;
|
||||
FlipTriangles( nTA, nTOther) ;
|
||||
InvalidMap[nTA] = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -36,25 +36,25 @@ class Tool
|
||||
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
|
||||
bool SetToolNum( int nToolNum)
|
||||
{ m_nCurrentNum = nToolNum ; return true ; }
|
||||
int GetType() const
|
||||
int GetType( void) const
|
||||
{ return m_nType ; }
|
||||
int GetToolNum() const
|
||||
int GetToolNum( void) const
|
||||
{ return m_nCurrentNum ; }
|
||||
double GetHeigth() const
|
||||
double GetHeigth( void) const
|
||||
{ return m_dHeight ; }
|
||||
double GetTipHeigth() const
|
||||
double GetTipHeigth( void) const
|
||||
{ return m_dTipHeight ; }
|
||||
double GetRadius() const
|
||||
double GetRadius( void) const
|
||||
{ return m_dRadius ; }
|
||||
double GetTipRadius() const
|
||||
double GetTipRadius( void) const
|
||||
{ return m_dTipRadius ; }
|
||||
double GetCornRadius() const
|
||||
double GetCornRadius( void) const
|
||||
{ return m_dRCorner ; }
|
||||
double GetRefRadius() const
|
||||
double GetRefRadius( void) const
|
||||
{ return m_dRefRadius ; }
|
||||
double GetMrtChsWidth() const
|
||||
double GetMrtChsWidth( void) const
|
||||
{ return m_dMrtChsWidth ; }
|
||||
double GetMrtChsThickness() const
|
||||
double GetMrtChsThickness( void) const
|
||||
{ return m_dMrtChsThickness ; }
|
||||
const CurveComposite& GetOutline( void) const
|
||||
{ return ( m_Outline) ; }
|
||||
|
||||
@@ -20,26 +20,42 @@
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
struct PairHashInt64 {
|
||||
size_t
|
||||
operator()( const std::pair<int64_t, int64_t>& key) const {
|
||||
size_t h1 = std::hash<int64_t>{}(key.first) ;
|
||||
size_t h2 = std::hash<int64_t>{}(key.second) ;
|
||||
return h1 ^ (h2 << 1); // Combine hashes
|
||||
}
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
struct Inters {
|
||||
int nIn ;
|
||||
PNTVECTOR vpt ;
|
||||
int nOut ;
|
||||
PNTVECTOR vpt ;
|
||||
bool bCCW ;
|
||||
int nChunk ;
|
||||
bool bSortedbyStart ;
|
||||
// riordino le intersezioni per lato in senso antiorario dal top
|
||||
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
|
||||
bool operator < ( Inters& b)
|
||||
|
||||
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
|
||||
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
|
||||
// -1 se la curva è sempre dentro la cella
|
||||
|
||||
// riordino le intersezioni per lato in senso antiorario dal top
|
||||
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
|
||||
bool
|
||||
operator < ( Inters& b)
|
||||
{
|
||||
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
|
||||
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
|
||||
int nPos1 = std::distance( vEdges.begin(), iter1) ;
|
||||
const auto iter2 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
|
||||
int nPos2 = std::distance( vEdges.begin(), iter2) ;
|
||||
// se sono loop interni li ordino in modo decrescente rispetto all'area
|
||||
// se sono loop interni li ordino in modo decrescente rispetto all'area
|
||||
bool bEqIn = ( nIn == b.nIn) ;
|
||||
double dAreaA = 0 , dAreaB = 0 ;
|
||||
if ( bEqIn && nIn == -1) {
|
||||
@@ -54,7 +70,7 @@ struct Inters {
|
||||
pl.Close() ;
|
||||
pl.GetAreaXY( dAreaB) ;
|
||||
}
|
||||
// se nIn è un vertice sistemo il valore
|
||||
// se nIn è un vertice sistemo il valore
|
||||
int nEdgeIn = nIn ;
|
||||
if ( nIn > 3)
|
||||
nEdgeIn = nIn - 4 ;
|
||||
@@ -66,13 +82,14 @@ struct Inters {
|
||||
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
|
||||
}
|
||||
|
||||
static bool FirstEncounter ( Inters& a, Inters& b)
|
||||
static bool
|
||||
FirstEncounter( Inters& a, Inters& b)
|
||||
{
|
||||
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
|
||||
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
|
||||
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
|
||||
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
|
||||
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
|
||||
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
// trovo i lati di ingresso e uscita
|
||||
// trovo i lati di ingresso e uscita
|
||||
const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ;
|
||||
int nPos1 = std::distance( vEdges.begin(), iter1) ;
|
||||
const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ;
|
||||
@@ -83,13 +100,13 @@ struct Inters {
|
||||
int nPos4 = std::distance( vEdges.begin(), iter4) ;
|
||||
int nFirstA = 0 ;
|
||||
int nFirstB = 0 ;
|
||||
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
|
||||
// salvo il lato che viene prima confrontando ingresso e uscita
|
||||
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
|
||||
// salvo il lato che viene prima confrontando ingresso e uscita
|
||||
if ( nPos2 < nPos1) {
|
||||
nPos1 = nPos2 ;
|
||||
nFirstA = int( a.vpt.size()) - 1 ;
|
||||
}
|
||||
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
|
||||
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
|
||||
else if ( nPos2 == nPos1 ) {
|
||||
if ( nPos1 == 0 )
|
||||
nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
|
||||
@@ -116,28 +133,28 @@ struct Inters {
|
||||
}
|
||||
a.bSortedbyStart = nFirstA == 0 ;
|
||||
b.bSortedbyStart = nFirstB == 0 ;
|
||||
// se sono diversi ritorno il confronto
|
||||
// se sono diversi ritorno il confronto
|
||||
if ( nPos1 != nPos3)
|
||||
return nPos1 < nPos3 ;
|
||||
// se sono uguali devo valutare il punto di intersezione
|
||||
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
|
||||
// se sono uguali devo valutare il punto di intersezione
|
||||
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
|
||||
( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) ||
|
||||
( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) ||
|
||||
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
|
||||
}
|
||||
|
||||
bool operator == ( Inters& b)
|
||||
bool
|
||||
operator == ( Inters& b)
|
||||
{
|
||||
return AreSamePointExact( vpt[0], b.vpt[0]) ;
|
||||
}
|
||||
bool operator != ( Inters& b)
|
||||
|
||||
bool
|
||||
operator != ( Inters& b)
|
||||
{
|
||||
return ! AreSamePointExact( vpt[0], b.vpt[0]) ;
|
||||
}
|
||||
} ;
|
||||
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
|
||||
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
|
||||
// -1 se la curva è sempre dentro la cella
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class Cell
|
||||
@@ -151,20 +168,25 @@ class Cell
|
||||
// | |
|
||||
// |_________________|
|
||||
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
|
||||
|
||||
public :
|
||||
enum Collapsed { TO_VERIFY = -1, // da verificare
|
||||
NO_COLLAPSE = 0, // non ho coppie di lati collassati
|
||||
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
|
||||
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
|
||||
|
||||
public :
|
||||
~Cell( void) {}
|
||||
Cell( void)
|
||||
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1),
|
||||
m_ptPbl( ORIG), m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true)
|
||||
{
|
||||
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
|
||||
m_ptPtr = ptTr ;
|
||||
}
|
||||
: m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( false), m_nRightEdgeIn( -1),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_nCollapsed( -1), m_ptPbl( ORIG),
|
||||
m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
Cell( const Point3d& ptBL, const Point3d& ptTR)
|
||||
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1),
|
||||
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
: m_nId( -1), m_nTop( -2), m_nBottom( -2), m_nLeft( -2), m_nRight( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_dSplit( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_bLabelled( 0), m_nRightEdgeIn( -1),
|
||||
m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1), m_nCollapsed( -1), m_ptPbl( ptBL),
|
||||
m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
|
||||
bool IsSame( const Cell& cOtherCell) const
|
||||
{ return ( m_nId == cOtherCell.m_nId) ; }
|
||||
void SetBottomLeft( const Point3d& ptBL)
|
||||
@@ -183,9 +205,11 @@ class Cell
|
||||
{ return Point3d( m_ptPbl.x, m_ptPtr.y) ; }
|
||||
Point3d GetBottomRight( void) const
|
||||
{ return Point3d( m_ptPtr.x, m_ptPbl.y); }
|
||||
Point3d GetCenter( void) const
|
||||
{ return ( m_ptPbl + m_ptPtr) / 2 ; }
|
||||
double GetSplitValue( void) const
|
||||
{ return m_dSplit ; }
|
||||
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente
|
||||
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, altrimenti orizzontalmente
|
||||
{ return m_bSplitVert ; }
|
||||
bool IsLeaf( void) const // flag che indica se la cella ha figli o se è una foglia
|
||||
{ return ( m_nChild1 == -2 && m_nChild2 == -2) ; }
|
||||
@@ -194,9 +218,11 @@ class Cell
|
||||
void SetProcessed( bool bProcessed = true)
|
||||
{ m_bProcessed = bProcessed ; }
|
||||
static bool minorX( const Cell& c1, const Cell& c2)
|
||||
{ return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
|
||||
{ return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
|
||||
static bool minorY( const Cell& c1, const Cell& c2)
|
||||
{ return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
|
||||
{ return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
|
||||
void AddPoly( int nPolyId)
|
||||
{ m_vnPolyId.push_back( nPolyId) ;}
|
||||
|
||||
public :
|
||||
int m_nId ; // Id della cella
|
||||
@@ -209,9 +235,9 @@ class Cell
|
||||
double m_dSplit ; // parametro a cui è stata splittata la cella
|
||||
int m_nChild1 ; // prima cella figlio
|
||||
int m_nChild2 ; // seconda cella figlio
|
||||
int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim
|
||||
int m_nFlag ; // flag che indica la caratterizzazione della cella rispetto ai loop di trim
|
||||
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
|
||||
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
|
||||
bool m_bLabelled ; // flag che indica se la cella è stata attraversata durante l'ultima fase del labelling
|
||||
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
|
||||
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse sul parametro U)
|
||||
bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V)
|
||||
@@ -219,6 +245,8 @@ class Cell
|
||||
// ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella
|
||||
int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo
|
||||
// contati in senso CCW a partire dal bottom left
|
||||
INTVECTOR m_vnPolyId ; // indici dei poligoni associati a questa cella nel vettore m_vPolygons del Tree
|
||||
int m_nCollapsed ; // flag che indica se la coppia di lati verticali (1) o orizzontali(2) sono collassati
|
||||
|
||||
private :
|
||||
Point3d m_ptPbl ; // punto bottom left
|
||||
@@ -233,53 +261,50 @@ class Tree
|
||||
public :
|
||||
~Tree( void) ;
|
||||
Tree( void) ;
|
||||
//Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
|
||||
bool SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
|
||||
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh
|
||||
// dSideMin è lunghezza minima del lato di una cella nello spazio reale
|
||||
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells = {}) ; // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||
// se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ;
|
||||
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
|
||||
bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline
|
||||
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
|
||||
{ for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; };
|
||||
void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell
|
||||
Tree( const Point3d ptBl, const Point3d ptTr) ; // da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
|
||||
bool SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
|
||||
bool BuildTree( double dLinTol = LIN_TOL_STD,
|
||||
double dSideMin = 1, // è la minima lunghezza del lato di una cella
|
||||
double dSideMax = INFINITO) ; // è la massima dimensione di un triangolo della trimesh
|
||||
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, std::vector<ICRVCOMPOPOVECTOR>& vCCEdges3D, ICRVCOMPOPOVECTOR& vCCLoops, bool bUpdateEdges) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||
// ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
|
||||
bool GetLeaves( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
|
||||
bool GetEdges3D( std::vector<ICRVCOMPOPOVECTOR>& mCCEdge, POLYLINEVECTOR& vPolygons) ; // restituisce gli edge 3D come polyline
|
||||
bool GetSplitLoops( ICRVCOMPOPOVECTOR& vCCLoopSplit) const // restituisce i loop splitatti ai confini delle celle
|
||||
{ for ( int i = 0 ; i < int( m_vCCLoop2D.size()); ++i)
|
||||
vCCLoopSplit.emplace_back( m_vCCLoop2D[i]->Clone()) ;
|
||||
return true ; }
|
||||
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
|
||||
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
|
||||
bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli
|
||||
bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U
|
||||
bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V
|
||||
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
|
||||
bool IsClosedU( void) const // restituisce flag di chiusara in U
|
||||
{ return m_bClosedU ; }
|
||||
bool IsClosedV( void) const // restituisce flag di chiusara in V
|
||||
{ return m_bClosedV ; }
|
||||
BOOLVECTOR GetPoles( void) // restituisce i flag che indicano se i lati sono collassati in dei poli
|
||||
{ return m_vbPole ; }
|
||||
|
||||
private :
|
||||
bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico
|
||||
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
|
||||
bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
|
||||
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondità di +- 1
|
||||
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
|
||||
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
|
||||
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top
|
||||
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
|
||||
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left
|
||||
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right
|
||||
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
|
||||
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
|
||||
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato top ( la coppia di double è per dare un intervallo diverso su cui limitare i vicini)
|
||||
void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
|
||||
void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato left
|
||||
void GetRightNeigh( int nId, INTVECTOR& vRightNeighs, DBLDBL ddInt = DBLDBL(0,0)) const ; // restituisce le celle foglie che sono adiacenti al lato right
|
||||
void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario
|
||||
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
|
||||
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
|
||||
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
|
||||
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
|
||||
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
|
||||
bool FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
|
||||
// resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto
|
||||
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
|
||||
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation,
|
||||
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
|
||||
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
|
||||
bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario
|
||||
bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR.
|
||||
@@ -294,39 +319,30 @@ class Tree
|
||||
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW)
|
||||
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL
|
||||
bool AdjustCuts( void) ;
|
||||
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
|
||||
bool CloseOpenCuts( void) ;
|
||||
bool CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& pl) const ;
|
||||
bool UpdateSplitLoop( ICurveComposite* pCC, Point3d& pt) ;
|
||||
bool VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const ; // verifico l'orientazione ( CCW o CW) delle polyline in base a come sono contenute le une nelle altre
|
||||
bool AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ;
|
||||
|
||||
bool GetPoint(double dU, double dV, Point3d& ptP) const ;
|
||||
bool SavePoint( double dU, double dV, const Point3d& ptP) ;
|
||||
|
||||
private :
|
||||
const SurfBezier* m_pSrfBz ; // superficie di bezier
|
||||
DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00
|
||||
bool m_bTrimmed ; // superficie trimmata
|
||||
//INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
|
||||
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||
//ICURVEPOVECTOR m_vLoop ; // curve di loop
|
||||
std::unordered_map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
|
||||
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
|
||||
bool m_bBilinear ; // superficie bilineare
|
||||
bool m_bMulti ; // superficie multi-patch
|
||||
bool m_bClosedU ; // superficie chiusa lungo il parametro U
|
||||
bool m_bClosedV ; // superficie chiusa lungo il parametro V
|
||||
BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge)
|
||||
bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero
|
||||
int m_nDegU ; // grado della superficie nel parametro U
|
||||
int m_nDegV ; // grado della superficie nel parametro V
|
||||
int m_nSpanU ; // numero di span lungo il parametro U
|
||||
int m_nSpanV ; // numero di span lungo il parametro V
|
||||
POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree
|
||||
POLYLINEMATRIX m_vPolygonsCorr ; // matrice dei poligoni del tree, corretti per i punti che sono nei poli
|
||||
POLYLINEMATRIX m_vPolygons3d ; // matrice dei poligoni3d del tree
|
||||
std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||
std::unordered_map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01
|
||||
std::unordered_map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
|
||||
mutable std::unordered_map<std::pair<int64_t,int64_t>,Point3d,PairHashInt64> m_mPt3d ; // mappa che contiene tutti i punti 3d della superficie calcolati (la chiave sono le coordinate, moltiplicate per 2^24 e trasformate in int)
|
||||
INTVECTOR m_vnLeaves ; // vettore delle foglie
|
||||
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
|
||||
bool m_bTestMode ; // bool che indica se la test mode è attiva
|
||||
POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle
|
||||
ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle
|
||||
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||
} ;
|
||||
} ;
|
||||
|
||||
+53
-34
@@ -818,7 +818,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
}
|
||||
}
|
||||
// If vertex k is inside the ear triangle, then this is not an ear
|
||||
else if ( TestPointInTriangle( vPt[vPol[k]], vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) {
|
||||
else if ( TestPointInOrOnTriangle( vPt[vPol[k]], vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) {
|
||||
bIsEar = false ;
|
||||
break ;
|
||||
}
|
||||
@@ -978,6 +978,28 @@ Triangulate::TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// test if point p is inside or on the border of triangle (a, b, c)
|
||||
bool
|
||||
Triangulate::TestPointInOrOnTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
|
||||
{
|
||||
// If P is on a vertex is considered inside
|
||||
if ( AreSamePoint( ptP, ptA))
|
||||
return true ;
|
||||
if ( AreSamePoint( ptP, ptB))
|
||||
return true ;
|
||||
if ( AreSamePoint( ptP, ptC))
|
||||
return true ;
|
||||
// If P is on the right of at least one edge is outside
|
||||
if ( TriangleIsCCW( ptA, ptP, ptB, EPS_SMALL))
|
||||
return false ;
|
||||
if ( TriangleIsCCW( ptB, ptP, ptC, EPS_SMALL))
|
||||
return false ;
|
||||
if ( TriangleIsCCW( ptC, ptP, ptA, EPS_SMALL))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd)
|
||||
@@ -1385,6 +1407,7 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
// I triangoli cap se eliminati danno origine a T-junctions, quindi devono essere gestiti opportunamente con dei flip.
|
||||
// I triangoli needle se eliminati non sono problematici, ma i loro vertici coincidenti vanno gestiti opportunamente nel
|
||||
// calcolo delle adiacenze dei triangoli cap.
|
||||
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
|
||||
|
||||
int nTria = int( vTr.size()) / 3 ;
|
||||
INTVECTOR vCapTria ;
|
||||
@@ -1482,46 +1505,40 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
INTVECTOR vChain, vChainEdges ;
|
||||
vChain.emplace_back( nTA) ;
|
||||
vChainEdges.emplace_back( nEA) ;
|
||||
|
||||
while ( nTB != -1 && ! vbIsValidTria[nTB]) {
|
||||
// aggiungo alla catena
|
||||
vChain.emplace_back( nTB) ;
|
||||
int nTCurr = nTB ;
|
||||
int nEOther ;
|
||||
while ( nTCurr != -1 && ! vbIsValidTria[nTCurr]) {
|
||||
|
||||
// calcolo il successivo
|
||||
nTA = nTB ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
|
||||
vChainEdges.emplace_back( nEA) ;
|
||||
int nTOther, nECurr ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, nTCurr, nECurr, nTOther, nEOther) ;
|
||||
|
||||
// verifico di non aver trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// e quindi di non essere entrato in un loop
|
||||
if ( nTB == vChain[vChain.size()-2]) {
|
||||
if ( nTOther == vChain.back()) {
|
||||
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
|
||||
// aggiorno per iterazione successiva
|
||||
if ( vChain.size() == 2) {
|
||||
FlipTrg( vTr, nTCurr, nTOther, nECurr, nEOther) ;
|
||||
if ( vChain.size() > 1) {
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, vChain.back(), nEA, nTB, nEB) ;
|
||||
vChainEdges[0] = nEA ;
|
||||
// individuo il nuovo adiacente all'ultimo triangolo della catena tra i due appena flippati
|
||||
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTCurr, nTOther, nTB, nEB) ;
|
||||
nTOther = nTB ;
|
||||
}
|
||||
else {
|
||||
// elimino gli ultimi due triangoli che sono appena stati flippati e ricalcolo adiacenza del triangolo
|
||||
// precedente
|
||||
vChain.pop_back() ;
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
int nTTest1 = nTA ;
|
||||
int nTTest2 = nTB ;
|
||||
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTTest1, nTTest2, nTB, nEB) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vChain.emplace_back( nTCurr) ;
|
||||
vChainEdges.emplace_back( nECurr) ;
|
||||
}
|
||||
// aggiorno per iterazione successiva
|
||||
nTCurr = nTOther ;
|
||||
}
|
||||
|
||||
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
|
||||
if ( nTB == -1) {
|
||||
if ( nTCurr == -1) {
|
||||
bRemovedTrg = true ;
|
||||
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||
if ( vbIsValidTria[vChain[k]])
|
||||
continue ;
|
||||
vTr[3*vChain[k]] = -1 ;
|
||||
vTr[3*vChain[k] + 1] = -1 ;
|
||||
vTr[3*vChain[k] + 2] = -1 ;
|
||||
@@ -1530,14 +1547,16 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
}
|
||||
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido
|
||||
else {
|
||||
FlipTrg( vTr, vChain.back(), nTB, vChainEdges.back(), nEB) ;
|
||||
FlipTrg( vTr, vChain.back(), nTCurr, vChainEdges.back(), nEOther) ;
|
||||
vbIsValidTria[vChain.back()] = true ;
|
||||
int nTrgTest1 = vChain.back() ;
|
||||
int nTrgTest2 = nTB ;
|
||||
for ( int i = int( vChain.size()-2) ; i >= 0 ; i--) {
|
||||
int nTrgTest2 = nTCurr ;
|
||||
for ( int j = int( vChain.size()-2) ; j >= 0 ; j--) {
|
||||
// triangolo corrente
|
||||
int nTA = vChain[i] ;
|
||||
int nEA = vChainEdges[i] ;
|
||||
int nTA = vChain[j] ;
|
||||
if ( vbIsValidTria[nTA])
|
||||
continue ;
|
||||
int nEA = vChainEdges[j] ;
|
||||
// devo trovare il nuovo adiacente dopo il flip dei successivi nella catena
|
||||
TestAdjacentOnEdge( vTr, nTA, nEA, nTrgTest1, nTrgTest2, nTB, nEB) ;
|
||||
// flip per rendere valido il triangolo corrente
|
||||
@@ -1608,7 +1627,7 @@ MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vPt.reserve( fist.c_vertex.num_vertices) ;
|
||||
for ( int i = 0 ; i < fist.c_vertex.num_vertices ; i ++)
|
||||
vPt.emplace_back( fist.c_vertex.vertices[i].x, fist.c_vertex.vertices[i].y, fist.c_vertex.vertices[i].z) ;
|
||||
|
||||
|
||||
// recupero i triangoli da fist
|
||||
vTr.reserve( 3 * fist.c_vertex.num_triangles) ;
|
||||
for ( int i = 0 ; i < fist.c_vertex.num_triangles ; i ++) {
|
||||
|
||||
@@ -45,6 +45,7 @@ class Triangulate
|
||||
bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, double dToler = 0.1 * EPS_SMALL) ;
|
||||
bool TestIntersection( const Point3d& ptA1, const Point3d& ptA2, const Point3d& ptB1, const Point3d& ptB2) ;
|
||||
bool TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
|
||||
bool TestPointInOrOnTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
|
||||
bool SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd) ;
|
||||
bool GetPntVectorFromPolyline( const PolyLine& PL, bool bXmaxStart, PNTVECTOR& vPi) ;
|
||||
bool GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& nI) ;
|
||||
|
||||
+5398
File diff suppressed because it is too large
Load Diff
+536
-140
File diff suppressed because it is too large
Load Diff
@@ -18,11 +18,15 @@
|
||||
#include "Tool.h"
|
||||
#include "/EgtDev/Include/EGkVolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMesh.h"
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <tuple>
|
||||
#include <atomic>
|
||||
|
||||
typedef std::pair<Point3d, Vector3d> PNTVEC3D ;
|
||||
typedef std::vector<PNTVEC3D> PNTVEC3DVECTOR ; // vettore di intersezioni punto, vettore, tipo superficie
|
||||
|
||||
// ------------------------- FORWARD -------------------------------------------------------------
|
||||
class IntersParLinesSurfTm ;
|
||||
|
||||
@@ -77,13 +81,14 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
public : // IVolZmap
|
||||
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
|
||||
bool Clear( void) override ;
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ;
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||
ISurfTriMesh* GetSurfTriMesh( void) const override ;
|
||||
bool GetEdges( ICURVEPOVECTOR& vpCurve) const override ;
|
||||
bool GetVolume( double& dVol) const override ;
|
||||
bool IsTriDexel( void) const override
|
||||
@@ -93,7 +98,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
{ return m_nDexVoxRatio ; }
|
||||
bool ChangeResolution( int nDexVoxRatio) override ;
|
||||
void SetShowEdges( bool bShow) override
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
m_OGrMgr.Clear() ; }
|
||||
bool GetShowEdges( void) const override
|
||||
{ return m_bShowEdges ; }
|
||||
@@ -144,7 +149,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool RemovePart( int nPart) override ;
|
||||
int GetPartMinDistFromPoint( const Point3d& ptP) const override ;
|
||||
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool MakeUniform( double dToler) override ;
|
||||
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ;
|
||||
bool RemoveFins( const Vector3d& vtDir, double dThick) override ;
|
||||
bool Offset( double dOffs, int nType) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -165,6 +173,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
return *this ; }
|
||||
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const ;
|
||||
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const ;
|
||||
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) ;
|
||||
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) ;
|
||||
|
||||
private :
|
||||
enum CubeType { VOX_EXTERN = 1,
|
||||
@@ -217,7 +227,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
typedef std::unordered_map<int, Voxel> VoxelContainer ;
|
||||
// Unordered map per la coerenza topologica
|
||||
typedef std::unordered_map<int, bool> InterVoxMatter ;
|
||||
|
||||
#if !defined(_WIN64)
|
||||
// Numero massimo approssimativo di Dexel per versione 32-bit per evitare Crash con memoria
|
||||
#if defined(_DEBUG)
|
||||
static const int MAX_DEXEL_32_BIT = 3000000 + 1 ;
|
||||
#else
|
||||
static const int MAX_DEXEL_32_BIT = 5000000 + 1 ;
|
||||
#endif
|
||||
static int m_nDexelNbr ; // numero corrente di Dexel presenti
|
||||
#endif
|
||||
|
||||
private :
|
||||
bool CopyFrom( const VolZmap& clSrc) ;
|
||||
bool ResetGraphics( void) ;
|
||||
@@ -250,17 +269,22 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool AddIntervals( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler,
|
||||
Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) ;
|
||||
bool AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax,
|
||||
double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
|
||||
const Vector3d& vtToolMax) ;
|
||||
bool AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum) ;
|
||||
bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
// Spostamenti utensile
|
||||
bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ;
|
||||
bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) ;
|
||||
bool SelectGeneralMotion( int nGrid, const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtLs, const Vector3d& vtLe, int n5AxisType) ;
|
||||
bool SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL) ;
|
||||
bool InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3]) ;
|
||||
bool InitializeAuxPoints( Point3d ptTop1s[3], Point3d ptTop1e[3], Point3d ptTop2s[3], Point3d ptTop2e[3],
|
||||
Point3d ptBottom1s[3], Point3d ptBottom1e[3], Point3d ptBottom2s[3], Point3d ptBottom2e[3]) ;
|
||||
// SOTTRAZIONI
|
||||
// UTENSILI
|
||||
// Asse di simmetria parallelo a Z
|
||||
@@ -288,11 +312,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool Mrt_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
|
||||
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp
|
||||
bool Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt� un Perp
|
||||
bool Chs_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ;
|
||||
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realtà un Perp
|
||||
bool Chs_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) ; // E' in realt� un Perp
|
||||
bool GenTool_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
bool GenTool_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) ;
|
||||
// lavorazioni a 5 assi
|
||||
bool GenTool_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType = ACROSS) ;
|
||||
bool Cyl_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, double dHeightCorr = 0, int n5AxisType = ACROSS) ;
|
||||
bool CylBall_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType = ACROSS) ;
|
||||
bool Conus_5AxisMilling(int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, int nToolNum, int n5AxisType = ACROSS) ;
|
||||
|
||||
// COMPONENTI
|
||||
// Asse di simmetria diretto come l'asse Z
|
||||
@@ -311,7 +340,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
|
||||
bool CompPar_ZMilling( int nGrid, double dLenX, double dLenY, double dLenZ,
|
||||
const Point3d& ptS, const Point3d& ptE,
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realt� MillingPerp
|
||||
// Asse di simmetria con orientazione generica
|
||||
bool CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
|
||||
double dHei, double dRad, bool bTapB, bool bTapT, int nToolNum) ;
|
||||
@@ -327,7 +356,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum) ;
|
||||
bool CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ,
|
||||
const Point3d& ptS, const Point3d& ptE,
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
// lavorazioni a 5 assi
|
||||
bool Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe,
|
||||
double dHeight, double dMaxRad, double dMinRad, int nToolNum, int n5AxisType) ;
|
||||
bool CompCyl_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe,
|
||||
double dHeight, double dRadius, int nToolNum, int n5AxisType) ;
|
||||
bool CompConus_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDirS, const Vector3d& vtToolDirE, double dHei, double dMaxRad, double dMinRad,
|
||||
bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR, int nToolNum, int n5AxisType) ;
|
||||
|
||||
// Generica traslazione sfera
|
||||
bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ;
|
||||
// Additivi
|
||||
@@ -341,7 +378,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
// BBox per utensili e solidi semplici con movimenti di traslazione
|
||||
inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
inline bool TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, const Vector3d& vtV2,
|
||||
double dRad, double dTipRad, double dHei,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
|
||||
@@ -432,17 +469,62 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
// Funzioni per Offset di superfici
|
||||
bool InitVolZMapOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool InitVolZMapThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByOpenSurfSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByClosedSurfSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapBySurfThickeningSharpedOffset( const ISurfTriMesh* Surf, int nType, double dOffs, double dTol) ;
|
||||
bool CreateOffsetSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateFatOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs, bool bThickle, int nTool = 0) ;
|
||||
bool CreateOrientedOffsetExtrusionFace( const ISurfTriMesh* Surf, double dOffs) ;
|
||||
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolMin, int nToolMax, bool bSkipSwap = false) ;
|
||||
bool CutByPlaneForOffset( const Plane3d& plCut) ;
|
||||
bool AddSurfTmForOffset( const ISurfTriMesh* pStm, int nTool) ;
|
||||
bool AddMapPartForOffset( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, int nTool, IntersParLinesSurfTm& intPLSTM) ;
|
||||
// Funzioni per Offset di Zmap
|
||||
bool OffsetFillet( double dOffs) ;
|
||||
bool OffsetSharped( double dOffs, int nType) ;
|
||||
// Funzione analisi punti/Normali per Alette
|
||||
bool GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc) ;
|
||||
bool ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
|
||||
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
|
||||
Vector3d& vtN, double& dNewZ) ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
enum Shape { GENERIC = 0, BOX = 1, EXTRUSION = 2} ;
|
||||
enum Move5Axis {
|
||||
ALONG_CONVEX = 0 ,
|
||||
ALONG_CONCAVE = 1 ,
|
||||
ACROSS = 2 ,
|
||||
NO_BASE_INTERS = 3} ;
|
||||
enum Status {
|
||||
ERR = 0,
|
||||
OK = 1,
|
||||
TO_VERIFY = 2} ;
|
||||
enum Shape {
|
||||
GENERIC = 0,
|
||||
BOX = 1,
|
||||
EXTRUSION = 2,
|
||||
OFFSET = 3} ;
|
||||
static const int N_MAPS = 3 ;
|
||||
static const int N_VOXBLOCK = 32 ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
Status m_nStatus ; // stato
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
|
||||
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
|
||||
@@ -476,8 +558,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable BOOLVECTOR m_BlockToUpdate ;
|
||||
mutable INTVECTOR m_BlockUpdatingCounter ;
|
||||
|
||||
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non è noto
|
||||
// Se >= 0 è il numero di componenti connesse
|
||||
int m_nConnectedCompoCount ; // Se == - 1 il numero di componenti non è noto
|
||||
// Se >= 0 è il numero di componenti connesse
|
||||
|
||||
mutable std::vector<VoxelContainer> m_InterBlockVox ;
|
||||
mutable SharpTriaMatrix m_InterBlockOriginalSharpTria ;
|
||||
@@ -490,9 +572,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable std::vector<InterVoxMatter> m_SliceXY ;
|
||||
mutable std::vector<InterVoxMatter> m_SliceXZ ;
|
||||
mutable std::vector<InterVoxMatter> m_SliceYZ ;
|
||||
mutable std::mutex m_SliceMutex ;
|
||||
mutable std::atomic_flag m_SliceFlag ;
|
||||
|
||||
std::atomic<bool> m_bIsBox ;
|
||||
bool m_bIsBox ;
|
||||
|
||||
int m_nCurrTool ;
|
||||
std::vector<Tool> m_vTool ;
|
||||
@@ -500,6 +582,12 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
double m_dToolAngTolDeg ;
|
||||
} ;
|
||||
|
||||
// Offset
|
||||
enum {
|
||||
VOLZMAP_OFFS_FILLET = 0,
|
||||
VOLZMAP_OFFS_CHANFER = 1,
|
||||
VOLZMAP_OFFS_EXTENDED = 2
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline VolZmap* CreateBasicVolZmap( void)
|
||||
|
||||
+24
-22
@@ -2294,7 +2294,7 @@ VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
vtN1.Normalize() ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if( nBasInt == 1) {
|
||||
else if ( nBasInt == 1) {
|
||||
// Punto di intersezione
|
||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cono verso l'interno
|
||||
@@ -3080,17 +3080,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
return false ;
|
||||
// Se c'è intersezione valuto tutti i voxel interni
|
||||
if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) {
|
||||
// Ciclo sui voxel del blocco.
|
||||
// Triangoli smooth
|
||||
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
|
||||
// ciclo sui voxel del blocco.
|
||||
for ( int nV = 0 ; nV < ssize( m_BlockSmoothTria[nB]) ; ++ nV) {
|
||||
// Box del voxel
|
||||
BBox3d b3Vox ;
|
||||
GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ;
|
||||
// Se non c'è intersezione col voxel, passo al successivo.
|
||||
// Se non c'è intersezione col voxel, passo al successivo.
|
||||
if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox))
|
||||
continue ;
|
||||
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
|
||||
// ciclo sui triangoli del voxel
|
||||
for ( int nT = 0 ; nT < ssize( m_BlockSmoothTria[nB][nV].vTria) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
@@ -3102,18 +3103,18 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
}
|
||||
}
|
||||
// Triangoli sharp interni al blocco
|
||||
for ( int nV = 0 ; nV < int( m_BlockSharpTria[nB].size()) ; ++ nV) {
|
||||
// ciclo sui voxel del blocco.
|
||||
for ( int nV = 0 ; nV < ssize( m_BlockSharpTria[nB]) ; ++ nV) {
|
||||
// Box del voxel
|
||||
BBox3d b3Vox ;
|
||||
GetVoxelBox( m_BlockSharpTria[nB][nV].i, m_BlockSharpTria[nB][nV].j, m_BlockSharpTria[nB][nV].k, b3Vox) ;
|
||||
// Se non c'è intersezione col voxel, passo al successivo.
|
||||
// Ciclo sulle componenti connesse
|
||||
for ( int nC = 0 ; nC < int( m_BlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < int( m_BlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
for ( int nC = 0 ; nC < ssize( m_BlockSharpTria[nB][nV].vCompoTria) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < ssize( m_BlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_BlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
|
||||
if (nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
// Costruisco il tratto di curva
|
||||
CurveLine cvLine ;
|
||||
if ( cvLine.Set(ptSt, ptEn))
|
||||
@@ -3123,10 +3124,10 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
}
|
||||
}
|
||||
// Triangoli grandi del blocco
|
||||
for ( int nT = 0 ; nT < int( m_BlockBigTria[nB].size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_BlockBigTria[nB][nT] ;
|
||||
for ( int nT = 0 ; nT < ssize( m_BlockBigTria[nB]) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_BlockBigTria[nB][nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria(plPlane, trTria, ptSt, ptEn) ;
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
// Costruisco il tratto di curva
|
||||
CurveLine cvLine ;
|
||||
@@ -3136,11 +3137,11 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
}
|
||||
}
|
||||
// In ogni caso valuto i triangoli sharp fra blocchi
|
||||
for ( int nV = 0 ; nV < int( m_InterBlockSharpTria[nB].size()) ; ++ nV) {
|
||||
for ( int nV = 0 ; nV < ssize( m_InterBlockSharpTria[nB]) ; ++ nV) {
|
||||
// Ciclo sulle componenti connesse
|
||||
for ( int nC = 0 ; nC < int( m_InterBlockSharpTria[nB][nV].vCompoTria.size()) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < int( m_InterBlockSharpTria[nB][nV].vCompoTria[nC].size()) ; ++ nT) {
|
||||
Triangle3d trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
for ( int nC = 0 ; nC < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria) ; ++ nC) {
|
||||
for ( int nT = 0 ; nT < ssize( m_InterBlockSharpTria[nB][nV].vCompoTria[nC]) ; ++ nT) {
|
||||
const Triangle3d& trTria = m_InterBlockSharpTria[nB][nV].vCompoTria[nC][nT] ;
|
||||
Point3d ptSt, ptEn ;
|
||||
int nIntersType = IntersPlaneTria( plPlane, trTria, ptSt, ptEn) ;
|
||||
if ( nIntersType == IPTT_EDGE || nIntersType == IPTT_YES) {
|
||||
@@ -3156,9 +3157,9 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
|
||||
// Creo i loop
|
||||
ChainCurves LoopCreator ;
|
||||
LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ;
|
||||
LoopCreator.Init( false, EPS_SMALL, ssize( vLine)) ;
|
||||
// Carico le curve per concatenarle
|
||||
for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) {
|
||||
for ( int nCv = 0 ; nCv < ssize( vLine) ; ++ nCv) {
|
||||
Point3d ptSt = vLine[nCv].GetStart() ;
|
||||
Point3d ptEn = vLine[nCv].GetEnd() ;
|
||||
Vector3d vtDir; vLine[nCv].GetStartDir(vtDir) ;
|
||||
@@ -3176,6 +3177,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
|
||||
if ( ! pLoop->AddCurve( vLine[i - 1], true, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
}
|
||||
pLoop->TestClosure( 10 * EPS_SMALL) ;
|
||||
pLoop->SetExtrusion( plPlane.GetVersN()) ;
|
||||
pLoop->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
||||
// Inserisco la curva composita nella raccolta da ritornare
|
||||
|
||||
+245
-69
@@ -17,6 +17,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "VolZmap.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <future>
|
||||
@@ -26,8 +27,8 @@ using namespace std ;
|
||||
// ------------------------- CREAZIONE MAPPA --------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
@@ -50,7 +51,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_nNx[0] = max( int( ( dDimX + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNy[0] = max( int( ( dDimY + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
|
||||
// Numero di componenti connesse
|
||||
// Numero di componenti connesse
|
||||
m_nConnectedCompoCount = 1 ;
|
||||
|
||||
// Se tridexel
|
||||
@@ -66,7 +67,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nNx[2] = 0 ;
|
||||
m_nNy[2] = 0 ;
|
||||
m_nNy[2] = 0 ;
|
||||
}
|
||||
|
||||
// Definisco il numero di blocchi lungo x,y e z
|
||||
@@ -80,12 +81,24 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
|
||||
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Creazione delle celle per ogni mappa
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_Values[i].resize( m_nDim[i]) ;
|
||||
|
||||
// Riempimento delle celle
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
|
||||
for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
|
||||
|
||||
// Aggiungo il tratto al dexel vuoto
|
||||
@@ -97,7 +110,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
switch ( i) {
|
||||
case 0 :
|
||||
m_Values[i][j][0].vtMinN = - Z_AX ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].vtMaxN = Z_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
@@ -112,9 +125,10 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_Values[i][j][0].dMax = dDimY ;
|
||||
m_Values[i][j][0].vtMaxN = Y_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definizione delle limitazioni iniziali in Z per ogni mappa
|
||||
m_dMinZ[0] = 0 ;
|
||||
@@ -135,7 +149,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
@@ -186,6 +200,18 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
|
||||
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Creazione delle celle per ogni mappa
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_Values[i].resize( m_nDim[i]) ;
|
||||
@@ -209,7 +235,7 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Aggiorno la dimensione della mappa 1 o 3
|
||||
m_nMapNum = ( bTriDex ? 3 : 1) ;
|
||||
@@ -249,14 +275,35 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ;
|
||||
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
m_nDim[2] = m_nNx[2] * m_nNy[2] ;
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_Values[2].resize( m_nDim[2]) ;
|
||||
}
|
||||
|
||||
// Se dimensione singola
|
||||
else {
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
m_nDexelNbr += m_nDim[0] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nDim[1] = 0 ;
|
||||
@@ -504,6 +551,8 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
nSupJ < 0 || nSupJ > m_nNy[nMap])
|
||||
return false ;
|
||||
|
||||
double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ;
|
||||
|
||||
// Determinazione e ridimensionamento dei dexel interni alla trimesh
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||
@@ -551,7 +600,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
double dCos = IntersectionResults[k].dCosDN ;
|
||||
|
||||
// entro nella superficie trimesh
|
||||
if ( dCos < - EPS_SMALL) {
|
||||
if ( dCos < - dCosSmall) {
|
||||
|
||||
ptIn = IntersectionResults[k].ptI ;
|
||||
|
||||
@@ -564,7 +613,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
}
|
||||
|
||||
// esco dalla superficie trimesh
|
||||
else if ( dCos > EPS_SMALL && bInside) {
|
||||
else if ( dCos > dCosSmall && bInside) {
|
||||
|
||||
Point3d ptOut = IntersectionResults[k].ptI ;
|
||||
|
||||
@@ -597,6 +646,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
|
||||
@@ -691,7 +741,100 @@ VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex)
|
||||
VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
|
||||
{
|
||||
// controllo sui parametri
|
||||
if ( nMap < 0 || nMap > 2 ||
|
||||
nInfI < 0 || nInfI > m_nNx[nMap] ||
|
||||
nSupI < 0 || nSupI > m_nNx[nMap] ||
|
||||
nInfJ < 0 || nInfJ > m_nNy[nMap] ||
|
||||
nSupJ < 0 || nSupJ > m_nNy[nMap])
|
||||
return false ;
|
||||
|
||||
// determinazione e ridimensionamento dei dexel interni alla trimesh
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||
|
||||
// definisco la retta da intersecare con la trimesh
|
||||
double dX = ( i + 0.5) * m_dStep ;
|
||||
double dY = ( j + 0.5) * m_dStep ;
|
||||
Point3d ptP0( dX, dY, 0) ;
|
||||
|
||||
// intersezioni della retta con la TriMesh
|
||||
ILSIVECTOR IntersectionResults ;
|
||||
intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ;
|
||||
|
||||
// rimuovo le intersezioni in eccesso
|
||||
for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) {
|
||||
int nJ = nI + 1 ; // prima successiva
|
||||
int nK = nJ + 1 ; // seconda successiva
|
||||
int nT = nK + 1 ; // terza successiva
|
||||
// determino i segni delle 4 intersezioni tra la linea e il trangolo della TriMesh
|
||||
int nSgnI = IntersectionResults[nI].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nI].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnJ = IntersectionResults[nJ].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nJ].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnK = IntersectionResults[nK].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nK].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnT = IntersectionResults[nT].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nT].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
// parametri dell'intersezione sulla linea
|
||||
double dUJ = IntersectionResults[nJ].dU ;
|
||||
double dUK = IntersectionResults[nK].dU ;
|
||||
// controllo coerenza con segni...
|
||||
if ( nSgnI != 0 && nSgnI == nSgnJ &&
|
||||
nSgnK != 0 && nSgnK == nSgnT &&
|
||||
nSgnI == - nSgnT &&
|
||||
abs( dUJ - dUK) < EPS_SMALL) {
|
||||
// ... ed elimino le intersezioni in eccesso...
|
||||
IntersectionResults.erase( IntersectionResults.begin() + nK) ;
|
||||
IntersectionResults.erase( IntersectionResults.begin() + nJ) ;
|
||||
}
|
||||
}
|
||||
|
||||
int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide
|
||||
bool bInside = false ; // Flag entrata/uscita per tratto di retta
|
||||
Point3d ptIn ; Vector3d vtInN ;
|
||||
|
||||
// per ogni intersezione valida trovata...
|
||||
for ( int k = 0 ; k < nInt ; ++ k) {
|
||||
// ricavo il tipo di intersezione
|
||||
int nIntType = IntersectionResults[k].nILTT ;
|
||||
// se c'è intersezione
|
||||
if ( nIntType != ILTT_NO) {
|
||||
// ricavo il cos tra i vettori ( normale del triangolo e tangente alla retta)
|
||||
double dCos = IntersectionResults[k].dCosDN ;
|
||||
|
||||
// se entro nella superficie trimesh...
|
||||
if ( dCos < - EPS_SMALL) {
|
||||
ptIn = IntersectionResults[k].ptI ; // punto di intersezione
|
||||
int nT = IntersectionResults[k].nT ; // triangolo di interesse
|
||||
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
|
||||
Surf.GetFacetNormal( nF, vtInN) ;
|
||||
bInside = true ; // entrata
|
||||
}
|
||||
// ...se esco dalla superficie trimesh ( prima sono per forza entrato)
|
||||
else if ( dCos > EPS_SMALL && bInside) {
|
||||
Point3d ptOut = IntersectionResults[k].ptI ; // punto di intersezione
|
||||
int nT = IntersectionResults[k].nT ; // triangolo di interesse
|
||||
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
|
||||
Vector3d vtOutN ; Surf.GetFacetNormal( nF, vtOutN) ; // vettore d'uscita
|
||||
|
||||
// Aggiungo un tratto al dexel
|
||||
SubtractIntervals( nMap, i, j,
|
||||
ptIn.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
|
||||
ptOut.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
|
||||
- vtInN, - vtOutN, 0, true) ;
|
||||
bInside = false ; // uscita
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError)
|
||||
{
|
||||
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
|
||||
double dVol ;
|
||||
@@ -704,14 +847,17 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
// Determino il bounding box della TriMesh
|
||||
BBox3d SurfBBox ;
|
||||
Surf.GetLocalBBox( SurfBBox) ;
|
||||
|
||||
// Determino i punti estremi del bounding box
|
||||
Point3d ptMapOrig, ptMapEnd ;
|
||||
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
|
||||
|
||||
// Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione,
|
||||
// quindi espandiamo il bounding box per ovviare al problema.
|
||||
SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ;
|
||||
if ( dExtraBox > EPS_ZERO)
|
||||
SurfBBox.Expand( dExtraBox) ;
|
||||
else
|
||||
dExtraBox = 0 ;
|
||||
|
||||
// Determino i punti estremi del bounding box
|
||||
Point3d ptMapOrig, ptMapEnd ;
|
||||
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
|
||||
|
||||
// Sistema di riferimento intrinseco dello Zmap
|
||||
m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ;
|
||||
@@ -738,14 +884,33 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ;
|
||||
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
m_nDim[2] = m_nNx[2] * m_nNy[2] ;
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_Values[2].resize( m_nDim[2]) ;
|
||||
}
|
||||
|
||||
// Se a dimensione singola
|
||||
else {
|
||||
#if !defined(_WIN64)
|
||||
m_nDexelNbr += m_nDim[0] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nDim[1] = 0 ;
|
||||
@@ -760,72 +925,83 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
|
||||
// ciclo sulle griglie
|
||||
bool bCompleted = true ;
|
||||
for ( int g = 0 ; g < m_nMapNum ; ++ g) {
|
||||
for ( int nG = 0 ; nG < m_nMapNum ; ++ nG) {
|
||||
|
||||
// Definisco dei sistemi di riferimento ausiliari
|
||||
Frame3d frMapFrame ;
|
||||
if ( g == 0)
|
||||
if ( nG == 0)
|
||||
frMapFrame = m_MapFrame ;
|
||||
else if ( g == 1)
|
||||
else if ( nG == 1)
|
||||
frMapFrame.Set( ptMapOrig, Y_AX, Z_AX, X_AX) ;
|
||||
else if ( g == 2)
|
||||
else if ( nG == 2)
|
||||
frMapFrame.Set( ptMapOrig, Z_AX, X_AX, Y_AX) ;
|
||||
|
||||
// Oggetto per calcolo massivo intersezioni
|
||||
IntersParLinesSurfTm intPLSTM( frMapFrame, Surf) ;
|
||||
|
||||
// Numero massimo di thread
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
if ( m_nNx[g] > m_nNy[g]) {
|
||||
int nDexNum = m_nNx[g] / nThreadMax ;
|
||||
int nRemainder = m_nNx[g] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g,
|
||||
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nDexNum = m_nNy[g] / nThreadMax ;
|
||||
int nRemainder = m_nNy[g] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g,
|
||||
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Ciclo per attendere che tutti gli async abbiano terminato.
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nThreadMax) {
|
||||
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
|
||||
// Async terminato
|
||||
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
|
||||
++ nTerminated ;
|
||||
bCompleted = bCompleted && vRes[nL].get() ;
|
||||
// Standarda è multithread
|
||||
constexpr bool MULTITHREAD = true ;
|
||||
if ( MULTITHREAD) {
|
||||
|
||||
// Numero massimo di thread
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
if ( m_nNx[nG] > m_nNy[nG]) {
|
||||
int nDexNum = m_nNx[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNx[nG] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
nInfI, nSupI, 0, m_nNy[nG], ref( vtLen), ref( ptMapOrig), ref( Surf), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nDexNum = m_nNy[nG] / nThreadMax ;
|
||||
int nRemainder = m_nNy[nG] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, nG,
|
||||
0, m_nNx[nG], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), ref( Surf),ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Ciclo per attendere che tutti gli async abbiano terminato.
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nThreadMax) {
|
||||
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
|
||||
// Async terminato
|
||||
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
|
||||
++ nTerminated ;
|
||||
bCompleted = bCompleted && vRes[nL].get() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// !!!! NON MULTITHREAD : SOLO PER DEBUG !!!!
|
||||
else {
|
||||
CreateMapPart( nG, 0, m_nNx[nG], 0, m_nNy[nG], vtLen, ptMapOrig, Surf, intPLSTM) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Assegno il minimo e massimo valore di Z della mappa
|
||||
m_dMinZ[0] = 0 ;
|
||||
m_dMaxZ[0] = vtLen.z ;
|
||||
m_dMinZ[1] = 0 ;
|
||||
m_dMaxZ[1] = ( bTriDex ? vtLen.x : 0) ;
|
||||
m_dMinZ[2] = 0 ;
|
||||
m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ;
|
||||
m_dMinZ[0] = dExtraBox ;
|
||||
m_dMaxZ[0] = vtLen.z - dExtraBox ;
|
||||
m_dMinZ[1] = ( bTriDex ? dExtraBox : 0) ;
|
||||
m_dMaxZ[1] = ( bTriDex ? vtLen.x - dExtraBox : 0) ;
|
||||
m_dMinZ[2] = ( bTriDex ? dExtraBox : 0) ;
|
||||
m_dMaxZ[2] = ( bTriDex ? vtLen.y - dExtraBox : 0) ;
|
||||
|
||||
// Tipologia
|
||||
m_nShape = ( IsBox() ? BOX : GENERIC) ;
|
||||
// Con espansione non va considerato box (calcolo trimesh va in crash)
|
||||
m_nShape = ( dExtraBox <= EPS_ZERO && IsBox() ? BOX : GENERIC) ;
|
||||
|
||||
// Aggiornamento dello stato
|
||||
m_nStatus = OK ;
|
||||
|
||||
+88
-29
@@ -19,10 +19,12 @@
|
||||
#include "MC_Tables.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Core"
|
||||
#include "/EgtDev/Extern/Eigen/SVD"
|
||||
#include <thread>
|
||||
@@ -571,6 +573,35 @@ VolZmap::GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
VolZmap::GetSurfTriMesh( void) const
|
||||
{
|
||||
// controllo che lo Zmap sia valido
|
||||
if ( ! IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// inizializzo la superficie
|
||||
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pStm) || ! pStm->Init( 3, 1))
|
||||
return nullptr ;
|
||||
PointGrid3d VertGrid ; VertGrid.Init( 50000) ;
|
||||
|
||||
// ciclo lungo i blocchi dello Zmap
|
||||
for ( int nB = 0 ; nB < GetBlockCount() ; ++ nB) {
|
||||
TRIA3DEXVECTOR vTria ;
|
||||
GetBlockTriangles( nB, vTria) ;
|
||||
if ( ! pStm->AddTriaFromZMap( vTria, VertGrid))
|
||||
return nullptr ;
|
||||
}
|
||||
|
||||
// sistemo la topologia
|
||||
if ( ! pStm->AdjustTopologyFromZMap())
|
||||
return nullptr ;
|
||||
|
||||
return ( Release( pStm)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
VolZmap::GetBlockCount( void) const
|
||||
@@ -920,25 +951,41 @@ VolZmap::UpdateTripleMapGraphics( void) const
|
||||
}
|
||||
}
|
||||
|
||||
// Calcolo i triangoli sui blocchi
|
||||
int nBlockUpdated = 0 ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( m_nNumBlock) ;
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
// Se il blocco deve essere processato
|
||||
if ( m_BlockToUpdate[i]) {
|
||||
// processo ...
|
||||
++ nBlockUpdated ;
|
||||
vRes[i] = async( launch::async, &VolZmap::ExtMarchingCubes, this, i, ref( vVoxContainerVec[i])) ;
|
||||
// Standard è multithread
|
||||
constexpr bool MULTITHREAD = true ;
|
||||
if ( MULTITHREAD) {
|
||||
|
||||
// Calcolo i triangoli sui blocchi
|
||||
int nBlockUpdated = 0 ;
|
||||
vector< future<bool>> vRes ;
|
||||
vRes.resize( m_nNumBlock) ;
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
// Se il blocco deve essere processato
|
||||
if ( m_BlockToUpdate[i]) {
|
||||
// processo ...
|
||||
++ nBlockUpdated ;
|
||||
vRes[i] = async( launch::async, &VolZmap::ExtMarchingCubes, this, i, ref( vVoxContainerVec[i])) ;
|
||||
}
|
||||
}
|
||||
bool bOk = true ;
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nBlockUpdated) {
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
if ( m_BlockToUpdate[i] && vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nTerminated ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOk = true ;
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nBlockUpdated) {
|
||||
else {
|
||||
// Calcolo i triangoli sui blocchi
|
||||
bool bOk = true ;
|
||||
for ( int i = 0 ; i < m_nNumBlock ; ++ i) {
|
||||
if ( m_BlockToUpdate[i] && vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) {
|
||||
bOk = vRes[i].get() && bOk ;
|
||||
++ nTerminated ;
|
||||
// Se il blocco deve essere processato
|
||||
if ( m_BlockToUpdate[i]) {
|
||||
// processo ...
|
||||
bOk = ExtMarchingCubes( i, vVoxContainerVec[i]) && bOk ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1142,7 +1189,7 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
}
|
||||
|
||||
// Controllo se il voxel ha una sola faccia che giace in un piano canonico e quindi ha gestione speciale
|
||||
if ( m_nShape != BOX) {
|
||||
if ( m_nShape != BOX && m_nShape != OFFSET) {
|
||||
// Faccia XY normale Z+
|
||||
if ( nIndex == 15) {
|
||||
int nTool ; double dPos ;
|
||||
@@ -1224,13 +1271,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceYZ[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs( nAdjVox3[nCount]) == 2) {
|
||||
@@ -1240,13 +1289,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceXZ[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs( nAdjVox3[nCount]) == 3) {
|
||||
@@ -1256,13 +1307,15 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
bDefTopology = true ;
|
||||
}
|
||||
if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
auto it = m_SliceXY[nSlBlockN].find( nSliceN) ;
|
||||
if ( it != m_SliceXY[nSlBlockN].end()) {
|
||||
bMatOnSlice = it->second ;
|
||||
bDefTopology = true ;
|
||||
}
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1327,27 +1380,33 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceYZ.emplace( nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceYZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs(nAdjVox3[nCount]) == 2) {
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceXZ.emplace( nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceXZ[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
else if ( abs(nAdjVox3[nCount]) == 3) {
|
||||
if ( nSlBlockN == nBlock)
|
||||
SliceXY.emplace(nSliceN, bMatOnSlice) ;
|
||||
else {
|
||||
m_SliceMutex.lock() ;
|
||||
while ( m_SliceFlag.test_and_set( memory_order_acquire))
|
||||
m_SliceFlag.wait( true, memory_order_relaxed) ;
|
||||
m_SliceXY[nSlBlockN].emplace( nSliceN, bMatOnSlice) ;
|
||||
m_SliceMutex.unlock() ;
|
||||
m_SliceFlag.clear( memory_order_release) ;
|
||||
m_SliceFlag.notify_one() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2806
File diff suppressed because it is too large
Load Diff
+2180
-432
File diff suppressed because it is too large
Load Diff
+277
-171
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