//---------------------------------------------------------------------------- // EgalTech 2017-2022 //---------------------------------------------------------------------------- // File : RemoveCurveDefects.cpp Data : 28.11.22 Versione : 2.4k6 // Contenuto : Implementazione rimozione spikes di curva. // // // // Modifiche : 02.10.17 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "GeoConst.h" #include "CurveComposite.h" #include "RemoveCurveDefects.h" #include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include using namespace std ; //---------------------------------------------------------------------------- bool RemoveCurveSpikes( ICurveComposite* pCurve, double dLinTol) { // verifico validità curva if ( pCurve == nullptr) return false ; // verifico e sistemo tolleranza lineare dLinTol = max( dLinTol, EPS_SMALL) ; // recupero il numero di curve semplici componenti la composta int nCrvCount = pCurve->GetCurveCount() ; if ( nCrvCount < 2 || ( nCrvCount < 3 && pCurve->IsClosed())) return true ; // ciclo sulle curve elementari della composita int nStart = pCurve->IsClosed() ? 0 : 1 ; for ( int i = nStart ; i < nCrvCount ; ++ i) { // recupero due curve consecutive const ICurve* pPrevCrv = pCurve->GetCurve( ( i > 0 ? i - 1 : nCrvCount - 1)) ; const ICurve* pNextCrv = pCurve->GetCurve( i) ; // se sono entrambe rette if ( pPrevCrv->GetType() == CRV_LINE && pNextCrv->GetType() == CRV_LINE) { // recupero i punti estremi Point3d ptStart ; pPrevCrv->GetStartPoint( ptStart) ; Point3d ptMid ; pPrevCrv->GetEndPoint( ptMid) ; Point3d ptEnd ; pNextCrv->GetEndPoint( ptEnd) ; // recupero le direzioni negli estremi Vector3d vtPrev ; pPrevCrv->GetStartDir( vtPrev) ; Vector3d vtNext ; pNextCrv->GetStartDir( vtNext) ; // verifico se spike double dPrevDist, dNextDist ; if ( vtPrev * vtNext < cos( 175 * DEGTORAD) && (( DistPointLine( ptStart, ptMid, ptEnd).GetDist( dPrevDist) && dPrevDist < dLinTol) || ( DistPointLine( ptEnd, ptStart, ptMid).GetDist( dNextDist) && dNextDist < dLinTol))) { // se spike ha base abbastanza larga, basta togliere uno dei due lati if ( SqDist( ptStart, ptEnd) > SQ_EPS_SMALL) { pCurve->RemoveJoint( i) ; -- nCrvCount ; -- i ; } // altrimenti bisogna togliere entrambi else { pCurve->RemoveJoint( i - 1) ; pCurve->RemoveJoint( i) ; nCrvCount -= 2 ; i = max( i - 2, nStart - 1) ; } } } // !!! Aggiungere la gestione degli altri tipi di curve !!! } return true ; } //---------------------------------------------------------------------------- bool RemoveCurveSmallZs( ICurveComposite* pCurve, double dLinTol) { // verifico validità curva if ( pCurve == nullptr) return false ; // verifico e sistemo tolleranza lineare dLinTol = max( dLinTol, EPS_SMALL) ; // recupero il numero di curve semplici componenti la composta int nCrvCount = pCurve->GetCurveCount() ; if ( nCrvCount < 2 || ( nCrvCount < 3 && pCurve->IsClosed())) return true ; // ciclo sulle curve elementari della composita int nStart = pCurve->IsClosed() ? 0 : 1 ; int nEnd = pCurve->IsClosed() ? nCrvCount : nCrvCount - 1 ; for ( int i = nStart ; i < nEnd ; ++ i) { // recupero tre curve consecutive const ICurve* pPrevCrv = pCurve->GetCurve( ( i > 0 ? i - 1 : nCrvCount - 1)) ; const ICurve* pCurrCrv = pCurve->GetCurve( i) ; const ICurve* pNextCrv = pCurve->GetCurve( ( i < nCrvCount - 1 ? i + 1 : 0)) ; // se la curva corrente è una retta if ( pCurrCrv->GetType() == CRV_LINE) { // recupero tre punti notevoli della curva Point3d ptStart ; pCurrCrv->GetStartPoint( ptStart) ; Point3d ptMid ; pCurrCrv->GetMidPoint( ptMid) ; Point3d ptEnd ; pCurrCrv->GetEndPoint( ptEnd) ; // recupero le direzioni negli estremi Vector3d vtPrev ; pPrevCrv->GetEndDir( vtPrev) ; Vector3d vtNext ; pNextCrv->GetStartDir( vtNext) ; // verifico se Small Z double dDistS, dDistM1, dDistM2, dDistE ; if ( vtPrev * vtNext > cos( 30 * DEGTORAD) && (( DistPointCurve( ptStart, *pNextCrv).GetDist( dDistS) && dDistS < dLinTol) && ( DistPointCurve( ptMid, *pNextCrv).GetDist( dDistM1) && dDistM1 < dLinTol) && ( DistPointCurve( ptMid, *pPrevCrv).GetDist( dDistM2) && dDistM2 < dLinTol) && ( DistPointCurve( ptEnd, *pPrevCrv).GetDist( dDistE) && dDistE < dLinTol))) { // rimuovo il segmento if ( pCurve->RemoveJoint( i)) { -- nCrvCount ; -- nEnd ; -- i ; // porto il nuovo estremo sul punto medio pCurve->ModifyJoint( i + 1, ptMid) ; } // altrimenti devo rimuovere anche il successivo else if ( pCurve->RemoveJoint( i + 1) && pCurve->RemoveJoint( i)) { nCrvCount -= 2 ; nEnd -= 2 ; -- i ; // porto il nuovo estremo sul punto medio pCurve->ModifyJoint( i + 1, ptMid) ; } } } } return true ; } //---------------------------------------------------------------------------- bool RemoveCurveSmallParts( ICurveComposite* pCurve, double dLinTol) { // verifico validità curva if ( pCurve == nullptr) return false ; // verifico e sistemo tolleranza lineare dLinTol = max( dLinTol, EPS_SMALL) ; // recupero il numero di curve semplici componenti la composta int nCrvCount = pCurve->GetCurveCount() ; if ( nCrvCount < 2 || ( nCrvCount < 3 && pCurve->IsClosed())) return true ; // se aperta, verifico le due curve agli estremi if ( ! pCurve->IsClosed()) { // curva iniziale const ICurve* pFirstCrv = pCurve->GetFirstCurve() ; double dFirstLen ; pFirstCrv->GetLength( dFirstLen) ; if ( dFirstLen < dLinTol) { Point3d ptStart ; pFirstCrv->GetStartPoint( ptStart) ; delete( pCurve->RemoveFirstOrLastCurve( false)) ; pCurve->ModifyStart( ptStart) ; -- nCrvCount ; } // curva finale const ICurve* pLastCrv = pCurve->GetLastCurve() ; double dLastLen ; pLastCrv->GetLength( dLastLen) ; if ( dLastLen < dLinTol) { Point3d ptEnd ; pLastCrv->GetStartPoint( ptEnd) ; delete( pCurve->RemoveFirstOrLastCurve( true)) ; pCurve->ModifyEnd( ptEnd) ; -- nCrvCount ; } } // ciclo sulle curve elementari della composita int nStart = pCurve->IsClosed() ? 0 : 1 ; int nEnd = pCurve->IsClosed() ? nCrvCount : nCrvCount - 1 ; for ( int i = nStart ; i < nEnd ; ++ i) { // recupero la curva corrente const ICurve* pCurrCrv = pCurve->GetCurve( i) ; // se la curva corrente è troppo corta double dLen ; pCurrCrv->GetLength( dLen) ; if ( dLen < dLinTol) { // recupero il punto medio della curva Point3d ptMid ; pCurrCrv->GetMidPoint( ptMid) ; // rimuovo il segmento if ( pCurve->RemoveJoint( i)) { // porto il nuovo estremo sul punto medio pCurve->ModifyJoint( i, ptMid) ; // aggiorno valore di i tenendo conto che ModifyJoint potrebbe modificare la curva precedente // che quindi va ricontrollata i = max( i - 2, nStart - 1) ; // aggiorno valore di nEnd ( ModifyJoint potrebbe aver rimosso la curva precedente e la successiva) nEnd = pCurve->GetCurveCount() - ( pCurve->IsClosed() ? 0 : 1) ; } // altrimenti rimuovo anche il successivo else if ( pCurve->RemoveJoint( i + 1)) { pCurve->RemoveJoint( i) ; pCurve->ModifyJoint( i, ptMid) ; i = max( i - 2, nStart - 1) ; nEnd = pCurve->GetCurveCount() - ( pCurve->IsClosed() ? 0 : 1) ; } } } return true ; }