diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 46e6c7d..695a16a 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -26,11 +26,13 @@ #include "/EgtDev/Include/EgkIntersLineTria.h" #include "/EgtDev/Include/EgkIntersLineBox.h" #include "/EgtDev/Include/EgkIntersPlanePlane.h" +#include "/EgtDev/Include/EgkIntersLinePlane.h" #include "/EgtDev/Include/EgkIntersTriaTria.h" #include "/EgtDev/Include/EgkSfrCreate.h" #include "/EgtDev/Include/EGkChainCurves.h" #include "/EgtDev/Include/EGkGeoCollection.h" #include "/EgtDev/Include/EGkPolygon3d.h" +#include "/EgtDev/Include/EGkIntersPlaneTria.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EgnStringUtils.h" #include @@ -45,6 +47,9 @@ static int IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3d& vtL2, const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg) { +#define bUseTria false + +#if bUseTria // Definisco i due triangoli formanti il rettangolo Triangle3d trTriaA ; trTriaA.Set( ptP, ptP + vtL1, ptP + vtL2) ; @@ -122,13 +127,81 @@ IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3 } else return 0 ; +#else + + // Definisco il piano; se non definibile, segnalo un errore. + Plane3d plRectanglePlane ; + if ( ! plRectanglePlane.Set( ptP, vtL1 ^ vtL2)) + return - 1 ; + // Interseco il triangolo con il piano: passo gli estremi del segmento al + // contrario per rispettare la regola che i loop hanno l'esterno a destra. + int nPlaneTriaIntersRes = IntersPlaneTria( plRectanglePlane, trTria, ptEnSeg, ptStSeg) ; + // Non trovo intersezione fra triangolo e piano; ho finito. + if ( nPlaneTriaIntersRes != IntPlaneTriaType::IPTT_YES) + return 0 ; + // Limito la linea col rettangolo. + Vector3d vtSegDir = ptEnSeg - ptStSeg ; + double dSegLen = vtSegDir.Len() ; + vtSegDir /= dSegLen ; + // Limito con un piano ortogonale al rettangolo. + Point3d ptLinePlaneInfInt ; + Plane3d plTrimPlaneInf ; + if ( vtSegDir * vtL1 > 0.) + plTrimPlaneInf.Set( ptP, - vtL1) ; + else + plTrimPlaneInf.Set( ptP + vtL1, vtL1) ; + int nLinePlaneInfInters = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrimPlaneInf, ptLinePlaneInfInt, false) ; + // Limito con l'altro piano ortogonale al rettangolo. + Point3d ptLinePlaneSupInt ; + Plane3d plTrimPlaneSup ; + if ( vtSegDir * vtL1 > 0.) + plTrimPlaneSup.Set( ptP + vtL1, vtL1) ; + else + plTrimPlaneSup.Set( ptP, - vtL1) ; + int nLinePlaneSupInters = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrimPlaneSup, ptLinePlaneSupInt, false) ; + // + double dTol = EPS_SMALL/*EPS_ZERO*/ ; + if ( ( nLinePlaneInfInters == ILPT_NO && nLinePlaneSupInters == ILPT_INPLANE) || + ( nLinePlaneSupInters == ILPT_NO && nLinePlaneInfInters == ILPT_INPLANE) || + ( nLinePlaneInfInters == ILPT_NO && nLinePlaneSupInters == ILPT_NO && + ( ptEnSeg - plTrimPlaneInf.GetPoint()) * plTrimPlaneInf.GetVersN() < 0. && + ( ptEnSeg - plTrimPlaneSup.GetPoint()) * plTrimPlaneSup.GetVersN() < 0.)) { + if ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol)) + return 1 ; + return 2 ; + } + // + double dInfU = ( ptLinePlaneInfInt - ptStSeg) * vtSegDir ; + double dSupU = ( ptLinePlaneSupInt - ptStSeg) * vtSegDir ; + if ( dInfU > dSegLen) { + return 0 ; + } + else if ( dInfU > 0.) { + ptStSeg += dInfU * vtSegDir ; + dSegLen -= dInfU ; + dSupU -= dInfU ; + } + if ( dSupU < 0.) + return 0 ; + else if ( dSupU < dSegLen) { + dSegLen = dSupU ; + ptEnSeg = ptStSeg + dSegLen * vtSegDir ; + } + + if ( dSegLen > dTol) { + return 2 ; + } + else + return 1 ; + +#endif } //---------------------------------------------------------------------------- static bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) { - // Se la catena da aggiungere è vuota, non devo fare alcunchè + // Se la catena da aggiungere è vuota, non devo fare alcunché. if ( ChainToAdd.size() == 0) return true ; // Se la catena originale è vuota, non è possibile aggiungere nulla @@ -294,15 +367,16 @@ SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PN if ( bLast) ++ nMinSeg ; // Inglobo fino a nSeg nel primo loop - for ( int nPt = 0 ; nPt <= nMinSeg ; ++ nPt) - Loop1.emplace_back( Loop[nPt]) ; + for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt) + Loop1.emplace_back( Loop[nPt]) ; // Se il punto è interno al segmento, lo inglobo in entrambi i loop if ( ! ( bFirst || bLast)) { Loop1.emplace_back( ptStop) ; Loop2.emplace_back( ptStop) ; } else { - Loop2.emplace_back( Loop[nMinSeg]) ; + if ( nMinSeg != int( Loop.size()) ) + Loop2.emplace_back( Loop[nMinSeg]) ; } // Inglobo gli ultimi vertici in Loop2 for ( int nPt = nMinSeg + 1 ; nPt < int( Loop.size()) ; ++ nPt) @@ -439,13 +513,40 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) } pCrv = cvCompo.GetNextCurve() ; } + + for ( auto itI = vChain.begin() ; itI != vChain.end() ; ) { + bool bErased = false ; + auto itJ = itI ; + ++ itJ ; + for ( ; itJ != vChain.end() && ! bErased ; ) { + if ( int( itI->size()) == 1 && int( itJ->size()) == 1 && + AreSamePointEpsilon( itI->back().ptSt, itJ->back().ptEn, 2 * EPS_SMALL) && + AreSamePointEpsilon( itI->back().ptEn, itJ->back().ptSt, 2 * EPS_SMALL)) { + itJ = vChain.erase( itJ) ; + bErased = true ; + } + else + ++ itJ ; + } + if ( bErased) { + itI = vChain.erase( itI) ; + bErased = false ; + } + else + ++ itI ; + } + + nChainCnt = int( vChain.size()) ; if ( nChainCnt == 0 && nVertOutside > 0) { nVertInside = 0 ; vChain.clear() ; nChainCnt = 0 ; } + // unisco eventuali catene estreme che sono parte di una stessa catena if ( nChainCnt > 1) { + /*double dDist1 = sqrt( SqDist(vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)); + double dDist2 = sqrt( SqDist(vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt));*/ if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) { vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ; vChain.pop_back() ; @@ -484,7 +585,16 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) CHAINVECTOR cvOpenChain ; for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) { int nCurLoopLast = max( int(vChain[nL].size()) - 1, 0) ; - if ( AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn)) + if (nCurLoopLast <= 1) { + static int nTimeCount = 0; + ++nTimeCount; + if (nTimeCount == 211) + int Stop = 0; + string sOut = "nTimeCount = " + ToString( nTimeCount) ; + LOG_ERROR( GetEGkLogger(), sOut.c_str()) + + } + if ( AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn) && nCurLoopLast > 1) cvClosedChain.emplace_back( vChain[nL]) ; else { cvOpenChain.emplace_back( vChain[nL]) ;