EgtGeomKernel :

- correzioni e migliorie alla triangolazione con le bezier.
This commit is contained in:
Daniele Bariletti
2024-07-25 16:25:05 +02:00
parent c3e7d3d8c7
commit 9b87de9fa2
3 changed files with 178 additions and 304 deletions
+50 -13
View File
@@ -88,6 +88,7 @@ SurfBezier::Init( int nDegU, int nDegV, int nSpanU, int nSpanV, bool bIsRational
else
m_vWeCtrl.clear() ;
m_nStatus = TO_VERIFY ;
m_nIsPlanar = NOT_CALCULATED ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
@@ -1583,7 +1584,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
if ( ! Tri.Make( vPL, vPnt, vTria))
return nullptr ;
//vedo se la polyline 3d che passo io corrisponde a quella che usavo prima
POLYLINEVECTOR vPL3d = vvPL3d[c] ;
// porto i punti in 3d
@@ -1598,6 +1598,17 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
}
}
// se ho ottenuto meno triangoli di quelli che avrei dovuto avere allora potrei aver avuto un problema in prossimità di un polo
// se comunque ho corrispondenza tra vPnt e vPnt3d allora eseguo la trinagolazione in 3d
if ( ( vPnt.size() - 2 ) != ( vTria.size() ) / 3 && vPnt.size() == vPnt3d.size() ) {
if ( ! Tri.Make( vPL3d, vPnt, vTria))
return nullptr ;
if ( ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 )
LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) RESOLVED")
else
LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one")
}
// controllo per ogni polyline se è stato invertito il vettore dei punti
int nCurrPoint = 0 ;
for( int i = 0 ; i < int( vPL.size()) ; ++i) {
@@ -3197,6 +3208,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
else
pCrvBz0->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ;
}
pCrvBz0->Invert() ;
pCrvCompo->AddCurve( Release( pCrvBz0)) ;
}
}
@@ -3218,6 +3230,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
else
pCrvBz1->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ;
}
pCrvBz1->Invert() ;
pCrvCompo->AddCurve( Release( pCrvBz1)) ;
}
}
@@ -3272,19 +3285,40 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
bool
SurfBezier::IsPlanar( void) const
{
// costruisco il contorno della superficie unendo gli edge e chiedo se la polyline è piana.
PtrOwner<ICurveComposite> pCCEdge( GetSingleEdge3D( false, 0)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 1)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 2)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 3)) ;
if ( m_nIsPlanar != NOT_CALCULATED) {
switch ( m_nIsPlanar ) {
case PLANAR_SURF : return true ; break ;
case NOT_PLANAR_SURF : return false ; break ;
}
}
PolyLine plApprox ;
pCCEdge->ApproxWithLines( 0.01, 15, 0, plApprox) ;
Plane3d plPlane ;
if ( ! plApprox.IsFlat( plPlane, 2 * EPS_SMALL))
return false ;
// in questo caso se è grado 1 in U e V e ho un unica Patch allora sono sicuro sia piana
if ( m_nDegU == 1 && m_nSpanU == 1 && m_nDegV == 1 && m_nSpanV == 1) // questa condizione da sola non è sufficiente ( posso avere superfici torte anche se i lati sono segmenti)
return true ;
if( ! m_bTrimmed) {
// costruisco il contorno della superficie unendo gli edge e chiedo se la polyline è piana.
PtrOwner<ICurveComposite> pCCEdge( GetSingleEdge3D( false, 0)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 1)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 2)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 3)) ;
pCCEdge->ApproxWithLines( 0.01, 15, 0, plApprox) ;
if ( ! plApprox.IsFlat( plPlane, 2 * EPS_SMALL)){
m_nIsPlanar = 0 ;
return false ;
}
// in questo caso se è grado 1 in U e V e ho un unica Patch allora sono sicuro sia piana
if ( m_nDegU == 1 && m_nSpanU == 1 && m_nDegV == 1 && m_nSpanV == 1) {
m_nIsPlanar = 1 ;
return true ;
}
}
else {
Point3d ptCtrl ;
bool bOk = true ;
plApprox.AddUPoint( 0, GetControlPoint(0, &bOk)) ;
plApprox.AddUPoint( 1, GetControlPoint(m_nDegU * m_nSpanU, &bOk)) ;
plApprox.AddUPoint( 2, GetControlPoint(( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV + 1), &bOk)) ;
plApprox.AddUPoint( 3, GetControlPoint(( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk)) ;
}
double dULast ; plApprox.GetLastU( dULast) ;
++ dULast ;
@@ -3299,10 +3333,13 @@ SurfBezier::IsPlanar( void) const
}
}
plPlane.Reset() ;
if ( plApprox.IsFlat( plPlane, 2 * EPS_SMALL))
if ( plApprox.IsFlat( plPlane, 2 * EPS_SMALL)) {
m_nIsPlanar = 1 ;
return true ;
}
// nel dubbio restituisco false
m_nIsPlanar = 0 ;
return false ;
}
+1
View File
@@ -224,6 +224,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
double m_dTempParam[2] ; // vettore parametri temporanei
mutable vector<ICRVCOMPOPOVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato)
} ;
//-----------------------------------------------------------------------------
+127 -291
View File
@@ -68,43 +68,6 @@ Tree::Tree( const Point3d ptBl, const Point3d ptTr)
bool
Tree::LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const
{
// //questo metodo NON VA BENE perchè tiene anche parte dei loop che stanno fuori dal parametrico e quindi il FINDCELL può fallire
//
//// creo la flat region di trim, quella del parametrico e li interseco
//PtrOwner<ISurfFlatRegion> pSfrTrim( GetSurfFlatRegionFromPolyLine( pl)) ;
//bool bInverted = false ;
//if ( ! pSfrTrim->GetNormVersor().IsZplus()) {
// pSfrTrim->Invert() ;
// bInverted = true ;
//}
//PtrOwner<ISurfFlatRegion> pParamTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ;
//if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) {
// if ( ! pParamTrim->Offset( 10 * EPS_SMALL, ICurve::OFF_EXTEND))
// return false ;
// if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid())
// return false ;
// if ( ! pParamTrim->Offset( -10 * EPS_SMALL, ICurve::OFF_EXTEND))
// return false ;
//}
//// ricostruisco la curva tenendo solo le parti dentro lo spazio parametrico
//// devo recuperare la polyline dei bordi dei vari chunk creati
//for ( int c = 0 ; c < int( pParamTrim->GetChunkCount()) ; ++c) {
// for ( int l = 0 ; l < pParamTrim->GetLoopCount(c) ; ++l) {
// PtrOwner<ICurve> pCrv ( pParamTrim->GetLoop( c, l)) ;
// if ( bInverted)
// pCrv->Invert() ;
// PolyLine plApprox ;
// double dLinTol = 10 * EPS_SMALL, dAngTolDeg = 5 ;
// int nType = 0 ;
// pCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, plApprox) ;
// // aggiungo la polyline del chunk
// vPl.push_back( plApprox) ;
// }
//}
//// CON LE CURVE ( INTERSEZIONI CON BORDO PARAMETRICO)
PtrOwner<ICurveComposite> pCCEdge( CreateCurveComposite()) ;
pCCEdge->AddPoint( m_mTree.at(-1).GetTopRight()) ;
@@ -321,121 +284,124 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_mVert.insert( pair<int, PNTVECTOR>( -1, vVert)) ;
// se richiesto divido preliminarmente le patches
m_vnParents.clear() ;
if ( m_bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) {
int nId = -1 ;
// se la superficie è chiusa lungo il parametro U, sistemo le adiacenze al bordo
if ( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) {
m_mTree[-1].m_nLeft = -1 ;
m_mTree[-1].m_nRight = -1 ;
m_bClosedU = true ;
}
// se la superficie è chiusa lungo il parametro V, sistemo le adiacenze al bordo
if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) ) {
m_mTree[-1].m_nTop = -1 ;
m_mTree[-1].m_nBottom = -1 ;
m_bClosedV = true ;
}
for ( int i = 1 ; i < nSpanU ; ++i) {
// chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000)
if ( i * SBZ_TREG_COEFF > ptMin.x + 5 && i * SBZ_TREG_COEFF < ptTop.x - 5){
m_mTree[nId].SetSplitDirVert( true) ;
if ( Split( nId, i * SBZ_TREG_COEFF)) {
++ nId ;
++ nId ;
}
bool bIsPlanar = m_pSrfBz->IsPlanar() ;
if( ! bIsPlanar) {
if ( m_bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) {
int nId = -1 ;
// se la superficie è chiusa lungo il parametro U, sistemo le adiacenze al bordo
if ( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) {
m_mTree[-1].m_nLeft = -1 ;
m_mTree[-1].m_nRight = -1 ;
m_bClosedU = true ;
}
}
INTVECTOR vLeaves ;
GetHeightLeaves( -1, vLeaves) ;
for ( int nId : vLeaves) {
for ( int j = nSpanV - 1 ; j > 0 ; --j) {
// chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000)
if ( j * SBZ_TREG_COEFF > ptMin.y + 5 && j * SBZ_TREG_COEFF < ptTop.y - 5){
m_mTree[nId].SetSplitDirVert( false) ;
if ( Split( nId, j * SBZ_TREG_COEFF))
nId = m_mTree[nId].m_nChild2 ;
}
}
}
vLeaves.clear() ;
}
// controllo se la superficie è chiusa.
// se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa
// e sistemo le adiacenze
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) ||
( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) {
// m_bClosed = true ;
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) && (int) m_mTree.size() == 1) {
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) {
// se la superficie è chiusa lungo il parametro V, sistemo le adiacenze al bordo
if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) ) {
m_mTree[-1].m_nTop = -1 ;
m_mTree[-1].m_nBottom = -1 ;
m_bClosedV = true ;
}
m_mTree[-1].SetSplitDirVert( false) ;
Split( -1) ;
// qui devo fare il controllo capped ( chiusura a semisfera)
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
bool bOk = false ;
bool bPole0 = true, bPole1 = true ;
Point3d ptU0, ptU1 ;
// controllo se tutti i punti di controllo sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ;
ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ;
}
m_vbPole[1] = bPole0 ;
m_vbPole[3] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ;
Split( 1) ;
}
}
// nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo
if ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11)) {
if ( m_mTree.size() == 1) {
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) {
m_mTree[-1].m_nLeft = -1 ;
m_mTree[-1].m_nRight = -1 ;
m_bClosedU = true ;
for ( int i = 1 ; i < nSpanU ; ++i) {
// chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000)
if ( i * SBZ_TREG_COEFF > ptMin.x + 5 && i * SBZ_TREG_COEFF < ptTop.x - 5){
m_mTree[nId].SetSplitDirVert( true) ;
if ( Split( nId, i * SBZ_TREG_COEFF)) {
++ nId ;
++ nId ;
}
}
m_mTree[-1].SetSplitDirVert( true) ;
}
INTVECTOR vLeaves ;
GetHeightLeaves( -1, vLeaves) ;
for ( int nId : vLeaves) {
for ( int j = nSpanV - 1 ; j > 0 ; --j) {
// chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000)
if ( j * SBZ_TREG_COEFF > ptMin.y + 5 && j * SBZ_TREG_COEFF < ptTop.y - 5){
m_mTree[nId].SetSplitDirVert( false) ;
if ( Split( nId, j * SBZ_TREG_COEFF))
nId = m_mTree[nId].m_nChild2 ;
}
}
}
vLeaves.clear() ;
}
// controllo se la superficie è chiusa.
// se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa
// e sistemo le adiacenze
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) ||
( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) {
// m_bClosed = true ;
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) && (int) m_mTree.size() == 1) {
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) {
m_mTree[-1].m_nTop = -1 ;
m_mTree[-1].m_nBottom = -1 ;
m_bClosedV = true ;
}
m_mTree[-1].SetSplitDirVert( false) ;
Split( -1) ;
// devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti
// qui devo fare il controllo capped ( chiusura a semisfera)
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
bool bOk = false ;
bool bPole0 = true, bPole1 = true ;
Point3d ptV0, ptV1 ;
// controllo se tutti i punti sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) {
ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ;
ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ;
Point3d ptU0, ptU1 ;
// controllo se tutti i punti di controllo sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ;
ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ;
}
m_vbPole[0] = bPole0 ;
m_vbPole[2] = bPole1 ;
m_vbPole[1] = bPole0 ;
m_vbPole[3] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( false) ;
m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( false) ;
m_mTree[1].SetSplitDirVert( true) ;
Split( 1) ;
}
}
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4 && ! m_mTree.at(-1).IsSplitVert()) { // si può mettere anche < 5
m_mTree[0].m_nLeft = -1 ;
m_mTree[0].m_nRight = -1 ;
m_mTree[1].m_nLeft = -1 ;
m_mTree[1].m_nRight = -1 ;
m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ;
Split( 1) ;
// nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo
if ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11)) {
if ( m_mTree.size() == 1) {
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) {
m_mTree[-1].m_nLeft = -1 ;
m_mTree[-1].m_nRight = -1 ;
m_bClosedU = true ;
}
m_mTree[-1].SetSplitDirVert( true) ;
Split( -1) ;
// devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
bool bOk = false ;
bool bPole0 = true, bPole1 = true ;
Point3d ptV0, ptV1 ;
// controllo se tutti i punti sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) {
ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ;
ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ;
}
m_vbPole[0] = bPole0 ;
m_vbPole[2] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( false) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( false) ;
Split( 1) ;
}
}
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4 && ! m_mTree.at(-1).IsSplitVert()) { // si può mettere anche < 5
m_mTree[0].m_nLeft = -1 ;
m_mTree[0].m_nRight = -1 ;
m_mTree[1].m_nLeft = -1 ;
m_mTree[1].m_nRight = -1 ;
m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ;
Split( 1) ;
}
}
}
}
@@ -1003,6 +969,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
}
// bilineare
else {
bool bIsPlanar = m_pSrfBz->IsPlanar() ;
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
if ( m_mTree[nCToSplit].IsLeaf()) {
// vertici della cella
@@ -1079,7 +1047,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
}
}
}
else {
else if ( ! bIsPlanar){
dErr = 1. / 4. * ( ( ptP00 - ptP01) + ( ptP11 - ptP10)).Len() ;
//int dErr2 = 1. / 4. * ( ( ptP10 - ptP01) + ( ptP11 - ptP00)).Len() ; //correzione che mi verrebbe intuitiva, ma che fa dividere la superficie molto di più ( probabilmente troppo)!! quindi probabilmente sbagliata
}
@@ -1557,16 +1525,6 @@ Tree::GetDepth( int nId, int nRef = -2) const
return i ;
}
////----------------------------------------------------------------------------
//struct generator
//{
// int value ;
// generator( void)
// { value = -1 ; }
// int operator() ()
// { return ++value ; }
//} ;
//----------------------------------------------------------------------------
bool
Tree::GetPolygons( POLYLINEMATRIX& vvPolygons)
@@ -1792,7 +1750,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
// se la superficie è chiusa lungo il parametro U e le celle vicine right sono sul lato Left
// devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico.
vnVert.push_back( int(vVertices.size())) ;
vnVert.push_back( int(vVertices.size() - 1)) ;
if ( m_bClosedU && m_mTree.at( vNeigh[0]).m_bOnLeftEdge ) {
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ;
@@ -1825,7 +1783,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
if ( ! vNeigh.empty() && vNeigh.size() != 1) {
// se la superficie è chiusa lungo il parametro V e la cella è sul lato top
// devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico.
vnVert.push_back( int(vVertices.size())) ;
vnVert.push_back( int(vVertices.size() - 1)) ;
if ( m_bClosedV && m_mTree.at( nId).m_bOnTopEdge) {
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ;
@@ -1851,7 +1809,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
// se la superficie è chiusa lungo il parametro U e la cella è sul lato left
// devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico.
vnVert.push_back( int(vVertices.size())) ;
vnVert.push_back( int(vVertices.size() - 1)) ;
if ( m_bClosedU && m_mTree.at( nId).m_bOnLeftEdge) {
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ;
@@ -2236,40 +2194,6 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
}
// rilancio la rigida ricerca
nCells = FindCell( ptIntersPlus, cl, vCells, true) ;
/////////////////////////// questa versione funziona, ma forse potrebbe fallire in alcuni casi///
// for ( int nCell : vCells) {
// if ( ptToAssign.x > m_mTree.at( nCell).GetBottomLeft().x - EPS_SMALL && ptToAssign.x < m_mTree.at( nCell).GetTopRight().x + EPS_SMALL &&
// ptToAssign.y > m_mTree.at( nCell).GetBottomLeft().y - EPS_SMALL && ptToAssign.y < m_mTree.at( nCell).GetTopRight().y + EPS_SMALL) {
// nId = nCell ;
// nCells.push_back( nId) ;
// }
// }
// if ( (int)nCells.size() == 1)
// return nCells ;
// // sono su vertice o un lato, quindi avanzo con il parametro lungo la curva
// else if ( (int)nCells.size() > 1 ) {
// // la CurveLine è il segmento di trim su cui giace ptToAssign
// Point3d ptIntersPlus ;
// Vector3d vtDir ;
// cl.GetStartDir( vtDir) ;
// // mi sposto appena più avanti di ptToAssign
// // se la curva è orientata come l'asse x o y mi sto muovendo su un lato e sarò ancora sul lato, quindi dovrei ruotare il vettore a destra prima di spostarmi
// if ( abs( vtDir.x) >= 1 - EPS_SMALL || abs( vtDir.y) >= 1 - EPS_SMALL)
// vtDir.Rotate( Z_AX, -45) ;
// ptIntersPlus = ptToAssign + vtDir * EPS_SMALL ;
// // se sono finito fuori dallo spazio parametrico giro invece a sinistra
// if ( ptIntersPlus.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptIntersPlus.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL||
// ptIntersPlus.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptIntersPlus.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) {
// vtDir.Rotate( Z_AX, 90) ;
// ptIntersPlus = ptToAssign + vtDir * EPS_SMALL ;
// }
// nCells = FindCell( ptIntersPlus, cl, vCells) ;
// }
//// se vuoto allora il punto non è in nessuna delle celle passate in input
// else
// return nCells ;
//////////////////////////////////////////////////////////////////////////
}
return nCells ;
@@ -2405,19 +2329,13 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ;
}
// VERSIONE NUOVA
// controllo di aggiungere un punto abbastanza distante dal precedente
if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 2 * EPS_SMALL)) {
if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) {
// aggiungo la fine del segmento nel vettore delle intersezioni
vptInters.push_back( ptCurr) ;
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ;
}
////VECCHIA VERSIONE
//// aggiungo la fine del segmento nel vettore delle intersezioni
//vptInters.push_back( ptCurr) ;
//// aggiorno la polyline splittata
//UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ;
}
if ( nId == nFirstCell)
vptInters.pop_back() ;
@@ -2626,91 +2544,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon,
int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario
Point3d ptInters ;
//CurveLine clEdge , clEdge2 ;
//Point3d ptStart , ptEnd ;
//clTrim.GetStartPoint( ptStart) ;
//clTrim.GetEndPoint( ptEnd) ;
//// trovo da quale lato sto uscendo
////int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario
//// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
//// -1 se la curva è sempre dentro la cella
////int nEdge2 ;
//if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) {
// //nEdge = 0 ;
// // lato sopra
// clEdge.Set( ptTR, ptTl) ;
// // lato sinistro
// if ( ptEnd.x < ptBL.x) {
// //nEdge2 = 1 ;
// clEdge2.Set( ptTl, ptBL) ;
// }
//}
//else if ( ptEnd.x <= ptBL.x && ptEnd.y <= ptTR.y) {
// nEdge = 1 ;
// // lato sinistro
// clEdge.Set( ptTl, ptBL) ;
// // lato sotto
// if ( ptEnd.y < ptBL.y) {
// //nEdge2 = 2 ;
// clEdge2.Set( ptBL, ptBr) ;
// }
//}
//else if ( ptEnd.y <= ptBL.y && ptEnd.x >= ptBL.x) {
// nEdge = 2 ;
// // lato sotto
// clEdge.Set( ptBL, ptBr) ;
// // lato destro
// if ( ptEnd.x > ptTR.x) {
// //nEdge2 = 3 ;
// clEdge2.Set( ptBr, ptTR) ;
// }
//}
//else if ( ptEnd.x >= ptTR.x && ptEnd.y >= ptBL.y) {
// nEdge = 3 ;
// // lato desto
// clEdge.Set( ptBr, ptTR) ;
// // lato sopra
// if ( ptEnd.y > ptTR.y) {
// //nEdge2 = 0 ;
// clEdge2.Set( ptTR, ptTl) ;
// }
//}
//else
// return false ;
//bool bIntersFound = false ;
//// intersezione e controlli
//IntersLineLine illExit( clTrim, clEdge, true) ;
//IntCrvCrvInfo aInfo, aInfo2 ;
//if ( ! illExit.GetIntCrvCrvInfo( aInfo)) {
// bIntersFound = false ;
// if ( ! clEdge2.IsValid())
// return false ;
//}
//else {
// bIntersFound = true ;
// if ( aInfo.bOverlap)
// ptInters = aInfo.IciA[1].ptI ;
// else
// ptInters = aInfo.IciA[0].ptI ;
//}
//if ( clEdge2.IsValid() && ! bIntersFound){
// IntersLineLine illExit2( clTrim, clEdge2, true) ;
// // verifico su quale dei due lati ho l'intersezione
// if ( ! illExit2.GetIntCrvCrvInfo( aInfo2))
// bIntersFound = false ;
// else {
// bIntersFound = true ;
// //// solo intersezione sul lato 2
// if ( aInfo2.bOverlap)
// ptInters = aInfo2.IciA[1].ptI ;
// else
// ptInters = aInfo2.IciA[0].ptI ;
// }
//}
//if ( ! bIntersFound)
// return false ;
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
PolyLine plSimplePolygon ;
plSimplePolygon = plPolygon ;
@@ -2765,7 +2598,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon,
else if ( nEdge == 7)
ptInters = ptTR ;
// aggiungo il nuovo punto al vettore delle intersezioni
if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 2 * EPS_SMALL))
if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 10 * EPS_SMALL))
vptInters.push_back( ptInters) ;
else {
// se l'ultimo punto del vettore delle intersezioni è quasi uguale al punto che devo aggiungere allora lo sostituisco con quest'ultimo
@@ -3140,15 +2973,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
}
else {
double dPar = 0 ;
bool bAdvanced = false ;
while ( plCell.GetNextUPoint( &dPar, &ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) {
vEdgeVertex[j].push_back( ptToAdd) ;
if ( dPar > 0)
plCell3d.GetNextPoint( pt3d) ;
vEdgeVertex3d[j].push_back( pt3d) ;
bAdvanced = true ;
}
if ( ! bAdvanced && dPar > 0)
if ( dPar > 0)
plCell3d.GetNextPoint( pt3d) ;
}
}
@@ -3198,7 +3029,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
Vector3d vEdge ;
// estendo: se l'ultimo tratto è sovrapposto e controverso allora elimino l'ultimo punto
bool bNotEquiverseOverlap = false ;
if ( nEdge == 0 || nEdge == 7 ) {
int nEdgeLast = -1 ;
OnWhichEdge(nId,ptLast, nEdgeLast) ;
if ( (nEdge == 0 || nEdge == 7) && nEdge == nEdgeLast) {
vEdge.Set( 1,0,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
@@ -3207,7 +3040,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
bNotEquiverseOverlap = true ;
}
}
else if ( nEdge == 1 || nEdge == 4 ) {
else if ( ( nEdge == 1 || nEdge == 4 ) && nEdge == nEdgeLast) {
vEdge.Set( 0,-1,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
@@ -3216,7 +3049,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
bNotEquiverseOverlap = true ;
}
}
else if ( nEdge == 2 || nEdge == 5 ) {
else if ( ( nEdge == 2 || nEdge == 5) && nEdge == nEdgeLast) {
vEdge.Set( -1,0,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
@@ -3225,7 +3058,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
bNotEquiverseOverlap = true ;
}
}
else if ( nEdge == 3 || nEdge == 6 ) {
else if ( ( nEdge == 3 || nEdge == 6) && nEdge == nEdgeLast) {
vEdge.Set( 0,1,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
@@ -3313,8 +3146,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
else if ( ! bNotCameBack){
Point3d ptStart ;
plTrimmedPoly.GetFirstPoint( ptStart) ;
Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ;
for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) {
if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) {
if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) {
plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ;
++ c ;
@@ -3348,8 +3182,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
// aggiorno le condizioni per il while
bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ;
}
Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ;
for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) {
if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) {
if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) {
plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ;
++ c ;
@@ -3458,10 +3293,11 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR
vPolygons.push_back( vCellPolygons) ;
++ nPoly ;
if ( bForTriangulation) {
plInLoop3d.AddUPoint( 0, m_mVert[nId][2]);
plInLoop3d.AddUPoint( 1, m_mVert[nId][3]);
plInLoop3d.AddUPoint( 2, m_mVert[nId][0]);
plInLoop3d.AddUPoint( 3, m_mVert[nId][1]);
plInLoop3d.AddUPoint( 0, m_mVert[nId][2]) ;
plInLoop3d.AddUPoint( 1, m_mVert[nId][3]) ;
plInLoop3d.AddUPoint( 2, m_mVert[nId][0]) ;
plInLoop3d.AddUPoint( 3, m_mVert[nId][1]) ;
plInLoop3d.Close() ;
vCellPolygons3d.push_back( plInLoop3d) ;
vPolygons3d.push_back( vCellPolygons3d) ;
vCellPolygons3d.clear() ;
@@ -3884,7 +3720,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe
bool
Tree::SetRightEdgeIn( int nId)
{
// categorizzo la cella in base a quanta parte del lato destro è conenuta all'interno delle curve di trim
// categorizzo la cella in base a quanta parte del lato destro è contenuta all'interno delle curve di trim
// RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto
int nPass = (int) m_mTree[nId].m_vInters.size() ;
if ( nPass == 0) {