diff --git a/CurveCompositeOffset.cpp b/CurveCompositeOffset.cpp
index 4e0c3e0..32c96b9 100644
--- a/CurveCompositeOffset.cpp
+++ b/CurveCompositeOffset.cpp
@@ -227,7 +227,7 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAu
// calcolo l'intersezione tra le due curve
IntersCurveCurve intCC( *pCrv1, *pCrv2) ;
- if ( intCC.GetNumInters() == 0)
+ if ( intCC.GetIntersCount() == 0)
return false ;
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
Point3d ptP1, ptP2 ;
diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc
index 7cf5b92..ec3523f 100644
Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ
diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj
index d0e1317..9e76505 100644
--- a/EgtGeomKernel.vcxproj
+++ b/EgtGeomKernel.vcxproj
@@ -323,6 +323,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters
index 27fe0a9..759102a 100644
--- a/EgtGeomKernel.vcxproj.filters
+++ b/EgtGeomKernel.vcxproj.filters
@@ -306,6 +306,9 @@
File di origine\GeoCreate
+
+ File di origine\Geo
+
diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp
index 22c3265..c0fb3fb 100644
--- a/GdbExecutor.cpp
+++ b/GdbExecutor.cpp
@@ -5290,10 +5290,10 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
IntersCurveCurve intCC( *pCrv1, *pCrv2, true) ;
// preparo il testo con i risultati
string sText = "Inters CrvA=" + ToString( nIdEnt1) + " CrvB=" + ToString( nIdEnt2) ;
- sText += "
Nbr=" + ToString( intCC.GetNumInters()) ;
+ sText += "
Nbr=" + ToString( intCC.GetIntersCount()) ;
if ( intCC.GetOverlaps())
sText += " Overlaps" ;
- for ( int i = 0 ; i < intCC.GetNumInters() ; ++ i) {
+ for ( int i = 0 ; i < intCC.GetIntersCount() ; ++ i) {
IntCrvCrvInfo aInfo ;
intCC.GetIntCrvCrvInfo( i, aInfo) ;
int nMax = ( aInfo.bOverlap ? 2 : 1) ;
diff --git a/IntersCrvCompoCrvCompo.cpp b/IntersCrvCompoCrvCompo.cpp
index 8d14b8a..dd98918 100644
--- a/IntersCrvCompoCrvCompo.cpp
+++ b/IntersCrvCompoCrvCompo.cpp
@@ -525,7 +525,7 @@ IntersCrvCompoCrvCompo::IntersSimpleCurves( const ICurve& CurveA, int nA, const
// eseguo l'intersezione di queste curve semplici
IntersCurveCurve intCC( CurveA, CurveB) ;
// ne recupero i risultati
- int nCurrInters = intCC.GetNumInters() ;
+ int nCurrInters = intCC.GetIntersCount() ;
if ( nCurrInters > 0) {
m_bOverlaps = ( intCC.GetOverlaps() ? true : m_bOverlaps) ;
for ( int j = 0 ; j < nCurrInters ; ++ j) {
diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp
index af83743..5d7c83c 100644
--- a/IntersCurveCurve.cpp
+++ b/IntersCurveCurve.cpp
@@ -36,7 +36,7 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& CurveA, const ICurve& CurveB,
// inizializzazioni
m_bOverlaps = false ;
- m_nNumInters = 0 ;
+ m_nIntersCount = 0 ;
m_pCurve[0] = &CurveA ;
m_pCurve[1] = &CurveB ;
@@ -132,8 +132,8 @@ IntersCurveCurve::LineLineCalculate( const ICurve& CurveA, const ICurve& CurveB,
if ( intLnLn.m_nNumInters > 0) {
m_bOverlaps = intLnLn.m_bOverlaps ;
- m_nNumInters = intLnLn.m_nNumInters ;
- if ( m_nNumInters == 1)
+ m_nIntersCount = intLnLn.m_nNumInters ;
+ if ( m_nIntersCount == 1)
m_Info.push_back( intLnLn.m_Info) ;
}
}
@@ -146,8 +146,8 @@ IntersCurveCurve::LineArcCalculate( const ICurve& CurveA, const ICurve& CurveB)
if ( intLnAr.m_nNumInters > 0) {
m_bOverlaps = false ;
- m_nNumInters = intLnAr.m_nNumInters ;
- for ( int i = 0 ; i < m_nNumInters ; ++ i)
+ m_nIntersCount = intLnAr.m_nNumInters ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i)
m_Info.push_back( intLnAr.m_Info[i]) ;
}
}
@@ -171,8 +171,8 @@ IntersCurveCurve::ArcLineCalculate( const ICurve& CurveA, const ICurve& CurveB)
if ( intLnAr.m_nNumInters > 0) {
m_bOverlaps = false ;
- m_nNumInters = intLnAr.m_nNumInters ;
- for ( int i = 0 ; i < m_nNumInters ; ++ i)
+ m_nIntersCount = intLnAr.m_nNumInters ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i)
m_Info.push_back( intLnAr.m_Info[i]) ;
// devo scambiare opportunamente le info di intersezione tra A e B
SwapInfoAB( m_Info, 0) ;
@@ -187,8 +187,8 @@ IntersCurveCurve::ArcArcCalculate( const ICurve& CurveA, const ICurve& CurveB)
if ( intArAr.m_nNumInters > 0) {
m_bOverlaps = intArAr.m_bOverlaps ;
- m_nNumInters = intArAr.m_nNumInters ;
- for ( int i = 0 ; i < m_nNumInters ; ++ i)
+ m_nIntersCount = intArAr.m_nNumInters ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i)
m_Info.push_back( intArAr.m_Info[i]) ;
}
}
@@ -234,8 +234,8 @@ IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& CurveA, const ICurve&
if ( intCcCc.m_nNumInters > 0) {
m_bOverlaps = intCcCc.m_bOverlaps ;
- m_nNumInters = intCcCc.m_nNumInters ;
- for ( int i = 0 ; i < m_nNumInters ; ++ i)
+ m_nIntersCount = intCcCc.m_nNumInters ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i)
m_Info.push_back( intCcCc.m_Info[i]) ;
}
}
@@ -278,16 +278,55 @@ IntersCurveCurve::GetOverlaps( void)
//----------------------------------------------------------------------------
int
-IntersCurveCurve::GetNumInters( void)
+IntersCurveCurve::GetIntersCount( void)
{
- return m_nNumInters ;
+ return m_nIntersCount ;
+}
+
+//----------------------------------------------------------------------------
+int
+IntersCurveCurve::GetCrossIntersCount( void)
+{
+ int nCrossIntersCount = 0 ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
+ // se con sovrapposizione
+ if ( m_Info[i].bOverlap) {
+ if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[1].nNextTy &&
+ m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[1].nNextTy != ICCT_NULL)
+ ++ nCrossIntersCount ;
+ }
+ // altrimenti
+ else {
+ if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy &&
+ m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
+ ++ nCrossIntersCount ;
+ }
+ }
+ return nCrossIntersCount ;
+}
+
+//----------------------------------------------------------------------------
+int
+IntersCurveCurve::GetCrossOrOverlapIntersCount( void)
+{
+ int nCrossOverIntersCount = 0 ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
+ // se con sovrapposizione
+ if ( m_Info[i].bOverlap)
+ ++ nCrossOverIntersCount ;
+ // se altrimenti con attraversamento
+ else if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy &&
+ m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
+ ++ nCrossOverIntersCount ;
+ }
+ return nCrossOverIntersCount ;
}
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
{
- if ( nInd < 0 || nInd >= m_nNumInters)
+ if ( nInd < 0 || nInd >= m_nIntersCount)
return false ;
aInfo = m_Info[nInd] ;
return true ;
@@ -297,13 +336,13 @@ IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
bool
IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d& ptI)
{
- if ( m_nNumInters == 0 || nCrv < 0 || nCrv > 1)
+ if ( m_nIntersCount == 0 || nCrv < 0 || nCrv > 1)
return false ;
// ricerca del punto più vicino tra le intersezioni singole
bool bFound = false ;
double dMinSqDist = INFINITO * INFINITO ;
- for ( int i = 0 ; i < m_nNumInters ; ++ i) {
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// se è un'intersezione singola
if ( ! m_Info[i].bOverlap) {
// faccio la verifica sul punto
@@ -367,7 +406,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
if ( ! m_pCurve[1]->IsClosed())
return false ;
// se esiste almeno una intersezione
- if ( m_nNumInters >= 1)
+ if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
@@ -384,7 +423,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
// esecuzione scambio e controlli
SwapInfoAB( InfoTmp, 1) ;
// se esiste almeno una intersezione
- if ( m_nNumInters >= 1)
+ if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
@@ -403,7 +442,7 @@ IntersCurveCurve::SwapInfoAB( ICCIVECTOR& Info, int IndCrvOrd)
return false ;
// eseguo lo scambio
- for ( int i = 0 ; i < m_nNumInters ; ++ i) {
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// scambio le informazioni tra A e B
swap( Info[i].IciA[0], Info[i].IciB[0]) ;
swap( Info[i].IciA[1], Info[i].IciB[1]) ;
@@ -538,7 +577,7 @@ IntersCurveCurve::CalcCurveInOrOut( const ICurve* pCurveA, const ICurve* pCurveB
// dichiaro la classe della curva per default
int nClass = CRVC_OUT ;
// se c'è almeno una intersezione
- if ( iCC.GetNumInters() > 0) {
+ if ( iCC.GetIntersCount() > 0) {
// se quanto precede la prima intersezione è interno, allora la curva è interna
IntCrvCrvInfo aInfo ;
iCC.GetIntCrvCrvInfo( 0, aInfo) ;
diff --git a/Intervals.cpp b/Intervals.cpp
index 06cc63d..455fa36 100644
--- a/Intervals.cpp
+++ b/Intervals.cpp
@@ -92,7 +92,7 @@ Intervals::Add( double dMin, double dMax)
//----------------------------------------------------------------------------
void
-Intervals::Remove( double dMin, double dMax)
+Intervals::Subtract( double dMin, double dMax)
{
// verifico ordine
if ( dMin > dMax)
@@ -142,7 +142,7 @@ Intervals::Remove( double dMin, double dMax)
//----------------------------------------------------------------------------
void
-Intervals::Union( const Intervals& Other)
+Intervals::Add( const Intervals& Other)
{
// aggiungo tutti gli intervalli dell'altro
for ( auto& Interv : Other.m_lInts)
@@ -151,7 +151,16 @@ Intervals::Union( const Intervals& Other)
//----------------------------------------------------------------------------
void
-Intervals::Intersection( const Intervals& Other)
+Intervals::Subtract( const Intervals& Other)
+{
+ // sottraggo tutti gli intervalli dell'altro
+ for ( auto& Interv : Other.m_lInts)
+ Subtract( Interv.first, Interv.second) ;
+}
+
+//----------------------------------------------------------------------------
+void
+Intervals::Intersect( const Intervals& Other)
{
// se l'insieme è vuoto non devo fare alcunché
if ( m_lInts.empty())
@@ -160,18 +169,9 @@ Intervals::Intersection( const Intervals& Other)
Intervals Aux ;
Aux.Set( m_lInts.front().first, m_lInts.back().second) ;
// Sottraggo Other da Aux
- Aux.Difference( Other) ;
+ Aux.Subtract( Other) ;
// Sottraggo Aux dal corrente
- Difference( Aux) ;
-}
-
-//----------------------------------------------------------------------------
-void
-Intervals::Difference( const Intervals& Other)
-{
- // sottraggo tutti gli intervalli dell'altro
- for ( auto& Interv : Other.m_lInts)
- Remove( Interv.first, Interv.second) ;
+ Subtract( Aux) ;
}
//----------------------------------------------------------------------------
diff --git a/SelfIntersCurve.cpp b/SelfIntersCurve.cpp
index 7e25acd..715ed76 100644
--- a/SelfIntersCurve.cpp
+++ b/SelfIntersCurve.cpp
@@ -176,18 +176,37 @@ SelfIntersCurve::GetCrossIntersCount( void)
for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
// se con sovrapposizione
if ( m_Info[i].bOverlap) {
- if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[1].nNextTy)
+ if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[1].nNextTy &&
+ m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[1].nNextTy != ICCT_NULL)
++ nCrossIntersCount ;
}
// altrimenti
else {
- if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy)
+ if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy &&
+ m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
++ nCrossIntersCount ;
}
}
return nCrossIntersCount ;
}
+//----------------------------------------------------------------------------
+int
+SelfIntersCurve::GetCrossOrOverlapIntersCount( void)
+{
+ int nCrossOverIntersCount = 0 ;
+ for ( int i = 0 ; i < m_nIntersCount ; ++ i) {
+ // se con sovrapposizione
+ if ( m_Info[i].bOverlap)
+ ++ nCrossOverIntersCount ;
+ // se altrimenti con attraversamento
+ else if ( m_Info[i].IciA[0].nPrevTy != m_Info[i].IciA[0].nNextTy &&
+ m_Info[i].IciA[0].nPrevTy != ICCT_NULL && m_Info[i].IciA[0].nNextTy != ICCT_NULL)
+ ++ nCrossOverIntersCount ;
+ }
+ return nCrossOverIntersCount ;
+}
+
//----------------------------------------------------------------------------
bool
SelfIntersCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp
index bc2fd4e..4cce55e 100644
--- a/SurfFlatRegion.cpp
+++ b/SurfFlatRegion.cpp
@@ -116,16 +116,16 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
// porto la curva nel riferimento intrinseco
if ( ! pMyCrv->ToLoc( m_frF))
return false ;
- // verifico non abbia auto-intersezioni
+ // verifico non abbia auto-intersezioni che si attraversano
SelfIntersCurve sInt( *pMyCrv) ;
- if ( sInt.GetIntersCount() > 0)
+ if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// verifico che sia esterna alle curve esterne degli altri chunk
bool bOk = true ;
CRVCVECTOR ccClass ;
for ( auto i : m_vExtInd) {
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
- if ( ccInt.GetNumInters() > 0 ||
+ if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_OUT) {
bOk = false ;
@@ -138,7 +138,7 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
if ( binary_search( m_vExtInd.begin(), m_vExtInd.end(), i))
continue ;
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
- if ( ccInt.GetNumInters() == 0 &&
+ if ( ccInt.GetCrossOrOverlapIntersCount() == 0 &&
ccInt.GetCurveClassification( 0, ccClass) &&
! ccClass.empty() && ccClass[0].nClass == CRVC_OUT) {
bOk = true ;
@@ -148,15 +148,30 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
if ( ! bOk)
return false ;
// assegno la curva come loop esterno
- m_vpLoop.push_back( Release( pMyCrv)) ;
- m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
- m_nStatus = OK ;
+ if ( MyAddExtLoop( Get( pMyCrv)))
+ Release( pMyCrv) ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
return true ;
}
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
+{
+ try {
+ m_vpLoop.push_back( pCrv) ;
+ m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
+ m_nStatus = OK ;
+ }
+ catch (...) {
+ return false ;
+ }
+
+ return true ;
+}
+
//----------------------------------------------------------------------------
bool
SurfFlatRegion::AddIntLoop( const ICurve& cCrv)
@@ -201,25 +216,40 @@ SurfFlatRegion::AddIntLoop( ICurve* pCrv)
pMyCrv->Invert() ;
// verifico non abbia auto-intersezioni
SelfIntersCurve sInt( *pMyCrv) ;
- if ( sInt.GetIntersCount() > 0)
+ if ( sInt.GetCrossOrOverlapIntersCount() > 0)
return false ;
// verifico non abbia intersezioni e non sia esterna ai loop già definiti del medesimo chunk
CRVCVECTOR ccClass ;
for ( int i = m_vExtInd.back() ; i < int( m_vpLoop.size()) ; ++ i) {
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
- if ( ccInt.GetNumInters() > 0 ||
+ if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
return false ;
}
// aggiungo la curva all'elenco dei loop
- m_vpLoop.push_back( Release( pMyCrv)) ;
+ if ( MyAddIntLoop( Get( pMyCrv)))
+ Release( pMyCrv) ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
return true ;
}
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::MyAddIntLoop( ICurve* pCrv)
+{
+ try {
+ m_vpLoop.push_back( pCrv) ;
+ }
+ catch (...) {
+ return false ;
+ }
+
+ return true ;
+}
+
//----------------------------------------------------------------------------
SurfFlatRegion*
SurfFlatRegion::Clone( void) const
@@ -831,7 +861,8 @@ SurfFlatRegion::GetAuxSurf( void) const
int j = 0 ;
ICurve* pLoop = GetMyLoop( i, j) ;
while ( pLoop != nullptr) {
- if ( ! pLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_STD, vPL[j]))
+ // approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
+ if ( ! pLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, vPL[j]))
return nullptr ;
pLoop = GetMyLoop( i, ++j) ;
}
@@ -888,8 +919,9 @@ SurfFlatRegion::CloneChunk( int nChunk) const
//----------------------------------------------------------------------------
bool
-SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
+SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
{
+ // la curva devono già essere nel riferimento intrinseco della regione
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
@@ -900,18 +932,6 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
double dStart, dEnd ;
if ( ! Crv.GetDomain( dStart, dEnd))
return false ;
- // curva in locale nel riferimento intrinseco
- const ICurve* pCrvLoc = nullptr ;
- PtrOwner pCopyCrv ;
- if ( AreSameFrame( m_frF, GLOB_FRM))
- pCrvLoc = &Crv ;
- else {
- pCopyCrv.Set( Crv.Clone()) ;
- if ( IsNull( pCopyCrv))
- return false ;
- pCopyCrv->ToLoc( m_frF) ;
- pCrvLoc = Get( pCopyCrv) ;
- }
// intervalli totali delle diverse classi
Intervals inTIn, inTOut, inTOnP, inTOnM ;
@@ -925,7 +945,7 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
for ( int nLoop = 0 ; nLoop < GetLoopCount( nChunk) ; ++ nLoop) {
const ICurve* pLoop = GetMyLoop( nChunk, nLoop) ;
// intersezione
- IntersCurveCurve ccInt( *pCrvLoc, *pLoop) ;
+ IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
@@ -936,16 +956,46 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
// IN è Remove degli altri
break ;
case CRVC_OUT :
- inCOut.Add( ccOne.dParS, ccOne.dParE) ;
- inCIn.Remove( ccOne.dParS, ccOne.dParE) ;
+ // intervallo standard
+ if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) {
+ inCOut.Add( ccOne.dParS, ccOne.dParE) ;
+ inCIn.Subtract( ccOne.dParS, ccOne.dParE) ;
+ }
+ // intervallo che attraversa punto di chiusura della curva
+ else {
+ inCOut.Add( ccOne.dParS, dEnd) ;
+ inCOut.Add( dStart, ccOne.dParE) ;
+ inCIn.Subtract( ccOne.dParS, dEnd) ;
+ inCIn.Subtract( dStart, ccOne.dParE) ;
+ }
break ;
case CRVC_ON_P :
- inCOnP.Add( ccOne.dParS, ccOne.dParE) ;
- inCIn.Remove( ccOne.dParS, ccOne.dParE) ;
+ // intervallo standard
+ if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) {
+ inCOnP.Add( ccOne.dParS, ccOne.dParE) ;
+ inCIn.Subtract( ccOne.dParS, ccOne.dParE) ;
+ }
+ // intervallo che attraversa punto di chiusura della curva
+ else {
+ inCOnP.Add( ccOne.dParS, dEnd) ;
+ inCOnP.Add( dStart, ccOne.dParE) ;
+ inCIn.Subtract( ccOne.dParS, dEnd) ;
+ inCIn.Subtract( dStart, ccOne.dParE) ;
+ }
break ;
case CRVC_ON_M :
- inCOnM.Add( ccOne.dParS, ccOne.dParE) ;
- inCIn.Remove( ccOne.dParS, ccOne.dParE) ;
+ // intervallo standard
+ if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) {
+ inCOnM.Add( ccOne.dParS, ccOne.dParE) ;
+ inCIn.Subtract( ccOne.dParS, ccOne.dParE) ;
+ }
+ // intervallo che attraversa punto di chiusura della curva
+ else {
+ inCOnM.Add( ccOne.dParS, dEnd) ;
+ inCOnM.Add( dStart, ccOne.dParE) ;
+ inCIn.Subtract( ccOne.dParS, dEnd) ;
+ inCIn.Subtract( dStart, ccOne.dParE) ;
+ }
break ;
default : return false ;
}
@@ -953,13 +1003,13 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
}
// aggiorno gli intervalli di classificazione totali
// In, OnP e OnM vengono aggiornati per somma
- inTIn.Union( inCIn) ;
- inTOnP.Union( inCOnP) ;
- inTOnM.Union( inCOnM) ;
+ inTIn.Add( inCIn) ;
+ inTOnP.Add( inCOnP) ;
+ inTOnM.Add( inCOnM) ;
// Out viene ricavato per differenza degli altri
- inTOut.Difference( inCIn) ;
- inTOut.Difference( inCOnP) ;
- inTOut.Difference( inCOnM) ;
+ inTOut.Subtract( inCIn) ;
+ inTOut.Subtract( inCOnP) ;
+ inTOut.Subtract( inCOnM) ;
}
// ricostruisco la classificazione completa e la ordino
@@ -987,4 +1037,30 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
sort( ccClass.begin(), ccClass.end(),
[]( const CrvClass& a, const CrvClass& b) { return a.dParS < b.dParS ; }) ;
return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
+{
+ // verifico lo stato
+ if ( m_nStatus != OK || m_vpLoop.empty())
+ return false ;
+ // verifico la curva
+ if ( &Crv == nullptr || ! Crv.IsValid())
+ return false ;
+ // curva in locale nel riferimento intrinseco
+ const ICurve* pCrvLoc = nullptr ;
+ PtrOwner pCopyCrv ;
+ if ( AreSameFrame( m_frF, GLOB_FRM))
+ pCrvLoc = &Crv ;
+ else {
+ pCopyCrv.Set( Crv.Clone()) ;
+ if ( IsNull( pCopyCrv))
+ return false ;
+ pCopyCrv->ToLoc( m_frF) ;
+ pCrvLoc = Get( pCopyCrv) ;
+ }
+ // esecuzione classificazione nel riferimento intrinseco
+ return MyGetCurveClassification( *pCrvLoc, ccClass) ;
}
\ No newline at end of file
diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h
index e47e407..49f2845 100644
--- a/SurfFlatRegion.h
+++ b/SurfFlatRegion.h
@@ -75,6 +75,9 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
virtual bool AddExtLoop( ICurve* pCrv) ;
virtual bool AddIntLoop( const ICurve& cCrv) ;
virtual bool AddIntLoop( ICurve* pCrv) ;
+ virtual bool Add( const ISurfFlatRegion& Other) ;
+ virtual bool Subtract( const ISurfFlatRegion& Other) ;
+ virtual bool Intersect( const ISurfFlatRegion& Other) ;
virtual const Vector3d& GetNormVersor( void) const
{ return m_frF.VersZ() ; }
virtual int GetChunkCount( void) const ;
@@ -98,14 +101,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
{ if ( ! CopyFrom( stSrc))
LOG_ERROR( GetEGkLogger(), "SurfFlatRegion : copy error")
return *this ; }
- private :
- bool CopyFrom( const SurfFlatRegion& clSrc) ;
- int GetIndFromChunkLoop( int nChunk, int nLoop) const ;
- bool GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const ;
- ICurve* GetMyLoop( int nInd) const ; // indice nel vettore di tutti i loop
- ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
- void ResetAuxSurf( void) const ;
- bool ConvertArcsToBezierCurves( void) ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
@@ -113,6 +108,23 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
private :
typedef std::deque PCRV_DEQUE ;
+ private :
+ bool CopyFrom( const SurfFlatRegion& clSrc) ;
+ bool MyAddExtLoop( ICurve* pCrv) ;
+ bool MyAddIntLoop( ICurve* pCrv) ;
+ int GetIndFromChunkLoop( int nChunk, int nLoop) const ;
+ bool GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const ;
+ ICurve* GetMyLoop( int nInd) const ; // indice nel vettore di tutti i loop
+ ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
+ void ResetAuxSurf( void) const ;
+ bool ConvertArcsToBezierCurves( void) ;
+ bool MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const ;
+ static bool MySelectCurves( const PCRV_DEQUE& vpLoop, const SurfFlatRegion& Other,
+ int nType1, bool bInvert1, int nType2, bool bInvert2, PCRV_DEQUE& vpCurve) ;
+ static bool MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) ;
+ static SurfFlatRegion* MyNewSurfFromLoops( PCRV_DEQUE& vpLoop) ;
+ static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ;
+
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
mutable SurfTriMesh* m_pSTM ; // superficie trimesh ausiliaria
diff --git a/SurfFlatRegionBooleans.cpp b/SurfFlatRegionBooleans.cpp
new file mode 100644
index 0000000..b3b7497
--- /dev/null
+++ b/SurfFlatRegionBooleans.cpp
@@ -0,0 +1,426 @@
+//----------------------------------------------------------------------------
+// EgalTech 2015-2015
+//----------------------------------------------------------------------------
+// File : SurfFlatRegion.cpp Data : 18.08.15 Versione : 1.6h4
+// Contenuto : Implementazione delle funzioni booleane per SurfFlatRegion.
+//
+//
+//
+// Modifiche : 18.08.15 DS Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+//--------------------------- Include ----------------------------------------
+#include "stdafx.h"
+#include "SurfFlatRegion.h"
+#include "CurveComposite.h"
+#include "GeoConst.h"
+#include "/EgtDev/Include/EGkChainCurves.h"
+#include "/EgtDev/Include/EGkIntervals.h"
+#include "/EgtDev/Include/EgtPointerOwner.h"
+
+using namespace std ;
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::Add( const ISurfFlatRegion& Other)
+{
+ // converto l'altra regione nell'oggetto base
+ const SurfFlatRegion& SfrOther = dynamic_cast( Other) ;
+ if ( &SfrOther == nullptr)
+ return false ;
+
+ // verifico che le due regioni giacciano nello stesso piano
+ if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ()) ||
+ fabs( ( m_frF.Orig() - SfrOther.m_frF.Orig()) * m_frF.VersZ()) > EPS_SMALL)
+ return false ;
+
+ // gestione eventuale copia dell'altra per trasformare il riferimento
+ const SurfFlatRegion* pOther = &SfrOther ;
+ PtrOwner pCopyOth ;
+ // se riferimenti intrinseci diversi, la trasformo
+ if ( ! AreSameFrame( m_frF, SfrOther.m_frF)) {
+ // creo la copia
+ pCopyOth.Set( SfrOther.Clone()) ;
+ if ( IsNull( pCopyOth))
+ return false ;
+ // calcolo riferimento di traformazione
+ Frame3d frTransf = pCopyOth->m_frF ;
+ frTransf.ToLoc( m_frF) ;
+ // trasformo le curve
+ for ( auto& pLoop : pCopyOth->m_vpLoop)
+ pLoop->ToGlob( frTransf) ;
+ // assegno il nuovo riferimento
+ pCopyOth->m_frF = m_frF ;
+ // aggiorno puntatore della copia in lavoro
+ pOther = Get( pCopyOth) ;
+ }
+
+ // vettore con curve utili da entrambe le regioni
+ PCRV_DEQUE vpCurve ;
+ if ( ! MySelectCurves( m_vpLoop, *pOther, CRVC_OUT, false, CRVC_ON_P, false, vpCurve) ||
+ ! MySelectCurves( pOther->m_vpLoop, *this, CRVC_OUT, false, CRVC_NULL, false, vpCurve)) {
+ MyTestAndDelete( vpCurve) ;
+ return false ;
+ }
+
+ // vettore con curve concatenate che sono i contorni del risultato
+ PCRV_DEQUE vpLoop ;
+ // concateno e verifico di aver usato tutte le curve
+ if ( ! MyChainCurves( vpCurve, vpLoop) || ! MyTestAndDelete( vpCurve)) {
+ MyTestAndDelete( vpLoop) ;
+ return false ;
+ }
+
+ // creo una nuova regione a partire da questi loop
+ PtrOwner pSfr( MyNewSurfFromLoops( vpLoop)) ;
+ if ( IsNull( pSfr))
+ return false ;
+
+ // 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 ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
+{
+ // converto l'altra regione nell'oggetto base
+ const SurfFlatRegion& SfrOther = dynamic_cast( Other) ;
+ if ( &SfrOther == nullptr)
+ return false ;
+
+ // verifico che le due regioni giacciano nello stesso piano
+ if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ()) ||
+ fabs( ( m_frF.Orig() - SfrOther.m_frF.Orig()) * m_frF.VersZ()) > EPS_SMALL)
+ return false ;
+
+ // gestione eventuale copia dell'altra per trasformare il riferimento
+ const SurfFlatRegion* pOther = &SfrOther ;
+ PtrOwner pCopyOth ;
+ // se riferimenti intrinseci diversi, la trasformo
+ if ( ! AreSameFrame( m_frF, SfrOther.m_frF)) {
+ // creo la copia
+ pCopyOth.Set( SfrOther.Clone()) ;
+ if ( IsNull( pCopyOth))
+ return false ;
+ // calcolo riferimento di traformazione
+ Frame3d frTransf = pCopyOth->m_frF ;
+ frTransf.ToLoc( m_frF) ;
+ // trasformo le curve
+ for ( auto& pLoop : pCopyOth->m_vpLoop)
+ pLoop->ToGlob( frTransf) ;
+ // assegno il nuovo riferimento
+ pCopyOth->m_frF = m_frF ;
+ // aggiorno puntatore della copia in lavoro
+ pOther = Get( pCopyOth) ;
+ }
+
+ // vettore con curve utili da entrambe le regioni
+ PCRV_DEQUE vpCurve ;
+ if ( ! MySelectCurves( m_vpLoop, *pOther, CRVC_OUT, false, CRVC_ON_M, false, vpCurve) ||
+ ! MySelectCurves( pOther->m_vpLoop, *this, CRVC_IN, true, CRVC_NULL, false, vpCurve)) {
+ MyTestAndDelete( vpCurve) ;
+ return false ;
+ }
+
+ // vettore con curve concatenate che sono i contorni del risultato
+ PCRV_DEQUE vpLoop ;
+ // concateno e verifico di aver usato tutte le curve
+ if ( ! MyChainCurves( vpCurve, vpLoop) || ! MyTestAndDelete( vpCurve)) {
+ MyTestAndDelete( vpLoop) ;
+ return false ;
+ }
+
+ // creo una nuova regione a partire da questi loop
+ PtrOwner pSfr( MyNewSurfFromLoops( vpLoop)) ;
+ if ( IsNull( pSfr))
+ return false ;
+
+ // 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 ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::Intersect( const ISurfFlatRegion& Other)
+{
+ // converto l'altra regione nell'oggetto base
+ const SurfFlatRegion& SfrOther = dynamic_cast( Other) ;
+ if ( &SfrOther == nullptr)
+ return false ;
+
+ // verifico che le due regioni giacciano nello stesso piano
+ if ( ! AreSameVectorApprox( m_frF.VersZ(), SfrOther.m_frF.VersZ()) ||
+ fabs( ( m_frF.Orig() - SfrOther.m_frF.Orig()) * m_frF.VersZ()) > EPS_SMALL)
+ return false ;
+
+ // gestione eventuale copia dell'altra per trasformare il riferimento
+ const SurfFlatRegion* pOther = &SfrOther ;
+ PtrOwner pCopyOth ;
+ // se riferimenti intrinseci diversi, la trasformo
+ if ( ! AreSameFrame( m_frF, SfrOther.m_frF)) {
+ // creo la copia
+ pCopyOth.Set( SfrOther.Clone()) ;
+ if ( IsNull( pCopyOth))
+ return false ;
+ // calcolo riferimento di traformazione
+ Frame3d frTransf = pCopyOth->m_frF ;
+ frTransf.ToLoc( m_frF) ;
+ // trasformo le curve
+ for ( auto& pLoop : pCopyOth->m_vpLoop)
+ pLoop->ToGlob( frTransf) ;
+ // assegno il nuovo riferimento
+ pCopyOth->m_frF = m_frF ;
+ // aggiorno puntatore della copia in lavoro
+ pOther = Get( pCopyOth) ;
+ }
+
+ // vettore con curve utili da entrambe le regioni
+ PCRV_DEQUE vpCurve ;
+ if ( ! MySelectCurves( m_vpLoop, *pOther, CRVC_IN, false, CRVC_ON_P, false, vpCurve) ||
+ ! MySelectCurves( pOther->m_vpLoop, *this, CRVC_IN, false, CRVC_NULL, false, vpCurve)) {
+ MyTestAndDelete( vpCurve) ;
+ return false ;
+ }
+
+ // vettore con curve concatenate che sono i contorni del risultato
+ PCRV_DEQUE vpLoop ;
+ // concateno e verifico di aver usato tutte le curve
+ if ( ! MyChainCurves( vpCurve, vpLoop) || ! MyTestAndDelete( vpCurve)) {
+ MyTestAndDelete( vpLoop) ;
+ return false ;
+ }
+
+ // creo una nuova regione a partire da questi loop
+ PtrOwner pSfr( MyNewSurfFromLoops( vpLoop)) ;
+ if ( IsNull( pSfr))
+ return false ;
+
+ // 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 ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::MySelectCurves( const PCRV_DEQUE& vpLoop, const SurfFlatRegion& Other,
+ int nType1, bool bInvert1, int nType2, bool bInvert2,
+ PCRV_DEQUE& vpCurve)
+{
+ // classifico le curve rispetto alla regione altra e copio le parti utili
+ for ( auto& pLoop : vpLoop) {
+ // eseguo classificazione
+ CRVCVECTOR ccClass ;
+ if ( ! Other.MyGetCurveClassification( *pLoop, ccClass))
+ return false ;
+ // creo intervalli validi, tenendo classificazioni ricevute
+ Intervals inOk1, inOk2 ;
+ for ( auto& ccOne : ccClass) {
+ if ( nType1 != CRVC_NULL && ccOne.nClass == nType1)
+ inOk1.Add( ccOne.dParE, ccOne.dParS) ;
+ else if ( nType2 != CRVC_NULL && ccOne.nClass == nType2)
+ inOk2.Add( ccOne.dParE, ccOne.dParS) ;
+ }
+ // copio queste parti
+ double dParS, dParE ;
+ bool bFound = inOk1.GetFirst( dParS, dParE) ;
+ while ( bFound) {
+ ICurve* pCrv = pLoop->CopyParamRange( dParS, dParE) ;
+ if ( pCrv != nullptr) {
+ if ( bInvert1)
+ pCrv->Invert() ;
+ vpCurve.push_back( pCrv) ;
+ }
+ bFound = inOk1.GetNext( dParS, dParE) ;
+ }
+ bFound = inOk2.GetFirst( dParS, dParE) ;
+ while ( bFound) {
+ ICurve* pCrv = pLoop->CopyParamRange( dParS, dParE) ;
+ if ( pCrv != nullptr) {
+ if ( bInvert2)
+ pCrv->Invert() ;
+ vpCurve.push_back( pCrv) ;
+ }
+ bFound = inOk2.GetNext( dParS, dParE) ;
+ }
+ }
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop)
+{
+ // concateno le curve
+ ChainCurves chainC ;
+ chainC.Init( false, 5 * EPS_SMALL, int( vpCurve.size())) ;
+ for ( int i = 0 ; i < int( vpCurve.size()) ; ++i) {
+ // recupero i dati della curva necessari al concatenamento e li assegno
+ Point3d ptStart, ptEnd ;
+ Vector3d vtStart, vtEnd ;
+ if ( ! vpCurve[i]->GetStartPoint( ptStart) || ! vpCurve[i]->GetStartDir( vtStart) ||
+ ! vpCurve[i]->GetEndPoint( ptEnd) || ! vpCurve[i]->GetEndDir( vtEnd))
+ return false ;
+ if ( ! chainC.AddCurve( i + 1, ptStart, vtStart, ptEnd, vtEnd))
+ return false ;
+ }
+ // recupero i percorsi concatenati
+ INTVECTOR vIds ;
+ Point3d ptNearStart ;
+ while ( chainC.GetChainFromNear( ptNearStart, false, vIds)) {
+ // creo una curva composita
+ PtrOwner pCrvCompo( CreateBasicCurveComposite()) ;
+ if ( IsNull( pCrvCompo))
+ return false ;
+ // recupero le curve e le inserisco nella nuova curva composita
+ for ( auto i : vIds) {
+ // la aggiungo alla curva composta
+ if ( ! pCrvCompo->AddCurve( vpCurve[i-1], true, 5 * EPS_SMALL))
+ return false ;
+ vpCurve[i-1] = nullptr ;
+ }
+ // aggiorno il nuovo punto vicino
+ if ( pCrvCompo->GetCurveCount() > 0)
+ pCrvCompo->GetEndPoint( ptNearStart) ;
+ // compatto la nuova curva
+ pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
+ // inserisco la curva composita nel gruppo destinazione
+ if ( pCrvCompo->GetCurveCount() > 0) {
+ vpLoop.push_back( ::Release( pCrvCompo)) ;
+ }
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+SurfFlatRegion*
+SurfFlatRegion::MyNewSurfFromLoops( PCRV_DEQUE& vpLoop)
+{
+ // verifico che le curve siano chiuse e ne determino l'area
+ typedef std::pair INDAREA ; // coppia indice, area
+ typedef std::vector INDAREAVECTOR ; // vettore di coppie indice, area
+ INDAREAVECTOR vArea ;
+ vArea.reserve( vpLoop.size()) ;
+ for ( int i = 0 ; i < int( vpLoop.size()) ; ++ i) {
+ double dArea ;
+ if ( ! vpLoop[i]->GetAreaXY( dArea))
+ return nullptr ;
+ vArea.emplace_back( i, dArea) ;
+ }
+ // ordino in senso decrescente sull'area
+ sort( vArea.begin(), vArea.end(),
+ []( const INDAREA& a, const INDAREA&b) { return a.second > b.second ; }) ;
+
+ // determino quanti sono i nuovi cicli esterni (area positiva)
+ int nLoopCount = int( vArea.size()) ;
+ int nExtCount = 0 ;
+ for ( int i = 0 ; i < nLoopCount ; ++ i) {
+ if ( vArea[i].second > 0)
+ ++ nExtCount ;
+ }
+
+ // creo una nuova regione
+ PtrOwner pSfr( CreateBasicSurfFlatRegion()) ;
+ // ciclo sui loop esterni, all'indietro dal più piccolo al più grande
+ for ( int i = nExtCount - 1 ; i >= 0 ; -- i) {
+ // inserisco il nuovo esterno
+ int j = vArea[i].first ;
+ ICurve* pExtLoop = vpLoop[j] ;
+ double dExtArea = vArea[i].second ;
+ if ( pSfr->MyAddExtLoop( vpLoop[j])) {
+ vpLoop[j] = nullptr ;
+ vArea[i].first = - 1 ;
+ }
+ else
+ continue ;
+ // provo ad inserire i loop interni
+ for ( int k = nExtCount ; k < nLoopCount ; ++ k) {
+ // verifico non sia già stato inserito
+ if ( vArea[k].first < 0)
+ continue ;
+ // salto gli interni con area maggiore dell'esterno corrente
+ if ( fabs( vArea[k].second) > dExtArea)
+ continue ;
+ int l = vArea[k].first ;
+ // verifico che sia interno all'esterno corrente
+ CRVCVECTOR ccClass ;
+ IntersCurveCurve ccInt( *vpLoop[l], *pExtLoop) ;
+ if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
+ ! ccInt.GetCurveClassification( 0, ccClass) ||
+ ccClass.empty() || ccClass[0].nClass != CRVC_IN)
+ continue ;
+ // lo inserisco
+ if ( pSfr->MyAddIntLoop( vpLoop[l])) {
+ vpLoop[l] = nullptr ;
+ vArea[k].first = - 1 ;
+ }
+ }
+ }
+ // se non valida, errore
+ if ( ! pSfr->IsValid())
+ return nullptr ;
+ // verifico non siano rimasti loop inutilizzati
+ if ( ! MyTestAndDelete( vpLoop))
+ return nullptr ;
+ // tutto bene, ritorno la superficie appena creata
+ return Release( pSfr) ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFlatRegion::MyTestAndDelete( PCRV_DEQUE& vpCrv)
+{
+ bool bOk = true ;
+ for ( auto& pCrv : vpCrv) {
+ if ( pCrv != nullptr) {
+ delete pCrv ;
+ pCrv = nullptr ;
+ bOk = false ;
+ }
+ }
+ return bOk ;
+}