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:
Dario Sassi
2015-08-22 13:48:19 +00:00
parent bab45eb4f3
commit b2db80edc9
12 changed files with 661 additions and 85 deletions
+1 -1
View File
@@ -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 ;
BIN
View File
Binary file not shown.
+1
View File
@@ -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" />
+3
View File
@@ -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
View File
@@ -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) ;
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+426
View File
@@ -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 ;
}