diff --git a/BiArcs.cpp b/BiArcs.cpp index 573162e..ab1e60b 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -73,7 +73,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir } // se il biarco non esiste - if ( pBiArc->GetCurveNumber() == 0) + if ( pBiArc->GetCurveCount() == 0) return nullptr ; return ::Release( pBiArc) ; diff --git a/CurveArc.h b/CurveArc.h index 08a86e7..68424d1 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -100,6 +100,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW { return ::GetNearestExtremityToPoint( ptP, *this, bStart) ; } virtual bool GetAreaXY( double& dArea) const { return CurveGetAreaXY( *this, dArea) ; } + virtual bool GetArea( Plane3d& plPlane, double& dArea) const + { return CurveGetArea( *this, plPlane, dArea) ; } virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const ; virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ; virtual bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const diff --git a/CurveAux.cpp b/CurveAux.cpp index 3738070..02080c2 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -259,6 +259,33 @@ GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGe return true ; } +//---------------------------------------------------------------------------- +bool +ImproveCurveParamAtPoint( double& dU, const Point3d& ptP, const ICurve* pCrv) +{ + // Da usare quando il parametro è già molto vicino a quello esatto + + // calcolo il punto della curva in corrispondenza al parametro + Point3d ptQ ; + Vector3d vtD ; + if ( ! pCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptQ, &vtD)) + return false ; + // se sono uguali, è già tutto ok + if ( AreSamePointExact( ptP, ptQ)) + return true ; + // se derivata nulla, non posso migliorare + if ( vtD.IsZero()) + return false ; + // incremento parametro su linea tangente (uso la derivata) + double dDeltaU = ( ptP - ptQ) * vtD / vtD.SqLen() ; + // se migliorato, tengo nuovo valore + Point3d ptR ; + if ( pCrv->GetPointD1D2( dU + dDeltaU, ICurve::FROM_MINUS, ptR) && + ( ptP - ptR).SqLen() < ( ptP - ptQ).SqLen()) + dU += dDeltaU ; + return true ; +} + //---------------------------------------------------------------------------- bool CurveGetAreaXY( const ICurve& crvC, double& dArea) @@ -278,6 +305,29 @@ CurveGetAreaXY( const ICurve& crvC, double& dArea) return true ; } +//---------------------------------------------------------------------------- +bool +CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) +{ + // verifico sia chiusa + if ( ! crvC.IsClosed()) + return false ; + // approssimo la curva con una polilinea + PolyLine PL ; + crvC.ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) ; + // calcolo l'area + Plane3d plMyPlane ; + double dMyArea = 0 ; + if ( ! PL.IsClosedAndFlat( plMyPlane, dMyArea, 50 * EPS_SMALL)) + return false ; + // restituisco i valori + if ( &plPlane != nullptr) + plPlane = plMyPlane ; + if ( &dArea != nullptr) + dArea = dMyArea ; + return true ; +} + //---------------------------------------------------------------------------- bool CurveDump( const ICurve& crvC, string& sOut, bool bMM, const char* szNewLine) @@ -646,4 +696,42 @@ NurbsToBezierCurve( const CNurbsData& cnData) // restituisco la curva composita return Release( pCrvCompo) ; +} + +//---------------------------------------------------------------------------- +ICurve* +ProjectCurveOnPlane( const ICurve& crCrv, const Plane3d& plPlane) +{ + // determino se curva piana e suo eventuale piano + Plane3d plCrv ; + if ( crCrv.IsFlat( plCrv)) { + // se il piano della curva è parallelo a quello di proiezione + if ( AreSameOrOppositeVectorApprox( plCrv.vtN, plPlane.vtN)) { + // copio la curva + PtrOwner pCrv( crCrv.Clone()) ; + if ( IsNull( pCrv)) + return nullptr ; + // se non coincidenti, basta eseguire una traslazione + Point3d ptOC = ORIG + plCrv.dDist * plCrv.vtN ; + Point3d ptOP = ORIG + plPlane.dDist * plPlane.vtN ; + if ( ! AreSamePointApprox( ptOC, ptOP)) + pCrv->Translate( ptOP - ptOC) ; + // restituisco la nuova curva + return Release( pCrv) ; + } + } + + // mi assicuro che la curva non contenga archi + PtrOwner pCrv( CurveToNoArcsCurve( &crCrv)) ; + if ( IsNull( pCrv)) + return nullptr ; + // calcolo un riferimento con piano XY coincidente con il piano di proiezione + Frame3d frRef ; + if ( ! frRef.Set( ORIG + plPlane.dDist * plPlane.vtN, plPlane.vtN)) + return nullptr ; + // eseguo scalatura con fattori X e Y unitari e fattore Z nullo + if ( ! pCrv->Scale( frRef, 1, 1, 0)) + return nullptr ; + // restituisco la nuova curva + return Release( pCrv) ; } \ No newline at end of file diff --git a/CurveAux.h b/CurveAux.h index 72087cb..069e4b7 100644 --- a/CurveAux.h +++ b/CurveAux.h @@ -25,7 +25,9 @@ bool MoveParamToAvoidTg( double& dU, ICurve::Side nSide, const ICurve& Curve) ; bool GetTang( const ICurve& crvC, double dU, ICurve::Side nS, Vector3d& vtTang) ; bool GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Vector3d& vtTang) ; bool GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGeom& oDiffG) ; +bool ImproveCurveParamAtPoint( double& dU, const Point3d& ptP, const ICurve* pCrv) ; bool CurveGetAreaXY( const ICurve& crvC, double& dArea) ; +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) ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 88a94ce..e915ddb 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -60,7 +60,6 @@ CurveBezier::~CurveBezier( void) bool CurveBezier::Init( int nDeg, bool bIsRational) { - // verifico validità grado if ( nDeg < 1 || nDeg > MAXDEG) return false ; diff --git a/CurveBezier.h b/CurveBezier.h index 24f599a..7b89850 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -101,6 +101,8 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW { return ::GetNearestExtremityToPoint( ptP, *this, bStart) ; } virtual bool GetAreaXY( double& dArea) const { return CurveGetAreaXY( *this, dArea) ; } + virtual bool GetArea( Plane3d& plPlane, double& dArea) const + { return CurveGetArea( *this, plPlane, dArea) ; } virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const ; virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ; virtual bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const diff --git a/CurveByApprox.cpp b/CurveByApprox.cpp index b782b16..4ad1b57 100644 --- a/CurveByApprox.cpp +++ b/CurveByApprox.cpp @@ -82,6 +82,10 @@ CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, double dLinFea, PolyA // pulisco il poliarco PA.Clear() ; + // calcolo una parametrizzazione + if ( ! CalcParameterization()) + return false ; + // calcolo le tangenti if ( ! CalcAkimaTangents( true)) return false ; @@ -109,12 +113,10 @@ CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, double dLinFea, PolyA //---------------------------------------------------------------------------- bool -CurveByApprox::CalcAkimaTangents( bool bDetectCorner) +CurveByApprox::CalcParameterization( void) { - // pulisco i vettori dei parametri e delle tangenti + // pulisco il vettore dei parametri m_vPar.clear() ; - m_vPrevDer.clear() ; - m_vNextDer.clear() ; // numero di punti int nSize = int( m_vPnt.size()) ; @@ -133,6 +135,24 @@ CurveByApprox::CalcAkimaTangents( bool bDetectCorner) m_vPar.push_back( dPar) ; } + return true ; +} + +//---------------------------------------------------------------------------- +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) ; @@ -254,8 +274,7 @@ CurveByApprox::CalcAkimaTangents( bool bDetectCorner) bool CurveByApprox::CalcBesselTangents( void) { - // pulisco i vettori dei parametri e delle tangenti - m_vPar.clear() ; + // pulisco i vettori delle tangenti m_vPrevDer.clear() ; m_vNextDer.clear() ; @@ -266,16 +285,6 @@ CurveByApprox::CalcBesselTangents( void) 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) ; @@ -349,24 +358,33 @@ CurveByApprox::CalcSplitPoints( double dLinTol, double dAngTolDeg, double dLinFe // precalcolo funzioni dei limiti double dSqLinTol = dLinTol * dLinTol ; double dAngTolCos = cos( max( dAngTolDeg, 0.) * DEGTORAD) ; + double d2AngTolCos = cos( max( 2 * dAngTolDeg, 0.) * DEGTORAD) ; double dSqLinFea = dLinFea * dLinFea ; // cerco punti angolosi e punti di separazione di tratti lineari e non // verifico i punti tranne primo e ultimo int nSize = int( m_vPnt.size()) ; for ( int i = 1 ; i < nSize - 1 ; ++ i) { - // se angolo, allora punto di divisione + // se stimato angolo, allora punto di divisione if ( ( m_vPrevDer[i] * m_vNextDer[i]) < dAngTolCos) { m_vSplits.push_back(i) ; continue ; } - // verifico linearità del tratto precedente + // dati sui segmenti precedente e successivo Vector3d vtPrev = m_vPnt[i] - m_vPnt[i-1] ; + double dLenPrev = m_vPar[i] - m_vPar[i-1] ; + Vector3d vtNext = m_vPnt[i+1] - m_vPnt[i] ; + double dLenNext = m_vPar[i+1] - m_vPar[i] ; + // se i segmenti formano un angolo maggiore del doppio ammesso, allora punto di divisione + if ( ( vtPrev * vtNext) / ( dLenPrev * dLenNext) < d2AngTolCos) { + m_vSplits.push_back(i) ; + continue ; + } + // verifico linearità del tratto precedente bool bPrevLin = vtPrev.SqLen() > dSqLinFea && ( m_vNextDer[i-1] * m_vPrevDer[i]) > dAngTolCos && ( vtPrev ^ m_vNextDer[i-1]).SqLen() < dSqLinTol && ( vtPrev ^ m_vPrevDer[i]).SqLen() < dSqLinTol ; // verifico linearità del tratto successivo - Vector3d vtNext = m_vPnt[i+1] - m_vPnt[i] ; bool bNextLin = vtNext.SqLen() > dSqLinFea && ( m_vNextDer[i] * m_vPrevDer[i+1]) > dAngTolCos && ( vtNext ^ m_vNextDer[i]).SqLen() < dSqLinTol && diff --git a/CurveComposite.h b/CurveComposite.h index 870af0c..9782b42 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -96,6 +96,8 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW { return ::GetNearestExtremityToPoint( ptP, *this, bStart) ; } virtual bool GetAreaXY( double& dArea) const { return CurveGetAreaXY( *this, dArea) ; } + virtual bool GetArea( Plane3d& plPlane, double& dArea) const + { return CurveGetArea( *this, plPlane, dArea) ; } virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const ; virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ; virtual bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const ; @@ -128,7 +130,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW virtual bool PolygonCenterCorner( int nSides, const Point3d& ptCen, const Point3d& ptCorner, const Vector3d& vtN) ; virtual bool PolygonCenterMidSide( int nSides, const Point3d& ptCen, const Point3d& ptMidSide, const Vector3d& vtN) ; virtual bool PolygonSide( int nSides, const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtN) ; - virtual int GetCurveNumber( void) const + virtual int GetCurveCount( void) const { return int( m_CrvSmplS.size()) ; } virtual const ICurve* GetCurve( int nCrv) const ; virtual const ICurve* GetFirstCurve( void) const ; diff --git a/CurveCompositeOffset.cpp b/CurveCompositeOffset.cpp index 9bf06e5..4e0c3e0 100644 --- a/CurveCompositeOffset.cpp +++ b/CurveCompositeOffset.cpp @@ -104,7 +104,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) if ( VerifyAndAdjustSamePoint( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustInternalAngle( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustExternalAngle( pCrv1, pCrv2, dDist, nType, ccTemp)) { - if ( ccTemp.GetCurveNumber() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp)) + if ( ccTemp.GetCurveCount() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp)) return false ; } // nessun caso è andato a buon fine, errore @@ -120,7 +120,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) } // se originale chiuso, devo confrontare anche ultima e prima curva - if ( bClosed && ccOffs.GetCurveNumber() > 0) { + if ( bClosed && ccOffs.GetCurveCount() > 0) { // la curva successiva ora è la prima dell'offset ICurve* pCrv2 = ccOffs.m_CrvSmplS.front() ; // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie @@ -128,7 +128,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) if ( VerifyAndAdjustSamePoint( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustInternalAngle( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustExternalAngle( pCrv1, pCrv2, dDist, nType, ccTemp)) { - if ( ccTemp.GetCurveNumber() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp)) + if ( ccTemp.GetCurveCount() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp)) return false ; } // nessun caso è andato a buon fine, errore @@ -137,7 +137,7 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) } // se originale aperto, devo rimettere eventuali lineee verticali iniziale e finale - if ( ! bClosed && ccOffs.GetCurveNumber() > 0 && + if ( ! bClosed && ccOffs.GetCurveCount() > 0 && ! AddFirstLastVerticalLines( ccOffs, dLenVertFirst, dLenVertLast)) return false ; diff --git a/CurveLine.h b/CurveLine.h index 4632f1b..4d8da80 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -101,6 +101,8 @@ class CurveLine : public ICurveLine, public IGeoObjRW { return ::GetNearestExtremityToPoint( ptP, *this, bStart) ; } virtual bool GetAreaXY( double& dArea) const { return false ; } + virtual bool GetArea( Plane3d& plPlane, double& dArea) const + { return false ; } virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const ; virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ; virtual bool ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) const diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 3f251a9..7cf5b92 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 5094aea..d0e1317 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -321,6 +321,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -400,9 +401,11 @@ copy $(TargetPath) \EgtProg\Dll64 + + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index b4ecf4f..27fe0a9 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -303,6 +303,9 @@ File di origine\Geo + + File di origine\GeoCreate + @@ -695,6 +698,12 @@ File di intestazione + + File di intestazione\Include + + + File di intestazione\Include + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 0a98d85..22c3265 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -5008,7 +5008,7 @@ GdbExecutor::CurveCopyBySplitClass( const STRVECTOR& vsParams) return false ; // verifico anche che non si autointersechi con attraversamento SelfIntersCurve sintC( *pCloCrv) ; - if ( sintC.GetNumCrossInters() > 0) + if ( sintC.GetCrossIntersCount() > 0) return false ; // recupero i riferimenti in cui sono immerse Frame3d frCrv ; @@ -5156,10 +5156,10 @@ GdbExecutor::CurveCopyByChain( const STRVECTOR& vsParams) return false ; } // aggiorno il nuovo punto vicino - if ( pCrvCompo->GetCurveNumber() > 0) + if ( pCrvCompo->GetCurveCount() > 0) pCrvCompo->GetEndPoint( ptNearStart) ; // inserisco la curva composita nel gruppo destinazione - if ( pCrvCompo->GetCurveNumber() > 0) { + if ( pCrvCompo->GetCurveCount() > 0) { if ( m_pGDB->AddGeoObj( GDB_ID_NULL, nIdDest, ::Release( pCrvCompo)) == GDB_ID_NULL) return false ; } diff --git a/GdbObj.cpp b/GdbObj.cpp index 8743760..87954d3 100644 --- a/GdbObj.cpp +++ b/GdbObj.cpp @@ -653,6 +653,10 @@ GdbObj::SetMaterial( int nMat) if ( nMat < GDB_MT_PARENT) return false ; + // se materiale da padre e non ci sono attributi è già così + if ( nMat == GDB_MT_PARENT && GetAttribs() == nullptr) + return true ; + // verifico esistenza (con eventuale creazione) degli attributi if ( GetSafeAttribs() == nullptr) return false ; diff --git a/GeomDB.cpp b/GeomDB.cpp index 9a32766..68094f1 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -2061,6 +2061,59 @@ GeomDB::GetCalcMark( int nId, int& nMark) const return pGdbObj->GetCalcMark( nMark) ; } +//---------------------------------------------------------------------------- +bool +GeomDB::CopyMaterial( int nIdSou, int nIdDest) +{ + // verifico esistenza del sorgente + GdbObj* pGdOSou = GetGdbObj( nIdSou) ; + if ( pGdOSou == nullptr) + return false ; + // verifico esistenza della destinazione + GdbObj* pGdODest = GetGdbObj( nIdDest) ; + if ( pGdODest == nullptr) + return false ; + // recupero l'indice del materiale + int nMat ; + if ( ! pGdOSou->GetMaterial( nMat)) + nMat = GDB_MT_PARENT ; + // impostazione + switch ( nMat) { + case GDB_MT_COLOR : + { + Color cCol ; + if ( ! pGdOSou->GetMaterial( cCol)) + GetDefaultMaterial( cCol) ; + pGdODest->SetMaterial( cCol) ; + } + break ; + case GDB_MT_PARENT : + // hanno lo stesso padre + if ( pGdOSou->GetParentId() == pGdODest->GetParentId()) + pGdODest->SetMaterial( nMat) ; + // altrimenti hanno padre diverso + else { + // recupero indice calcolato + pGdOSou->GetCalcMaterial( nMat) ; + // se diverso da colore, lo posso assegnare direttamente + if ( nMat != GDB_MT_COLOR) + pGdODest->SetMaterial( nMat) ; + // altrimenti devo calcolare il colore e assegnarlo + else { + Color cCol ; + if ( ! pGdOSou->GetCalcMaterial( cCol)) + GetDefaultMaterial( cCol) ; + pGdODest->SetMaterial( cCol) ; + } + } + break ; + default : + pGdODest->SetMaterial( nMat) ; + break ; + } + return true ; +} + //---------------------------------------------------------------------------- bool GeomDB::SetDefaultMaterial( Color cCol) diff --git a/GeomDB.h b/GeomDB.h index 024433a..03e6596 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -138,6 +138,7 @@ class GeomDB : public IGeomDB virtual bool ResetMark( int nId) ; virtual bool GetMark( int nId, int& nMark) const ; virtual bool GetCalcMark( int nId, int& nMark) const ; + virtual bool CopyMaterial( int nIdSou, int nIdDest) ; virtual bool SetDefaultMaterial( Color cCol) ; virtual bool GetDefaultMaterial( Color& cCol) const ; virtual bool SetMaterial( int nId, int nMat) ; diff --git a/IntersCrvCompoCrvCompo.cpp b/IntersCrvCompoCrvCompo.cpp index 00c01bc..8d14b8a 100644 --- a/IntersCrvCompoCrvCompo.cpp +++ b/IntersCrvCompoCrvCompo.cpp @@ -60,8 +60,8 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, // creo HashGrids2d per curva con maggior numero di elementi const int LIM_CRVNBRSQUARED = 4095 ; - int nCrvNbrA = CCompoA.GetCurveNumber() ; - int nCrvNbrB = CCompoB.GetCurveNumber() ; + int nCrvNbrA = CCompoA.GetCurveCount() ; + int nCrvNbrB = CCompoB.GetCurveCount() ; if ( nCrvNbrA >= nCrvNbrB) { HashGrids2d HHGrids ; HHGrids.SetActivationGrid( nCrvNbrA * nCrvNbrB > LIM_CRVNBRSQUARED) ; diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index da05cfa..af83743 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2014 +// EgalTech 2015-2015 //---------------------------------------------------------------------------- -// File : IntersCurveCurve.cpp Data : 20.06.14 Versione : 1.5f6 +// File : IntersCurveCurve.cpp Data : 17.08.15 Versione : 1.6h3 // Contenuto : Implementazione della classe intersezione curva/curva. // // // // Modifiche : 15.06.14 DS Creazione modulo. -// +// 17.08.15 DS Modifiche per curve approssimate. // //---------------------------------------------------------------------------- @@ -37,71 +37,78 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB, // inizializzazioni m_bOverlaps = false ; m_nNumInters = 0 ; - m_pOriCrv[0] = &CurveA ; - m_pOriCrv[1] = &CurveB ; + m_pCurve[0] = &CurveA ; + m_pCurve[1] = &CurveB ; + + // puntatori alle curve usate nei calcoli (originali o temporanee) + const ICurve* pCalcCrv[2] ; + // per eventuale esplosione temporanea delle curve + PtrOwner pTmpCrv[2] ; // ciclo sulle curve per verificare se da approssimare for ( int i = 0 ; i < 2 ; ++ i) { // se curva è arco da approssimare oppure è curva di Bezier - if ( ( m_pOriCrv[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pOriCrv[i])) || - m_pOriCrv[i]->GetType() == CRV_BEZ) { + if ( ( m_pCurve[i]->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve[i])) || + m_pCurve[i]->GetType() == CRV_BEZ) { // approssimo con rette PolyLine PL ; - if ( ! m_pOriCrv[i]->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) + if ( ! m_pCurve[i]->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) return ; - m_pTmpCrv[i].Set( CreateBasicCurveComposite()) ; - if ( IsNull( m_pTmpCrv[i])) + pTmpCrv[i].Set( CreateBasicCurveComposite()) ; + if ( IsNull( pTmpCrv[i])) return ; - if ( ! GetBasicCurveComposite( Get( m_pTmpCrv[i]))->FromPolyLine( PL)) + if ( ! GetBasicCurveComposite( Get( pTmpCrv[i]))->FromPolyLine( PL)) return ; - m_pCurve[i] = Get( m_pTmpCrv[i]) ; + pCalcCrv[i] = Get( pTmpCrv[i]) ; } else - m_pCurve[i] = m_pOriCrv[i] ; + pCalcCrv[i] = m_pCurve[i] ; } // chiamo calcolatore opportuno - switch ( m_pCurve[0]->GetType()) { + switch ( pCalcCrv[0]->GetType()) { case CRV_LINE : - switch ( m_pCurve[1]->GetType()) { + switch ( pCalcCrv[1]->GetType()) { case CRV_LINE : - LineLineCalculate( *m_pCurve[0], *m_pCurve[1], bAreSegments) ; + LineLineCalculate( *pCalcCrv[0], *pCalcCrv[1], bAreSegments) ; break ; case CRV_ARC : - LineArcCalculate( *m_pCurve[0], *m_pCurve[1]) ; + LineArcCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; case CRV_COMPO : - LineCrvCompoCalculate( *m_pCurve[0], *m_pCurve[1]) ; + LineCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; } break ; case CRV_ARC : - switch ( m_pCurve[1]->GetType()) { + switch ( pCalcCrv[1]->GetType()) { case CRV_LINE : - ArcLineCalculate( *m_pCurve[0], *m_pCurve[1]) ; + ArcLineCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; case CRV_ARC : - ArcArcCalculate( *m_pCurve[0], *m_pCurve[1]) ; + ArcArcCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; case CRV_COMPO : - ArcCrvCompoCalculate( *m_pCurve[0], *m_pCurve[1]) ; + ArcCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; } break ; case CRV_COMPO : - switch ( m_pCurve[1]->GetType()) { + switch ( pCalcCrv[1]->GetType()) { case CRV_LINE : - CrvCompoLineCalculate( *m_pCurve[0], *m_pCurve[1]) ; + CrvCompoLineCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; case CRV_ARC : - CrvCompoArcCalculate( *m_pCurve[0], *m_pCurve[1]) ; + CrvCompoArcCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; case CRV_COMPO : - CrvCompoCrvCompoCalculate( *m_pCurve[0], *m_pCurve[1]) ; + CrvCompoCrvCompoCalculate( *pCalcCrv[0], *pCalcCrv[1]) ; break ; } break ; } + // per curve approssimate, sistemo... + AdjustIntersParams( ( pCalcCrv[0] != m_pCurve[0]), ( pCalcCrv[1] != m_pCurve[1])) ; } //---------------------------------------------------------------------------- @@ -233,6 +240,35 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve& } } +//---------------------------------------------------------------------------- +bool +IntersCurveCurve::AdjustIntersParams( bool bAdjCrvA, bool bAdjCrvB) +{ + // se non ci sono intersezioni, non va fatto alcunché + if ( m_Info.size() == 0) + return true ; + // se le curve originali non sono state approssimate, non va fatto alcunché + if ( ! bAdjCrvA && ! bAdjCrvB) + return true ; + // procedo ad aggiustare + for ( auto& aInfo : m_Info) { + // se curve originali approssimate, devo ricalcolare i parametri dei punti di intersezione + if ( bAdjCrvA) { + if ( ! m_pCurve[0]->GetParamAtPoint( aInfo.IciA[0].ptI, aInfo.IciA[0].dU, 10 * EPS_SMALL)) + return false ; + if ( aInfo.bOverlap && ! m_pCurve[0]->GetParamAtPoint( aInfo.IciA[1].ptI, aInfo.IciA[1].dU, 10 * EPS_SMALL)) + return false ; + } + if ( bAdjCrvB) { + if ( ! m_pCurve[1]->GetParamAtPoint( aInfo.IciB[0].ptI, aInfo.IciB[0].dU, 10 * EPS_SMALL)) + return false ; + if ( aInfo.bOverlap && ! m_pCurve[1]->GetParamAtPoint( aInfo.IciB[1].ptI, aInfo.IciB[1].dU, 10 * EPS_SMALL)) + return false ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool IntersCurveCurve::GetOverlaps( void) @@ -254,19 +290,6 @@ IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) if ( nInd < 0 || nInd >= m_nNumInters) return false ; aInfo = m_Info[nInd] ; - // se curve originali approssimate, devo ricalcolare i parametri dei punti di intersezione - if ( m_pCurve[0] != m_pOriCrv[0]) { - if ( ! m_pOriCrv[0]->GetParamAtPoint( aInfo.IciA[0].ptI, aInfo.IciA[0].dU, 10 * EPS_SMALL)) - return false ; - if ( aInfo.bOverlap && ! m_pOriCrv[0]->GetParamAtPoint( aInfo.IciA[1].ptI, aInfo.IciA[1].dU, 10 * EPS_SMALL)) - return false ; - } - if ( m_pCurve[1] != m_pOriCrv[1]) { - if ( ! m_pOriCrv[1]->GetParamAtPoint( aInfo.IciB[0].ptI, aInfo.IciB[0].dU, 10 * EPS_SMALL)) - return false ; - if ( aInfo.bOverlap && ! m_pOriCrv[1]->GetParamAtPoint( aInfo.IciB[1].ptI, aInfo.IciB[1].dU, 10 * EPS_SMALL)) - return false ; - } return true ; } diff --git a/Intervals.cpp b/Intervals.cpp index 16a8d93..06cc63d 100644 --- a/Intervals.cpp +++ b/Intervals.cpp @@ -24,6 +24,7 @@ void Intervals::Reset( void) { m_lInts.clear() ; + m_Iter = m_lInts.end() ; } //---------------------------------------------------------------------------- @@ -139,6 +140,40 @@ Intervals::Remove( double dMin, double dMax) } } +//---------------------------------------------------------------------------- +void +Intervals::Union( const Intervals& Other) +{ + // aggiungo tutti gli intervalli dell'altro + for ( auto& Interv : Other.m_lInts) + Add( Interv.first, Interv.second) ; +} + +//---------------------------------------------------------------------------- +void +Intervals::Intersection( const Intervals& Other) +{ + // se l'insieme è vuoto non devo fare alcunché + if ( m_lInts.empty()) + return ; + // Insieme di intervalli ausiliario ampio come il corrente + Intervals Aux ; + Aux.Set( m_lInts.front().first, m_lInts.back().second) ; + // Sottraggo Other da Aux + Aux.Difference( Other) ; + // Sottraggo Aux dal corrente + Difference( Aux) ; +} + +//---------------------------------------------------------------------------- +void +Intervals::Difference( const Intervals& Other) +{ + // sottraggo tutti gli intervalli dell'altro + for ( auto& Interv : Other.m_lInts) + Remove( Interv.first, Interv.second) ; +} + //---------------------------------------------------------------------------- bool Intervals::GetMinMax( double& dMin, double& dMax) diff --git a/SelfIntersCurve.cpp b/SelfIntersCurve.cpp index 92b00bd..7e25acd 100644 --- a/SelfIntersCurve.cpp +++ b/SelfIntersCurve.cpp @@ -19,6 +19,7 @@ #include "IntersCrvCompoCrvCompo.h" #include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; @@ -29,34 +30,48 @@ SelfIntersCurve::SelfIntersCurve( const ICurve& Curve) // inizializzazioni m_bOverlaps = false ; - m_nNumInters = 0 ; - m_pOriCrv = &Curve ; - m_pCurve = nullptr ; + m_nIntersCount = 0 ; + m_pCurve = &Curve ; // verifico che la curva sia definita if ( &Curve == nullptr || ! Curve.IsValid()) return ; + // puntatore alla curva usata nei calcoli (originale o temporanea) + const ICurve* pCalcCrv ; + // eventuale approssimazione temporanea della curva + PtrOwner pTmpCrv ; + // eventuale parametrizzazione della approssimazione temporanea + DBLVECTOR vTmpPar ; + // se curva è arco da approssimare oppure è curva di Bezier - if ( ( m_pOriCrv->GetType() == CRV_ARC && IsArcToApprox( *m_pOriCrv)) || - m_pOriCrv->GetType() == CRV_BEZ) { + if ( ( m_pCurve->GetType() == CRV_ARC && IsArcToApprox( *m_pCurve)) || + m_pCurve->GetType() == CRV_BEZ) { // approssimo con rette PolyLine PL ; - if ( ! m_pOriCrv->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) + if ( ! m_pCurve->ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) return ; - m_pTmpCrv.Set( CreateBasicCurveComposite()) ; - if ( IsNull( m_pTmpCrv)) + pTmpCrv.Set( CreateBasicCurveComposite()) ; + if ( IsNull( pTmpCrv)) return ; - if ( ! GetBasicCurveComposite( Get( m_pTmpCrv))->FromPolyLine( PL)) + if ( ! GetBasicCurveComposite( Get( pTmpCrv))->FromPolyLine( PL)) return ; - m_pCurve = Get( m_pTmpCrv) ; + pCalcCrv = Get( pTmpCrv) ; + // salvo la parametrizzazione della approssimazione temporanea + vTmpPar.reserve( PL.GetPointNbr()) ; + double dPar ; + bool bFound = PL.GetFirstU( dPar) ; + while ( bFound) { + vTmpPar.push_back( dPar) ; + bFound = PL.GetNextU( dPar) ; + } } // altrimenti uso la curva originale else - m_pCurve = m_pOriCrv ; + pCalcCrv = m_pCurve ; // chiamo calcolatore opportuno - switch ( m_pCurve->GetType()) { + switch ( pCalcCrv->GetType()) { case CRV_LINE : // un segmento non può autointersecarsi (non considero auto-intersezione un segmento perpendicolare a XY) break ; @@ -64,16 +79,18 @@ SelfIntersCurve::SelfIntersCurve( const ICurve& Curve) // un arco nel piano XY con angolo al centro non superiore al giro non può autointersecarsi break ; case CRV_COMPO : { - IntersCrvCompoCrvCompo intCcCc( *GetCurveComposite( &Curve), *GetCurveComposite( &Curve)) ; + IntersCrvCompoCrvCompo intCcCc( *GetCurveComposite( pCalcCrv), *GetCurveComposite( pCalcCrv)) ; if ( intCcCc.m_nNumInters > 0) { m_bOverlaps = intCcCc.m_bOverlaps ; - m_nNumInters = intCcCc.m_nNumInters ; - for ( int i = 0 ; i < m_nNumInters ; ++ i) + m_nIntersCount = intCcCc.m_nNumInters ; + for ( int i = 0 ; i < m_nIntersCount ; ++ i) m_Info.push_back( intCcCc.m_Info[i]) ; } } break ; } + // per curva approssimata, sistemo... + AdjustIntersParams( ( pCalcCrv != m_pCurve), pCalcCrv, vTmpPar) ; } //---------------------------------------------------------------------------- @@ -89,6 +106,54 @@ SelfIntersCurve::IsArcToApprox( const ICurve& Curve) fabs( pArc->GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO) ; } +//---------------------------------------------------------------------------- +bool +SelfIntersCurve::GetCurveParamFromApproxParam( double& dU, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar) +{ + int nInd = int( dU) ; + double dFraz = dU - nInd ; + if ( nInd >= 0 && nInd < int( vCalcPar.size()) - 1) { + // parametrizzazione da vettore dei parametri, uniforme in ogni intervallino + dU = vCalcPar[nInd] + dFraz * ( vCalcPar[nInd+1] - vCalcPar[nInd]) ; + } + else { + // domini parametrici delle due curve + double dCalcS, dCalcE ; + pCalcCrv->GetDomain( dCalcS, dCalcE) ; + double dCrvS, dCrvE ; + m_pCurve->GetDomain( dCrvS, dCrvE) ; + // considero una parametrizzazione uniforme sull'intero dominio + dU = dCrvS + ( dU - dCalcS) * ( dCrvE - dCrvS) / ( dCalcE - dCalcS) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SelfIntersCurve::AdjustIntersParams( bool bAdjCrv, const ICurve* pCalcCrv, const DBLVECTOR& vCalcPar) +{ + // se la curva originale non è stata approssimata o non ci sono auto-intersezioni, non va fatto alcunché + if ( ! bAdjCrv || m_Info.size() == 0) + return true ; + // procedo ad aggiustare + for ( auto& aInfo : m_Info) { + // devo ricalcolare i parametri dei punti di intersezione + GetCurveParamFromApproxParam( aInfo.IciA[0].dU, pCalcCrv, vCalcPar) ; + ImproveCurveParamAtPoint( aInfo.IciA[0].dU, aInfo.IciA[0].ptI, m_pCurve) ; + if ( aInfo.bOverlap) { + GetCurveParamFromApproxParam( aInfo.IciA[1].dU, pCalcCrv, vCalcPar) ; + ImproveCurveParamAtPoint( aInfo.IciA[1].dU, aInfo.IciA[1].ptI, m_pCurve) ; + } + GetCurveParamFromApproxParam( aInfo.IciB[0].dU, pCalcCrv, vCalcPar) ; + ImproveCurveParamAtPoint( aInfo.IciB[0].dU, aInfo.IciB[0].ptI, m_pCurve) ; + if ( aInfo.bOverlap) { + GetCurveParamFromApproxParam( aInfo.IciB[1].dU, pCalcCrv, vCalcPar) ; + ImproveCurveParamAtPoint( aInfo.IciB[1].dU, aInfo.IciB[1].ptI, m_pCurve) ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool SelfIntersCurve::GetOverlaps( void) @@ -98,49 +163,38 @@ SelfIntersCurve::GetOverlaps( void) //---------------------------------------------------------------------------- int -SelfIntersCurve::GetNumInters( void) +SelfIntersCurve::GetIntersCount( void) { - return m_nNumInters ; + return m_nIntersCount ; } //---------------------------------------------------------------------------- int -SelfIntersCurve::GetNumCrossInters( void) +SelfIntersCurve::GetCrossIntersCount( void) { - int nNumCrossInters = 0 ; - for ( int i = 0 ; i < m_nNumInters ; ++ i) { + int nCrossIntersCount = 0 ; + for ( int i = 0 ; i < m_nIntersCount ; ++ i) { // se con sovrapposizione if ( m_Info[i].bOverlap) { if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[1].nNextTy) - ++ nNumCrossInters ; + ++ nCrossIntersCount ; } // altrimenti else { if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy) - ++ nNumCrossInters ; + ++ nCrossIntersCount ; } } - return nNumCrossInters ; + return nCrossIntersCount ; } //---------------------------------------------------------------------------- bool SelfIntersCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) { - if ( nInd < 0 || nInd >= m_nNumInters) + if ( nInd < 0 || nInd >= m_nIntersCount) return false ; aInfo = m_Info[nInd] ; - // se curva originale approssimata, devo ricalcolare i parametri dei punti di intersezione - if ( m_pCurve != m_pOriCrv) { - if ( ! m_pOriCrv->GetParamAtPoint( aInfo.IciA[0].ptI, aInfo.IciA[0].dU, 10 * EPS_SMALL)) - return false ; - if ( aInfo.bOverlap && ! m_pOriCrv->GetParamAtPoint( aInfo.IciA[1].ptI, aInfo.IciA[1].dU, 10 * EPS_SMALL)) - return false ; - if ( ! m_pOriCrv->GetParamAtPoint( aInfo.IciB[0].ptI, aInfo.IciB[0].dU, 10 * EPS_SMALL)) - return false ; - if ( aInfo.bOverlap && ! m_pOriCrv->GetParamAtPoint( aInfo.IciB[1].ptI, aInfo.IciB[1].dU, 10 * EPS_SMALL)) - return false ; - } return true ; } @@ -148,13 +202,13 @@ SelfIntersCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) bool SelfIntersCurve::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI) { - if ( m_nNumInters == 0) + if ( m_nIntersCount == 0) return false ; // ricerca del punto più vicino tra le intersezioni singole bool bFound = false ; double dMinSqDist = INFINITO * INFINITO ; - for ( int i = 0 ; i < m_nNumInters ; ++ i) { + for ( int i = 0 ; i < m_nIntersCount ; ++ i) { // se è un'intersezione singola if ( ! m_Info[i].bOverlap) { // faccio la verifica sul punto diff --git a/SfrCreate.cpp b/SfrCreate.cpp new file mode 100644 index 0000000..9bcdf49 --- /dev/null +++ b/SfrCreate.cpp @@ -0,0 +1,247 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1 +// Contenuto : Implementazione di funzioni per creazione di superfici Stm +// a partire da curve, con diversi metodi. +// +// +// Modifiche : 01.02.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveArc.h" +#include "CurveComposite.h" +#include "SurfFlatRegion.h" +#include "/EgtDev/Include/EGkSfrCreate.h" +#include "/EgtDev/Include/EgtPointerOwner.h" +#include + +using namespace std ; + +//------------------------------------------------------------------------------- +ISurfFlatRegion* +GetSurfFlatRegionRectangle( double dWidth, double dLen) +{ + // le dimensioni devono essere significative + if ( dWidth < EPS_SMALL || dLen < EPS_SMALL) + return nullptr ; + // creo il contorno + PolyLine PL ; + PL.AddUPoint( 0, ORIG) ; + PL.AddUPoint( 1, Point3d( dWidth, 0, 0)) ; + PL.AddUPoint( 2, Point3d( dWidth, dLen, 0)) ; + PL.AddUPoint( 3, Point3d( 0, dLen, 0)) ; + PL.AddUPoint( 4, ORIG) ; + PtrOwner pCC( CreateBasicCurveComposite()) ; + if ( IsNull( pCC) || ! pCC->FromPolyLine( PL)) + return nullptr ; + // creo il rettangolo + PtrOwner pSfr( CreateSurfFlatRegion()) ; + if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pCC))) + return nullptr ; + else + return Release( pSfr) ; +} + +//------------------------------------------------------------------------------- +ISurfFlatRegion* +GetSurfFlatRegionStadium( double dWidth, double dLen) +{ + // le dimensioni devono essere significative + if ( dWidth < EPS_SMALL || dLen < EPS_SMALL) + return nullptr ; + // se dimensioni praticamente uguali, è un disco + if ( fabs( dWidth - dLen) < 10 * EPS_SMALL) + return GetSurfFlatRegionDisk( ( dWidth + dLen) / 4) ; + // creo il contorno + PolyArc PA ; + if ( dWidth > dLen) { + double dRad = dLen / 2 ; + PA.AddUPoint( 0, Point3d( dRad, 0, 0), 0) ; + PA.AddUPoint( 1, Point3d( dWidth - dRad, 0, 0), 1) ; + PA.AddUPoint( 2, Point3d( dWidth - dRad, dLen, 0), 0) ; + PA.AddUPoint( 3, Point3d( dRad, dLen, 0), 1) ; + PA.AddUPoint( 4, Point3d( dRad, 0, 0), 0) ; + } + else { + double dRad = dWidth / 2 ; + PA.AddUPoint( 0, Point3d( dWidth, dRad, 0), 0) ; + PA.AddUPoint( 1, Point3d( dWidth, dLen - dRad, 0), 1) ; + PA.AddUPoint( 2, Point3d( 0, dLen - dRad, 0), 0) ; + PA.AddUPoint( 3, Point3d( 0, dRad, 0), 1) ; + PA.AddUPoint( 4, Point3d( dWidth, dRad, 0), 0) ; + } + PtrOwner pCC( CreateBasicCurveComposite()) ; + if ( IsNull( pCC) || ! pCC->FromPolyArc( PA)) + return nullptr ; + // creo il rettangolo + PtrOwner pSfr( CreateSurfFlatRegion()) ; + if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pCC))) + return nullptr ; + else + return Release( pSfr) ; +} + +//------------------------------------------------------------------------------- +ISurfFlatRegion* +GetSurfFlatRegionDisk( double dRadius) +{ + // le dimensioni devono essere significative + if ( dRadius < EPS_SMALL) + return nullptr ; + // creo la circonferenza di riferimento + PtrOwner pArc( CreateBasicCurveArc()) ; + if ( IsNull( pArc)) + return nullptr ; + pArc->Set( ORIG, Z_AX, dRadius, X_AX, ANG_FULL, 0) ; + // creo il disco + PtrOwner pSfr( CreateSurfFlatRegion()) ; + if ( IsNull( pSfr) || ! pSfr->AddExtLoop( Release( pArc))) + return nullptr ; + else + return Release( pSfr) ; +} + +//------------------------------------------------------------------------------- +// Classe SurfFlatRegionByContours +//------------------------------------------------------------------------------- +SurfFlatRegionByContours::~SurfFlatRegionByContours(void) +{ + // cancello eventuali curve rimaste + for ( auto& pCrv : m_vpCrv) { + if ( pCrv != nullptr) + delete pCrv ; + pCrv = nullptr ; + } + m_vpCrv.clear() ; +} + +//------------------------------------------------------------------------------- +bool +SurfFlatRegionByContours::AddCurve( ICurve* pCrv) +{ + // acquisisco la curva + PtrOwner pMyCrv( pCrv) ; + if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) + return false ; + // verifico sia chiusa + if ( ! pMyCrv->IsClosed()) + return false ; + // la inserisco nel vettore delle curve + m_vpCrv.push_back( Release( pMyCrv)) ; + return true ; +} + +//------------------------------------------------------------------------------- +bool +SurfFlatRegionByContours::Prepare( void) +{ + // calcolo piano medio e area delle curve + m_vArea.reserve( m_vpCrv.size()) ; + Vector3d vtN0 ; + for ( int i = 0 ; i < int( m_vpCrv.size()) ; ++ i) { + // calcolo piano medio e area + Plane3d plPlane ; + double dArea ; + if ( ! m_vpCrv[i]->GetArea( plPlane, dArea)) + return false ; + // imposto la normale del primo contorno come riferimento + if ( i == 0) + vtN0 = plPlane.vtN ; + // verifico che le normali siano molto vicine + if ( ! AreSameOrOppositeVectorApprox( plPlane.vtN, vtN0)) + return false ; + // assegno il segno all'area secondo il verso della normale + if ( ( plPlane.vtN * vtN0) > 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 fabs( a.second) > fabs( b.second) ; }) ; + return true ; +} + +//------------------------------------------------------------------------------- +ISurfFlatRegion* +SurfFlatRegionByContours::GetSurf( void) +{ + // se è la prima superficie, devo preparare + if ( m_bFirst) { + if ( ! Prepare()) + return nullptr ; + m_bFirst = false ; + } + // altrimenti, se ammessa una sola superficie errore + else if ( ! m_bAllowedMore) { + return nullptr ; + } + // creo la superficie + PtrOwner pSfr( CreateBasicSurfFlatRegion()) ; + if ( IsNull( pSfr)) + return nullptr ; + // aggiungo le diverse curve + bool bFirstCrv ; + 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 ; + // la prima deve essere il loop esterno + if ( bFirstCrv) { + // ne faccio una copia + PtrOwner pCrv( m_vpCrv[j]->Clone()) ; + if ( IsNull( pCrv)) { + m_vArea[i].first = - 1 ; + continue ; + } + // provo a inserirla + if ( pSfr->AddExtLoop( Release( pCrv))) { + bFirstCrv = false ; + delete m_vpCrv[j] ; + m_vpCrv[j] = nullptr ; + m_vArea[i].first = - 1 ; + } + } + // gli altri sono loop interni + else { + // ne faccio una copia + PtrOwner pCrv( m_vpCrv[j]->Clone()) ; + if ( IsNull( pCrv)) { + m_vArea[i].first = - 1 ; + continue ; + } + // provo a inserirla + if ( pSfr->AddIntLoop( Release( pCrv))) { + delete m_vpCrv[j] ; + m_vpCrv[j] = nullptr ; + m_vArea[i].first = - 1 ; + } + } + } + } while ( m_bAllowedMultiChunk && ! bFirstCrv) ; + // se non valida, errore + if ( ! pSfr->IsValid()) + return nullptr ; + // restituisco la superficie + return Release( pSfr) ; +} + +//------------------------------------------------------------------------------- +bool +SurfFlatRegionByContours::AllCurvesUsed( void) +{ + // verifico se cono rimaste delle curve + for ( auto& pCrv : m_vpCrv) { + if ( pCrv != nullptr) + return true ; + } + return false ; +} \ No newline at end of file diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index ed42d82..634ec8b 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -21,7 +21,7 @@ using namespace std ; //------------------------------------------------------------------------------- -static bool CalcRegionPolyLines( const ICURVEPVECTOR& vpCurve, double dLinTol, +static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, POLYLINEVECTOR& vPL, Vector3d& vtN) ; //------------------------------------------------------------------------------- @@ -47,7 +47,7 @@ GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol) //------------------------------------------------------------------------------- ISurfTriMesh* -GetSurfTriMeshByRegion( const ICURVEPVECTOR& vpCurve, double dLinTol) +GetSurfTriMeshByRegion( const CICURVEPVECTOR& vpCurve, double dLinTol) { // verifica parametri if ( &vpCurve == nullptr || vpCurve.empty()) @@ -126,7 +126,7 @@ GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, //------------------------------------------------------------------------------- ISurfTriMesh* -GetSurfTriMeshByRegionExtrusion( const ICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) +GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol) { // verifica parametri if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr) @@ -330,7 +330,7 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, double dLinTo //------------------------------------------------------------------------------- bool -CalcRegionPolyLines( const ICURVEPVECTOR& vpCurve, double dLinTol, +CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, POLYLINEVECTOR& vPL, Vector3d& vtN) { // calcolo le polilinee che approssimano le curve @@ -341,8 +341,8 @@ CalcRegionPolyLines( const ICURVEPVECTOR& vpCurve, double dLinTol, return nullptr ; } // ne calcolo l'area e genero un ordine in senso decrescente - typedef std::pair INDAREA ; // coppia indice, area - typedef std::vector INDAREAVECTOR ; // vettore di coppie indice, area + typedef pair INDAREA ; // coppia indice, area + typedef vector INDAREAVECTOR ; // vettore di coppie indice, area INDAREAVECTOR vArea ; vArea.reserve( vPLtmp.size()) ; Vector3d vtN0 ; diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index dc42fcd..bc2fd4e 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -31,7 +31,7 @@ GEOOBJ_REGISTER( SRF_FLATRGN, NGE_S_FRG, SurfFlatRegion) ; //---------------------------------------------------------------------------- SurfFlatRegion::SurfFlatRegion( void) - : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_pExtLoop( nullptr), m_nTempProp(), m_Iter( m_vpIntLoop.end()) + : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nTempProp() { } @@ -45,32 +45,26 @@ SurfFlatRegion::~SurfFlatRegion( void) bool SurfFlatRegion::Clear( void) { - if ( m_pSTM != nullptr) - delete( m_pSTM) ; - m_pSTM = nullptr ; m_nStatus = TO_VERIFY ; m_frF.Reset() ; - // ciclo di pulizia - if ( m_pExtLoop != nullptr) - delete( m_pExtLoop) ; - m_pExtLoop = nullptr ; - for ( auto Iter = m_vpIntLoop.begin() ; Iter != m_vpIntLoop.end() ; ++Iter) - delete (*Iter) ; - m_vpIntLoop.clear() ; + // pulizia dei loop + for ( auto& pLoop : m_vpLoop) + delete pLoop ; + m_vpLoop.clear() ; m_nTempProp = 0 ; - m_Iter = m_vpIntLoop.end() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; + ResetAuxSurf() ; return true ; } //---------------------------------------------------------------------------- bool -SurfFlatRegion::SetExtLoop( const ICurve& cCrv) +SurfFlatRegion::AddExtLoop( const ICurve& cCrv) { // verifico validità curva if ( &cCrv == nullptr) @@ -80,15 +74,13 @@ SurfFlatRegion::SetExtLoop( const ICurve& cCrv) if ( pCrv == nullptr) return false ; // procedo - return SetExtLoop( pCrv) ; + return AddExtLoop( pCrv) ; } //---------------------------------------------------------------------------- bool -SurfFlatRegion::SetExtLoop( ICurve* pCrv) +SurfFlatRegion::AddExtLoop( ICurve* pCrv) { - // resetto tutto - Clear() ; // acquisisco la curva PtrOwner pMyCrv( pCrv) ; if ( IsNull( pMyCrv)) @@ -97,28 +89,71 @@ SurfFlatRegion::SetExtLoop( ICurve* pCrv) if ( ! pMyCrv->IsClosed()) return false ; // verifico sia piana + double dArea ; Plane3d plPlane ; - if ( ! pMyCrv->IsFlat( plPlane)) - return false ; - // assegno il riferimento intrinseco - if ( ! m_frF.Set( ORIG + plPlane.vtN * plPlane.dDist, plPlane.vtN)) + if ( ! pMyCrv->GetArea( plPlane, dArea)) return false ; + // se sto costruendo il primo chunk + if ( m_vExtInd.size() == 0) { + // assegno il riferimento intrinseco + if ( ! m_frF.Set( ORIG + plPlane.vtN * plPlane.dDist, plPlane.vtN)) + return false ; + // sistemo il senso di rotazione (deve essere CCW -> area > 0) + if ( dArea < 0) + pMyCrv->Invert() ; + } + // altrimenti + else { + // verifico che il piano della curva coincida con quello XY intrinseco + plPlane.ToLoc( m_frF) ; + if ( ! ( plPlane.vtN.IsZplus() || plPlane.vtN.IsZminus()) || fabs( plPlane.dDist) > EPS_SMALL) + return false ; + // sistemo il senso di rotazione (deve essere CCW -> area > 0) + if ( ( plPlane.vtN.IsZplus() && dArea < 0) || + ( plPlane.vtN.IsZminus() && dArea > 0)) + pMyCrv->Invert() ; + } // porto la curva nel riferimento intrinseco if ( ! pMyCrv->ToLoc( m_frF)) return false ; // verifico non abbia auto-intersezioni SelfIntersCurve sInt( *pMyCrv) ; - if ( sInt.GetNumInters() > 0) + if ( sInt.GetIntersCount() > 0) return false ; - // sistemo il senso di rotazione (deve essere CCW -> area > 0) - double dArea ; - if ( ! pMyCrv->GetAreaXY( dArea) || fabs( dArea) < 100 * EPS_SMALL * EPS_SMALL) + // verifico che sia esterna alle curve esterne degli altri chunk + bool bOk = true ; + CRVCVECTOR ccClass ; + for ( auto i : m_vExtInd) { + IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ; + if ( ccInt.GetNumInters() > 0 || + ! ccInt.GetCurveClassification( 0, ccClass) || + ccClass.empty() || ccClass[0].nClass != CRVC_OUT) { + bOk = false ; + break ; + } + } + // oppure esterna ad un loop interno degli altri chunk + for ( int i = 0 ; i < int( m_vpLoop.size()) ; ++ i) { + // se loop esterno, salto + if ( binary_search( m_vExtInd.begin(), m_vExtInd.end(), i)) + continue ; + IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ; + if ( ccInt.GetNumInters() == 0 && + ccInt.GetCurveClassification( 0, ccClass) && + ! ccClass.empty() && ccClass[0].nClass == CRVC_OUT) { + bOk = true ; + break ; + } + } + if ( ! bOk) return false ; - if ( dArea < 0) - pMyCrv->Invert() ; - // assegno la curva al loop esterno - m_pExtLoop = Release( pMyCrv) ; + // assegno la curva come loop esterno + m_vpLoop.push_back( Release( pMyCrv)) ; + m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ; m_nStatus = OK ; + // imposto ricalcolo della grafica + ResetAuxSurf() ; + m_OGrMgr.Reset() ; return true ; } @@ -143,10 +178,10 @@ SurfFlatRegion::AddIntLoop( ICurve* pCrv) { // acquisisco la curva PtrOwner pMyCrv( pCrv) ; - if ( IsNull( pMyCrv)) + if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) return false ; // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // verifico sia chiusa if ( ! pMyCrv->IsClosed()) @@ -155,36 +190,33 @@ SurfFlatRegion::AddIntLoop( ICurve* pCrv) if ( ! pMyCrv->ToLoc( m_frF)) return false ; // verifico sia piana e il piano coincida con quello XY intrinseco + double dArea ; Plane3d plPlane ; - if ( ! pMyCrv->IsFlat( plPlane)) + if ( ! pMyCrv->GetArea( plPlane, dArea)) return false ; - if ( ! plPlane.vtN.IsZplus() && ! plPlane.vtN.IsZminus() && fabs( plPlane.dDist) > EPS_SMALL) + if ( ! ( plPlane.vtN.IsZplus() || plPlane.vtN.IsZminus()) || fabs( plPlane.dDist) > EPS_SMALL) return false ; + // sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area>0) + if ( ( plPlane.vtN.IsZplus() && dArea > 0) || ( plPlane.vtN.IsZminus() && dArea < 0)) + pMyCrv->Invert() ; // verifico non abbia auto-intersezioni SelfIntersCurve sInt( *pMyCrv) ; - if ( sInt.GetNumInters() > 0) + if ( sInt.GetIntersCount() > 0) return false ; - // verifico non abbia intersezioni e sia interna al loop esterno - IntersCurveCurve ccInt( *pMyCrv, *m_pExtLoop) ; + // verifico non abbia intersezioni e non sia esterna ai loop già definiti del medesimo chunk CRVCVECTOR ccClass ; - if ( ccInt.GetNumInters() > 0 || - ! ccInt.GetCurveClassification( 0, ccClass) || - ccClass.empty() || ccClass[0].nClass != CRVC_IN) - return false ; - // verifico non abbia intersezioni con eventuali altri loop interni - for ( auto& pIntLoop : m_vpIntLoop) { - IntersCurveCurve ccInt( *pMyCrv, *pIntLoop) ; - if ( ccInt.GetNumInters() > 0) + for ( int i = m_vExtInd.back() ; i < int( m_vpLoop.size()) ; ++ i) { + IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ; + if ( ccInt.GetNumInters() > 0 || + ! ccInt.GetCurveClassification( 0, ccClass) || + ccClass.empty() || ccClass[0].nClass != CRVC_IN) return false ; } - // sistemo il senso di rotazione (deve essere CW -> area < 0) - double dArea ; - if ( ! pMyCrv->GetAreaXY( dArea) || fabs( dArea) < 100 * EPS_SMALL * EPS_SMALL) - return false ; - if ( dArea > 0) - pMyCrv->Invert() ; - // aggiungo la curva all'elenco dei loop interni - m_vpIntLoop.push_back( Release( pMyCrv)) ; + // aggiungo la curva all'elenco dei loop + m_vpLoop.push_back( Release( pMyCrv)) ; + // imposto ricalcolo della grafica + ResetAuxSurf() ; + m_OGrMgr.Reset() ; return true ; } @@ -224,17 +256,16 @@ SurfFlatRegion::CopyFrom( const SurfFlatRegion& sfrSrc) if ( sfrSrc.m_pSTM != nullptr) m_pSTM = sfrSrc.m_pSTM->Clone() ; m_frF = sfrSrc.m_frF ; - if ( sfrSrc.m_pExtLoop != nullptr) - m_pExtLoop = sfrSrc.m_pExtLoop->Clone() ; - for ( auto& pIntLoop : sfrSrc.m_vpIntLoop) { - ICurve* pCrv = pIntLoop->Clone() ; + for ( auto& pLoop : sfrSrc.m_vpLoop) { + ICurve* pCrv = pLoop->Clone() ; if ( pCrv == nullptr) return false ; - m_vpIntLoop.push_back( pCrv) ; + m_vpLoop.push_back( pCrv) ; } + m_vExtInd = sfrSrc.m_vExtInd ; m_nTempProp = sfrSrc.m_nTempProp ; m_nStatus = sfrSrc.m_nStatus ; - return ( m_nStatus == OK && m_pExtLoop != nullptr) ; + return ( m_nStatus == OK && ! m_vpLoop.empty()) ; } //---------------------------------------------------------------------------- @@ -268,19 +299,27 @@ SurfFlatRegion::Dump( string& sOut, bool bMM, const char* szNewLine) const sOut += "VX(" + ToString( m_frF.VersX()) + ")" + szNewLine ; sOut += "VY(" + ToString( m_frF.VersY()) + ")" + szNewLine ; sOut += "VZ(" + ToString( m_frF.VersZ()) + ")" + szNewLine ; - // loop esterno - if ( m_pExtLoop != nullptr) { - sOut += string( "External Loop :") + szNewLine ; - m_pExtLoop->Dump( sOut, bMM, szNewLine) ; - } - else - sOut += string( "External Loop Invalid") + szNewLine ; - // loop interni - sOut += "Internal Loops=" + ToString( GetIntLoopNumber()) + szNewLine ; - int i = 0 ; - for ( auto& pIntLoop : m_vpIntLoop) { - sOut += "##" + ToString( ++i) + szNewLine ; - pIntLoop->Dump( sOut, bMM, szNewLine) ; + // ciclo sui chunk (parti connesse) + int nChunkCount = GetChunkCount() ; + sOut += string( "Chunks =") + ToString( nChunkCount) + szNewLine ; + for ( int i = 0 ; i < nChunkCount ; ++ i) { + int nLoopCount = GetLoopCount( i) ; + // ciclo sui loop del chunk + for ( int j = 0 ; j < nLoopCount ; ++ j) { + int k = GetIndFromChunkLoop( i, j) ; + // loop esterno + if ( j == 0) { + sOut += "Chunk # " + ToString( i) + szNewLine ; + sOut += string( "External Loop : ") + szNewLine ; + m_vpLoop[k]->Dump( sOut, bMM, szNewLine) ; + sOut += "Internal Loops =" + ToString( GetLoopCount( i) - 1) + szNewLine ; + } + // loop interno + else { + sOut += "## " + ToString( j) + szNewLine ; + m_vpLoop[k]->Dump( sOut, bMM, szNewLine) ; + } + } } return true ; @@ -301,29 +340,33 @@ SurfFlatRegion::Save( NgeWriter& ngeOut) const if ( ! ngeOut.WriteFrame( m_frF, ";", true)) return false ; // numero di loops (esterno + interni) - if ( ! ngeOut.WriteInt( 1 + int( m_vpIntLoop.size()), nullptr, true)) + if ( ! ngeOut.WriteInt( int( m_vpLoop.size()), nullptr, true)) return false ; // ciclo sui loop int i = 0 ; - const ICurve* pCrv = GetMyLoop( i) ; - while ( pCrv != nullptr) { + for ( auto& pLoop : m_vpLoop) { // recupero il gestore di lettura/scrittura della curva - const IGeoObjRW* pCSmplRW = dynamic_cast( pCrv) ; - if ( pCSmplRW == nullptr) + const IGeoObjRW* pLoopRW = dynamic_cast( pLoop) ; + if ( pLoopRW == nullptr) return false ; // emetto il tipo della curva - if ( ! ngeOut.WriteKey( pCSmplRW->GetNgeId())) + if ( ! ngeOut.WriteKey( pLoopRW->GetNgeId())) return false ; - // assegno ed emetto il nome della curva + // assegno ed emetto il nome della curva, seguito da chunk e loop string sCrvName = "##" + ToString( i) ; - if ( ! ngeOut.WriteString( sCrvName, nullptr, true)) + if ( ! ngeOut.WriteString( sCrvName, ";")) + return false ; + int nChunk, nLoop ; + if ( ! GetChunkLoopFromInd( i, nChunk, nLoop)) + return false ; + if ( ! ngeOut.WriteInt( nChunk, ",") || + ! ngeOut.WriteInt( nLoop, ";", true)) return false ; // salvo la curva - if ( ! pCSmplRW->Save( ngeOut)) + if ( ! pLoopRW->Save( ngeOut)) return false ; // passo alla successiva ++ i ; - pCrv = GetMyLoop( i) ; } return true ; } @@ -352,11 +395,14 @@ SurfFlatRegion::Load( NgeReader& ngeIn) IGeoObj* pGeoO = GEOOBJ_CREATE( nType) ; if ( pGeoO == nullptr) return false ; - // recupero la linea con il nome + // recupero la linea con il nome, chunk e loop string sName ; int j ; - bool bOk = ngeIn.ReadString( sName, nullptr, true) && + bool bOk = ngeIn.ReadString( sName, ";") && FromString( sName.substr(2), j) && i == j ; + int nChunk, nLoop ; + bOk = ngeIn.ReadInt( nChunk, ",") && + ngeIn.ReadInt( nLoop, ";", true) ; // ne leggo i dati IGeoObjRW* pGObjRW = dynamic_cast( pGeoO) ; bOk = bOk && ( pGObjRW != nullptr && pGObjRW->Load( ngeIn)) ; @@ -365,10 +411,11 @@ SurfFlatRegion::Load( NgeReader& ngeIn) bOk = bOk && ( pCrv != nullptr) ; // aggiungo questa curva if ( bOk) { - if ( i == 0) - m_pExtLoop = pCrv ; - else - m_vpIntLoop.push_back( pCrv) ; + m_vpLoop.push_back( pCrv) ; + if ( nLoop == 0) { + m_vExtInd.push_back( i) ; + bOk = ( nChunk + 1 == int( m_vExtInd.size())) ; + } } // se errore if ( ! bOk) @@ -384,10 +431,10 @@ bool SurfFlatRegion::GetLocalBBox( BBox3d& b3Loc, int nFlag) const { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // è il bounding box del loop esterno - return m_pExtLoop->GetBBox( m_frF, b3Loc, nFlag) ; + return m_vpLoop[0]->GetBBox( m_frF, b3Loc, nFlag) ; } //---------------------------------------------------------------------------- @@ -395,12 +442,12 @@ bool SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // frame composito Frame3d frCompo = m_frF * frRef ; // è il bounding box del loop esterno - return m_pExtLoop->GetBBox( frCompo, b3Ref, nFlag) ; + return m_vpLoop[0]->GetBBox( frCompo, b3Ref, nFlag) ; } //---------------------------------------------------------------------------- @@ -437,7 +484,7 @@ bool SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // imposto ricalcolo della grafica ResetAuxSurf() ; @@ -455,18 +502,17 @@ SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou // porto i loop nel nuovo riferimento, senza modificarne la geometria in globale frTrasf.ToLoc( m_frF) ; - m_pExtLoop->ToGlob( frTrasf) ; - for ( auto& pIntLoop : m_vpIntLoop) - pIntLoop->ToGlob( frTrasf) ; + for ( auto& pLoop : m_vpLoop) + pLoop->ToGlob( frTrasf) ; // porto il riferimento di scalatura nel nuovo riferimento del gruppo Frame3d frRefLoc = frRef ; frRefLoc.ToLoc( m_frF) ; // ciclo sui loop - bool bOk = m_pExtLoop->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ) ; - for ( auto& pIntLoop : m_vpIntLoop) { - if ( ! pIntLoop->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ)) + bool bOk = true ; + for ( auto& pLoop : m_vpLoop) { + if ( ! pLoop->Scale( frRefLoc, dCoeffX, dCoeffY, dCoeffZ)) bOk = false ; } @@ -478,7 +524,7 @@ bool SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // imposto ricalcolo della grafica ResetAuxSurf() ; @@ -490,9 +536,8 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // porto i loop nel nuovo riferimento, senza modificarne la geometria in globale frTrasf.ToLoc( m_frF) ; - m_pExtLoop->ToGlob( frTrasf) ; - for ( auto& pIntLoop : m_vpIntLoop) - pIntLoop->ToGlob( frTrasf) ; + for ( auto& pLoop : m_vpLoop) + pLoop->ToGlob( frTrasf) ; // porto i dati del piano di mirror nel riferimento del gruppo Point3d ptOnLoc = ptOn ; @@ -501,9 +546,9 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) vtNormLoc.ToLoc( m_frF) ; // ciclo sui loop (mirror + invert) - bool bOk = m_pExtLoop->Mirror( ptOnLoc, vtNormLoc) && m_pExtLoop->Invert() ; - for ( auto& pIntLoop : m_vpIntLoop) { - if ( ! pIntLoop->Mirror( ptOnLoc, vtNormLoc) || ! pIntLoop->Invert()) + bool bOk = true ; + for ( auto& pLoop : m_vpLoop) { + if ( ! pLoop->Mirror( ptOnLoc, vtNormLoc) || ! pLoop->Invert()) bOk = false ; } @@ -523,7 +568,7 @@ bool SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // imposto ricalcolo della grafica ResetAuxSurf() ; @@ -541,9 +586,8 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector // porto i loop nel nuovo riferimento, senza modificarne la geometria in globale frTrasf.ToLoc( m_frF) ; - m_pExtLoop->ToGlob( frTrasf) ; - for ( auto& pIntLoop : m_vpIntLoop) - pIntLoop->ToGlob( frTrasf) ; + for ( auto& pLoop : m_vpLoop) + pLoop->ToGlob( frTrasf) ; // porto i dati di scorrimento nel riferimento del gruppo Point3d ptOnLoc = ptOn ; @@ -554,9 +598,9 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector vtDirLoc.ToLoc( m_frF) ; // ciclo sugli oggetti - bool bOk = m_pExtLoop->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff) ; - for ( auto& pIntLoop : m_vpIntLoop) { - if ( ! pIntLoop->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff)) + bool bOk = true ; + for ( auto& pLoop : m_vpLoop) { + if ( ! pLoop->Shear( ptOnLoc, vtNormLoc, vtDirLoc, dCoeff)) bOk = false ; } @@ -568,24 +612,16 @@ bool SurfFlatRegion::ConvertArcsToBezierCurves( void) { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; - // loop esterno - if ( m_pExtLoop->GetType() == CRV_ARC) { - ICurve* pCrvNew = ArcToBezierCurve( m_pExtLoop) ; - if ( pCrvNew == nullptr) - return false ; - delete m_pExtLoop ; - m_pExtLoop = pCrvNew ; - } - // eventuali loop interni - for ( auto& pIntLoop : m_vpIntLoop) { - if ( pIntLoop->GetType() == CRV_ARC) { - ICurve* pCrvNew = ArcToBezierCurve( pIntLoop) ; + // ciclo sui loop + for ( auto& pLoop : m_vpLoop) { + if ( pLoop->GetType() == CRV_ARC) { + ICurve* pCrvNew = ArcToBezierCurve( pLoop) ; if ( pCrvNew == nullptr) return false ; - delete pIntLoop ; - pIntLoop = pCrvNew ; + delete pLoop ; + pLoop = pCrvNew ; } } return true ; @@ -634,13 +670,13 @@ SurfFlatRegion::GetArea( double& dArea) const // inizio con area nulla dArea = 0 ; // la regione deve essere validata - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // sommo l'area di tutti i loop (gli interni hanno area negativa) - bool bOk = m_pExtLoop->GetAreaXY( dArea) ; - for ( auto& pIntLoop : m_vpIntLoop) { + bool bOk = true ; + for ( auto& pLoop : m_vpLoop) { double dTemp ; - if ( pIntLoop->GetAreaXY( dTemp)) + if ( pLoop->GetAreaXY( dTemp)) dArea += dTemp ; else bOk = false ; @@ -657,35 +693,111 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const if ( &ptCen == nullptr) return false ; // la regione deve essere validata - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // determino il centroide del solo loop esterno - return m_pExtLoop->GetCentroid( ptCen) ; + if ( ! m_vpLoop[0]->GetCentroid( ptCen)) + return false ; + // lo porto dal riferimento intrinseco a quello in cui è immersa l'entità + ptCen.ToGlob( m_frF) ; + return true ; +} + +//---------------------------------------------------------------------------- +int +SurfFlatRegion::GetChunkCount( void) const +{ + // la regione deve essere validata + if ( m_nStatus != OK) + return 0 ; + return int( m_vExtInd.size()) ; +} + +//---------------------------------------------------------------------------- +int +SurfFlatRegion::GetLoopCount( int nChunk) const +{ + // la regione deve essere validata + if ( m_nStatus != OK || m_vpLoop.empty()) + return 0 ; + // non deve superare l'indice massimo ( Count - 1) + int nChunkMax = int( m_vExtInd.size()) - 1 ; + if ( nChunk < 0 || nChunk > nChunkMax) + return 0 ; + // se non è l'ultimo Chunk + if ( nChunk < nChunkMax) + return ( m_vExtInd[nChunk+1] - m_vExtInd[nChunk]) ; + // altrimenti + else + return ( int( m_vpLoop.size()) - m_vExtInd[nChunk]) ; +} + +//---------------------------------------------------------------------------- +int +SurfFlatRegion::GetIndFromChunkLoop( int nChunk, int nLoop) const +{ + // recupero il numero di loop nel chunk + int nLoopCount = GetLoopCount( nChunk) ; + if ( nLoopCount <= 0) + return - 1 ; + // verifico che il loop esista + if ( nLoop < 0 || nLoop >= nLoopCount) + return - 1 ; + // ritorno il suo indice + return ( m_vExtInd[nChunk] + nLoop) ; +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const +{ + // valori non validi + nChunk = - 1 ; + nLoop = - 1 ; + // verifico validità di nInd + if ( nInd < 0 || nInd >= int( m_vpLoop.size())) + return false ; + // verifica esistenza array di chunks + if ( m_vExtInd.empty()) + return false ; + // ricerca del chunk e del loop + nChunk = 0 ; + while ( ( nChunk + 1) < int( m_vExtInd.size())) { + if ( nInd < m_vExtInd[nChunk+1]) + break ; + ++ nChunk ; + } + nLoop = nInd - m_vExtInd[nChunk] ; + return true ; } //---------------------------------------------------------------------------- ICurve* -SurfFlatRegion::GetMyLoop( int nLoop) const +SurfFlatRegion::GetMyLoop( int nInd) const { // la regione deve essere validata if ( m_nStatus != OK) return nullptr ; - // se esterno - if ( nLoop == 0) - return m_pExtLoop ; - // altrimenti interno, verifico che l'indice sia nei limiti - if ( nLoop < 1 || nLoop > int( m_vpIntLoop.size())) + // verifico che l'indice sia nei limiti + if ( nInd < 0 || nInd >= int( m_vpLoop.size())) return nullptr ; else - return m_vpIntLoop[nLoop-1] ; + return m_vpLoop[nInd] ; } //---------------------------------------------------------------------------- ICurve* -SurfFlatRegion::GetLoop( int nLoop) const +SurfFlatRegion::GetMyLoop( int nChunk, int nLoop) const +{ + return GetMyLoop( GetIndFromChunkLoop( nChunk, nLoop)) ; +} + +//---------------------------------------------------------------------------- +ICurve* +SurfFlatRegion::GetLoop( int nChunk, int nLoop) const { // recupero il loop nel riferimento intrinseco - const ICurve* pMyCrv = GetMyLoop( nLoop) ; + const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ; if ( pMyCrv == nullptr) return nullptr ; // ne faccio una copia @@ -702,29 +814,37 @@ const ISurfTriMesh* SurfFlatRegion::GetAuxSurf( void) const { // la superficie deve essere validata - if ( m_nStatus != OK || m_pExtLoop == nullptr) - return false ; + if ( m_nStatus != OK || m_vpLoop.empty()) + return nullptr ; // se già calcolata, la restituisco - if ( m_pSTM != nullptr) + if ( m_pSTM != nullptr) return m_pSTM ; - // la calcolo - // calcolo le polilinee che approssimano i loop - POLYLINEVECTOR vPL ; - vPL.resize( 1 + int( m_vpIntLoop.size())) ; - int i = - 1 ; - if ( ! m_pExtLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL[++i])) - return nullptr ; - for ( auto& pIntLoop : m_vpIntLoop) { - if ( ! pIntLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL[++i])) - return nullptr ; - } - // porto le polilinee in globale al riferimento intrinseco - for ( auto& PL : vPL) - PL.ToGlob( m_frF) ; - // creo, setto la superficie trimesh ed elimino punti ripetuti + // la creo PtrOwner pSTM( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL) || ! pSTM->DoCompacting()) + if ( IsNull( pSTM)) return nullptr ; + // per ogni chunk (componente connesso) + for ( int i = 0 ; i < GetChunkCount() ; ++ i) { + // calcolo le polilinee che approssimano i loop + POLYLINEVECTOR vPL ; + vPL.resize( GetLoopCount( i)) ; + int j = 0 ; + ICurve* pLoop = GetMyLoop( i, j) ; + while ( pLoop != nullptr) { + if ( ! pLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL[j])) + return nullptr ; + pLoop = GetMyLoop( i, ++j) ; + } + // porto le polilinee in globale al riferimento intrinseco + for ( auto& PL : vPL) + PL.ToGlob( m_frF) ; + // creo, setto la superficie trimesh ed elimino punti ripetuti + PtrOwner pChSTM( CreateBasicSurfTriMesh()) ; + if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL) || ! pChSTM->DoCompacting()) + return nullptr ; + // inserisco questa trimesh in quella complessiva + pSTM->DoSewing( *Get( pChSTM)) ; + } // la salvo m_pSTM = Release( pSTM) ; return m_pSTM ; @@ -739,16 +859,47 @@ SurfFlatRegion::ResetAuxSurf( void) const m_pSTM = nullptr ; } +//---------------------------------------------------------------------------- +SurfFlatRegion* +SurfFlatRegion::CloneChunk( int nChunk) const +{ + // verifico esistenza del chunk (implicitamente anche lo stato) + int nLoop = GetLoopCount( nChunk) ; + if ( nLoop == 0) + return nullptr ; + // alloco la nuova regione + PtrOwner pSfr( CreateBasicSurfFlatRegion()) ; + if ( IsNull( pSfr)) + return nullptr ; + // copio il riferimento intrinseco + pSfr->m_frF = m_frF ; + // copio i loop del chunk indicato + for ( int i = 0 ; i < nLoop ; ++i) { + ICurve* pCrv = GetMyLoop( nChunk, i)->Clone() ; + if ( pCrv == nullptr) + return nullptr ; + pSfr->m_vpLoop.push_back( pCrv) ; + } + // sistemo indice dell'unico loop esterno + pSfr->m_vExtInd.push_back( 0) ; + pSfr->m_nStatus = OK ; + return Release( pSfr) ; +} + //---------------------------------------------------------------------------- bool SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const { // verifico lo stato - if ( m_nStatus != OK || m_pExtLoop == nullptr) + if ( m_nStatus != OK || m_vpLoop.empty()) return false ; // verifico la curva if ( &Crv == nullptr || ! Crv.IsValid()) return false ; + // dominio della curva + double dStart, dEnd ; + if ( ! Crv.GetDomain( dStart, dEnd)) + return false ; // curva in locale nel riferimento intrinseco const ICurve* pCrvLoc = nullptr ; PtrOwner pCopyCrv ; @@ -761,72 +912,77 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) pCopyCrv->ToLoc( m_frF) ; pCrvLoc = Get( pCopyCrv) ; } - // intervalli delle diverse classi - Intervals inIn, inOut, inOnP, inOnM ; - // classifico la curva con tutti i loop presenti - int nLoop = 0 ; - const ICurve* pLoop = GetMyLoop( nLoop) ; - while ( pLoop != nullptr) { - // intersezione - IntersCurveCurve ccInt( *pCrvLoc, *pLoop) ; - // classificazione - CRVCVECTOR ccPart ; - if ( ! ccInt.GetCurveClassification( 0, ccPart)) - return false ; - for ( auto& ccOne : ccPart) { - switch ( ccOne.nClass) { - case CRVC_IN : inIn.Add( ccOne.dParS, ccOne.dParE) ; break ; - case CRVC_OUT : inOut.Add( ccOne.dParS, ccOne.dParE) ; break ; - case CRVC_ON_P : inOnP.Add( ccOne.dParS, ccOne.dParE) ; break ; - case CRVC_ON_M : inOnM.Add( ccOne.dParS, ccOne.dParE) ; break ; - default : return false ; + + // intervalli totali delle diverse classi + Intervals inTIn, inTOut, inTOnP, inTOnM ; + inTOut.Set( dStart, dEnd) ; // inizializzo come tutta la linea per poi poter rimuovere parti + // ciclo sui chunk + for ( int nChunk = 0 ; nChunk < GetChunkCount() ; ++ nChunk) { + // intervalli di Chunk delle diverse classi + Intervals inCIn, inCOut, inCOnP, inCOnM ; + inCIn.Set( dStart, dEnd) ; // inizializzo come tutta la linea per poi poter rimuovere parti + // classifico la curva con tutti i loop presenti nel chunk + for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) { + const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ; + // intersezione + IntersCurveCurve ccInt( *pCrvLoc, *pLoop) ; + // classificazione + CRVCVECTOR ccPart ; + if ( ! ccInt.GetCurveClassification( 0, ccPart)) + return false ; + for ( auto& ccOne : ccPart) { + switch ( ccOne.nClass) { + case CRVC_IN : + // IN è Remove degli altri + break ; + case CRVC_OUT : + inCOut.Add( ccOne.dParS, ccOne.dParE) ; + inCIn.Remove( ccOne.dParS, ccOne.dParE) ; + break ; + case CRVC_ON_P : + inCOnP.Add( ccOne.dParS, ccOne.dParE) ; + inCIn.Remove( ccOne.dParS, ccOne.dParE) ; + break ; + case CRVC_ON_M : + inCOnM.Add( ccOne.dParS, ccOne.dParE) ; + inCIn.Remove( ccOne.dParS, ccOne.dParE) ; + break ; + default : return false ; + } } } - // passo al loop successivo - ++ nLoop ; - pLoop = GetMyLoop( nLoop) ; - } - // sistemo gli intervalli di classificazione - // Out prevale su tutto - double dMin, dMax ; - bool bFound = inOut.GetFirst( dMin, dMax) ; - while ( bFound) { - inIn.Remove( dMin, dMax) ; - inOnP.Remove( dMin, dMax) ; - inOnM.Remove( dMin, dMax) ; - bFound = inOut.GetNext( dMin, dMax) ; - } - // OnP e OnM prevalgono su In e sono sicuramente disgiunti tra loro - bFound = inOnP.GetFirst( dMin, dMax) ; - while ( bFound) { - inIn.Remove( dMin, dMax) ; - bFound = inOnP.GetNext( dMin, dMax) ; - } - bFound = inOnM.GetFirst( dMin, dMax) ; - while ( bFound) { - inIn.Remove( dMin, dMax) ; - bFound = inOnM.GetNext( dMin, dMax) ; + // aggiorno gli intervalli di classificazione totali + // In, OnP e OnM vengono aggiornati per somma + inTIn.Union( inCIn) ; + inTOnP.Union( inCOnP) ; + inTOnM.Union( inCOnM) ; + // Out viene ricavato per differenza degli altri + inTOut.Difference( inCIn) ; + inTOut.Difference( inCOnP) ; + inTOut.Difference( inCOnM) ; } + // ricostruisco la classificazione completa e la ordino - bFound = inIn.GetFirst( dMin, dMax) ; + double dMin, dMax ; + bool bFound = inTIn.GetFirst( dMin, dMax) ; while ( bFound) { ccClass.emplace_back( dMin, dMax, CRVC_IN) ; - bFound = inIn.GetNext( dMin, dMax) ; + bFound = inTIn.GetNext( dMin, dMax) ; } - bFound = inOut.GetFirst( dMin, dMax) ; + bFound = inTOut.GetFirst( dMin, dMax) ; while ( bFound) { ccClass.emplace_back( dMin, dMax, CRVC_OUT) ; - bFound = inOut.GetNext( dMin, dMax) ; + bFound = inTOut.GetNext( dMin, dMax) ; } - bFound = inOnP.GetFirst( dMin, dMax) ; + bFound = inTOnP.GetFirst( dMin, dMax) ; while ( bFound) { ccClass.emplace_back( dMin, dMax, CRVC_ON_P) ; - bFound = inOnP.GetNext( dMin, dMax) ; + bFound = inTOnP.GetNext( dMin, dMax) ; } - bFound = inOnM.GetFirst( dMin, dMax) ; + bFound = inTOnM.GetFirst( dMin, dMax) ; while ( bFound) { ccClass.emplace_back( dMin, dMax, CRVC_ON_M) ; - bFound = inOnM.GetNext( dMin, dMax) ; + bFound = inTOnM.GetNext( dMin, dMax) ; } sort( ccClass.begin(), ccClass.end(), []( const CrvClass& a, const CrvClass& b) { return a.dParS < b.dParS ; }) ; diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index 3ad3958..e47e407 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -71,14 +71,17 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW public : // ISurfFlatRegion virtual bool CopyFrom( const IGeoObj* pGObjSrc) ; virtual bool Clear( void) ; - virtual bool SetExtLoop( const ICurve& cCrv) ; - virtual bool SetExtLoop( ICurve* pCrv) ; + virtual bool AddExtLoop( const ICurve& cCrv) ; + virtual bool AddExtLoop( ICurve* pCrv) ; virtual bool AddIntLoop( const ICurve& cCrv) ; virtual bool AddIntLoop( ICurve* pCrv) ; - virtual ICurve* GetLoop( int nLoop) const ; // nLoop=0 esterno, successivi interni - virtual int GetIntLoopNumber( void) const - { return int( m_vpIntLoop.size()) ; } + virtual const Vector3d& GetNormVersor( void) const + { return m_frF.VersZ() ; } + virtual int GetChunkCount( void) const ; + virtual int GetLoopCount( int nChunk) const ; + virtual ICurve* GetLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni) virtual const ISurfTriMesh* GetAuxSurf( void) const ; + virtual SurfFlatRegion* CloneChunk( int nChunk) const ; virtual bool GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const ; public : // IGeoObjRW @@ -97,7 +100,10 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW return *this ; } private : bool CopyFrom( const SurfFlatRegion& clSrc) ; - virtual ICurve* GetMyLoop( int nLoop) const ; // nLoop=0 esterno, successivi interni + int GetIndFromChunkLoop( int nChunk, int nLoop) const ; + bool GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const ; + ICurve* GetMyLoop( int nInd) const ; // indice nel vettore di tutti i loop + ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni) void ResetAuxSurf( void) const ; bool ConvertArcsToBezierCurves( void) ; @@ -106,18 +112,15 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW private : typedef std::deque PCRV_DEQUE ; - typedef PCRV_DEQUE::iterator PCRD_ITER ; - typedef PCRV_DEQUE::const_iterator PCRD_CONST_ITER ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria Status m_nStatus ; // stato Frame3d m_frF ; // riferimento intrinseco - ICurve* m_pExtLoop ; // curva che forma il loop esterno - PCRV_DEQUE m_vpIntLoop ; // deque delle curve che formano i loop interni + PCRV_DEQUE m_vpLoop ; // deque delle curve che formano i loop + INTVECTOR m_vExtInd ; // indice dei loop esterni nel precedente vettore int m_nTempProp ; // proprietà temporanea - mutable PCRD_CONST_ITER m_Iter ; // iteratore sui loop interni } ; //----------------------------------------------------------------------------- diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 85b3b21..cd63341 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -283,7 +283,7 @@ SurfTriMesh::GetCentroid( Point3d& ptCen) const //---------------------------------------------------------------------------- int -SurfTriMesh::GetVertexNum( void) const +SurfTriMesh::GetVertexCount( void) const { // calcolo il numero dei vertici cancellati int nErased = 0 ; @@ -297,7 +297,7 @@ SurfTriMesh::GetVertexNum( void) const //---------------------------------------------------------------------------- int -SurfTriMesh::GetTriangleNum( void) const +SurfTriMesh::GetTriangleCount( void) const { // calcolo il numero dei triangoli cancellati int nErased = 0 ; @@ -682,14 +682,14 @@ SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const if ( ! m_bOriented) sOut += string( "Inconsistent Orientation") + szNewLine ; // numero di vertici - sOut += "Vert : Nbr=" + ToString( GetVertexNum()) + + sOut += "Vert : Nbr=" + ToString( GetVertexCount()) + " Size=" + ToString( GetVertexSize()) + szNewLine ; // numero di triangoli - sOut += "Tria : Nbr=" + ToString( GetTriangleNum()) + + sOut += "Tria : Nbr=" + ToString( GetTriangleCount()) + " Size=" + ToString( GetTriangleSize()) + szNewLine ; // numero facce, se calcolate if ( m_bFaceted) - sOut += "Facet : Nbr=" + ToString( GetFacetNum()) + + sOut += "Facet : Nbr=" + ToString( GetFacetCount()) + " Size=" + ToString( GetFacetSize()) + szNewLine ; return true ; diff --git a/SurfTriMesh.h b/SurfTriMesh.h index a15f937..7944404 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -139,8 +139,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW double dAngRot, double dStepRot, double dMove) ; virtual bool DoCompacting( void) ; virtual bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM) ; - virtual int GetVertexNum( void) const ; - virtual int GetTriangleNum( void) const ; + virtual int GetVertexCount( void) const ; + virtual int GetTriangleCount( void) const ; virtual int GetVertexSize( void) const { return int( m_vVert.size()) ; } virtual int GetTriangleSize( void) const @@ -162,7 +162,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW virtual bool GetVertexSmoothNormal( int nV, int nT, Vector3d& vtN) const ; virtual bool GetTriangleBoundaryEdges( int nId, TriFlags3d& TFlags) const ; virtual bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const ; - virtual int GetFacetNum( void) const ; + virtual int GetFacetCount( void) const ; virtual int GetFacetSize( void) const { return int( m_vFacet.size()) ; } virtual int GetFacetFromTria( int nT) const ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index ba2dc20..f5238a5 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -119,7 +119,7 @@ SurfTriMesh::UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, //---------------------------------------------------------------------------- int -SurfTriMesh::GetFacetNum( void) const +SurfTriMesh::GetFacetCount( void) const { // la superficie deve essere validata if ( m_nStatus != OK)