diff --git a/ArcPntDirTgCurve.cpp b/ArcPntDirTgCurve.cpp index bb74150..9c2a9ad 100644 --- a/ArcPntDirTgCurve.cpp +++ b/ArcPntDirTgCurve.cpp @@ -204,7 +204,7 @@ GetArcPntDirTgArc( const Point3d& ptP, const Vector3d& vtDir, const CurveArc& cr if ( bOk1) { double dOffset = ( bOutSide ? crvArcL.GetRadius() : - crvArcL.GetRadius()) ; if ( pCrv1->GetType() == CRV_ARC) - bOk1 = (dynamic_cast(Get(pCrv1)))->ExtendedOffset( dOffset) ; + bOk1 = (static_cast( Get( pCrv1)))->ExtendedOffset( dOffset) ; else bOk1 = pCrv1->SimpleOffset( dOffset) ; } @@ -235,7 +235,7 @@ GetArcPntDirTgArc( const Point3d& ptP, const Vector3d& vtDir, const CurveArc& cr if ( bOk2) { double dOffset = ( bOutSide ? - crvArcL.GetRadius() : crvArcL.GetRadius()) ; if ( pCrv2->GetType() == CRV_ARC) - bOk2 = (dynamic_cast(Get(pCrv2)))->ExtendedOffset( dOffset) ; + bOk2 = (static_cast( Get( pCrv2)))->ExtendedOffset( dOffset) ; else bOk2 = pCrv2->SimpleOffset( dOffset) ; } diff --git a/ArcSpecial.cpp b/ArcSpecial.cpp index 908e39c..b06b486 100644 --- a/ArcSpecial.cpp +++ b/ArcSpecial.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2022 +// EgalTech 2014-2023 //---------------------------------------------------------------------------- -// File : ArcSpecial.cpp Data : 18.08.22 Versione : 2.4h2 +// File : ArcSpecial.cpp Data : 04.08.23 Versione : 2.5h1 // Contenuto : Implementazione funzioni per calcoli speciali archi. // // @@ -20,7 +20,6 @@ using namespace std ; - //---------------------------------------------------------------------------- // Come la CurveArc::Set2PD, ma se raggio infinito restituisce una retta //---------------------------------------------------------------------------- @@ -28,7 +27,7 @@ ICurve* GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; @@ -43,7 +42,7 @@ GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg) // verifico se i punti sono allineati con la direzione e nel giusto verso if ( abs( CrossXY( vtDiff, vtDir)) < EPS_SMALL && ScalarXY( vtDiff, vtDir) > EPS_SMALL) { // creo l'oggetto retta - PtrOwner pLine( CreateCurveLine()) ; + PtrOwner pLine( CreateBasicCurveLine()) ; if ( IsNull( pLine)) return nullptr ; // calcolo retta, se ok la restituisco ed esco @@ -61,7 +60,7 @@ ICurve* GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS, const Vector3d& vtN) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; @@ -74,7 +73,7 @@ GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS // verifico se i punti sono allineati con la direzione e nel giusto verso nel piano perpendicolare a vtN if ( abs( ( vtDiff ^ vtDirS) * vtN) < EPS_SMALL && vtDiff * vtDirS > EPS_SMALL) { // creo l'oggetto retta - PtrOwner pLine( CreateCurveLine()) ; + PtrOwner pLine( CreateBasicCurveLine()) ; if ( IsNull( pLine)) return nullptr ; // calcolo retta, se ok la restituisco ed esco @@ -85,6 +84,35 @@ GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS return nullptr ; } +//---------------------------------------------------------------------------- +// Come la CurveArc::Set2PNB, ma se bulge nullo restituisce una retta +//---------------------------------------------------------------------------- +ICurve* +GetArc2PNB( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtN, double dBulge) +{ + // creo l'oggetto arco + PtrOwner pArc( CreateBasicCurveArc()) ; + if ( IsNull( pArc)) + return nullptr ; + + // calcolo l'arco, se ok lo restituisco ed esco + if ( pArc->Set2PNB( ptStart, ptEnd, vtN, dBulge)) + return Release( pArc) ; + + // calcolo arco non riuscito, verifico se retta va bene + if ( abs( dBulge) > EPS_SMALL) + return nullptr ; + // creo l'oggetto retta + PtrOwner pLine( CreateBasicCurveLine()) ; + if ( IsNull( pLine)) + return nullptr ; + // calcolo retta, se ok la restituisco ed esco + if ( pLine->Set( ptStart, ptEnd)) + return Release( pLine) ; + + return nullptr ; +} + //---------------------------------------------------------------------------- // Come la CurveArc::Set3P, ma se raggio infinito restituisce una retta //---------------------------------------------------------------------------- @@ -92,7 +120,7 @@ ICurve* GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd, bool bCirc) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; @@ -108,7 +136,7 @@ GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd, // verifico se i punti sono allineati nel giusto verso if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) { // creo l'oggetto retta - PtrOwner pLine( CreateCurveLine()) ; + PtrOwner pLine( CreateBasicCurveLine()) ; if ( IsNull( pLine)) return nullptr ; // calcolo retta, se ok la restituisco ed esco @@ -126,7 +154,7 @@ ICurveArc* GetArc2PCN( const Point3d& ptStart, const Point3d& ptEnd, const Point3d& ptNearCen, const Vector3d& vtN) { // creo l'oggetto arco - PtrOwner pArc( CreateCurveArc()) ; + PtrOwner pArc( CreateBasicCurveArc()) ; if ( IsNull( pArc)) return nullptr ; diff --git a/BiArcs.cpp b/BiArcs.cpp index fac2397..0906fc3 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -20,6 +20,7 @@ #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkArcSpecial.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; @@ -97,7 +98,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir CurveArc* pArc = GetBasicCurveArc( pJCrv) ; if ( pArc == nullptr) return nullptr ; - double dU = - 1 ; + double dU = -1 ; double dRad = pArc->GetRadius() ; double dSqRad = dRad * dRad ; Point3d ptCen = pArc->GetCenter() ; @@ -121,9 +122,11 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir } } } - // elimino casi vicino agli estremi, danno solo problemi - if ( dU < 0.1 || dU > 0.9) + // non c'è intersezione, assegno valore medio + if ( dU < -0.5) dU = 0.5 ; + // elimino casi vicino agli estremi, danno solo problemi + dU = Clamp( dU, 0.1, 0.9) ; pBiArc.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, dU)) ; } @@ -132,15 +135,24 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir return nullptr ; // determino la massima distanza tra la curva e il biarco - Point3d ptP ; double dSqDist = 0 ; - for ( bool bPnt = PL.GetFirstPoint( ptP) ; - bPnt ; - bPnt = PL.GetNextPoint( ptP)) { - DistPointCurve dstPC( ptP, *pBiArc) ; - double dSqDistPC ; - if ( dstPC.GetSqDist( dSqDistPC) && dSqDistPC > dSqDist) - dSqDist = dSqDistPC ; + const double STEP = 10 ; + Point3d ptCurr ; + bool bPnt = PL.GetFirstPoint( ptCurr) ; + Point3d ptPrev = ptCurr ; + while ( bPnt) { + double dLen = Dist( ptCurr, ptPrev) ; + int nStep = ( dLen < STEP ? 2 : 1) * int( dLen / STEP) + 1 ; + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCoeff = double( i) / nStep ; + Point3d ptP = Media( ptPrev, ptCurr, dCoeff) ; + DistPointCurve dstPC( ptP, *pBiArc) ; + double dSqDistPC ; + if ( dstPC.GetSqDist( dSqDistPC) && dSqDistPC > dSqDist) + dSqDist = dSqDistPC ; + } + ptPrev = ptCurr ; + bPnt = PL.GetNextPoint( ptCurr) ; } dDist = sqrt( dSqDist) ; diff --git a/CDeClosedSurfTmClosedSurfTm.cpp b/CDeClosedSurfTmClosedSurfTm.cpp index a877e19..8d1cfd1 100644 --- a/CDeClosedSurfTmClosedSurfTm.cpp +++ b/CDeClosedSurfTmClosedSurfTm.cpp @@ -67,8 +67,8 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf INTVECTOR vNearTria ; pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ; // Settare tutti i triangoli come già processati. - // Al termine della chiamata i TFlags dei triangoli valgono 0. - pSrfB->ResetTempInt() ; + // Al termine della chiamata i TempInt dei triangoli valgono 0. + pSrfB->ResetTempInts() ; // Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A. for ( int nTB : vNearTria) { // Recupero il triangolo corrente della superficie B. @@ -85,7 +85,7 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf // Se il triangolo adiacente al triangolo corrente su questo edge // non è stato processato, processo il vertice e l'edge. int nAdjTriaTempFlag ; - if ( ! ( pSrfB->GetTriangleTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) + if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0)) continue ; // Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito. if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA)) diff --git a/CurveArc.cpp b/CurveArc.cpp index b9f8fb9..63f27bf 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -26,6 +26,7 @@ #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/ENkPolynomialRoots.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include @@ -567,7 +568,7 @@ CurveArc::Clone( void) const bool CurveArc::CopyFrom( const IGeoObj* pGObjSrc) { - const CurveArc* pCA = dynamic_cast( pGObjSrc) ; + const CurveArc* pCA = GetBasicCurveArc( pGObjSrc) ; if ( pCA == nullptr) return false ; return CopyFrom( *pCA) ; @@ -950,10 +951,7 @@ CurveArc::GetDir( double dU, Vector3d& vtDir) const return false ; // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; + dU = Clamp( dU, 0., 1.) ; // versore al punto nel piano della circonferenza (ruoto m_VtS di dU * m_dAngCenDeg attorno a m_VtN) double dAng = dU * m_dAngCenDeg * DEGTORAD ; @@ -975,10 +973,7 @@ CurveArc::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, V return false ; // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; + dU = Clamp( dU, 0., 1.) ; // versore al punto nel piano della circonferenza (ruoto m_VtS di dU di m_dAngCenDeg attorno a m_VtN) double dAng = dU * m_dAngCenDeg * DEGTORAD ; @@ -1427,7 +1422,7 @@ bool CurveArc::TrimStartAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -1443,7 +1438,7 @@ bool CurveArc::TrimEndAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -1803,11 +1798,14 @@ CurveArc::ToGlob( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1825,11 +1823,14 @@ CurveArc::ToLoc( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1850,11 +1851,14 @@ CurveArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; + // trasformo il centro e i versori return ( m_PtCen.LocToLoc( frOri, frDest) && m_VtN.LocToLoc( frOri, frDest) && diff --git a/CurveArc.h b/CurveArc.h index 69ba383..02eba06 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -217,12 +217,16 @@ class CurveArc : public ICurveArc, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveArc* CreateBasicCurveArc( void) - { return (static_cast( CreateGeoObj( CRV_ARC))) ; } + { return ( static_cast( CreateGeoObj( CRV_ARC))) ; } inline CurveArc* CloneBasicCurveArc( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveArc* GetBasicCurveArc( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveArc* GetBasicCurveArc( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/CurveAux.cpp b/CurveAux.cpp index 4e0ba4d..795c6e4 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -617,6 +617,7 @@ NurbsToBezierCurve( const CNurbsData& cnData) int b = cnData.nDeg ; bool bPrevRejected = false ; // ciclo + int n = 0 ; // debug while ( b < nU - 1) { int i = b ; while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO) @@ -684,7 +685,8 @@ NurbsToBezierCurve( const CNurbsData& cnData) pCrvBez.Reset() ; bPrevRejected = true ; } - + // debug + ++n ; // inizializzazioni per la prossima curva di Bezier if ( b < nU - 1) { if ( ! cnData.bRat) { diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 3514473..703ddec 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -266,7 +266,7 @@ CurveBezier::Clone( void) const bool CurveBezier::CopyFrom( const IGeoObj* pGObjSrc) { - const CurveBezier* pCB = dynamic_cast( pGObjSrc) ; + const CurveBezier* pCB = GetBasicCurveBezier( pGObjSrc) ; if ( pCB == nullptr) return false ; return CopyFrom( *pCB) ; @@ -1991,11 +1991,14 @@ CurveBezier::ToGlob( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2015,11 +2018,14 @@ CurveBezier::ToLoc( const Frame3d& frRef) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2039,11 +2045,14 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la curva deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché + if ( AreSameFrame( frOri, frDest)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; diff --git a/CurveBezier.h b/CurveBezier.h index d5e96ac..ade321d 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -195,12 +195,16 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveBezier* CreateBasicCurveBezier( void) - { return (static_cast( CreateGeoObj( CRV_BEZIER))) ; } + { return ( static_cast( CreateGeoObj( CRV_BEZIER))) ; } inline CurveBezier* CloneBasicCurveBezier( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZIER) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveBezier* GetBasicCurveBezier( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveBezier* GetBasicCurveBezier( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/CurveByApprox.cpp b/CurveByApprox.cpp index 89e30f3..fd5ff91 100644 --- a/CurveByApprox.cpp +++ b/CurveByApprox.cpp @@ -57,11 +57,17 @@ ICurve* CurveByApprox::GetCurve( int nType, double dLinTol, double dAngTolDeg, double dLinFea) { // se da approssimare con archi - if ( nType == ARCS_CORNER) { + if ( nType == ARCS || nType == ARCS_CORNER) { // calcolo approssimazione PolyArc PA ; - if ( ! GetArcs( dLinTol, dAngTolDeg, dLinFea, PA)) - return nullptr ; + if ( nType == ARCS) { + if ( ! GetArcs( dLinTol, dAngTolDeg, PA)) + return nullptr ; + } + else { + if ( ! GetArcsCorner( dLinTol, dAngTolDeg, dLinFea, PA)) + return nullptr ; + } // creo la composita formata da questa approssimazione PtrOwner pCC( CreateBasicCurveComposite()) ; if ( ! pCC->FromPolyArc( PA)) @@ -74,13 +80,55 @@ CurveByApprox::GetCurve( int nType, double dLinTol, double dAngTolDeg, double dL return Release( pCC) ; } // altrimenti con curve di Bezier cubiche - // !!! NON ANCORA IMPLEMENTATA !!! + else if ( nType == CUBIC_BEZIERS) { + // !!! NON ANCORA IMPLEMENTATA !!! + return nullptr ; + } + // tipi non previsti return nullptr ; } //---------------------------------------------------------------------------- bool -CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) +CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) +{ + // pulisco il poliarco + PA.Clear() ; + + // calcolo una parametrizzazione + if ( ! CalcParameterization()) + return false ; + + // calcolo le tangenti + if ( ! CalcAkimaTangents( false)) + return false ; + + // approssimo come unico tratto + + // creo la polilinea che unisce i punti + PolyLine PL ; + int nPnt = int( m_vPnt.size()) ; + for ( int j = 0 ; j < nPnt ; ++ j) + PL.AddUPoint( j, m_vPnt[j]) ; + // verifico se retta verticale + BBox3d b3PL ; + if ( ! PL.GetLocalBBox( b3PL)) + return false ; + if ( b3PL.GetDimX() < EPS_SMALL && b3PL.GetDimY() < EPS_SMALL) { + PA.AddUPoint( 0, m_vPnt[0], 0) ; + PA.AddUPoint( nPnt - 1, m_vPnt[nPnt - 1], 0) ; + } + // altrimenti eseguo l'approssimazione con archi + else { + if ( ! BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA)) + return false ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByApprox::GetArcsCorner( double dLinTol, double dAngTolDeg, double dLinFea, PolyArc& PA) { // pulisco il poliarco PA.Clear() ; @@ -105,9 +153,18 @@ CurveByApprox::GetArcs( double dLinTol, double dAngTolDeg, double dLinFea, PolyA PolyLine PL ; for ( int j = nPrev ; j <= m_vSplits[i] ; ++ j) PL.AddUPoint( j, m_vPnt[j]) ; - // eseguo l'approssimazione con archi - if ( ! BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA)) + // verifico se retta verticale + BBox3d b3PL ; + if ( ! PL.GetLocalBBox( b3PL)) return false ; + if ( b3PL.GetDimX() < EPS_SMALL && b3PL.GetDimY() < EPS_SMALL) { + PA.AddUPoint( m_vSplits[i], m_vPnt[m_vSplits[i]], 0) ; + } + // altrimenti eseguo l'approssimazione con archi + else { + if ( ! BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA)) + return false ; + } // salvo fine come prox inizio nPrev = m_vSplits[i] ; } @@ -456,9 +513,7 @@ CurveByApprox::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAng return true ; // costruisco la retta che li unisce PtrOwner pCC( CreateBasicCurveComposite()) ; - if ( IsNull( pCC)) - return false ; - if ( ! pCC->FromPolyLine( PL)) + if ( IsNull( pCC) || ! pCC->FromPolyLine( PL)) return false ; pCrv.Set( pCC) ; dMaxDist = 0 ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 4d88fa5..68d74e0 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -1385,30 +1385,52 @@ CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) if ( m_nStatus != OK) return false ; + // determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla + Frame3d frNat ; + if ( ! m_VtExtr.IsSmall()) { + frNat.Set( ORIG, m_VtExtr) ; + } + else { + Plane3d plPlane ; + IsFlat( plPlane, false) ; + if ( plPlane.IsValid()) { + if ( plPlane.GetVersN().z < -EPS_ZERO) + plPlane.Invert() ; + frNat.Set( ORIG, plPlane.GetVersN()) ; + } + } + // eseguo approssimazione double dStartPar = 0 ; - for ( auto& pCrv : m_CrvSmplS) { + for ( const auto& pCrv : m_CrvSmplS) { + // ne faccio una copia + PtrOwner pCrvL( pCrv->Clone()) ; + if ( IsNull( pCrvL)) + return false ; // assegno estrusione e spessore della curva composita - pCrv->SetExtrusion( m_VtExtr) ; - pCrv->SetThickness( m_dThick) ; + pCrvL->SetExtrusion( m_VtExtr) ; + pCrvL->SetThickness( m_dThick) ; + // la porto nel riferimento naturale + pCrvL->ToLoc( frNat) ; // recupero approssimazione per curva semplice PolyArc PASmpl ; - if ( ! pCrv->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) + if ( ! pCrvL->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dStartPar)) return false ; - // ripristino estrusione e spessore della curva semplice (annullandoli) - pCrv->SetExtrusion( V_NULL) ; - pCrv->SetThickness( 0) ; // incremento inizio parametro per prossima curva semplice dStartPar += 1 ; } + // riporto l'approssimazione nel riferimento della composita + PA.ToGlob( frNat) ; + // assegno estrusione della curva composita PA.SetExtrusion( m_VtExtr) ; - return true ; + // eliminazione dei punti in tolleranza (opportunamente diminuita) + return PA.RemoveAlignedPoints( 0.5 * dLinTol) ; } //---------------------------------------------------------------------------- @@ -1427,16 +1449,37 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin double dMlStartPar = 0 ; CurveByApprox crvByApprox ; + // determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla + Frame3d frNat ; + if ( ! m_VtExtr.IsSmall()) { + frNat.Set( ORIG, m_VtExtr) ; + } + else { + Plane3d plPlane ; + IsFlat( plPlane, false) ; + if ( plPlane.IsValid()) { + if ( plPlane.GetVersN().z < -EPS_ZERO) + plPlane.Invert() ; + frNat.Set( ORIG, plPlane.GetVersN()) ; + } + } + // eseguo approssimazione double dStartPar = 0 ; - for ( auto& pCrv : m_CrvSmplS) { + for ( const auto& pCrv : m_CrvSmplS) { + // ne faccio una copia + PtrOwner pCrvL( pCrv->Clone()) ; + if ( IsNull( pCrvL)) + return false ; // assegno estrusione e spessore della curva composita - pCrv->SetExtrusion( m_VtExtr) ; - pCrv->SetThickness( m_dThick) ; + pCrvL->SetExtrusion( m_VtExtr) ; + pCrvL->SetThickness( m_dThick) ; + // la porto nel riferimento naturale + pCrvL->ToLoc( frNat) ; // se segmento di linea non feature double dLen ; - if ( pCrv->GetType() == CRV_LINE && pCrv->GetLength( dLen) && dLen < dLinFea) { - CurveLine* pLine = GetBasicCurveLine( pCrv) ; + if ( pCrvL->GetType() == CRV_LINE && pCrvL->GetLength( dLen) && dLen < dLinFea) { + CurveLine* pLine = GetBasicCurveLine( pCrvL) ; // se inizio di approx multilinea if ( ! bMultiLine) { bMultiLine = true ; @@ -1444,23 +1487,38 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin crvByApprox.Reset() ; crvByApprox.AddPoint( pLine->GetStart()) ; } - // aggiungo punti a distanza opportuna - const double STEP = 5 ; - int nStep = int( dLen / STEP) ; - for ( int i = 1 ; i < nStep ; ++ i) { - double dCoeff = i / double( nStep) ; - crvByApprox.AddPoint( Media( pLine->GetStart(), pLine->GetEnd(), dCoeff)) ; - } // aggiungo il punto finale crvByApprox.AddPoint( pLine->GetEnd()) ; } + // se altrimenti arco di circonferenza o curva di Bezier non feature + else if ( ( pCrvL->GetType() == CRV_ARC || pCrvL->GetType() == CRV_BEZIER) && + pCrvL->GetLength( dLen) && dLen < dLinFea) { + // se inizio di approx multilinea + if ( ! bMultiLine) { + bMultiLine = true ; + dMlStartPar = dStartPar ; + crvByApprox.Reset() ; + Point3d ptStart ; + if ( ! pCrvL->GetStartPoint( ptStart)) + return false ; + crvByApprox.AddPoint( ptStart) ; + } + // aggiungo i punti opportunamente campionati sulla curva (compreso il finale) + PolyLine PL ; + if ( ! pCrvL->ApproxWithLines( dLinTol / 2, dAngTolDeg / 2, ICurve::APL_STD, PL)) + return false ; + Point3d ptFin ; + PL.GetFirstPoint( ptFin) ; + while ( PL.GetNextPoint( ptFin)) + crvByApprox.AddPoint( ptFin) ; + } // altrimenti else { // se in corso approx multilinee if ( bMultiLine) { bMultiLine = false ; PolyArc PASmpl ; - if ( ! crvByApprox.GetArcs( dLinTol, dAngTolDeg, dLinFea, PASmpl)) + if ( ! crvByApprox.GetArcsCorner( dLinTol, dAngTolDeg, dLinFea, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dMlStartPar)) @@ -1468,15 +1526,12 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin } // recupero approssimazione per curva semplice PolyArc PASmpl ; - if ( ! pCrv->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) + if ( ! pCrvL->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dStartPar)) return false ; } - // ripristino estrusione e spessore della curva semplice (annullandoli) - pCrv->SetExtrusion( V_NULL) ; - pCrv->SetThickness( 0) ; // incremento inizio parametro per prossima curva semplice dStartPar += 1 ; } @@ -1484,13 +1539,16 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin if ( bMultiLine) { bMultiLine = false ; PolyArc PASmpl ; - if ( ! crvByApprox.GetArcs( dLinTol, dAngTolDeg, dLinFea, PASmpl)) + if ( ! crvByApprox.GetArcsCorner( dLinTol, dAngTolDeg, dLinFea, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita if ( ! PA.Join( PASmpl, dMlStartPar)) return false ; } + // riporto l'approssimazione nel riferimento della composita + PA.ToGlob( frNat) ; + // assegno estrusione della curva composita PA.SetExtrusion( m_VtExtr) ; @@ -1542,7 +1600,7 @@ CurveComposite::CopyParamRange( double dUStart, double dUEnd) const // eseguo il trim della copia if ( ! pCopy->TrimStartEndAtParam( dUStart, dUEnd)) return nullptr ; - return ( ::Release( pCopy)) ; + return ( pCopy->m_CrvSmplS.empty() ? nullptr : ::Release( pCopy)) ; } //---------------------------------------------------------------------------- @@ -2112,7 +2170,15 @@ CurveComposite::ModifyCurveToLine( int nCrv) bool CurveComposite::TrimStartAtParam( double dUTrim) { - // ciclo sulle diverse curve dall'inizio + // verifico validità parametro + double dMaxU = double( m_CrvSmplS.size()) ; + if ( dUTrim < -EPS_PARAM || dUTrim > dMaxU - EPS_PARAM) + return false ; + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + // ciclo sulle diverse curve dall'inizio double dUToTrim = dUTrim ; for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice @@ -2123,17 +2189,13 @@ CurveComposite::TrimStartAtParam( double dUTrim) // se lunghezza ancora da tagliare non nulla if ( dUToTrim > EPS_PARAM) { delete (*Iter) ; - Iter ++ ; - m_CrvSmplS.pop_front() ; + Iter = m_CrvSmplS.erase( Iter) ; } // se lunghezza ancora da tagliare nulla (entro la tolleranza) else if ( dUToTrim > - EPS_PARAM || ! (*Iter)->TrimStartAtParam( 1 + dUToTrim)) { delete (*Iter) ; - Iter ++ ; - m_CrvSmplS.pop_front() ; - if ( m_CrvSmplS.empty()) - return false ; + Iter = m_CrvSmplS.erase( Iter) ; break ; } // altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra) @@ -2142,9 +2204,6 @@ CurveComposite::TrimStartAtParam( double dUTrim) } } - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - return true ; } @@ -2152,6 +2211,14 @@ CurveComposite::TrimStartAtParam( double dUTrim) bool CurveComposite::TrimEndAtParam( double dUTrim) { + // verifico validità parametro + double dMaxU = double( m_CrvSmplS.size()) ; + if ( dUTrim < EPS_PARAM || dUTrim > dMaxU + EPS_PARAM) + return false ; + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + // ciclo sulle diverse curve dalla fine bool bToErase = false ; double dUToTrim = dUTrim ; @@ -2193,9 +2260,6 @@ CurveComposite::TrimEndAtParam( double dUTrim) } } - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - return true ; } @@ -2418,6 +2482,9 @@ CurveComposite::ExtendEndByLen( double dLenExt) bool CurveComposite::Translate( const Vector3d& vtMove) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2432,6 +2499,9 @@ CurveComposite::Translate( const Vector3d& vtMove) bool CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -2453,6 +2523,9 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn bool CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; @@ -2537,6 +2610,9 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou bool CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -2558,6 +2634,9 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) bool CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -2588,10 +2667,17 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector bool CurveComposite::ToGlob( const Frame3d& frRef) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2609,10 +2695,17 @@ CurveComposite::ToGlob( const Frame3d& frRef) bool CurveComposite::ToLoc( const Frame3d& frRef) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2630,6 +2723,9 @@ CurveComposite::ToLoc( const Frame3d& frRef) bool CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; diff --git a/CurveComposite.h b/CurveComposite.h index eac578d..5f1cf2f 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -215,12 +215,41 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveComposite* CreateBasicCurveComposite( void) - { return (static_cast( CreateGeoObj( CRV_COMPO))) ; } + { return ( static_cast( CreateGeoObj( CRV_COMPO))) ; } inline CurveComposite* CloneBasicCurveComposite( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveComposite* GetBasicCurveComposite( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveComposite* GetBasicCurveComposite( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline CurveComposite* ConvertCurveToBasicComposite( IGeoObj* pGObj) + { if ( pGObj == nullptr || ( pGObj->GetType() & GEO_CURVE) == 0) { + delete pGObj ; + return nullptr ; + } + CurveComposite* pCrvCo = CreateBasicCurveComposite() ; + if ( pCrvCo == nullptr) { + delete pGObj ; + return nullptr ; + } + ICurve* pCrv = static_cast( pGObj) ; + Vector3d vtExtr ; + if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) + pCrvCo->SetExtrusion( vtExtr) ; + double dThick ; + if ( pCrv->GetThickness( dThick) && abs( dThick) > EPS_SMALL) + pCrvCo->SetThickness( dThick) ; + for ( int i = 0 ; i < 2 ; ++ i) { + int nProp = pCrv->GetTempProp( i) ; + if ( nProp != 0) + pCrvCo->SetTempProp( nProp, i) ; + } + pCrvCo->AddCurve( pCrv) ; + return pCrvCo ; + } diff --git a/CurveLine.cpp b/CurveLine.cpp index 79ce9e5..aee34df 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -19,6 +19,7 @@ #include "NgeWriter.h" #include "NgeReader.h" #include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include @@ -111,7 +112,7 @@ CurveLine::Clone( void) const bool CurveLine::CopyFrom( const IGeoObj* pGObjSrc) { - const CurveLine* pCL = dynamic_cast( pGObjSrc) ; + const CurveLine* pCL = GetBasicCurveLine( pGObjSrc) ; if ( pCL == nullptr) return false ; return CopyFrom( *pCL) ; @@ -356,10 +357,7 @@ CurveLine::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, return false ; // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; + dU = Clamp( dU, 0., 1.) ; // calcolo del punto ptPos = Media( m_PtStart, m_PtEnd, dU) ; @@ -642,7 +640,7 @@ bool CurveLine::TrimStartAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -658,7 +656,7 @@ bool CurveLine::TrimEndAtParam( double dUTrim) { // riporto i parametri nel loro range - dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ; + dUTrim = Clamp( dUTrim, 0., 1.) ; // recupero lunghezza double dLen ; @@ -787,6 +785,7 @@ CurveLine::Translate( const Vector3d& vtMove) // la curva deve essere validata if ( m_nStatus != OK) return false ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -919,6 +918,10 @@ CurveLine::ToGlob( const Frame3d& frRef) if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -937,6 +940,10 @@ CurveLine::ToLoc( const Frame3d& frRef) if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -954,6 +961,7 @@ CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; diff --git a/CurveLine.h b/CurveLine.h index a3179d6..53d4fd6 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -170,12 +170,16 @@ class CurveLine : public ICurveLine, public IGeoObjRW //----------------------------------------------------------------------------- inline CurveLine* CreateBasicCurveLine( void) - { return (static_cast( CreateGeoObj( CRV_LINE))) ; } + { return ( static_cast( CreateGeoObj( CRV_LINE))) ; } inline CurveLine* CloneBasicCurveLine( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const CurveLine* GetBasicCurveLine( const IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE) + return nullptr ; + return ( static_cast( pGObj)) ; } inline CurveLine* GetBasicCurveLine( IGeoObj* pGObj) - { return (dynamic_cast(pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/DistPointSurfTm.cpp b/DistPointSurfTm.cpp index 31ef065..44b340f 100644 --- a/DistPointSurfTm.cpp +++ b/DistPointSurfTm.cpp @@ -12,6 +12,7 @@ //---------------------------------------------------------------------------- #include "stdafx.h" +#include "SurfTriMesh.h" #include "/EgtDev/Include/EGkDistPointTria.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" @@ -24,7 +25,7 @@ using namespace std ; // I casi in cui non vengono trovati box di misura positiva sono quelli in cui o il box A è contenuto // nel box B; uno di questi si verifica se il box A è vuoto. // Nel vettore vBoxDiff vengono restituiti i box la cui unione costituisce la differenza fra A e B. -bool +static bool BoundingBoxDifference( const BBox3d& boxA, const BBox3d& boxB, BOXVECTOR& vBoxDiff) { // Svuoto il risultato @@ -93,30 +94,33 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // Inizializzo distanza non calcolata m_dDist = - 1. ; + // Lavoro con l'oggetto superficie trimesh di base + const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; + if ( pStm == nullptr) + return ; + // Recupero e verifico il box locale della superficie - BBox3d b3Stm = tmSurf.GetAllTriaBox() ; + BBox3d b3Stm = pStm->GetAllTriaBox() ; if ( b3Stm.IsEmpty()) return ; - // Determino i triangoli vicini e fra di essi cerco quello di minima distanza. - // Considero un box centrato nel punto P; finché all'interno del box non trovo un set di triangoli - // fra cui quello a distanza minima dal punto P ha distanza minore del minimo semi-lato del box, - // continuo a ingrandire il box. La condizione di terminazione garantisce di trovare il tiangolo di - // distanza minima della trimesh intera. + // Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // Termino quando non trovo più triangoli che possano soddisfare la richiesta. Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; - double dDeltaLen = max( min( min( ptMax.x - ptMin.x, ptMax.y - ptMin.y), ptMax.z - ptMin.z) / 40., 10.) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; - // Considero anche il box precedente per poter analizzare solo lo spazio differenza tra i due + // Considero anche il box precedente per poter analizzare solo il volume differenza tra i due BBox3d boxPPrev( ptP) ; BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; // Variabili distanza minima, indice del triangolo di distanza minima, punto di distanza minima double dMinSqDist = DBL_MAX ; int nMinDistTriaIndex = SVT_NULL ; Point3d ptMinDistPoint ; - bool bContinue = true ; // Finché non si verifica la condizione di terminazione ingrandisco il box. + pStm->ResetTempInts() ; + bool bContinue = true ; while ( bContinue) { // Calcolo il box differenza con il precedente per non esplorare parti già considerate BOXVECTOR vBox ; @@ -131,18 +135,21 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) // ricerca sui triangoli nel box bCollide = true ; INTVECTOR vnIds ; - if ( tmSurf.GetAllTriaOverlapBox( b3Int, vnIds)) { + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { // Ciclo sui triangoli del sotto-box corrente for ( auto nT : vnIds) { + int nTriaTemp ; Triangle3d trCurTria ; - tmSurf.GetTriangle( nT, trCurTria) ; - DistPointTriangle distPT( ptP, trCurTria) ; - double dCurSqDist ; - // Se la distanza del triangolo è valida e minore di quella attuale aggiorno - if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) { - dMinSqDist = dCurSqDist ; - nMinDistTriaIndex = nT ; - distPT.GetMinDistPoint( ptMinDistPoint) ; + if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, trCurTria)) { + pStm->SetTempInt( nT, 1) ; + DistPointTriangle distPT( ptP, trCurTria) ; + double dCurSqDist ; + // Se la distanza del triangolo è valida e minore di quella attuale aggiorno + if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) { + dMinSqDist = dCurSqDist ; + nMinDistTriaIndex = nT ; + distPT.GetMinDistPoint( ptMinDistPoint) ; + } } } } @@ -161,9 +168,9 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf) m_nMinDistTriaIndex = nMinDistTriaIndex ; m_ptMinDistPoint = ptMinDistPoint ; Triangle3d trMinDistTria ; - tmSurf.GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; + pStm->GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ; trMinDistTria.Validate() ; - m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && tmSurf.IsClosed() ; + m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && pStm->IsClosed() ; } } @@ -202,3 +209,80 @@ DistPointSurfTm::GetMinDistTriaIndex( int& nMinDistIndex) nMinDistIndex = m_nMinDistTriaIndex ; return true ; } + +//---------------------------------------------------------------------------- +int +GetSurfTmNearestVertex( const Point3d& ptP, const ISurfTriMesh& tmSurf) +{ + // Lavoro con l'oggetto superficie trimesh di base + const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ; + if ( pStm == nullptr) + return SVT_NULL ; + + // Recupero e verifico il box locale della superficie + BBox3d b3Stm = pStm->GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return SVT_NULL ; + + // Cerco triangoli in box centrati sul punto dato di ampiezza crescente ed escludendo le parti già verificate. + // Termino quando non trovo più triangoli che possano soddisfare la richiesta. + Point3d ptMin, ptMax ; b3Stm.GetMinMax( ptMin, ptMax) ; + double dDeltaLen = max( min( min( b3Stm.GetDimX(), b3Stm.GetDimY()), b3Stm.GetDimZ()) / 40., 20.) ; + double dBoxHalfLenX = max( max( ptMin.x - ptP.x, ptP.x - ptMax.x), 0.) + dDeltaLen ; + double dBoxHalfLenY = max( max( ptMin.y - ptP.y, ptP.y - ptMax.y), 0.) + dDeltaLen ; + double dBoxHalfLenZ = max( max( ptMin.z - ptP.z, ptP.z - ptMax.z), 0.) + dDeltaLen ; + // Considero anche il box precedente per poter analizzare solo il volume differenza tra i due + BBox3d boxPPrev( ptP) ; + BBox3d boxP( ptP, dBoxHalfLenX, dBoxHalfLenY, dBoxHalfLenZ) ; + // Variabili distanza minima + int nVert = SVT_NULL ; + double dMinSqDist = DBL_MAX ; + // Finché non si verifica la condizione di terminazione ingrandisco il box. + pStm->ResetTempInts() ; + bool bContinue = true ; + while ( bContinue) { + // Calcolo il box differenza con il precedente per non esplorare parti già considerate + BOXVECTOR vBox ; + BoundingBoxDifference( boxP, boxPPrev, vBox) ; + // Ciclo sui box differenza + bool bCollide = false ; + for ( const auto& b3Box : vBox) { + // interseco il box con quello della superficie e ne verifico la distanza minima dal punto + BBox3d b3Int ; + if ( ! b3Box.FindIntersection( b3Stm, b3Int) || b3Int.SqDistFromPoint( ptP) > dMinSqDist) + continue ; + // ricerca sui triangoli nel box + bCollide = true ; + INTVECTOR vnIds ; + if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) { + // Ciclo sui triangoli del sotto-box corrente + for ( auto nT : vnIds) { + int nTriaTemp ; + int nIdVert[3] ; + if ( pStm->GetTempInt( nT, nTriaTemp) && nTriaTemp == 0 && pStm->GetTriangle( nT, nIdVert)) { + pStm->SetTempInt( nT, 1) ; + for ( int i = 0 ; i < 3 ; ++ i) { + Point3d ptVert ; + if ( ! pStm->GetVertex( nIdVert[i], ptVert)) + continue ; + double dCurrSqDist = SqDist( ptP, ptVert) ; + if ( dCurrSqDist < dMinSqDist) { + dMinSqDist = dCurrSqDist ; + nVert = nIdVert[i] ; + } + } + } + } + } + } + // Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box + if ( ! bCollide || dMinSqDist < EPS_SMALL * EPS_SMALL) + bContinue = false ; + else { + boxPPrev = boxP ; + boxP.Expand( dDeltaLen) ; + } + } + + return nVert ; +} diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 7ebcefa..919251a 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index b96a850..29c83a8 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -401,6 +401,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -621,6 +622,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index ae40974..e2ac335 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -483,6 +483,9 @@ File di origine\GeoInters + + File di origine\Geo + @@ -1127,6 +1130,9 @@ File di intestazione + + File di intestazione + diff --git a/ExtDimension.cpp b/ExtDimension.cpp index c5af800..d190c54 100644 --- a/ExtDimension.cpp +++ b/ExtDimension.cpp @@ -305,7 +305,7 @@ ExtDimension::Clone( void) const bool ExtDimension::CopyFrom( const IGeoObj* pGObjSrc) { - const ExtDimension* pDim = dynamic_cast( pGObjSrc) ; + const ExtDimension* pDim = GetBasicExtDimension( pGObjSrc) ; if ( pDim == nullptr) return false ; return CopyFrom( *pDim) ; @@ -666,6 +666,7 @@ ExtDimension::Translate( const Vector3d& vtMove) // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { m_ptP1.Translate( vtMove) ; @@ -685,9 +686,14 @@ ExtDimension::Translate( const Vector3d& vtMove) bool ExtDimension::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { return ( m_vtN.Rotate( vtAx, dCosAng, dSinAng) && @@ -711,9 +717,11 @@ ExtDimension::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, doubl // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // sistemo i vettori @@ -757,9 +765,11 @@ ExtDimension::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // eseguo il mirror dei versori @@ -795,9 +805,11 @@ ExtDimension::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // sistemo i vettori @@ -841,12 +853,15 @@ ExtDimension::ToGlob( const Frame3d& frRef) // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se riferimento globale, non devo fare alcunch� - if ( AreSameFrame( frRef, GLOB_FRM)) + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) return true ; - // imposto ricalcolo + + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori @@ -871,12 +886,15 @@ ExtDimension::ToLoc( const Frame3d& frRef) // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se riferimento globale, non devo fare alcunch� - if ( AreSameFrame( frRef, GLOB_FRM)) + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) return true ; - // imposto ricalcolo + + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori @@ -901,12 +919,15 @@ ExtDimension::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo m_bToCalc = true ; m_OGrMgr.Reset() ; + // se valido if ( m_nType >= DT_LINEAR && m_nType <= DT_ANGULAR) { // trasformo punto e versori diff --git a/ExtDimension.h b/ExtDimension.h index 688244e..f8ccc70 100644 --- a/ExtDimension.h +++ b/ExtDimension.h @@ -159,3 +159,19 @@ class ExtDimension : public IExtDimension, public IGeoObjRW double m_dTextHeight ; // altezza del testo int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline ExtDimension* CreateBasicExtDimension( void) + { return ( static_cast( CreateGeoObj( EXT_DIMENSION))) ; } +inline ExtDimension* CloneBasicExtDimension( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_DIMENSION) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const ExtDimension* GetBasicExtDimension( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_DIMENSION) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline ExtDimension* GetBasicExtDimension( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_DIMENSION) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/ExtText.cpp b/ExtText.cpp index 6662878..150a6dc 100644 --- a/ExtText.cpp +++ b/ExtText.cpp @@ -161,7 +161,7 @@ ExtText::Clone( void) const bool ExtText::CopyFrom( const IGeoObj* pGObjSrc) { - const ExtText* pTxt = dynamic_cast( pGObjSrc) ; + const ExtText* pTxt = GetBasicExtText( pGObjSrc) ; if ( pTxt == nullptr) return false ; return CopyFrom( *pTxt) ; @@ -399,8 +399,11 @@ ExtText::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const bool ExtText::Translate( const Vector3d& vtMove) { + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + + // eseguo m_ptP.Translate( vtMove) ; return true ; } @@ -409,8 +412,15 @@ ExtText::Translate( const Vector3d& vtMove) bool ExtText::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + + // eseguo return ( m_ptP.Rotate( ptAx, vtAx, dCosAng, dSinAng) && m_vtN.Rotate( vtAx, dCosAng, dSinAng) && m_vtD.Rotate( vtAx, dCosAng, dSinAng)) ; @@ -532,9 +542,18 @@ ExtText::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD bool ExtText::ToGlob( const Frame3d& frRef) { + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo punto e versori return ( m_ptP.ToGlob( frRef) && m_vtN.ToGlob( frRef) && @@ -545,9 +564,18 @@ ExtText::ToGlob( const Frame3d& frRef) bool ExtText::ToLoc( const Frame3d& frRef) { + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo punto e versori return ( m_ptP.ToLoc( frRef) && m_vtN.ToLoc( frRef) && @@ -561,12 +589,15 @@ ExtText::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo punto e versori return ( m_ptP.ToGlob( frOri) && m_ptP.ToLoc( frDest) && m_vtN.ToGlob( frOri) && m_vtN.ToLoc( frDest) && diff --git a/ExtText.h b/ExtText.h index 053ed4a..4b56bff 100644 --- a/ExtText.h +++ b/ExtText.h @@ -146,3 +146,19 @@ class ExtText : public IExtText, public IGeoObjRW int m_nInsPos ; // posizione del punto di inserimento rispetto al testo int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline ExtText* CreateBasicExtText( void) + { return ( static_cast( CreateGeoObj( EXT_TEXT))) ; } +inline ExtText* CloneBasicExtText( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_TEXT) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const ExtText* GetBasicExtText( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_TEXT) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline ExtText* GetBasicExtText( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != EXT_TEXT) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GdbGeo.h b/GdbGeo.h index cdc5c0d..acb42d4 100644 --- a/GdbGeo.h +++ b/GdbGeo.h @@ -54,6 +54,10 @@ class GdbGeo : public GdbObj //---------------------------------------------------------------------------- inline const GdbGeo* GetGdbGeo( const GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GEO) + return nullptr ; + return static_cast( pGObj) ; } inline GdbGeo* GetGdbGeo( GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GEO) + return nullptr ; + return static_cast( pGObj) ; } diff --git a/GdbGroup.h b/GdbGroup.h index 45981a2..b7d38f5 100644 --- a/GdbGroup.h +++ b/GdbGroup.h @@ -91,6 +91,10 @@ class GdbGroup : public GdbObj //---------------------------------------------------------------------------- inline const GdbGroup* GetGdbGroup( const GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GROUP) + return nullptr ; + return static_cast( pGObj) ; } inline GdbGroup* GetGdbGroup( GdbObj* pGObj) - { return dynamic_cast(pGObj) ; } + { if ( pGObj == nullptr || pGObj->GetGdbType() != GDB_TY_GROUP) + return nullptr ; + return static_cast( pGObj) ; } diff --git a/GdbIterator.cpp b/GdbIterator.cpp index ddf3b8a..f5f7d26 100644 --- a/GdbIterator.cpp +++ b/GdbIterator.cpp @@ -24,7 +24,7 @@ using namespace std ; IGdbIterator* CreateGdbIterator( IGeomDB* pGDB) { - if ( dynamic_cast( pGDB) == nullptr) + if ( static_cast( pGDB) == nullptr) return nullptr ; return static_cast ( new( nothrow) GdbIterator( pGDB)) ; } @@ -53,7 +53,7 @@ GdbIterator::~GdbIterator( void) bool GdbIterator::SetGDB( IGeomDB* pGDB) { - m_pGDB = dynamic_cast( pGDB) ; + m_pGDB = static_cast( pGDB) ; if ( m_pGDB == nullptr) return false ; @@ -105,7 +105,7 @@ GdbIterator::GoToFirstInGroup( const IGdbIterator& iIter) return false ; } - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -167,7 +167,7 @@ GdbIterator::GoToLastInGroup( const IGdbIterator& iIter) return false ; } - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -263,7 +263,7 @@ GdbIterator::GoToFirstNameInGroup( const IGdbIterator& iIter, const string& sNam return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -345,7 +345,7 @@ GdbIterator::GoToLastNameInGroup( const IGdbIterator& iIter, const string& sName return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -474,7 +474,7 @@ GdbIterator::GoToFirstGroupInGroup( const IGdbIterator& iIter) return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -553,7 +553,7 @@ GdbIterator::GoToLastGroupInGroup( const IGdbIterator& iIter) return false ; } // converto in oggetto iteratore di base - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB) { m_pCurrObj = nullptr ; return false ; @@ -1637,7 +1637,7 @@ GdbIterator::CopyAllInfoFrom( const IGdbIterator& iIter) return false ; // recupero l'oggetto sorgente - const GdbIterator* pIter = dynamic_cast (&iIter) ; + const GdbIterator* pIter = static_cast (&iIter) ; if ( pIter == nullptr || pIter->m_pGDB != m_pGDB || pIter->m_pCurrObj == nullptr) return false ; const GdbObj* pGdbObjSou = pIter->m_pCurrObj ; @@ -1651,6 +1651,29 @@ GdbIterator::CopyAllInfoFrom( const IGdbIterator& iIter) return true ; } +//---------------------------------------------------------------------------- +// Stipple (significativo solo per curve) + +//---------------------------------------------------------------------------- +bool +GdbIterator::SetStipple( int nFactor, int nPattern) +{ + if ( m_pGDB == nullptr || m_pCurrObj == nullptr) + return false ; + // imposto lo stipple + return m_pCurrObj->SetStipple( nFactor, nPattern) ; +} + +//---------------------------------------------------------------------------- +bool +GdbIterator::GetStipple( int& nFactor, int& nPattern) const +{ + if ( m_pGDB == nullptr || m_pCurrObj == nullptr) + return false ; + // recupero lo stipple + return m_pCurrObj->GetStipple( nFactor, nPattern) ; +} + //---------------------------------------------------------------------------- // TextureData //---------------------------------------------------------------------------- diff --git a/GdbIterator.h b/GdbIterator.h index 89a5848..f43ccac 100644 --- a/GdbIterator.h +++ b/GdbIterator.h @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2013-2022 +// EgalTech 2013-2023 //---------------------------------------------------------------------------- -// File : GdbIterator.h Data : 29.01.23 Versione : 2.5a2 +// File : GdbIterator.h Data : 09.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe GdbIterator. // // @@ -144,6 +144,9 @@ class GdbIterator : public IGdbIterator bool RemoveInfo( const std::string& sKey) override ; bool GetAllInfo( STRVECTOR& vsInfo) const override ; bool CopyAllInfoFrom( const IGdbIterator& iIter) override ; + // Stipple + bool SetStipple( int nFactor, int nPattern) override ; + bool GetStipple( int& nFactor, int& nPattern) const override ; // TextureData bool SetTextureName( const std::string& sTxrName) override ; bool SetTextureFrame( const Frame3d& frTxrRef) override ; diff --git a/GdbObj.cpp b/GdbObj.cpp index a9a4bd9..0bdda80 100644 --- a/GdbObj.cpp +++ b/GdbObj.cpp @@ -31,10 +31,9 @@ using namespace std ; //---------------------------------------------------------------------------- GdbObj::GdbObj( void) - : m_nId( GDB_ID_NULL), m_pAttribs( nullptr), m_pTxrData( nullptr), m_pUserObj( nullptr), - m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr), + : m_nId( GDB_ID_NULL), m_pAttribs( nullptr), m_nStpFactor( 0), m_nStpPattern( 0), m_pTxrData( nullptr), + m_pUserObj( nullptr), m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr), m_pSelNext( nullptr), m_pSelPrev( nullptr) - { } @@ -73,6 +72,9 @@ GdbObj::CopyFrom( const GdbObj* pSou) if ( m_pAttribs != nullptr) delete m_pAttribs ; m_pAttribs = nullptr ; + // reset stipple + m_nStpFactor = 0 ; + m_nStpPattern = 0 ; // elimino eventuali dati della texture pre-esistenti if ( m_pTxrData != nullptr) delete m_pTxrData ; @@ -91,6 +93,10 @@ GdbObj::CopyFrom( const GdbObj* pSou) // copio Id m_nId = pSou->m_nId ; + // copio stipple + m_nStpFactor = pSou->m_nStpFactor ; + m_nStpPattern = pSou->m_nStpPattern ; + // copio gli attributi, i dati della texture e UserObj return ( CopyAttribsFrom( pSou) && CopyTextureDataFrom( pSou) && CopyUserObjFrom( pSou)) ; } @@ -1037,6 +1043,26 @@ GdbObj::GetAllInfo( STRVECTOR& vsInfo) const return m_pAttribs->GetAllInfo( vsInfo) ; } +//---------------------------------------------------------------------------- +// Stipple (significativo solo per curve, per ora non viene salvato) +//---------------------------------------------------------------------------- +bool +GdbObj::SetStipple( int nFactor, int nPattern) +{ + m_nStpFactor = nFactor ; + m_nStpPattern = nPattern ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbObj::GetStipple( int& nFactor, int& nPattern) const +{ + nFactor = m_nStpFactor ; + nPattern = m_nStpPattern ; + return true ; +} + //---------------------------------------------------------------------------- // TextureData //---------------------------------------------------------------------------- diff --git a/GdbObj.h b/GdbObj.h index 5e1ae02..8b2a50b 100644 --- a/GdbObj.h +++ b/GdbObj.h @@ -120,6 +120,8 @@ class GdbObj bool ExistsInfo( const std::string& sKey) const ; bool RemoveInfo( const std::string& sKey) ; bool GetAllInfo( STRVECTOR& vsInfo) const ; + bool SetStipple( int nFactor, int nPattern) ; + bool GetStipple( int& nFactor, int& nPattern) const ; bool SaveTextureData( NgeWriter& ngeOut) const ; bool LoadTextureData( NgeReader& ngeIn) ; TextureData* GetTextureData( void) @@ -161,6 +163,8 @@ class GdbObj public : int m_nId ; Attribs* m_pAttribs ; + int m_nStpFactor ; + int m_nStpPattern ; TextureData* m_pTxrData ; IUserObj* m_pUserObj ; diff --git a/GeoFrame3d.cpp b/GeoFrame3d.cpp index 54d2be4..e3ca1f0 100644 --- a/GeoFrame3d.cpp +++ b/GeoFrame3d.cpp @@ -104,7 +104,7 @@ GeoFrame3d::Clone( void) const bool GeoFrame3d::CopyFrom( const IGeoObj* pGObjSrc) { - const GeoFrame3d* pGFr = dynamic_cast( pGObjSrc) ; + const GeoFrame3d* pGFr = GetBasicGeoFrame3d( pGObjSrc) ; if ( pGFr == nullptr) return false ; return CopyFrom( *pGFr) ; diff --git a/GeoFrame3d.h b/GeoFrame3d.h index 728c1b0..850a0a1 100644 --- a/GeoFrame3d.h +++ b/GeoFrame3d.h @@ -98,3 +98,19 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW Frame3d m_frF ; // oggetto int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline GeoFrame3d* CreateBasicGeoFrame3d( void) + { return ( static_cast( CreateGeoObj( GEO_FRAME3D))) ; } +inline GeoFrame3d* CloneBasicGeoFrame3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_FRAME3D) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const GeoFrame3d* GetBasicGeoFrame3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_FRAME3D) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline GeoFrame3d* GetBasicGeoFrame3d( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_FRAME3D) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GeoPoint3d.cpp b/GeoPoint3d.cpp index 0f53b5d..6f02969 100644 --- a/GeoPoint3d.cpp +++ b/GeoPoint3d.cpp @@ -72,7 +72,7 @@ GeoPoint3d::Clone( void) const bool GeoPoint3d::CopyFrom( const IGeoObj* pGObjSrc) { - const GeoPoint3d* pGP = dynamic_cast( pGObjSrc) ; + const GeoPoint3d* pGP = GetBasicGeoPoint3d( pGObjSrc) ; if ( pGP == nullptr) return false ; return CopyFrom( *pGP) ; diff --git a/GeoPoint3d.h b/GeoPoint3d.h index 59f08a0..532d6a4 100644 --- a/GeoPoint3d.h +++ b/GeoPoint3d.h @@ -92,3 +92,19 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW Point3d m_ptP ; // oggetto int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline GeoPoint3d* CreateBasicGeoPoint3d( void) + { return ( static_cast( CreateGeoObj( GEO_PNT3D))) ; } +inline GeoPoint3d* CloneBasicGeoPoint3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_PNT3D) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const GeoPoint3d* GetBasicGeoPoint3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_PNT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline GeoPoint3d* GetBasicGeoPoint3d( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_PNT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GeoVector3d.cpp b/GeoVector3d.cpp index eef867a..b93875a 100644 --- a/GeoVector3d.cpp +++ b/GeoVector3d.cpp @@ -88,7 +88,7 @@ GeoVector3d::Clone( void) const bool GeoVector3d::CopyFrom( const IGeoObj* pGObjSrc) { - const GeoVector3d* pGV = dynamic_cast( pGObjSrc) ; + const GeoVector3d* pGV = GetBasicGeoVector3d( pGObjSrc) ; if ( pGV == nullptr) return false ; return CopyFrom( *pGV) ; diff --git a/GeoVector3d.h b/GeoVector3d.h index aaeac07..b824f2e 100644 --- a/GeoVector3d.h +++ b/GeoVector3d.h @@ -107,3 +107,19 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW Point3d m_ptBase ; // punto base da cui tracciare il vettore int m_nTempProp[2] ; // vettore proprietà temporanee } ; + +//----------------------------------------------------------------------------- +inline GeoVector3d* CreateBasicGeoVector3d( void) + { return ( static_cast( CreateGeoObj( GEO_VECT3D))) ; } +inline GeoVector3d* CloneBasicGeoVector3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_VECT3D) + return nullptr ; + return ( static_cast( pGObj->Clone())) ; } +inline const GeoVector3d* GetBasicGeoVector3d( const IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_VECT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } +inline GeoVector3d* GetBasicGeoVector3d( IGeoObj* pGObj) + { if ( pGObj == nullptr || pGObj->GetType() != GEO_VECT3D) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/GeomDB.cpp b/GeomDB.cpp index 26f79fe..80a13bc 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -30,9 +30,31 @@ #include "/EgtDev/Include/SELkKeyProc.h" #include #include +#include using namespace std ; +//---------------------------------------------------------------------------- +class LockAddErase +{ + public : + LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) + { if ( ! m_bUse) return ; + while ( m_bAddEraseOn.test_and_set()) { + this_thread::sleep_for( chrono::nanoseconds{ 1}) ; + } + } ; + + ~LockAddErase( void) + { if ( ! m_bUse) return ; + m_bAddEraseOn.clear() ; + } ; + + private : + std::atomic_flag& m_bAddEraseOn ; + bool m_bUse ; +} ; + //---------------------------------------------------------------------------- IGeomDB* CreateGeomDB( void) @@ -68,6 +90,7 @@ CreateGeomDB( void) //---------------------------------------------------------------------------- GeomDB::GeomDB( void) { + m_bAddEraseOn.clear() ; m_GrpRadix.SetGeomDB( this) ; m_GrpRadix.m_nId = GDB_ID_ROOT ; m_GrpRadix.SetMaterial( Color()) ; @@ -430,7 +453,7 @@ GeomDB::Save( const INTVECTOR& vId, const string& sFileOut, int nFlag) const return false ; // ciclo sugli oggetti da esportare - unordered_set usSavedId ; + INTUNORDSET usSavedId ; for ( const auto nId : vId) { // se già salvato, passo oltre @@ -595,25 +618,32 @@ GeomDB::GetGdbObj( int nId) const //---------------------------------------------------------------------------- bool -GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTestId) +GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLockAddErase, bool bTestId) { // verifico validità oggetto puntato if ( pGObj == nullptr) return false ; - // se richiesta, verifica validità e unicità del nome - if ( bTestId && ( pGObj->m_nId <= GDB_ID_ROOT || ExistsObj( pGObj->m_nId))) + // verifico validità del riferimento + if ( nRefId < GDB_ID_ROOT) return false ; // oggetto e riferimento non possono essere la stessa cosa if ( pGObj->m_nId == nRefId) return ( ! IS_GDB_SON( nSonBeforeAfter)) ; + // verifico unicità esecuzione, se necessaria + LockAddErase Lock( m_bAddEraseOn, bLockAddErase) ; + // cerco il riferimento GdbObj* pGRef = GetGdbObj( nRefId) ; if ( pGRef == nullptr) return false ; + // se richiesta, verifica validità e unicità del nome + if ( bTestId && ( pGObj->m_nId <= GDB_ID_ROOT || ExistsObj( pGObj->m_nId))) + return false ; + // assegno il riferimento al DB geometrico pGObj->SetGeomDB( this) ; @@ -629,7 +659,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTe } // inserisco come figlio, in testa alla lista del padre else if ( nSonBeforeAfter == GDB_FIRST_SON){ - GdbGroup* pGroup = dynamic_cast ( pGRef) ; + GdbGroup* pGroup = ::GetGdbGroup( pGRef) ; if ( pGroup == nullptr) return false ; // inserisco in testa alla lista del padre @@ -638,7 +668,7 @@ GeomDB::InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTe } // inserisco come figlio, in coda alla lista del padre else { - GdbGroup* pGroup = dynamic_cast ( pGRef) ; + GdbGroup* pGroup = ::GetGdbGroup( pGRef) ; if ( pGroup == nullptr) return false ; // inserisco in coda alla lista del padre @@ -667,6 +697,8 @@ GeomDB::InsertGroup( int nId, int nRefId, int nSonBeforeAfter, const Frame3d& fr // verifico validità apparente RefId if ( nRefId < GDB_ID_ROOT) return GDB_ID_NULL ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; // verifico validità Id if ( nId <= GDB_ID_ROOT) nId = m_IdManager.GetNewId() ; @@ -681,7 +713,7 @@ GeomDB::InsertGroup( int nId, int nRefId, int nSonBeforeAfter, const Frame3d& fr // assegno riferimento pGdbGroup->SetFrame( frFrame) ; // inserisco nel DB - if ( ! InsertInGeomDB( pGdbGroup, nRefId, nSonBeforeAfter)) { + if ( ! InsertInGeomDB( pGdbGroup, nRefId, nSonBeforeAfter, false)) { delete pGdbGroup ; return GDB_ID_NULL ; } @@ -702,6 +734,8 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj { // assegno GeoObj a gestore puntatore con rilascio automatico PtrOwner pRPGeoObj( pGeoObj) ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; // verifico validità identificativo if ( nId <= GDB_ID_ROOT) nId = m_IdManager.GetNewId() ; @@ -719,7 +753,7 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj // assegno dati pGdbGeo->m_pGeoObj = Release( pRPGeoObj) ; // inserisco nel DB - if ( ! InsertInGeomDB( pGdbGeo, nRefId, nSonBeforeAfter)) { + if ( ! InsertInGeomDB( pGdbGeo, nRefId, nSonBeforeAfter, false)) { delete pGdbGeo ; return GDB_ID_NULL ; } @@ -1202,6 +1236,9 @@ GeomDB::GetRefBBox( int nId, const Frame3d& frRef, BBox3d& b3Ref, int nFlag) con int GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGlob) { + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // verifico Id destinazione if ( nIdDest <= GDB_ID_ROOT) nIdDest = m_IdManager.GetNewId() ; @@ -1244,7 +1281,7 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl } // inserisco nel DB (non rilascio il puntatore) - if ( ! InsertInGeomDB( pGdODest, nRefId, nSonBeforeAfter)) + if ( ! InsertInGeomDB( pGdODest, nRefId, nSonBeforeAfter, false)) return GDB_ID_NULL ; // rilascio il puntatore @@ -1256,10 +1293,17 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl bool GeomDB::Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) { - // l'oggetto e il riferimento non possono coincidere + // verifico validità del riferimento + if ( nRefId < GDB_ID_ROOT) + return false ; + + // l'oggetto e il riferimento non possono coincidere if ( nId == nRefId) return ( ! IS_GDB_SON( nSonBeforeAfter)) ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // verifico esistenza dell'oggetto GdbObj* pGdbObj = GetGdbObj( nId) ; if ( pGdbObj == nullptr) @@ -1303,7 +1347,7 @@ GeomDB::Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) pGdbObj->Remove() ; // lo inserisco nella posizione opportuna - if ( ! InsertInGeomDB( pGdbObj, nRefId, nSonBeforeAfter, false)) { + if ( ! InsertInGeomDB( pGdbObj, nRefId, nSonBeforeAfter, false, false)) { // in caso di errore (condizione assai remota qui) cancello tutto m_IdManager.RemoveObj( pGdbObj->m_nId) ; m_SelManager.RemoveObj( pGdbObj) ; @@ -1384,9 +1428,14 @@ GeomDB::GetNewId( void) const bool GeomDB::ChangeId( int nId, int nNewId) { + // se Id non validi, ritorno errore + if ( nId <= GDB_ID_ROOT || nNewId <= GDB_ID_ROOT) + return false ; // se Id identici, non faccio alcunché if ( nNewId == nId) return true ; + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; // verifico nuovo Id if ( ExistsObj( nNewId)) return false ; @@ -1427,7 +1476,10 @@ GeomDB::Erase( GdbObj* pGdbObj) if ( pGdbObj == nullptr || pGdbObj == &m_GrpRadix) return false ; - // notifico eventuale UserObj + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + + // notifico eventuale UserObj if ( pGdbObj->m_pUserObj != nullptr) { // recupero il successivo const GdbObj* pGdbNext = pGdbObj->GetNext() ; @@ -1452,6 +1504,10 @@ GeomDB::RemoveGeoObjAndErase( int nId) // non si può cancellare il gruppo radice (escludo anche Id non validi) if ( nId <= GDB_ID_ROOT) return nullptr ; + + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // recupero l'oggetto geometrico GdbGeo* pGdbGeo = ::GetGdbGeo( m_IdManager.FindObj( nId)) ; if ( pGdbGeo == nullptr) @@ -1459,6 +1515,7 @@ GeomDB::RemoveGeoObjAndErase( int nId) IGeoObj* pGeoObj = pGdbGeo->m_pGeoObj ; // annullo il riferimento alla geometria nell'entità pGdbGeo->m_pGeoObj = nullptr ; + // tolgo dalla lista e disalloco pGdbGeo->Remove() ; delete pGdbGeo ; @@ -1494,6 +1551,10 @@ GeomDB::EmptyGroup( GdbObj* pGdbObj) GdbGroup* pGrp = ::GetGdbGroup( pGdbObj) ; if ( pGrp == nullptr) return false ; + + // verifico unicità esecuzione + LockAddErase Lock( m_bAddEraseOn) ; + // lo svuoto return pGrp->Clear() ; } @@ -2929,6 +2990,51 @@ GeomDB::CopyAllInfoFrom( int nId, int nSouId) return true ; } +//---------------------------------------------------------------------------- +// Stipple (significativo solo per curve) +//---------------------------------------------------------------------------- +bool +GeomDB::DumpStipple( int nId, string& sOut, bool bMM, const char* szNewLine) const +{ + // recupero l'oggetto + const GdbObj* pGdbObj = GetGdbObj( nId) ; + if ( pGdbObj == nullptr) + return false ; + // eseguo il dump + if ( pGdbObj->m_nStpFactor != 0) { + // nome della texture + sOut += "Stipple=" ; + sOut += ToString( pGdbObj->m_nStpFactor) ; + sOut += "-" + ToString( pGdbObj->m_nStpPattern, 1, 16) ; + sOut += szNewLine ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GeomDB::SetStipple( int nId, int nFactor, int nPattern) +{ + // recupero l'oggetto + GdbObj* pGdbObj = GetGdbObj( nId) ; + if ( pGdbObj == nullptr) + return false ; + // imposto lo stipple + return pGdbObj->SetStipple( nFactor, nPattern) ; +} + +//---------------------------------------------------------------------------- +bool +GeomDB::GetStipple( int nId, int& nFactor, int& nPattern) const +{ + // recupero l'oggetto + const GdbObj* pGdbObj = GetGdbObj( nId) ; + if ( pGdbObj == nullptr) + return false ; + // recupero lo stipple + return pGdbObj->GetStipple( nFactor, nPattern) ; +} + //---------------------------------------------------------------------------- // TextureData //---------------------------------------------------------------------------- @@ -2940,7 +3046,7 @@ GeomDB::DumpTextureData( int nId, string& sOut, bool bMM, const char* szNewLine) if ( pGdbObj == nullptr) return false ; // eseguo il dump - if ( pGdbObj->m_pTxrData != nullptr) + if ( pGdbObj->m_pTxrData != nullptr) return pGdbObj->m_pTxrData->Dump( *this, sOut, bMM, szNewLine) ; else return true ; diff --git a/GeomDB.h b/GeomDB.h index 5295b92..3454ba9 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- -// EgalTech 2013-2014 +// EgalTech 2013-2023 //---------------------------------------------------------------------------- -// File : GeomDB.h Data : 03.12.14 Versione : 1.5l1 +// File : GeomDB.h Data : 09.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe GeomDB. // // // // Modifiche : 22.01.13 DS Creazione modulo. -// 03.12.14 DS Aggiunta gestione riferimento di griglia. +// // //---------------------------------------------------------------------------- @@ -20,6 +20,7 @@ #include "SelManager.h" #include "GdbMaterialMgr.h" #include "/EgtDev/Include/EGkGeomDB.h" +#include //---------------------------------------------------------------------------- class GeomDB : public IGeomDB @@ -181,6 +182,10 @@ class GeomDB : public IGeomDB bool RemoveInfo( int nId, const std::string& sKey) override ; bool GetAllInfo( int nId, STRVECTOR& vsInfo) const override ; bool CopyAllInfoFrom( int nId, int nSouId) override ; + // Stipple (significativo solo per curve) + bool DumpStipple( int nId, std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ; + bool SetStipple( int nId, int nFactor, int nPattern) override ; + bool GetStipple( int nId, int& nFactor, int& nPattern) const override ; // TextureData bool DumpTextureData( int nId, std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ; bool SetTextureName( int nId, const std::string& sTxrName) override ; @@ -222,14 +227,14 @@ class GeomDB : public IGeomDB GdbObj* GetGdbObj( int nId) ; const GdbObj* GetGdbObj( int nId) const ; GdbGeo* GetGdbGeo( int nId) - { return dynamic_cast( GetGdbObj( nId)) ; } + { return ::GetGdbGeo( GetGdbObj( nId)) ; } const GdbGeo* GetGdbGeo( int nId) const - { return dynamic_cast( GetGdbObj( nId)) ; } + { return ::GetGdbGeo( GetGdbObj( nId)) ; } GdbGroup* GetGdbGroup( int nId) - { return dynamic_cast( GetGdbObj( nId)) ; } + { return ::GetGdbGroup( GetGdbObj( nId)) ; } const GdbGroup* GetGdbGroup( int nId) const - { return dynamic_cast( GetGdbObj( nId)) ; } - bool InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bTestId = true) ; + { return ::GetGdbGroup( GetGdbObj( nId)) ; } + bool InsertInGeomDB( GdbObj* pGObj, int nRefId, int nSonBeforeAfter, bool bLockAddErase = true, bool bTestId = true) ; int Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGlob) ; bool Relocate( int nId, int nRefId, int nSonBeforeAfter, bool bGlob) ; bool Erase( GdbObj* pGObj) ; @@ -253,10 +258,11 @@ class GeomDB : public IGeomDB { return m_IterManager.RemoveGdbIterator( pIter) ; } private : - IdManager m_IdManager ; // gestore del nuovo Id - IterManager m_IterManager ; // gestore lista iteratori attivi - SelManager m_SelManager ; // gestore lista oggetti selezionati - GdbMaterialMgr m_MatManager ; // gestore lista materiali - GdbGroup m_GrpRadix ; // gruppo radice di tutto il DB - Frame3d m_GridFrame ; // riferimento della griglia + IdManager m_IdManager ; // gestore del nuovo Id + IterManager m_IterManager ; // gestore lista iteratori attivi + SelManager m_SelManager ; // gestore lista oggetti selezionati + GdbMaterialMgr m_MatManager ; // gestore lista materiali + GdbGroup m_GrpRadix ; // gruppo radice di tutto il DB + Frame3d m_GridFrame ; // riferimento della griglia + std::atomic_flag m_bAddEraseOn ; // flag esecuzione inserimento o cancellazione in corso (per multi thread) } ; diff --git a/LineTgTwoCurves.cpp b/LineTgTwoCurves.cpp index 48fd0d6..16cb6e4 100644 --- a/LineTgTwoCurves.cpp +++ b/LineTgTwoCurves.cpp @@ -171,7 +171,7 @@ GetLineTgTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, return nullptr ; // porto il secondo arco nel riferimento intrinseco del primo - CurveArc crvArc2Loc = dynamic_cast( crvArc2) ; + CurveArc crvArc2Loc = crvArc2 ; crvArc2Loc.ToLoc( frIntr) ; // calcolo le linee di tangenza alle due circonferenze diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index 9ec0978..466bacb 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2020 +// EgalTech 2015-2023 //---------------------------------------------------------------------------- -// File : OffsetCurve.cpp Data : 10.10.20 Versione : 2.2j2 +// File : OffsetCurve.cpp Data : 03.08.23 Versione : 2.5h1 // Contenuto : Classe per offset avanzato di Curve. // // @@ -9,6 +9,7 @@ // Modifiche : 23.09.15 DS Creazione modulo. // 24.06.19 DS Agg. GetShorterCurve. // 10.10.20 DS Migliorata gestione angoli interni. +// 03.08.23 DS Migliorato riconoscimento angoli esterni di valore circa 180deg. // //---------------------------------------------------------------------------- @@ -865,16 +866,30 @@ CalcAngle( const ICurve* pCrv1, const ICurve* pCrv2, double& dAngDeg) if ( ! vtDir1.GetAngleXY( vtDir2, dAngDeg)) return false ; // se vicino all'angolo piatto, si devono ricalcolare spostandosi un poco - if ( abs( dAngDeg) > ( ANG_STRAIGHT - EPS_ANG_SMALL)) { - // eseguo calcolo spostato + const double MAX_ANG_DELTA = 2 ; + double dAngDelta = abs( abs( dAngDeg) - ANG_STRAIGHT) ; + if ( dAngDelta < MAX_ANG_DELTA) { + // angolo al centro delle curve + double dAngCen1 = 0 ; + if ( pCrv1->GetType() == CRV_ARC) + dAngCen1 = abs( GetBasicCurveArc( pCrv1)->GetAngCenter()) ; + double dAngCen2 = 0 ; + if ( pCrv2->GetType() == CRV_ARC) + dAngCen2 = abs( GetBasicCurveArc( pCrv2)->GetAngCenter()) ; + // determino posizioni spostate double dU1 = 1 ; + if ( dAngCen1 > EPS_ANG_SMALL) { + dU1 = 1 - min( 1.1 * dAngDelta / ( dAngCen1 + dAngCen2), 0.5) ; + } double dU2 = 0 ; + if ( dAngCen2 > EPS_ANG_SMALL) { + dU2 = 0 + min( 1.1 * dAngDelta / ( dAngCen1 + dAngCen2), 0.5) ; + } + // eseguo calcolo spostato Point3d ptDummy ; Vector3d vtDir1b ; Vector3d vtDir2b ; - if ( ! MoveParamToAvoidTg( dU1, ICurve::FROM_MINUS, *pCrv1) || - ! pCrv1->GetPointTang( dU1, ICurve::FROM_MINUS, ptDummy, vtDir1b) || - ! MoveParamToAvoidTg( dU2, ICurve::FROM_PLUS, *pCrv2) || + if ( ! pCrv1->GetPointTang( dU1, ICurve::FROM_MINUS, ptDummy, vtDir1b) || ! pCrv2->GetPointTang( dU2, ICurve::FROM_PLUS, ptDummy, vtDir2b)) return false ; if ( ! vtDir1b.GetAngleXY( vtDir2b, dAngDeg)) diff --git a/Point3d.cpp b/Point3d.cpp index 236342d..c115d30 100644 --- a/Point3d.cpp +++ b/Point3d.cpp @@ -133,7 +133,7 @@ Point3d::ToGlob( const Frame3d& frRef) y = ptT.x * frRef.VersX().y + ptT.y * frRef.VersY().y + ptT.z * frRef.VersZ().y + frRef.Orig().y ; z = ptT.x * frRef.VersX().z + ptT.y * frRef.VersY().z + ptT.z * frRef.VersZ().z + frRef.Orig().z ; } - else { + else if ( ! frRef.Orig().IsZero()) { x += frRef.Orig().x ; y += frRef.Orig().y ; z += frRef.Orig().z ; @@ -159,7 +159,7 @@ Point3d::ToLoc( const Frame3d& frRef) y = vtT.x * frRef.VersY().x + vtT.y * frRef.VersY().y + vtT.z * frRef.VersY().z ; z = vtT.x * frRef.VersZ().x + vtT.y * frRef.VersZ().y + vtT.z * frRef.VersZ().z ; } - else { + else if ( ! frRef.Orig().IsZero()) { x -= frRef.Orig().x ; y -= frRef.Orig().y ; z -= frRef.Orig().z ; diff --git a/SfrCreate.cpp b/SfrCreate.cpp index 6e4fb9d..00392cf 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -124,8 +124,8 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; if ( vtExtr.IsSmall()) vtExtr = Z_AX ; - PtrOwner pCompo1( CreateBasicCurveComposite()) ; - if ( IsNull( pCompo1) || ! pCompo1->AddCurve( Release( pCurve))) + PtrOwner pCompo1 ; + if ( ! pCompo1.Set( ConvertCurveToBasicComposite( Release( pCurve)))) return nullptr ; pCompo1->SetExtrusion( vtExtr) ; // se distanza tra gli estremi minore di due volte il raggio la chiudo, purchè curva abbastanza lunga diff --git a/SurfAux.cpp b/SurfAux.cpp new file mode 100644 index 0000000..88db54c --- /dev/null +++ b/SurfAux.cpp @@ -0,0 +1,593 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : SurfAux.cpp Data : 09.08.23 Versione : +// Contenuto : Implementazione di alcune funzioni di utilità per le Superfici. +// +// +// +// Modifiche : 09.08.23 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveAux.h" +#include "GeoConst.h" +#include "CurveLine.h" +#include "CurveArc.h" +#include "CurveBezier.h" +#include "CurveComposite.h" +#include "/EgtDev/Include/EgtPointerOwner.h" +#include "/EgtDev/Include/EGkSurf.h" +#include "/EgtDev/Include/EGkSurfAux.h" +#include "/EgtDev/Include/EGkSurfBezier.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +ISurf* +NurbsToBezierSurface(const CNurbsSurfData& cnData) +{ + //INTVECTOR vInt_sub( 10) ; + //INTMATRIX vInt( 10, vInt_sub) ; + //for ( int i = 0 ; i < 10 ; ++i ) { + // for ( int j = 0 ; j < 10 ; ++j ) { + // vInt[i][j] = i + 10 * j ; + // } + //} + //vInt_sub.resize( 20) ; + //vInt[0].resize( 20) ; + + + + + + // la superficie Nurbs deve essere in forma canonica + if ( cnData.bPeriodicU || cnData.bPeriodicV || cnData.bExtraKnotes ) + return nullptr ; + // controllo sul numero dei nodi + int nU = cnData.nCPU + cnData.nDegU - 1 ; + int nV = cnData.nCPV + cnData.nDegV - 1 ; + // controllo nodi e punti di controllo + //if ( nU != int( cnData.vU.size()) || nV != int( cnData.vV.size()) || cnData.nCPU * cnData.nCPV != int( cnData.vCP.size())) + if ( nU != int(cnData.vU.size()) || nV != int(cnData.vV.size())) { + return nullptr ; + } + + //// numero degli intervalli + //int nInt = nU - 2 * cnData.nDeg + 1 ; + // verifico le condizioni agli estremi sui nodi (i primi nDeg nodi e gli ultimi nDeg nodi devono essere uguali tra loro) + bool bOk = true ; + // direzione U + for ( int i = 1 ; i < cnData.nDegU ; ++ i) { + if ( abs( cnData.vU[i] - cnData.vU[0]) >= EPS_ZERO) + bOk = false ; + } + for ( int i = 1 ; i < cnData.nDegU ; ++ i) { + if ( abs( cnData.vU[nU - 1 - i] - cnData.vU[nU - 1]) >= EPS_ZERO) + bOk = false ; + } + // direzione V + for ( int i = 1 ; i < cnData.nDegV ; ++ i) { + if ( abs( cnData.vV[i] - cnData.vV[0]) >= EPS_ZERO) + bOk = false ; + } + for ( int i = 1 ; i < cnData.nDegV ; ++ i) { + if ( abs( cnData.vV[nV - 1 - i] - cnData.vV[nV - 1]) >= EPS_ZERO) + bOk = false ; + } + if ( ! bOk) + return nullptr ; + + //// se 1 solo intervallo, la Nurbs è già una curva di Bezier + //if ( nInt == 1) { + // // creo la curva di Bezier + // PtrOwner pCrvBez( CreateCurveBezier()) ; + // if ( IsNull( pCrvBez)) + // return nullptr ; + // // la inizializzo + // if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat)) + // return nullptr ; + // for ( int i = 0 ; i <= cnData.nDeg ; ++ i) { + // if ( ! cnData.bRat) { + // if ( ! pCrvBez->SetControlPoint( i, cnData.vCP[i])) + // return nullptr ; + // } + // else { + // if ( ! pCrvBez->SetControlPoint( i, cnData.vCP[i], cnData.vW[i])) + // return nullptr ; + // } + // } + // // se non è una curva ma un punto, la invalido + // if ( pCrvBez->IsAPoint()) + // pCrvBez->Init( cnData.nDeg, cnData.bRat) ; + // // restituisco la curva + // return Release( pCrvBez) ; + //} + + + // algoritmo 5.7 del libro "The NURBS book"////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // creazione delle strips nella direzione U ( trasformo le curve iso con U costante in bezier) + int a = cnData.nDegU - 1 ; + int b = cnData.nDegU ; + int nb = 0 ; // numero di strisce in U ( lunghezza con U costante) + //PNTVECTOR vBC ; + //vBC.resize( cnData.nCPV * cnData.nDegU) ; + //for (int row = 0 ; row < cnData.nCPV ; ++row ) { + // for ( int i = 0 ; i <= cnData.nDegU ; ++i ) { + // vBC[nDegU*row + i] = ( cnData.vCP[nCPU*row + i]) ; + // } + //} + vector vCPV( cnData.nCPV) ; + vector< vector> mBC (cnData.nDegU + 1,vCPV ) ; + vector< vector> mBC_next (cnData.nDegU - 1, vCPV) ; + vector< vector> mPC_strip(cnData.nDegU + 1, vCPV) ; // matrice che verrà ingrandita e conterrà la superficie metà bezier e metà NURBS + DBLVECTOR vV_W( cnData.nCPV) ; + vector mW( cnData.nDegU + 1, vV_W) ; + vector mW_next( cnData.nDegU - 1, vV_W) ; + vector mW_strip( cnData.nDegU + 1, vV_W) ; + DBLVECTOR vAlpha ; + vAlpha.resize( cnData.nDegU - 1) ; + if ( ! cnData.bRat ) { + for ( int i = 0 ; i <= cnData.nDegU ; ++i ) { + for ( int row = 0 ; row < cnData.nCPV ; ++row ) { + mBC[i][row] = cnData.mCP[i][row] ; + } + } + } + else { + for ( int i = 0 ; i <= cnData.nDegU ; ++i ) { + for (int row = 0 ; row < cnData.nCPV ; ++ row) { + mW[i][row] = cnData.mW[i][row] ; + mBC[i][row] = cnData.mCP[i][row] * cnData.mW[i][row] ; + } + } + } + + bool bRef = false ; + while ( b < nU - 1) { // qui correggo un probabile errore, mettendo nU anziché nCPV, come indicato nell'algoritmo + int i = b ; + while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO) + ++ b ; + int mult = b - i + 1 ; + if ( mult < cnData.nDegU ) { + bRef = true ; + // calcolo numeratore e alpha + double numer = cnData.vU[b] - cnData.vU[a] ; + for ( int j = cnData.nDegU ; j > mult ; -- j) + vAlpha[j-mult-1] = numer / ( cnData.vU[a+j] - cnData.vU[a]) ; + int r = cnData.nDegU - mult ; + for ( int j = 1 ; j <= cnData.nDegU - mult ; ++j ) { + int save = r - j ; + int s = mult + j ; + //for ( int row = 0 ; row < cnData.nCPV ; ++row) { + // for ( int k = cnData.nDegU ; k >= s ; --k ) { + // vBC[nCPU*row + k] = vAlpha[k-s]*vBC[nCPU*row + k] + ( 1 - vAlfa[k-s]) * vBC[nCPU*row + k - 1] + // } + //} + if ( ! cnData.bRat ) { + for ( int k = cnData.nDegU ; k >= s ; --k ) { + for ( int row = 0 ; row < cnData.nCPV ; ++row) { + mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ; + } + } + } + else { + for ( int k = cnData.nDegU ; k >= s ; --k ) { + for ( int row = 0 ; row < cnData.nCPV ; ++row) { + mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ; + mW[k][row] = vAlpha[k-s] * mW[k][row] + ( 1 - vAlpha[k-s]) * mW[k-1][row] ; + } + } + } + + if ( b < nU - 1 ) { + for ( int row = 0 ; row < cnData.nCPV ; ++row) { + mBC_next[save][row] = mBC[cnData.nDegU][row] ; + } + if ( cnData.bRat ) + for ( int row = 0 ; row < cnData.nCPV ; ++row) { + mW_next[save][row] = mW[cnData.nDegU][row] ; + } + } + } + mPC_strip.resize( cnData.nDegU * ( nb + 1) + 1 , vCPV) ; + mW_strip.resize( cnData.nDegU * ( nb + 1) + 1, vV_W) ; + if ( ! cnData.bRat) + for ( int i = 0 ; i <= cnData.nDegU ; ++i) { + for ( int row = 0 ; row < cnData.nCPV ; ++row ) { + mPC_strip[i+ nb * cnData.nDegU][row] = mBC[i][row] ; + } + } + else { + for ( int i = 0 ; i <= cnData.nDegU ; ++i) { + for ( int row = 0 ; row < cnData.nCPV ; ++row ) { + mPC_strip[i+ nb * cnData.nDegU][row] = mBC[i][row]/mW[i][row] ; + mW_strip[i+ nb * cnData.nDegU][row] = mW[i][row] ; + } + } + } + } + ++ nb ; + // ho finito di definire la patch di Bezier attuale e passo alla successiva + + // aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nb = nb + 1 + if ( ! cnData.bRat){ + for (int i = 0 ; i < cnData.nDegU - 1 ; ++ i) { + for ( int row = 0 ; row < cnData.nCPV ; ++row) { + mBC[i][row] = mBC_next[i][row] ; + } + } + } + else { + for (int i = 0 ; i < cnData.nDegU - 1 ; ++ i) { + for ( int row = 0 ; row < cnData.nCPV ; ++row) { + mBC[i][row] = mBC_next[i][row] ; + mW[i][row] = mW_next[i][row] ; + } + } + } + + if ( b < nU - 1 ) { + for ( int i = cnData.nDegU - mult ; i <= cnData.nDegU ; ++ i) { + for (int row = 0 ; row < cnData.nCPV ; ++ row ) { + mBC[i][row] = cnData.mCP[b - cnData.nDegU + i + 1][row] ; + } + } + if ( cnData.bRat ) { + for ( int i = cnData.nDegU - mult ; i <= cnData.nDegU ; ++ i) { + for (int row = 0 ; row < cnData.nCPV ; ++ row ) { + mW[i][row] = cnData.mW[b - cnData.nDegU + i + 1][row] ; + } + } + } + a = b ; + ++b ; + } + } + + // se non ho raffinato allora tutti i nodi avevano già molteplicità massima. Converto direttamente in Bezier la dir U + int nCPU_ref ; // numero dei punti di controllo in U dopo il raffinamento + if ( ! bRef ) { + nCPU_ref = cnData.nCPU ; + mPC_strip.resize( cnData.nCPU, vCPV) ; + mW_strip.resize( cnData.nCPU, vV_W) ; + if ( ! cnData.bRat) { + for ( int i = 0 ; i < nCPU_ref ; ++i) { + for ( int row = 0 ; row < cnData.nCPV ; ++ row) { + mPC_strip[i][row] = cnData.mCP[i][row] ; + } + } + } + else { + for ( int i = 0 ; i < nCPU_ref ; ++i) { + for ( int row = 0 ; row < cnData.nCPV ; ++ row) { + mPC_strip[i][row] = cnData.mCP[i][row] ; + mW_strip[i][row] = cnData.mW[i][row] ; + } + } + } + // devo vedere quante patch ci stanno prendendo i punti che ci sono + nb = (cnData.nCPU - 1) / cnData.nDegU ; + } + else + nCPU_ref = cnData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento + + // ora ho ottenuto le strisce nDegU x nCPV + // devo ripetere la procedura, sulla dir V, per ottenere le patch nDegU x nDegV + a = cnData.nDegV - 1 ; + b = cnData.nDegV ; + int nc = 0 ; // numero di strisce in V ( lunghezza con V costante) + vector vDegV(cnData.nDegV + 1) ; + vector vDegV_1(cnData.nDegV - 1) ; + vector< vector> m_BC1( nCPU_ref, vDegV) ; + vector< vector> m_BC1_next( nCPU_ref, vDegV_1) ; + DBLVECTOR vV1_W(cnData.nDegV + 1) ; + DBLVECTOR vV2_W(cnData.nDegV - 1) ; + vector mW1( nCPU_ref, vV1_W) ; + vector mW1_next( nCPU_ref, vV2_W) ; + DBLVECTOR vAlpha1( cnData.nDegV - 1) ; + vector> mPC_tot( nCPU_ref, vDegV) ; + vector mW_tot( nCPU_ref, vV1_W) ; + if ( ! cnData.bRat ) { + for ( int i = 0 ; i < nCPU_ref ; ++i ) { + for ( int row = 0 ; row <= cnData.nDegV ; ++row ) { + m_BC1[i][row] = mPC_strip[i][row] ; + } + } + } + else { + for ( int i = 0 ; i < nCPU_ref ; ++i ) { + for (int row = 0 ; row <= cnData.nDegV ; ++ row) { + mW1[i][row] = mW_strip[i][row] ; + m_BC1[i][row] = mPC_strip[i][row] * mW_strip[i][row] ; + } + } + } + + bRef = false ; + while ( b < nV - 1) { // qui correggo un probabile errore, mettendo nU anziché nCPV, come indicato nell'algoritmo + int i = b ; + while ( b < nV - 1 && abs( cnData.vV[b+1] - cnData.vV[b]) < EPS_ZERO) + ++ b ; + int mult = b - i + 1 ; + if ( mult < cnData.nDegV ) { + bRef = true ; + // calcolo numeratore e alpha + double numer = cnData.vV[b] - cnData.vV[a] ; + for ( int j = cnData.nDegV ; j > mult ; -- j) + vAlpha1[j-mult-1] = numer / ( cnData.vV[a+j] - cnData.vV[a]) ; + int r = cnData.nDegV - mult ; + for ( int j = 1 ; j <= cnData.nDegV - mult ; ++j ) { + int save = r - j ; + int s = mult + j ; + //for ( int row = 0 ; row < cnData.nCPV ; ++row) { + // for ( int k = cnData.nDegU ; k >= s ; --k ) { + // vBC[nCPU*row + k] = vAlpha1[k-s]*vBC[nCPU*row + k] + ( 1 - vAlpha1[k-s]) * vBC[nCPU*row + k - 1] + // } + //} + if ( ! cnData.bRat) { + for ( int k = 0 ; k < nCPU_ref ; ++k) { + for ( int row = cnData.nDegV ; row >= s ; --row ) { + m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ; + } + } + } + else { + for ( int k = 0 ; k < nCPU_ref ; ++k) { + for ( int row = cnData.nDegV ; row >= s ; --row ) { + m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ; + mW1[k][row] = vAlpha1[row-s] * mW1[k][row] + ( 1 - vAlpha1[row-s]) * mW1[k][row-1] ; + } + } + } + + if ( b < nV - 1 ) { + if ( !cnData.bRat ){ + for ( int i = 0 ; i < nCPU_ref ; ++i) { + m_BC1_next[i][save] = m_BC1[i][cnData.nDegV] ; + } + } + else { + for ( int i = 0 ; i < nCPU_ref ; ++i) { + m_BC1_next[i][save] = m_BC1[i][cnData.nDegV] ; + mW1_next[save] = mW1[cnData.nDegV] ; + } + } + } + } + } + int nRef = cnData.nDegV * ( nc + 1) + 1 ; + for ( int k = 0 ; k < nCPU_ref; ++k){ + mPC_tot[k].resize( nRef) ; + mW_tot[k].resize( nRef) ; + } + if ( ! cnData.bRat) + for ( int i = 0 ; i < nCPU_ref ; ++i) { + for ( int row = 0 ; row <= cnData.nDegV ; ++row ) { + mPC_tot[i][row + nc * cnData.nDegV] = m_BC1[i][row] ; + } + } + else { + for ( int i = 0 ; i < nCPU_ref ; ++i) { + for ( int row = 0 ; row <= cnData.nDegV ; ++row ) { + mPC_tot[i][row + nc * cnData.nDegV] = m_BC1[i][row]/mW1[i][row] ; + mW_tot[i][row + nc * cnData.nDegV] = mW1[i][row] ; + } + } + } + ++ nc ; + // ho finito di definire la patch di Bezier attuale e passo alla successiva + + // aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nc = nc + 1 + if ( ! cnData.bRat){ + for (int i = 0 ; i < nCPU_ref ; ++ i) { + for ( int row = 0 ; row < cnData.nDegV - 1 ; ++row) { + m_BC1[i][row] = m_BC1_next[i][row] ; + } + } + } + else { + for (int i = 0 ; i < nCPU_ref ; ++ i) { + for ( int row = 0 ; row < cnData.nDegV - 1 ; ++row) { + m_BC1[i][row] = m_BC1_next[i][row] ; + mW1[i][row] = mW1_next[i][row] ; + } + } + } + + if ( b < nV - 1) { + for (int i = 0 ; i < nCPU_ref ; ++ i ) { + for ( int row = cnData.nDegV - mult ; row <= cnData.nDegV ; ++ row) { + m_BC1[i][row] = cnData.mCP[i][b - cnData.nDegV + row + 1] ; + } + } + if ( cnData.bRat ) { + for (int i = 0 ; i < nCPU_ref ; ++ i ) { + for ( int row = cnData.nDegV - mult ; row <= cnData.nDegV ; ++ row) { + mW1[i][row] = cnData.mW[i][b - cnData.nDegV + row + 1] ; + } + } + } + a = b ; + ++b ; + } + + } + // se non ho raffinato allora aggiungo direttamente alle matrici della superficie totale + int nCPV_ref ; // numero dei punti di controllo in V dopo il raffinamento + if ( ! bRef) { + nCPV_ref = cnData.nCPV ; + for ( int k = 0 ; k < nCPU_ref ; ++k){ + mPC_tot[k].resize( cnData.nCPV) ; + mW_tot[k].resize( cnData.nCPV) ; + } + if ( ! cnData.bRat) { + for ( int i = 0 ; i < nCPU_ref ; ++i) { + for ( int row = 0 ; row < nCPV_ref ; ++ row) { + mPC_tot[i][row] = mPC_strip[i][row] ; + } + } + } + else { + for ( int i = 0 ; i < nCPU_ref ; ++i) { + for ( int row = 0 ; row < nCPV_ref ; ++ row) { + mPC_tot[i][row] = mPC_strip[i][row] ; + mW_tot[i][row] = mW_strip[i][row] ; + } + } + } + // devo vedere quante patch ci stanno prendendo i punti che ci sono + nc = (cnData.nCPV - 1) / cnData.nDegV ; + } + else + nCPV_ref = cnData.nDegV * nc + 1 ; + + // finalmente setto la superficie di bezier totale divisa in nb patch in U e nc patch in V + PtrOwner pSrfBz( CreateSurfBezier()) ; + if ( IsNull( pSrfBz)) + return nullptr ; + pSrfBz->Init(cnData.nDegU, cnData.nDegV, nb, nc, cnData.bRat) ; + if ( !cnData.bRat ) { + for ( int i = 0 ; i < nCPU_ref; ++ i) { + for (int j = 0 ; j < nCPV_ref; ++j) { + pSrfBz->SetControlPoint( i + nCPU_ref * j, mPC_tot[i][j]) ; + } + } + } + else { + for ( int i = 0 ; i < nCPU_ref; ++ i) { + for (int j = 0 ; j < nCPV_ref; ++j) { + pSrfBz->SetControlPoint( i + nCPU_ref * j, mPC_tot[i][j] / mW_tot[i][j], mW_tot[i][j]) ; + } + } + } + return Release( pSrfBz) ; +} + +//// algoritmo per le curve, da usare come reference/////////////////////////////////////////////////////////////////////////////// +// +// +// // vettore dei punti di controllo della curva di Bezier +// PNTVECTOR vBC ; +// vBC.resize( cnData.nDeg + 1) ; +// DBLVECTOR vBW ; +// vBW.resize( cnData.nDeg + 1) ; +// if ( ! cnData.bRat) { +// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) +// vBC[i] = cnData.vCP[i] ; +// } +// else { +// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) { +// vBC[i] = cnData.vCP[i] * cnData.vW[i] ; +// vBW[i] = cnData.vW[i] ; +// } +// } +// // primi coefficienti della successiva +// PNTVECTOR vNextBC ; +// vNextBC.resize( cnData.nDeg - 1) ; +// DBLVECTOR vNextBW ; +// vNextBW.resize( cnData.nDeg - 1) ; +// // ... +// DBLVECTOR vAlfa ; +// vAlfa.resize( cnData.nDeg - 1) ; +// int a = cnData.nDeg - 1 ; +// int b = cnData.nDeg ; +// bool bPrevRejected = false ; +// // ciclo +// while ( b < nU - 1) { +// int i = b ; +// while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO) +// ++ b ; +// int mult = min( b - i + 1, cnData.nDeg) ; +// if ( mult < cnData.nDeg) { +// // numeratore di alfa +// double numer = cnData.vU[b] - cnData.vU[a] ; +// // calcola e salva gli alfa +// for ( int j = cnData.nDeg ; j > mult ; -- j) +// vAlfa[j-mult-1] = numer / ( cnData.vU[a+j] - cnData.vU[a]) ; +// // inserisco il nodo r volte +// int r = cnData.nDeg - mult ; +// for ( int j = 1 ; j <= r ; ++ j) { +// int save = r - j ; +// int s = mult + j ; +// for ( int k = cnData.nDeg ; k >= s ; -- k) +// vBC[k] = vAlfa[k-s] * vBC[k] + ( 1 - vAlfa[k-s]) * vBC[k-1] ; +// if ( cnData.bRat) { +// for ( int k = cnData.nDeg ; k >= s ; -- k) +// vBW[k] = vAlfa[k-s] * vBW[k] + ( 1 - vAlfa[k-s]) * vBW[k-1] ; +// } +// if ( b < nU - 1) { +// vNextBC[save] = vBC[cnData.nDeg] ; +// if ( cnData.bRat) +// vNextBW[save] = vBW[cnData.nDeg] ; +// } +// } +// } +// +// // costruisco la curva di Bezier e la inserisco nella curva composita +// PtrOwner pCrvBez( CreateCurveBezier()) ; +// if ( IsNull( pCrvBez)) +// return nullptr ; +// // se precedente saltata +// if ( bPrevRejected) { +// // prendo l'ultimo punto della curva composita per garantire la continuità +// Point3d ptEnd ; +// if ( pCrvCompo->GetEndPoint( ptEnd)) +// vBC[0] = ptEnd ; +// } +// // la inizializzo +// if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat)) +// return nullptr ; +// if ( ! cnData.bRat) { +// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) { +// if ( ! pCrvBez->SetControlPoint( i, vBC[i])) +// return nullptr ; +// } +// } +// else { +// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) { +// if ( ! pCrvBez->SetControlPoint( i, vBC[i] / vBW[i], vBW[i])) +// return nullptr ; +// } +// } +// // se è una vera curva, la aggiungo alla curva composita +// if ( ! pCrvBez->IsAPoint()) { +// if ( ! pCrvCompo->AddCurve( Release( pCrvBez))) +// return nullptr ; +// bPrevRejected = false ; +// } +// // altrimenti è un punto, la cancello +// else { +// pCrvBez.Reset() ; +// bPrevRejected = true ; +// } +// +// // inizializzazioni per la prossima curva di Bezier +// if ( b < nU - 1) { +// if ( ! cnData.bRat) { +// for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) +// vBC[i] = vNextBC[i] ; +// for ( int i = cnData.nDeg - mult ; i <= cnData.nDeg ; ++ i) +// vBC[i] = cnData.vCP[b-cnData.nDeg+i+1] ; +// } +// else { +// for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) { +// vBC[i] = vNextBC[i] ; +// vBW[i] = vNextBW[i] ; +// } +// for ( int i = cnData.nDeg - mult ; i <= cnData.nDeg ; ++ i) { +// vBC[i] = cnData.vCP[b-cnData.nDeg+i+1] * cnData.vW[b-cnData.nDeg+i+1] ; +// vBW[i] = cnData.vW[b-cnData.nDeg+i+1] ; +// } +// } +// a = b ; +// ++ b ; +// } +// } +// +// // restituisco la curva composita +// return Release( pCrvCompo) ; +//} \ No newline at end of file diff --git a/SurfAux.h b/SurfAux.h new file mode 100644 index 0000000..09867fc --- /dev/null +++ b/SurfAux.h @@ -0,0 +1,33 @@ +//---------------------------------------------------------------------------- +// EgalTech 2023-2023 +//---------------------------------------------------------------------------- +// File : SurfAux.h Data : 09.08.23 Versione : +// Contenuto : Dichiarazione di alcune funzioni di utilità per le superfici. +// +// +// +// Modifiche : 09.08.23 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkSurfAux.h" + +//---------------------------------------------------------------------------- +//bool IsClosed( const ICurve& crvC) ; +//bool IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide) ; +//bool IsStartParam( const ICurve& crvC, double dPar) ; +//bool IsEndParam( const ICurve& crvC, double dPar) ; +//bool GetNearestExtremityToPoint( const Point3d& ptP, const ICurve& Curve, bool& bStart) ; +//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/SurfBezier.cpp b/SurfBezier.cpp index 26339b9..c1c91ff 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -563,7 +563,7 @@ SurfBezier::Clone( void) const bool SurfBezier::CopyFrom( const IGeoObj* pGObjSrc) { - const SurfBezier* pSbz = dynamic_cast( pGObjSrc) ; + const SurfBezier* pSbz = GetBasicSurfBezier( pGObjSrc) ; if ( pSbz == nullptr) return false ; return CopyFrom( *pSbz) ; @@ -835,7 +835,6 @@ SurfBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, d // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -858,7 +857,6 @@ SurfBezier::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) return false ; @@ -893,7 +891,6 @@ SurfBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -917,7 +914,6 @@ SurfBezier::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -940,11 +936,14 @@ SurfBezier::ToGlob( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -963,11 +962,14 @@ SurfBezier::ToLoc( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -986,7 +988,6 @@ SurfBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; diff --git a/SurfBezier.h b/SurfBezier.h index cec073c..92e8dea 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -179,6 +179,10 @@ inline SurfBezier* CloneBasicSurfBezier( const IGeoObj* pGObj) return nullptr ; return ( static_cast( pGObj->Clone())) ; } inline const SurfBezier* GetBasicSurfBezier( const IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } inline SurfBezier* GetBasicSurfBezier( IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_BEZIER) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 0fdb481..da62396 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -378,7 +378,7 @@ SurfFlatRegion::Clone( void) const bool SurfFlatRegion::CopyFrom( const IGeoObj* pGObjSrc) { - const SurfFlatRegion* pSfr = dynamic_cast( pGObjSrc) ; + const SurfFlatRegion* pSfr = GetBasicSurfFlatRegion( pGObjSrc) ; if ( pSfr == nullptr) return false ; return CopyFrom( *pSfr) ; @@ -597,7 +597,7 @@ SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const // è il bounding box dei loop esterni for ( auto i : m_vExtInd) { BBox3d b3Tmp ; - if ( m_vpLoop[i]->GetBBox( frCompo, b3Ref, nFlag)) + if ( m_vpLoop[i]->GetBBox( frCompo, b3Tmp, nFlag)) b3Ref.Add( b3Tmp) ; } return ( ! b3Ref.IsEmpty()) ; @@ -625,9 +625,14 @@ SurfFlatRegion::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // ruoto il riferimento return m_frF.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; } @@ -639,6 +644,10 @@ SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou // verifico lo stato if ( m_nStatus != OK || m_vpLoop.empty()) return false ; + // verifico non sia nulla + if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -688,6 +697,10 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico lo stato if ( m_nStatus != OK || m_vpLoop.empty()) return false ; + // verifico validità del piano di specchiatura + if ( vtNorm.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -732,6 +745,10 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector // verifico lo stato if ( m_nStatus != OK || m_vpLoop.empty()) return false ; + // verifico validità dei parametri + if ( vtNorm.IsSmall() || vtDir.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; @@ -796,9 +813,18 @@ SurfFlatRegion::ToGlob( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo il riferimento return m_frF.ToGlob( frRef) ; ; } @@ -810,9 +836,18 @@ SurfFlatRegion::ToLoc( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo il riferimento return m_frF.ToLoc( frRef) ; ; } @@ -824,9 +859,18 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dei frame + if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) + return false ; + + // se i due riferimenti coincidono, non devo fare alcunché + if ( AreSameFrame( frOri, frDest)) + return true ; + // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // trasformo il riferimento return m_frF.LocToLoc( frOri, frDest) ; ; } diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index 37d8195..eb29c2d 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -152,12 +152,16 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW //----------------------------------------------------------------------------- inline SurfFlatRegion* CreateBasicSurfFlatRegion( void) - { return (static_cast( CreateGeoObj( SRF_FLATRGN))) ; } + { return ( static_cast( CreateGeoObj( SRF_FLATRGN))) ; } inline SurfFlatRegion* CloneBasicSurfFlatRegion( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != SRF_FLATRGN) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const SurfFlatRegion* GetBasicSurfFlatRegion( const IGeoObj* pGObj) - { return (dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_FLATRGN) + return nullptr ; + return ( static_cast( pGObj)) ; } inline SurfFlatRegion* GetBasicSurfFlatRegion( IGeoObj* pGObj) - { return (dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_FLATRGN) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/SurfFlatRegionBooleans.cpp b/SurfFlatRegionBooleans.cpp index 233916a..a06921e 100644 --- a/SurfFlatRegionBooleans.cpp +++ b/SurfFlatRegionBooleans.cpp @@ -27,9 +27,10 @@ bool SurfFlatRegion::Add( const ISurfFlatRegion& Other) { // converto l'altra regione nell'oggetto base - const SurfFlatRegion& SfrOther = dynamic_cast( Other) ; - if ( &SfrOther == nullptr) + const SurfFlatRegion* pSfrOther = GetBasicSurfFlatRegion( &Other) ; + if ( pSfrOther == nullptr) return false ; + const SurfFlatRegion& SfrOther = *pSfrOther ; // verifico che le due regioni giacciano in piani paralleli if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ())) @@ -110,9 +111,10 @@ bool SurfFlatRegion::Subtract( const ISurfFlatRegion& Other) { // converto l'altra regione nell'oggetto base - const SurfFlatRegion& SfrOther = dynamic_cast( Other) ; - if ( &SfrOther == nullptr) + const SurfFlatRegion* pSfrOther = GetBasicSurfFlatRegion( &Other) ; + if ( pSfrOther == nullptr) return false ; + const SurfFlatRegion& SfrOther = *pSfrOther ; // verifico che le due regioni giacciano in piani paralleli if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ())) @@ -197,9 +199,10 @@ bool SurfFlatRegion::Intersect( const ISurfFlatRegion& Other) { // converto l'altra regione nell'oggetto base - const SurfFlatRegion& SfrOther = dynamic_cast( Other) ; - if ( &SfrOther == nullptr) + const SurfFlatRegion* pSfrOther = GetBasicSurfFlatRegion( &Other) ; + if ( pSfrOther == nullptr) return false ; + const SurfFlatRegion& SfrOther = *pSfrOther ; // verifico che le due regioni giacciano in piani paralleli if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ())) diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index dbf19d5..76ad9e9 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -121,6 +121,27 @@ SurfTriMesh::AddVertex( const Point3d& ptVert) return int( m_vVert.size() - 1) ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::MoveVertex( int nInd, const Point3d& ptNewVert) +{ + // verifico validità indice + if ( nInd < 0 || nInd >= int( m_vVert.size())) + return false ; + // verifico non sia già cancellato + if ( m_vVert[nInd].nIdTria == SVT_DEL) + return false ; + // sposto il vertice + m_vVert[nInd].ptP = ptNewVert ; + // imposto ricalcolo + m_nStatus = TO_VERIFY ; + m_nParts = - 1 ; + m_OGrMgr.Reset() ; + ResetHashGrids3d() ; + // per aggiornare completamente la superficie chiamare DoCompacting + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::SetVertex( int nInd, const StmVert& vV) @@ -758,23 +779,23 @@ SurfTriMesh::GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const //---------------------------------------------------------------------------- bool -SurfTriMesh::GetTriangleFlag( int nId, int& nFlag) const +SurfTriMesh::GetTFlag( int nTriaId, int& nTFlag) const { // verifico esistenza del triangolo - if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nTriaId < 0 || nTriaId >= GetTriangleSize() || m_vTria[nTriaId].nIdVert[0] == SVT_DEL) return false ; - nFlag = m_vTria[nId].nTFlag ; + nTFlag = m_vTria[nTriaId].nTFlag ; return true ; } //---------------------------------------------------------------------------- bool -SurfTriMesh::GetTriangleTempInt( int nId, int& nTempInt) const +SurfTriMesh::GetTempInt( int nTriaId, int& nTempInt) const { // verifico esistenza del triangolo - if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nTriaId < 0 || nTriaId >= GetTriangleSize() || m_vTria[nTriaId].nIdVert[0] == SVT_DEL) return false ; - nTempInt = m_vTria[nId].nTemp ; + nTempInt = m_vTria[nTriaId].nTemp ; return true ; } @@ -1199,7 +1220,7 @@ SurfTriMesh::Clone( void) const bool SurfTriMesh::CopyFrom( const IGeoObj* pGObjSrc) { - const SurfTriMesh* pStm = dynamic_cast( pGObjSrc) ; + const SurfTriMesh* pStm = GetBasicSurfTriMesh( pGObjSrc) ; if ( pStm == nullptr) return false ; return CopyFrom( *pStm) ; @@ -2950,14 +2971,13 @@ SurfTriMesh::DoCompacting( double dTol) // sistemo gli indici dei vertici nei triangoli for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) { - // recupero gli indici dei vertici del triangolo - int vOId[3] ; - vOId[0] = m_vTria[nId].nIdVert[0] ; - vOId[1] = m_vTria[nId].nIdVert[1] ; - vOId[2] = m_vTria[nId].nIdVert[2] ; // salto i triangoli cancellati - if ( vOId[0] == SVT_DEL) + if ( m_vTria[nId].nIdVert[0] == SVT_DEL) continue ; + // recupero gli indici dei vertici del triangolo + int vOId[3]{ m_vTria[nId].nIdVert[0], + m_vTria[nId].nIdVert[1], + m_vTria[nId].nIdVert[2]} ; // verifico la validità degli indici if ( vOId[0] < 0 || vOId[0] >= nVIdSize || vOId[1] < 0 || vOId[1] >= nVIdSize || @@ -2967,11 +2987,12 @@ SurfTriMesh::DoCompacting( double dTol) m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ; m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ; m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ; - // se due vertici coincidono, cancello il triangolo + // se due vertici coincidono o la normale non è calcolabile, cancello il triangolo if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] || m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] || - m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) - RemoveTriangle( nId) ; + m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] || + ! CalcTriangleNormal( nId)) + RemoveTriangle( nId) ; } // compatto il vettore dei vertici @@ -2992,7 +3013,7 @@ bool SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, double dTol) { // recupero l'altra superficie - const SurfTriMesh* pOther = dynamic_cast( &stmOther) ; + const SurfTriMesh* pOther = GetBasicSurfTriMesh( &stmOther) ; if ( pOther == nullptr) return false ; @@ -3284,7 +3305,6 @@ SurfTriMesh::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -3317,7 +3337,6 @@ SurfTriMesh::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -3349,11 +3368,14 @@ SurfTriMesh::ToGlob( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica e di hashgrids3d m_OGrMgr.Reset() ; ResetHashGrids3d() ; @@ -3380,11 +3402,14 @@ SurfTriMesh::ToLoc( const Frame3d& frRef) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica e di hashgrids3d m_OGrMgr.Reset() ; ResetHashGrids3d() ; @@ -3411,7 +3436,6 @@ SurfTriMesh::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; @@ -3662,7 +3686,7 @@ SurfTriMesh::ResetTFlags( void) //---------------------------------------------------------------------------- bool -SurfTriMesh::ResetTempInt( void) const +SurfTriMesh::ResetTempInts( void) const { for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) m_vTria[i].nTemp = 0 ; diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 2082811..6ae2946 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2022 +// EgalTech 2014-2023 //---------------------------------------------------------------------------- -// File : SurfTriMesh.h Data : 10.10.22 Versione : 2.4i4 +// File : SurfTriMesh.h Data : 07.07.23 Versione : 2.5g1 // Contenuto : Dichiarazione della classe Superficie TriMesh. // // @@ -216,6 +216,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; m_OGrMgr.Reset() ; } int AddVertex( const Point3d& ptVert) override ; + bool MoveVertex( int nInd, const Point3d& ptNewVert) override ; int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ; bool RemoveTriangle( int nId) override ; bool AdjustTopology( void) override ; @@ -266,6 +267,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW { return int( m_vFacet.size()) ; } int GetFacetFromTria( int nT) const override ; bool GetAllTriaInFacet( int nF, INTVECTOR& vT) const override ; + bool GetAllVertInFacet( int nF, INTVECTOR& vVert) const override ; bool GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const override ; bool GetFacetAdjacencies( int nF, INTMATRIX& vAdj) const override ; bool GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const override ; @@ -315,9 +317,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool ExistsTriangle( int nT) const { return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; } bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ; - bool GetTriangleFlag( int nId, int& nFlag) const ; - bool GetTriangleTempInt( int nId, int& nTempInt) const ; - bool ResetTempInt( void) const ; + bool GetTFlag( int nId, int& nFlag) const ; + bool GetTempInt( int nId, int& nTempInt) const ; + bool ResetTempInts( void) const ; bool SetTFlag( int nId, int nTFlag) ; bool SetTempInt( int nId, int nTempInt) const ; @@ -412,6 +414,10 @@ inline SurfTriMesh* CloneBasicSurfTriMesh( const IGeoObj* pGObj) return nullptr ; return ( static_cast( pGObj->Clone())) ; } inline const SurfTriMesh* GetBasicSurfTriMesh( const IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH) + return nullptr ; + return ( static_cast( pGObj)) ; } inline SurfTriMesh* GetBasicSurfTriMesh( IGeoObj* pGObj) - { return ( dynamic_cast( pGObj)) ; } + { if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH) + return nullptr ; + return ( static_cast( pGObj)) ; } diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 71620a5..c3dfa8e 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -1441,8 +1441,18 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) if ( ! IsValid() || ! Other.IsValid()) return false ; + // Se la seconda è vuota non devo fare alcunchè + if ( Other.IsEmpty()) + return true ; + m_OGrMgr.Clear() ; + // Se la prima è vuota, copio la seconda nella prima + if ( IsEmpty()) { + CopyFrom( &Other) ; + return true ; + } + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; @@ -1501,8 +1511,20 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) if ( ! IsValid() || ! Other.IsValid()) return false ; + // Se la prima è vuota non devo fare alcunchè + if ( IsEmpty()) + return true ; + m_OGrMgr.Clear() ; + // Se la seconda è vuota, basta vuotare la prima + if ( Other.IsEmpty()) { + Clear() ; + m_bOriented = true ; + m_bClosed = true ; + return true ; + } + SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; @@ -1561,6 +1583,10 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) if ( ! IsValid() || ! Other.IsValid()) return false ; + // Se una delle due è vuota non devo fare alcunchè + if ( IsEmpty() || Other.IsEmpty()) + return true ; + m_OGrMgr.Clear() ; SurfTriMesh SurfB ; @@ -1671,6 +1697,10 @@ SurfTriMesh::CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bo if ( ! IsValid() || ! CutterSurf.IsValid()) return false ; + // Se una delle due è vuota non devo fare alcunchè + if ( IsEmpty() || CutterSurf.IsEmpty()) + return true ; + m_OGrMgr.Clear() ; SurfTriMesh SurfC ; diff --git a/SurfTriMeshCuts.cpp b/SurfTriMeshCuts.cpp index 8bfda97..7e8991c 100644 --- a/SurfTriMeshCuts.cpp +++ b/SurfTriMeshCuts.cpp @@ -32,10 +32,14 @@ const double CUT_SCALE = 1024 ; bool SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) { - // la superficie deve essere validata + // La superficie deve essere validata if ( m_nStatus != OK) return false ; + // Se la superficie è vuota non devo fare alcunchè + if ( IsEmpty()) + return true ; + // recupero il numero originale di triangoli e di facce int nTriaOriCnt = GetTriangleCount() ; int nFacetOriCnt = GetFacetCount() ; @@ -354,6 +358,10 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) if ( ! cvCurve.GetExtrusion( vtExtr) || vtExtr.IsSmall() || ! cvCurve.IsClosed()) return false ; + // Se la superficie è vuota non devo fare alcunchè + if ( IsEmpty()) + return true ; + // Recupero il numero originale di triangoli e di facce int nTriaOriCnt = GetTriangleCount() ; int nFacetOriCnt = GetFacetCount() ; @@ -367,7 +375,7 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) } // Eseguo scalature - Frame3d frScalingRef; + Frame3d frScalingRef ; frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ; cvCompo.Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index 0188cc4..ce55f56 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -254,6 +254,30 @@ SurfTriMesh::VerifyAdjacTriaFacet( INTVECTOR& vT) const return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetAllVertInFacet( int nF, INTVECTOR& vVert) const +{ + // recupero tutti i triangoli della faccia + INTVECTOR vTria ; + if ( ! GetAllTriaInFacet( nF, vTria)) + return false ; + // ne ricavo i vertici + vVert.clear() ; + INTUNORDSET usTempVert ; + for ( int nT : vTria) { + for ( int i = 0 ; i < 3 ; ++ i) { + int nV = m_vTria[nT].nIdVert[i] ; + if ( usTempVert.find( nV) == usTempVert.end()) { + usTempVert.insert( nV) ; + vVert.push_back( nV) ; + } + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& ptEnd, Vector3d& vtN) const diff --git a/VolZmap.cpp b/VolZmap.cpp index 7630931..a3af750 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -108,7 +108,7 @@ VolZmap::Clone( void) const bool VolZmap::CopyFrom( const IGeoObj* pGObjSrc) { - const VolZmap* pVzm = dynamic_cast( pGObjSrc) ; + const VolZmap* pVzm = GetBasicVolZmap( pGObjSrc) ; if ( pVzm == nullptr) return false ; return CopyFrom( *pVzm) ; @@ -630,8 +630,10 @@ VolZmap::Translate( const Vector3d& vtMove) // verifico lo stato if ( m_nStatus != OK) return false ; + // imposto ricalcolo della grafica ResetGraphics() ; + // traslo il riferimento m_MapFrame.Translate( vtMove) ; return true ; @@ -644,8 +646,13 @@ VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dell'asse di rotazione + if ( vtAx.IsSmall()) + return false ; + // imposto ricalcolo della grafica ResetGraphics() ; + // ruoto il riferimento m_MapFrame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; return true ; @@ -658,6 +665,10 @@ VolZmap::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCo // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico non sia nulla + if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO) + return false ; + return false ; } @@ -668,6 +679,10 @@ VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del piano di specchiatura + if ( vtNorm.IsSmall()) + return false ; + return false ; } @@ -678,6 +693,10 @@ VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dei parametri + if ( vtNorm.IsSmall() || vtDir.IsSmall()) + return false ; + return false ; } @@ -688,8 +707,17 @@ VolZmap::ToGlob( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetGraphics() ; + // trasformo il riferimento m_MapFrame.ToGlob( frRef) ; return true ; @@ -702,8 +730,17 @@ VolZmap::ToLoc( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità del frame + if ( frRef.GetType() == Frame3d::ERR) + return false ; + + // se frame identità, non devo fare alcunché + if ( IsGlobFrame( frRef)) + return true ; + // imposto ricalcolo della grafica ResetGraphics() ; + // trasformo il riferimento m_MapFrame.ToLoc( frRef) ; return true ; @@ -716,8 +753,17 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico lo stato if ( m_nStatus != OK) return false ; + // verifico validità dei frame + if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) + return false ; + + // se i due riferimenti coincidono, non devo fare alcunché + if ( AreSameFrame( frOri, frDest)) + return true ; + // imposto ricalcolo della grafica ResetGraphics() ; + // trasformo il riferimento m_MapFrame.LocToLoc( frOri, frDest) ; return true ; diff --git a/VolZmap.h b/VolZmap.h index ee11252..146c3d5 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -466,16 +466,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW //----------------------------------------------------------------------------- inline VolZmap* CreateBasicVolZmap( void) - { return (static_cast( CreateGeoObj( VOL_ZMAP))) ; } + { return ( static_cast( CreateGeoObj( VOL_ZMAP))) ; } inline VolZmap* CloneBasicVolZmap( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; - return (static_cast(pGObj->Clone())) ; } + return ( static_cast( pGObj->Clone())) ; } inline const VolZmap* GetBasicVolZmap( const IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; - return (static_cast(pGObj)) ; } + return ( static_cast( pGObj)) ; } inline VolZmap* GetBasicVolZmap( IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; - return (static_cast(pGObj)) ; } + return ( static_cast( pGObj)) ; }