EgtGeomKernel :

- correzione bug nelle sup di Bezier chiuse.
This commit is contained in:
Daniele Bariletti
2023-10-19 12:45:48 +02:00
parent a5714cc85d
commit 5bb1fdaed3
3 changed files with 166 additions and 59 deletions
+156 -54
View File
@@ -29,7 +29,7 @@
//----------------------------------------------------------------------------
Cell::Cell( void)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false),
m_ptPbl( ORIG), m_ptPtr(), m_bProcessed( false), m_bSplitVert( true)
{
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
@@ -40,7 +40,7 @@ Cell::Cell( void)
//----------------------------------------------------------------------------
Cell::Cell( const Point3d& ptBL, const Point3d& ptTR)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false),
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true)
{}
@@ -72,7 +72,7 @@ Cell::IsLeaf ( void) const
//----------------------------------------------------------------------------
Tree::Tree( void)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosed( false), m_bSplitPatches( true)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true)
{
Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
Cell cRoot( ptBl, ptTr) ;
@@ -81,7 +81,7 @@ Tree::Tree( void)
//----------------------------------------------------------------------------
Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d ptMin, const Point3d ptMax)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosed( false), m_bSplitPatches( true)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true)
{
SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ;
}
@@ -208,11 +208,13 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
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) {
if ( i * SBZ_TREG_COEFF > ptMin.x && i * SBZ_TREG_COEFF < ptTop.x){
@@ -242,11 +244,12 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
// e sistemo le adiacenze
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) ||
( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) {
m_bClosed = true ;
//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) ;
@@ -276,6 +279,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
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) ;
@@ -1411,10 +1415,10 @@ Tree::GetPolygons( std::vector<POLYLINEVECTOR>& vPolygons) {
}
// trimmata
else {
if ( ! TraceLoopLabelCell())
return false ;
POLYLINEVECTOR vPolygonsBasic ;
GetPolygonsBasic( vPolygonsBasic) ;
if ( ! TraceLoopLabelCell( vPolygonsBasic))
return false ;
// scorro sulle celle e costruisco i poligoni
int nCells = (int)vPolygonsBasic.size() ;
for ( int i = 0 ; i < nCells ; ++i) {
@@ -1465,8 +1469,23 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
if ( m_vPolygons.empty()) {
PNTVECTOR vVertices ;
INTVECTOR vNeigh ;
// setto le celle che sono sul LeftEdge e sul TopEdge
if ( m_bClosedU) {
GetRootNeigh( 1, vNeigh) ;
for ( int k : vNeigh) {
m_mTree[k].m_bOnLeftEdge = true ;
}
vNeigh.clear() ;
}
if ( m_bClosedV) {
GetRootNeigh( 0, vNeigh) ;
for ( int k : vNeigh) {
m_mTree[k].m_bOnTopEdge = true ;
}
}
bool bBottomRight , bTopLeft ;
// scorro lungo tutte le celle leaves e oltre agli angoli della cella aggiungo alla polyline anche i vertici sui lati
// scorro lungo tutte le celle leaves e oltre agli angoli della cella aggiungo alla polyline della cella anche i vertici, delle celle adiacenti,
// che sono sui lati della cella corrente
for ( int nId : m_vnLeaves) {
vVertices.clear() ;
vNeigh.clear() ;
@@ -1474,8 +1493,18 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
GetBottomNeigh( nId, vNeigh) ;
// aggiungo i vertici che sono sul lato bottom, solo se ho più di un vicino bottom
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetTopRight()) ;
// se la superficie è chiusa lungo il parametro V e le celle vicine bottom sono sul lato Top
// devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico.
if ( m_bClosedV && m_mTree.at(vNeigh[0]).m_bOnTopEdge) {
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( j).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ;
vVertices.push_back( pt) ;
}
}
else {
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetTopRight()) ;
}
bBottomRight = true ;
}
else
@@ -1484,8 +1513,19 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
GetRightNeigh ( nId, vNeigh) ;
// aggiungo i vertici che sono sul lato right, solo se ho più di un vicino right
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ;
// 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.
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) ;
vVertices.push_back( pt) ;
}
}
else {
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ;
}
}
// se non l'ho già aggiunto tramite i vicini bottom aggiungo il punto bottom right
else if ( ! bBottomRight) {
@@ -1498,8 +1538,18 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
std::reverse( vNeigh.begin(), vNeigh.end()) ;
// aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ;
// se la superficie è chiusa lungo il parametro U e la cella è sul lato top
// devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico.
if ( m_bClosedU && m_mTree.at( nId).m_bOnTopEdge) {
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ;
vVertices.push_back( pt) ;
}
}
else {
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ;
}
bTopLeft = true ;
}
else
@@ -1509,8 +1559,18 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
std::reverse( vNeigh.begin(), vNeigh.end()) ;
// aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetTopRight()) ;
// 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.
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) ;
vVertices.push_back( pt) ;
}
}
else {
for ( int j : vNeigh)
vVertices.push_back( m_mTree.at( j).GetTopRight()) ;
}
}
// se non l'ho già aggiunto tramite i vicini top aggiungo il punto top left
else if ( ! bTopLeft) {
@@ -1655,8 +1715,8 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
INTVECTOR nCells ;
int nId = -1 ;
for ( int nCell : vCells) {
if ( ptIntersPlus.x >= m_mTree.at( nCell).GetBottomLeft().x && ptIntersPlus.x <= m_mTree.at( nCell).GetTopRight().x &&
ptIntersPlus.y >= m_mTree.at( nCell).GetBottomLeft().y && ptIntersPlus.y <= m_mTree.at( nCell).GetTopRight().y) {
if ( ptIntersPlus.x > m_mTree.at( nCell).GetBottomLeft().x - EPS_ZERO && ptIntersPlus.x < m_mTree.at( nCell).GetTopRight().x + EPS_ZERO &&
ptIntersPlus.y > m_mTree.at( nCell).GetBottomLeft().y - EPS_ZERO && ptIntersPlus.y < m_mTree.at( nCell).GetTopRight().y + EPS_ZERO) {
nId = nCell ;
nCells.push_back( nId) ;
}
@@ -1666,12 +1726,13 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
//----------------------------------------------------------------------------
bool
Tree::TraceLoopLabelCell( void)
Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
{
// l'idea è di seguire il loop di trim, passando di cella in cella, restando, quando possibile, a destra del loop.
// ( destra e sinistra sono determinate dal verso del loop).
// il valore è negativo perché voglio considerare contenuto anche un punto che sta su un lato
double dLinTol = - EPS_SMALL ;
POLYLINEVECTOR vplPolygons ;
GetPolygonsBasic( vplPolygons) ;
// percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle
for ( int i = 0 ; i < (int) m_vPlApprox.size() ; ++ i) {
PolyLine plLoop = std::get<0>(m_vPlApprox[i]) ;
@@ -1855,7 +1916,7 @@ Tree::TraceLoopLabelCell( void)
// ( e controllo che non sia una cella sul lato sinistro ( adiacenza in caso di superficie chiusa))
for ( int t: vNeigh) {
if ( m_mTree[t].m_nFlag2 == 0 ) {
if ( ! m_bClosed) {
if ( ! m_bClosedU) {
bDone = false ;
break ;
}
@@ -1879,15 +1940,19 @@ Tree::TraceLoopLabelCell( void)
// trovo il vicino a sinistra, già categorizzato, più basso
vNeigh.clear() ;
GetLeftNeigh( nCell, vNeigh) ;
for ( int p = 0 ; p < (int)vNeigh.size() ; ++ p) {
if ( m_mTree[vNeigh[p]].m_nFlag2 != 0) {
nCell = vNeigh[p] ;
break ;
// però se sono già sul lato sinistro non cerco di spostarmi ancora più a sinistra.
if ( ! m_mTree[nCell].m_bOnLeftEdge) {
for ( int p = 0 ; p < (int)vNeigh.size() ; ++ p) {
if ( m_mTree[vNeigh[p]].m_nFlag2 != 0) {
nCell = vNeigh[p] ;
break ;
}
}
}
if ( ! m_bClosed) {
// se non ho vicini a sinistra sono tornato sul lato sinistro e quindi devo procedere alla cella più bassa non processata sul lato sinistro
if ( vNeigh.empty()) {
if ( ! m_bClosedU) {
// se non ho vicini a sinistra sono tornato sul lato sinistro
// se questa cella non è processata devo procedere alla cella più bassa non processata sul lato sinistro
if ( vNeigh.empty() && m_mTree[nCell].IsProcessed()) {
for ( int p = 0 ; p < (int)vFirst.size() ; ++ p) {
if ( m_mTree[vFirst[p]].m_nFlag2 == 0) {
nCell = vFirst[p] ;
@@ -1902,7 +1967,7 @@ Tree::TraceLoopLabelCell( void)
}
else {
// verifico se sono tornato sul lato sinistro, in questo caso procedo con la prima cella di vFirst non processata
if ( m_mTree[nCell].m_bOnLeftEdge) {
if ( m_mTree[nCell].m_bOnLeftEdge && m_mTree[nCell].IsProcessed()) {
for ( int p = 0 ; p < (int) vFirst.size(); ++ p) {
if ( nCell == vFirst[p] && nCell != nLastLeft) {
nCell = vFirst[p + 1] ;
@@ -1959,62 +2024,91 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
// -1 se la curva è sempre dentro la cella
bool bIntersFound = false ;
Point3d ptInters ;
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)
if ( ptEnd.x < ptBL.x) {
nEdge2 = 1 ;
clEdge2.Set( ptTl, ptBL) ;
else if ( AreSamePointExact( ptEnd, ptTl) && bFirstInters) {
nEdge = 4 ;
ptInters = ptTl ;
bIntersFound = true ;
}
//else if ( AreSamePointExact( ptEnd, ptTl) && bFirstInters) {
// nEdge = 4 ;
// ptInters = ptTl ;
// bIntersFound = true ;
//}
//else if ( AreSamePointExact( ptEnd, ptTR) && bFirstInters) {
// nEdge = 7 ;
// ptInters = ptTR ;
// bIntersFound = true ;
//}
}
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)
if ( ptEnd.y < ptBL.y) {
nEdge2 = 2 ;
clEdge2.Set( ptBL, ptBr) ;
else if ( AreSamePointExact( ptEnd, ptBL) && bFirstInters) {
nEdge = 5 ;
ptInters = ptBL ;
bIntersFound = true ;
}
//else if ( AreSamePointExact( ptEnd, ptBL) && bFirstInters) {
// nEdge = 5 ;
// ptInters = ptBL ;
// bIntersFound = true ;
//}
//else if ( AreSamePointExact( ptEnd, ptTl) && bFirstInters) {
// nEdge = 4 ;
// ptInters = ptTl ;
// bIntersFound = true ;
//}
}
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)
if ( ptEnd.x > ptTR.x) {
nEdge2 = 3 ;
clEdge2.Set( ptBr, ptTR) ;
else if ( AreSamePointExact( ptEnd, ptBr) && bFirstInters) {
nEdge = 6 ;
ptInters = ptBr ;
bIntersFound = true ;
}
//else if ( AreSamePointExact( ptEnd, ptBr) && bFirstInters) {
// nEdge = 6 ;
// ptInters = ptBr ;
// bIntersFound = true ;
//}
//else if ( AreSamePointExact( ptEnd, ptBL) && bFirstInters) {
// nEdge = 5 ;
// ptInters = ptBL ;
// bIntersFound = true ;
//}
}
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)
if ( ptEnd.y > ptTR.y) {
nEdge2 = 0 ;
clEdge2.Set( ptTR, ptTl) ;
else if ( AreSamePointExact( ptEnd, ptTR) && bFirstInters) {
nEdge = 7 ;
ptInters = ptTR ;
bIntersFound = true ;
}
//else if ( AreSamePointExact( ptEnd, ptTR) && bFirstInters) {
// nEdge = 7 ;
// ptInters = ptTR ;
// bIntersFound = true ;
//}
//else if ( AreSamePointExact( ptEnd, ptBr) && bFirstInters) {
// nEdge = 6 ;
// ptInters = ptBr ;
// bIntersFound = true ;
//}
}
else
return false ;
bool bIntersOn2Found = false ;
if ( ! bIntersFound) {
// intersezione e controlli
IntersLineLine illExit( clTrim, clEdge, true) ;
@@ -2045,6 +2139,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
}
else {
//// solo intersezione sul lato 2
bIntersOn2Found = true ;
if ( aInfo2.bOverlap && ! bFirstInters)
ptInters = aInfo2.IciA[1].ptI ;
else
@@ -2052,9 +2147,12 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
}
}
else
ptInters = aInfo.IciA[0].ptI ;
ptInters = aInfo.IciA[0].ptI ; // qui devo mettere il controllo su prima o seconda intersezione?
}
OnWhichEdge( nId, ptInters, nEdge) ;
if ( ! bIntersOn2Found)
OnWhichEdge( nId, ptInters, nEdge) ;
else
nEdge = nEdge2 ;
m_mTree[nId].m_vInters.back().nOut = nEdge ;
if ( (int)vptInters.size() == 0 || ! AreSamePointExact( ptInters , vptInters.back()))
vptInters.push_back( ptInters) ;
@@ -2069,7 +2167,11 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
m_mTree[nId].m_nFlag = 1 ;
else if ( m_mTree[nId].m_nFlag == 2)
m_mTree[nId].m_nFlag = 3 ;
// seleziono la cella successiva da analizzare
//
// se la superficie è chiusa su un parametro devo stare attento a considerare lo spazio parametrico come se non fosse periodico
// es: non posso saltare dal lato destro al lato sinistro anche se una cella sul lato sinistro risulta la RightNeigh di una cella sul lato destro!
INTVECTOR vNeigh, vNeigh1 ;
if ( nEdge == 0) {
GetTopNeigh( nId, vNeigh) ;
@@ -2331,7 +2433,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
}
// ingresso in diagonale
else {
if ( ! vNeigh.empty()) {
if ( ! vNeigh.empty() /*&& ! m_mTree[vNeigh[0]].m_bOnLeftEdge */) { // questa aggiunta in teoria non serve
int nIdTemp = vNeigh.back() ;
vNeigh.clear() ;
GetTopNeigh( nIdTemp, vNeigh) ;