diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 8c2a4f5..920a9e1 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 6de2a81..d48ee68 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -321,10 +321,12 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -472,6 +474,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 8dd2118..249bad2 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -318,6 +318,12 @@ File di origine\Gdb + + File di origine\Geo + + + File di origine\GeoInters + @@ -719,6 +725,9 @@ File di intestazione + + File di intestazione + diff --git a/IntersArcArc.cpp b/IntersArcArc.cpp index a6b4048..ca96ba7 100644 --- a/IntersArcArc.cpp +++ b/IntersArcArc.cpp @@ -80,6 +80,9 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2) Point3d ptS2, ptE2 ; if ( ! m_Arc2.GetStartPoint( ptS2) || ! m_Arc2.GetEndPoint( ptE2)) return ; + // determino se sono chiusi ( cerchi) + bool bClosed1 = AreSamePointApprox( ptS1, ptE1) ; + bool bClosed2 = AreSamePointApprox( ptS2, ptE2) ; // calcolo del parametro di inizio dell'arco 2 nel riferimento dell'arco 1 double dUS2 ; int nPosS2 ; @@ -157,8 +160,8 @@ IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2) m_bOverlaps = true ; m_nNumInters = 1 ; } - // se il massimo di 2 coincide con il minimo di 1 nel secondo giro e 1 non completo -> un punto estremo - if ( fabs( dTurnU - dU2max) * dU2L < EPS_SMALL && dTurnU < 1 - EPS_PARAM) { + // se il massimo di 2 coincide con il minimo di 1 nel secondo giro e 1 e 2 non completi -> un punto estremo + if ( fabs( dTurnU - dU2max) * dU2L < EPS_SMALL && ! bClosed1 && ! bClosed2) { m_Info[m_nNumInters].IciA[0].dU = 0 ; m_Info[m_nNumInters].IciB[0].dU = ( bEqVers ? 1 : 0) ; m_Info[m_nNumInters].IciA[0].ptI = ptS1 ; diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index 21ee627..6f4fd6b 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -36,6 +36,8 @@ static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2) ; static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, double dDist, int nType, CurveComposite& ccAux) ; static double GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2) ; +static bool IsFillet( ICurve* pCrv, double dDist) ; +static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, CurveComposite& ccAux) ; //---------------------------------------------------------------------------- @@ -54,16 +56,40 @@ OffsetCurve::~OffsetCurve( void) bool OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) { - // verifico che la curva esista e si trovi nel piano XY o in uno ad esso parallelo + // verifico che la curva esista e sia piana Plane3d plPlane ; - if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane) || - ! ( plPlane.vtN.IsZplus() || plPlane.vtN.IsZminus())) + if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane)) return false ; + // se esiste estrusione, verifico sia perpendicolare al piano della curva + Vector3d vtExtr ; + if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) { + if ( ! AreSameOrOppositeVectorApprox( plPlane.vtN, vtExtr)) + return false ; + } + else + vtExtr = plPlane.vtN ; - // creo una copia formata solo da rette e archi che giacciono nel piano XY (VtExtr è Z+) + // determino se necessario cambiare riferimento ( dal vettore estrusione) + bool bNeedRef = ( ! vtExtr.IsZplus()) ; + + // creo una copia della curva CurveComposite ccCopy ; - if ( ! ccCopy.CopyFrom( pCrv) || - ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG)) + if ( ! ccCopy.CopyFrom( pCrv)) + return false ; + ccCopy.SetExtrusion( vtExtr) ; + + // se necessario cambio il riferimento + Frame3d frExtr ; + if ( bNeedRef) { + // calcolo il riferimento OCS con VtExtr come asse Z + if ( ! frExtr.Set( ORIG, vtExtr)) + return false ; + // esprimo la curva in questo riferimento + ccCopy.ToLoc( frExtr) ; + } + + // verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+) + if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG)) return false ; // verifico se curva chiusa e non forzata aperta @@ -108,7 +134,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) vAngs.push_back( 0) ; } - // primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni + // primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet) CurveComposite ccCopy2 ; if ( ! ccCopy2.CopyFrom( &ccCopy)) return false ; @@ -119,27 +145,29 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) if ( IsNull( pCrv1)) return false ; pCrv1->SetTempProp( nInd1) ; - if ( ! pCrv1->SimpleOffset( dDist, nType) && - GetBasicCurveArc( Get( pCrv1))->MyExtendedOffset( dDist, true, nType)) + if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET) && + GetBasicCurveArc( Get( pCrv1))->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET)) pCrv1->SetTempProp( - nInd1) ; // curve successive PtrOwner pCrv2( ccCopy2.RemoveFirstOrLastCurve( false)) ; while ( ! IsNull( pCrv2)) { // eseguo semplice offset pCrv2->SetTempProp( nInd1 + 1) ; - if ( ! pCrv2->SimpleOffset( dDist, nType) && - GetBasicCurveArc( Get( pCrv2))->MyExtendedOffset( dDist, true, nType)) + if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET) && + GetBasicCurveArc( Get( pCrv2))->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET)) pCrv2->SetTempProp( - (nInd1 + 1)) ; // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie CurveComposite ccTemp ; - bool bOk = VerifyAndAdjustExternalAngle( Get( pCrv1), Get( pCrv2), vAngs[nInd1], dDist, nType, ccTemp) ; + bool bOk = VerifyAndAdjustExternalAngle( Get( pCrv1), Get( pCrv2), vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ; // metto in lista curva precedente m_CrvLst.push_back( Release( pCrv1)) ; // se aggiunto qualcosa, lo metto in lista if ( ccTemp.GetCurveCount() > 0) { PtrOwner pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv3)) + while ( ! IsNull( pCrv3)) { m_CrvLst.push_back( Release( pCrv3)) ; + pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; + } } // aggiorno curva precedente ++ nInd1 ; @@ -159,12 +187,14 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) ICurve* pCrv2 = m_CrvLst.front() ; // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie CurveComposite ccTemp ; - bool bOk = VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, nType, ccTemp) ; + bool bOk = VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ; // se aggiunto qualcosa, lo metto in lista if ( ccTemp.GetCurveCount() > 0) { PtrOwner pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv3)) + while ( ! IsNull( pCrv3)) { m_CrvLst.push_back( Release( pCrv3)) ; + pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; + } } } @@ -368,6 +398,48 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) ++ iIter ; } + // ottavo passo : se con smusso o estensione, sostituisco i fillet con questi + if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { + // processo le curve semplici della composita + CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; + ICURVEPLIST CrvLst ; + PtrOwner pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv)) { + // se fillet lo trasformo in smusso o estensione + if ( IsFillet( Get( pCrv), dDist)) { + CurveComposite ccTemp ; + bool bOk = ModifyFillet( Get( pCrv), dDist, nType, ccTemp) ; + // metto in lista le curve risultanti + if ( ccTemp.GetCurveCount() > 0) { + PtrOwner pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv2)) { + CrvLst.push_back( Release( pCrv2)) ; + pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; + } + } + } + // altrimenti salvo in lista + else + CrvLst.push_back( Release( pCrv)) ; + // passo alla curva successiva + pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ; + } + // rimetto le curve nella composita + for ( auto pCrv : CrvLst) { + pCrvCo->AddCurve( pCrv) ; + } + // unisco tratti allineati + pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; + } + } + + // riporto il risultato nel riferimento originale + if ( bNeedRef) { + for ( auto pCrv : m_CrvLst) + pCrv->ToGlob( frExtr) ; + } + return true ; } @@ -692,4 +764,109 @@ GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2) if ( ! dstPC.GetDist( dMinDist)) return 0 ; return dMinDist ; -} \ No newline at end of file +} + +//---------------------------------------------------------------------------- +bool +IsFillet( ICurve* pCrv, double dDist) +{ + // deve essere un arco + if ( pCrv->GetType() != CRV_ARC) + return false ; + CurveArc* pArc = GetBasicCurveArc( pCrv) ; + // deve avere raggio uguale alla distanza di offset + if ( fabs( pArc->GetRadius() - fabs( dDist)) > EPS_SMALL) + return false ; + // deve essere CCW se offset a destra e CW se offset a sinistra + return ( pArc->GetAngCenter() * dDist > 0) ; +} + +//---------------------------------------------------------------------------- +bool +ModifyFillet( ICurve* pCrv, double dDist, int nType, CurveComposite& ccAux) +{ + // la curva deve essere un arco + CurveArc* pArc = GetBasicCurveArc( pCrv) ; + if ( pArc == nullptr) + return false ; + + // angolo al centro dell'arco + double dAngDeg = pArc->GetAngCenter() ; + + // elimino dal tipo le parti estranee all'angolo esterno + nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ; + + // se l'angolo esterno supera il retto, offset extend diventa offset chamfer + if ( nType == ICurve::OFF_EXTEND && fabs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL) + nType = ICurve::OFF_CHAMFER ; + + // se angolo esterno molto piccolo, semplifico tutto + const double SMALL_EXT_ANG = 1.0 ; + bool bAngSmall = ( fabs( dAngDeg) < SMALL_EXT_ANG) ; + if ( bAngSmall) + nType = ICurve::OFF_EXTEND ; + + switch ( nType) { + case ICurve::OFF_CHAMFER : + { + // lunghezza aggiuntiva in tangenza + double dLen = fabs( dDist) * tan( fabs( dAngDeg) / 4 * DEGTORAD) ; + // punti di costruzione smusso + Point3d ptP1, ptP1a, ptP2a, ptP2 ; + if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2)) + return false ; + Vector3d vtDir1, vtDir2 ; + if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2)) + return false ; + ptP1a = ptP1 + vtDir1 * dLen ; + ptP2a = ptP2 - vtDir2 * dLen ; + // aggiungo una nuova linea + PtrOwner pLine1( CreateBasicCurveLine()) ; + if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptP1a)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine1))) + return false ; + // tratto intermedio + PtrOwner pLine2( CreateBasicCurveLine()) ; + if ( IsNull( pLine2) || ! pLine2->Set( ptP1a, ptP2a)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine2))) + return false ; + // aggiungo una nuova linea + PtrOwner pLine3( CreateBasicCurveLine()) ; + if ( IsNull( pLine3) || ! pLine3->Set( ptP2a, ptP2)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine3))) + return false ; + return true ; + } + break ; + case ICurve::OFF_EXTEND : + { + // lunghezza aggiuntiva in tangenza + double dLen = fabs( dDist) * tan( fabs( dAngDeg) / 2 * DEGTORAD) ; + // punti di costruzione estensione + Point3d ptP1, ptPc, ptP2 ; + if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2)) + return false ; + Vector3d vtDir1, vtDir2 ; + if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2)) + return false ; + ptPc = ptP1 + vtDir1 * dLen ; + // aggiungo una nuova linea + PtrOwner pLine1( CreateBasicCurveLine()) ; + if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptPc)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine1))) + return false ; + // aggiungo una nuova linea + PtrOwner pLine2( CreateBasicCurveLine()) ; + if ( IsNull( pLine2) || ! pLine2->Set( ptPc, ptP2)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine2))) + return false ; + return true ; + } + } + return false ; +} diff --git a/RemoveCurveOverlaps.cpp b/RemoveCurveOverlaps.cpp new file mode 100644 index 0000000..2a657a6 --- /dev/null +++ b/RemoveCurveOverlaps.cpp @@ -0,0 +1,158 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : RemoveCurveOverlaps.cpp Data : 02.11.15 Versione : 1.6K1 +// Contenuto : Implementazione rimozione sovrapposizioni di curva. +// +// +// +// Modifiche : 02.11.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "GeoConst.h" +#include "CurveComposite.h" +#include "RemoveCurveOverlaps.h" +#include "/EgtDev/Include/EGkIntersCurves.h" +#include "/EgtDev/Include/EGkIntervals.h" +#include "/EgtDev/Include/EgtPointerOwner.h" +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +RemoveCurveOverlaps( ICurve* pCurve, bool bRemoveSam, bool bRemoveCtr, ICURVEPLIST& CrvLst) +{ + // Pulisco lista di ritorno + CrvLst.clear() ; + + // Acquisisco la curva + PtrOwner pMyCrv( pCurve) ; + + // Verifico validità curva + if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) + return false ; + + // Se nulla da rimuovere, non devo fare alcunché + if ( ! bRemoveSam && ! bRemoveCtr) { + CrvLst.push_back( Release( pMyCrv)) ; + return true ; + } + + // --- la verifica ed eventuale rimozione va effettuata in un piano perpendicolare al vettore estrusione --- + + // verifico il vettore estrusione + Vector3d vtExtr ; + pMyCrv->GetExtrusion( vtExtr) ; + bool bNeedRef = ( ! vtExtr.IsSmall() && ! vtExtr.IsZplus()) ; + + // se necessario cambio il riferimento + Frame3d frExtr ; + if ( bNeedRef) { + // calcolo il riferimento OCS con VtExtr come asse Z + if ( ! frExtr.Set( ORIG, vtExtr)) + return false ; + // esprimo la curva in questo riferimento + pMyCrv->ToLoc( frExtr) ; + } + + // Calcolo le auto intersezioni + SelfIntersCurve sintC( *pMyCrv) ; + // se non ci sono sovrapposizioni, non devo fare alcunché + if ( ! sintC.GetOverlaps()) { + // riporto la curva nel riferimento originale + if ( bNeedRef) + pMyCrv->ToGlob( frExtr) ; + // la inserisco in lista + CrvLst.push_back( Release( pMyCrv)) ; + return true ; + } + + // Determino intervallo complessivo della curva + double dStart, dEnd ; + if ( ! pMyCrv->GetDomain( dStart, dEnd)) + return false ; + Intervals inOk( EPS_PARAM) ; + inOk.Set( dStart, dEnd) ; + + // Tolgo le parti in sovrapposizione da eliminare + IntCrvCrvInfo iccInfo ; + for ( int i = 0 ; sintC.GetIntCrvCrvInfo( i, iccInfo) ; ++ i) { + // se sovrapposti + if ( iccInfo.bOverlap) { + // se equiversi e da eliminare, elimino solo uno dei due tratti + if ( iccInfo.bCBOverEq && bRemoveSam) { + inOk.Subtract( iccInfo.IciB[0].dU, iccInfo.IciB[1].dU) ; + } + // se altrimenti controversi e da eliminare, elimino entrambi i tratti + else if ( ! iccInfo.bCBOverEq && bRemoveCtr) { + inOk.Subtract( iccInfo.IciA[0].dU, iccInfo.IciA[1].dU) ; + inOk.Subtract( iccInfo.IciB[0].dU, iccInfo.IciB[1].dU) ; + } + } + } + + // Copio le parti da conservare + double dParS, dParE ; + bool bFound = inOk.GetFirst( dParS, dParE) ; + while ( bFound) { + ICurve* pCrv = pMyCrv->CopyParamRange( dParS, dParE) ; + if ( pCrv != nullptr) { + if ( pCrv->GetType() == CRV_COMPO) + CrvLst.push_back( pCrv) ; + else { + CurveComposite* pCrvCo = new( std::nothrow) CurveComposite ; + if ( pCrvCo != nullptr) { + pCrvCo->AddCurve( pCrv) ; + CrvLst.push_back( pCrvCo) ; + } + } + } + bFound = inOk.GetNext( dParS, dParE) ; + } + + // Concateno i percorsi risultanti (senza cambiare verso) + for ( auto iIter = CrvLst.begin() ; iIter != CrvLst.end() ;) { + CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; + // recupero punti iniziale e finale della curva + Point3d ptStart, ptEnd ; + pCrvCo->GetStartPoint( ptStart) ; + pCrvCo->GetEndPoint( ptEnd) ; + // ciclo sulle curve successive per verificare se possibile concatenamento + for ( auto iIter2 = next( iIter) ; iIter2 != CrvLst.end() ;) { + CurveComposite* pCrvCo2 = GetBasicCurveComposite( *iIter2) ; + // recupero punti iniziale e finale della curva + Point3d ptStart2, ptEnd2 ; + pCrvCo2->GetStartPoint( ptStart2) ; + pCrvCo2->GetEndPoint( ptEnd2) ; + // verifiche di concatenamento + if ( AreSamePointEpsilon( ptEnd, ptStart2, 10 * EPS_SMALL)) { + pCrvCo->AddCurve( pCrvCo2, true, 10 * EPS_SMALL) ; + CrvLst.erase( iIter2) ; + ptEnd = ptEnd2 ; + iIter2 = next( iIter) ; + } + else if ( AreSamePointEpsilon( ptEnd2, ptStart, 10 * EPS_SMALL)) { + pCrvCo->AddCurve( pCrvCo2, false, 10 * EPS_SMALL) ; + CrvLst.erase( iIter2) ; + ptStart = ptStart2 ; + iIter2 = next( iIter) ; + } + else + ++ iIter2 ; + } + ++ iIter ; + } + + // riporto la curva nel riferimento originale + if ( bNeedRef) { + for ( auto pCrv : CrvLst) + pCrv->ToGlob( frExtr) ; + } + + return true ; +} \ No newline at end of file diff --git a/RemoveCurveOverlaps.h b/RemoveCurveOverlaps.h new file mode 100644 index 0000000..fa085de --- /dev/null +++ b/RemoveCurveOverlaps.h @@ -0,0 +1,20 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : RemoveCurveOverlaps.h Data : 02.11.15 Versione : 1.6k1 +// Contenuto : Dichiarazione funzione rimozione sovrapposizioni curve. +// +// +// +// Modifiche : 02.11.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkCurve.h" + + +//---------------------------------------------------------------------------- +bool RemoveCurveOverlaps( ICurve* pCurve, bool bRemoveSam, bool bRemoveCtr, ICURVEPLIST& CrvLst) ; diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index b879d5d..9d72d98 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -18,6 +18,8 @@ #include "NgeWriter.h" #include "NgeReader.h" #include "CurveAux.h" +#include "CurveComposite.h" +#include "RemoveCurveOverlaps.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" @@ -80,6 +82,28 @@ SurfFlatRegion::AddExtLoop( const ICurve& cCrv) //---------------------------------------------------------------------------- bool SurfFlatRegion::AddExtLoop( ICurve* pCrv) +{ + // rimuovo eventuali sovrapposizioni + ICURVEPLIST CrvLst ; + if ( ! RemoveCurveOverlaps( pCrv, true, true, CrvLst)) + return false ; + // aggiungo le singole curve + bool bOk = true ; + for ( auto& pCrv : CrvLst) { + // se curva composita, unisco eventuali tratti allineati + CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ; + if ( pCrvCo != nullptr) + pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; + // aggiungo il loop + if ( ! AddSimpleExtLoop( pCrv)) + bOk = false ; + } + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv) { // acquisisco la curva PtrOwner pMyCrv( pCrv) ; @@ -116,7 +140,10 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv) // porto la curva nel riferimento intrinseco if ( ! pMyCrv->ToLoc( m_frF)) return false ; - // verifico non abbia auto-intersezioni che si attraversano + Vector3d vtExtr ; + if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) + pMyCrv->SetExtrusion( Z_AX) ; + // verifico non abbia auto-intersezioni che si attraversano o si sovrappongano SelfIntersCurve sInt( *pMyCrv) ; if ( sInt.GetCrossOrOverlapIntersCount() > 0) return false ; @@ -190,6 +217,28 @@ SurfFlatRegion::AddIntLoop( const ICurve& cCrv) //---------------------------------------------------------------------------- bool SurfFlatRegion::AddIntLoop( ICurve* pCrv) +{ + // rimuovo eventuali sovrapposizioni + ICURVEPLIST CrvLst ; + if ( ! RemoveCurveOverlaps( pCrv, true, true, CrvLst)) + return false ; + // aggiungo le singole curve + bool bOk = true ; + for ( auto& pCrv : CrvLst) { + // se curva composita, unisco eventuali tratti allineati + CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ; + if ( pCrvCo != nullptr) + pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; + // aggiungo il loop + if ( ! AddSimpleIntLoop( pCrv)) + bOk = false ; + } + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv) { // acquisisco la curva PtrOwner pMyCrv( pCrv) ; @@ -204,6 +253,9 @@ SurfFlatRegion::AddIntLoop( ICurve* pCrv) // porto la curva nel riferimento intrinseco if ( ! pMyCrv->ToLoc( m_frF)) return false ; + Vector3d vtExtr ; + if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) + pMyCrv->SetExtrusion( Z_AX) ; // verifico sia piana e il piano coincida con quello XY intrinseco double dArea ; Plane3d plPlane ; diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index 49f2845..8b99ab6 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -78,6 +78,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW virtual bool Add( const ISurfFlatRegion& Other) ; virtual bool Subtract( const ISurfFlatRegion& Other) ; virtual bool Intersect( const ISurfFlatRegion& Other) ; + virtual bool Offset( double dDist, int nType) ; virtual const Vector3d& GetNormVersor( void) const { return m_frF.VersZ() ; } virtual int GetChunkCount( void) const ; @@ -110,7 +111,9 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW private : bool CopyFrom( const SurfFlatRegion& clSrc) ; + bool AddSimpleExtLoop( ICurve* pCrv) ; bool MyAddExtLoop( ICurve* pCrv) ; + bool AddSimpleIntLoop( ICurve* pCrv) ; bool MyAddIntLoop( ICurve* pCrv) ; int GetIndFromChunkLoop( int nChunk, int nLoop) const ; bool GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const ; diff --git a/SurfFlatRegionBooleans.cpp b/SurfFlatRegionBooleans.cpp index be03dbc..82b3571 100644 --- a/SurfFlatRegionBooleans.cpp +++ b/SurfFlatRegionBooleans.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- -// File : SurfFlatRegion.cpp Data : 18.08.15 Versione : 1.6h4 +// File : SurfFlatRegionBooleans.cpp Data : 18.08.15 Versione : 1.6h4 // Contenuto : Implementazione delle funzioni booleane per SurfFlatRegion. // // @@ -158,7 +158,11 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other) } // creo una nuova regione a partire da questi loop - PtrOwner pSfr( MyNewSurfFromLoops( vpLoop)) ; + PtrOwner pSfr ; + if ( vpLoop.size() == 0) + pSfr.Set( new SurfFlatRegion) ; + else + pSfr.Set( MyNewSurfFromLoops( vpLoop)) ; if ( IsNull( pSfr)) return false ; @@ -237,7 +241,11 @@ SurfFlatRegion::Intersect( const ISurfFlatRegion& Other) } // creo una nuova regione a partire da questi loop - PtrOwner pSfr( MyNewSurfFromLoops( vpLoop)) ; + PtrOwner pSfr ; + if ( vpLoop.size() == 0) + pSfr.Set( new SurfFlatRegion) ; + else + pSfr.Set( MyNewSurfFromLoops( vpLoop)) ; if ( IsNull( pSfr)) return false ; diff --git a/SurfFlatRegionOffset.cpp b/SurfFlatRegionOffset.cpp new file mode 100644 index 0000000..215185f --- /dev/null +++ b/SurfFlatRegionOffset.cpp @@ -0,0 +1,98 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : SurfFlatRegionOffset.cpp Data : 01.11.15 Versione : 1.6k1 +// Contenuto : Implementazione della funzione offset per SurfFlatRegion. +// +// +// +// Modifiche : 01.11.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "SurfFlatRegion.h" +#include "/EgtDev/Include/EgkOffsetCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::Offset( double dDist, int nType) +{ + // recupero il numero dei chunk + int nChunk = GetChunkCount() ; + if ( nChunk == 0) + return false ; + // creo una nuova regione + PtrOwner pSfr( new SurfFlatRegion) ; + if ( IsNull( pSfr)) + return false ; + // ciclo sui chunk + bool bFirstCurve = true ; + for ( int i = 0 ; i < nChunk ; ++ i) { + // ciclo sui loop di ogni chunk + int nLoop = GetLoopCount( i) ; + for ( int j = 0 ; j < nLoop ; ++ j) { + // recupero il loop + ICurve* pLoop = GetMyLoop( i, j) ; + if ( pLoop == nullptr) + return false ; + // ne eseguo l'offset + OffsetCurve OffsCrv ; + bool bOk = OffsCrv.Make( pLoop, dDist, nType) ; + // recupero le curve di offset + PtrOwner pOffs( OffsCrv.GetCurve()) ; + while ( bOk && ! IsNull( pOffs)) { + // se prima curva esterna in assoluto, è il primo contorno esterno della nuova regione + if ( bFirstCurve && j == 0) { + if ( ! pSfr->AddExtLoop( Release( pOffs))) + return false ; + bFirstCurve = false ; + } + // altrimenti aggiungo o sottraggo la regione della curva alla nuova regione + else if ( ! bFirstCurve) { + // se loop interno, inverto la curva + if ( j != 0) + pOffs->Invert() ; + // creo la regione + PtrOwner pSfr2( new SurfFlatRegion) ; + if ( IsNull( pSfr2) || ! pSfr2->AddExtLoop( Release( pOffs))) + return false ; + // se era loop esterno, lo aggiungo alla nuova regione + if ( j == 0) { + if ( ! pSfr->Add( *Get( pSfr2))) + return false ; + } + // altrimenti loop interno, lo sottraggo alla nuova regione + else { + if ( ! pSfr->Subtract( *Get( pSfr2))) + return false ; + } + } + // passo alla successiva + pOffs.Set( OffsCrv.GetCurve()) ; + } + } + } + + // pulisco la superficie corrente + for ( auto& pLoop : m_vpLoop) + delete pLoop ; + m_vpLoop.clear() ; + + // sposto i dati della nuova superficie in quella corrente + m_vExtInd = pSfr->m_vExtInd ; + m_vpLoop = pSfr->m_vpLoop ; + for ( auto& pLoop : pSfr->m_vpLoop) + pLoop = nullptr ; + m_nStatus = pSfr->m_nStatus ; + + // imposto ricalcolo della grafica + ResetAuxSurf() ; + m_OGrMgr.Reset() ; + return true ; +} \ No newline at end of file