EgtGeomKernel 1.6h4 :
- aggiunto metodo GetCrossOrOverlapIntersCount a SelfIntersCurve - aggiunti metodi GetCrossIntersCount e GetCrossOrOverlapIntersCount a IntersCurveCurve - allentati controlli sui loop delle regioni, ora possono toccarsi ma non attraversarsi in punti isolati - aggiunte funzioni per operazioni booleante tra regioni Add, Subtract e Intersect.
This commit is contained in:
@@ -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 ;
|
||||
|
||||
Binary file not shown.
@@ -323,6 +323,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="SelfIntersCurve.cpp" />
|
||||
<ClCompile Include="SfrCreate.cpp" />
|
||||
<ClCompile Include="SurfFlatRegion.cpp" />
|
||||
<ClCompile Include="SurfFlatRegionBooleans.cpp" />
|
||||
<ClCompile Include="UserObjDefault.cpp" />
|
||||
<ClCompile Include="UserObjFactory.cpp" />
|
||||
<ClCompile Include="OutTsc.cpp" />
|
||||
|
||||
@@ -306,6 +306,9 @@
|
||||
<ClCompile Include="SfrCreate.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfFlatRegionBooleans.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
||||
+2
-2
@@ -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 += "<br/>Nbr=" + ToString( intCC.GetNumInters()) ;
|
||||
sText += "<br/>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) ;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+59
-20
@@ -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) ;
|
||||
|
||||
+14
-14
@@ -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) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+21
-2
@@ -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)
|
||||
|
||||
+113
-37
@@ -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<ICurve> 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<ICurve> 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) ;
|
||||
}
|
||||
+20
-8
@@ -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<ICurve*> 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
|
||||
|
||||
@@ -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<const SurfFlatRegion&>( 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<SurfFlatRegion> 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<SurfFlatRegion> 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<const SurfFlatRegion&>( 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<SurfFlatRegion> 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<SurfFlatRegion> 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<const SurfFlatRegion&>( 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<SurfFlatRegion> 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<SurfFlatRegion> 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<CurveComposite> 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<int,double> INDAREA ; // coppia indice, area
|
||||
typedef std::vector<INDAREA> 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<SurfFlatRegion> 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 ;
|
||||
}
|
||||
Reference in New Issue
Block a user