From cc7aa66904ec43b5696060348d2cc866ed6d59d2 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 13 May 2024 10:30:24 +0200 Subject: [PATCH] EgtGeomKernel : - spostata la funzione CalcRegionPolyLines. --- SfrCreate.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++- StmFromCurves.cpp | 139 ---------------------------------------------- 2 files changed, 136 insertions(+), 140 deletions(-) diff --git a/SfrCreate.cpp b/SfrCreate.cpp index e84ece2..5b3d5ee 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -590,4 +590,139 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId) vId.push_back( pCrv->GetTempProp()) ; } return ( ! vId.empty()) ; -} \ No newline at end of file +} + +//------------------------------------------------------------------------------- +bool +CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, + POLYLINEVECTOR& vPL, Vector3d& vtN) +{ + // se non ho curve, non faccio nulla + if ( int( vpCurve.size()) == 0) + return true ; + + // calcolo le polilinee che approssimano le curve + vPL.resize( vpCurve.size()) ; + for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) { + if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i])) + return false ; + } + + // ricavo versore normale + Plane3d plPlane ; double dArea ; + if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) + return false ; + vtN = plPlane.GetVersN() ; + + typedef std::pair INDAREA ; + std::vector m_vArea ; + // calcolo piano medio e area delle curve + m_vArea.reserve( vPL.size()) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + // calcolo piano medio e area + Plane3d plPlane ; + double dArea ; + if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea)) + return false ; + // verifico che le normali siano molto vicine + if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN)) + return false ; + // assegno il segno all'area secondo il verso della normale + if ( ( plPlane.GetVersN() * vtN) > 0) + m_vArea.emplace_back( i, dArea) ; + else + m_vArea.emplace_back( i, - dArea) ; + } + // ordino in senso decrescente sull'area + sort( m_vArea.begin(), m_vArea.end(), + []( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ; + + // dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive) + Frame3d frRef ; frRef.Set( ORIG, vtN) ; + if ( ! frRef.IsValid()) + return false ; + ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + vCrvCompo[i].Set( CreateCurveComposite()) ; + vCrvCompo[i]->FromPolyLine( vPL[i]) ; + vCrvCompo[i]->ToLoc( frRef) ; + } + + // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle + // successive i loop interni + INTMATRIX vnPLIndMat ; + + // vettore di indici per ordinare le PolyLine + INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ; + for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) + vPL_IndOrder[i] = m_vArea[i].first ; + + // aggiungo le diverse curve + bool bFirstCrv ; + Plane3d plExtLoop ; + double dAreaExtLoop = 0. ; + do { + bFirstCrv = true ; + for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) { + // recupero indice di percorso e verifico sia valido + int j = m_vArea[i].first ; + if ( j < 0) + continue ; + // lo inserisco come esterno... + if ( bFirstCrv) { + vnPLIndMat.push_back({ j}) ; + m_vArea[i].first = -1 ; + dAreaExtLoop = m_vArea[i].second ; + // inverto se necessario + if ( m_vArea[i].second < EPS_SMALL) { + vPL[j].Invert() ; + vCrvCompo[j]->Invert() ; + dAreaExtLoop *= -1 ; + } + bFirstCrv = false ; + } + // ... altrimenti verifico se il loop è interno o no + else { + // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo + // esterno a tutti i loop già inseriti nella riga attuale. + // verifica rispetto loop esterno + IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; + CRVCVECTOR ccClass ; + if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || + ! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) || + ccClass.empty() || ccClass[0].nClass != CRVC_IN) + continue ; + // verifica rispetto ai loop interni + bool bOk = true ; + for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) { + IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ; + CRVCVECTOR ccClass2 ; + if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 || + ! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) || + ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) { + bOk = false ; + break ; + } + } + if ( bOk) { + // inserisco nella matrice + vnPLIndMat.back().push_back( j) ; + m_vArea[i].first = -1 ; + // inverto se necessario + if ( m_vArea[i].second * dAreaExtLoop > 0.) { + vPL[j].Invert() ; + vCrvCompo[j]->Invert() ; + } + } + } + } + } while ( ! bFirstCrv) ; + + // ordino le PolyLine per area + POLYLINEVECTOR vPL_tmp ; + for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i) + vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ; + swap( vPL, vPL_tmp) ; + + return true ; +} diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 156dcca..edd57d9 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -31,10 +31,6 @@ using namespace std ; -//------------------------------------------------------------------------------- -static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, - POLYLINEVECTOR& vPL, Vector3d& vtN) ; - //------------------------------------------------------------------------------- ISurfTriMesh* GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol) @@ -1127,138 +1123,3 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do // restituisco la superficie return Release( pSTM) ; } - -//------------------------------------------------------------------------------- -bool -CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, - POLYLINEVECTOR& vPL, Vector3d& vtN) -{ - // se non ho curve, non faccio nulla - if ( int( vpCurve.size()) == 0) - return true ; - - // calcolo le polilinee che approssimano le curve - vPL.resize( vpCurve.size()) ; - for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) { - if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i])) - return false ; - } - - // ricavo versore normale - Plane3d plPlane ; double dArea ; - if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) - return false ; - vtN = plPlane.GetVersN() ; - - typedef std::pair INDAREA ; - std::vector m_vArea ; - // calcolo piano medio e area delle curve - m_vArea.reserve( vPL.size()) ; - for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { - // calcolo piano medio e area - Plane3d plPlane ; - double dArea ; - if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea)) - return false ; - // verifico che le normali siano molto vicine - if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN)) - return false ; - // assegno il segno all'area secondo il verso della normale - if ( ( plPlane.GetVersN() * vtN) > 0) - m_vArea.emplace_back( i, dArea) ; - else - m_vArea.emplace_back( i, - dArea) ; - } - // ordino in senso decrescente sull'area - sort( m_vArea.begin(), m_vArea.end(), - []( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ; - - // dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive) - Frame3d frRef ; frRef.Set( ORIG, vtN) ; - if ( ! frRef.IsValid()) - return false ; - ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ; - for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { - vCrvCompo[i].Set( CreateCurveComposite()) ; - vCrvCompo[i]->FromPolyLine( vPL[i]) ; - vCrvCompo[i]->ToLoc( frRef) ; - } - - // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle - // successive i loop interni - INTMATRIX vnPLIndMat ; - - // vettore di indici per ordinare le PolyLine - INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ; - for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) - vPL_IndOrder[i] = m_vArea[i].first ; - - // aggiungo le diverse curve - bool bFirstCrv ; - Plane3d plExtLoop ; - double dAreaExtLoop = 0. ; - do { - bFirstCrv = true ; - for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) { - // recupero indice di percorso e verifico sia valido - int j = m_vArea[i].first ; - if ( j < 0) - continue ; - // lo inserisco come esterno... - if ( bFirstCrv) { - vnPLIndMat.push_back({ j}) ; - m_vArea[i].first = -1 ; - dAreaExtLoop = m_vArea[i].second ; - // inverto se necessario - if ( m_vArea[i].second < EPS_SMALL) { - vPL[j].Invert() ; - vCrvCompo[j]->Invert() ; - dAreaExtLoop *= -1 ; - } - bFirstCrv = false ; - } - // ... altrimenti verifico se il loop è interno o no - else { - // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo - // esterno a tutti i loop già inseriti nella riga attuale. - // verifica rispetto loop esterno - IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; - CRVCVECTOR ccClass ; - if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || - ! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) || - ccClass.empty() || ccClass[0].nClass != CRVC_IN) - continue ; - // verifica rispetto ai loop interni - bool bOk = true ; - for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) { - IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ; - CRVCVECTOR ccClass2 ; - if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 || - ! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) || - ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) { - bOk = false ; - break ; - } - } - if ( bOk) { - // inserisco nella matrice - vnPLIndMat.back().push_back( j) ; - m_vArea[i].first = -1 ; - // inverto se necessario - if ( m_vArea[i].second * dAreaExtLoop > 0.) { - vPL[j].Invert() ; - vCrvCompo[j]->Invert() ; - } - } - } - } - } while ( ! bFirstCrv) ; - - // ordino le PolyLine per area - POLYLINEVECTOR vPL_tmp ; - for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i) - vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ; - swap( vPL, vPL_tmp) ; - - return true ; -}