EgtGeomKernel :

- corrette e migliorate le funzioni per
il tracing dei loop di trim delle superifci
 di Bezier
- corretto un bug nella costruzione dei poligoni in superfici bezier
periodiche.
This commit is contained in:
Daniele Bariletti
2024-01-24 14:57:16 +01:00
parent d88de3576d
commit cc312f1529
3 changed files with 106 additions and 128 deletions
+86 -125
View File
@@ -35,7 +35,7 @@ using namespace std ;
//----------------------------------------------------------------------------
Tree::Tree( void)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( 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), m_bTestMode( false)
{
Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
Cell cRoot( ptBl, ptTr) ;
@@ -44,7 +44,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_bClosedU( false), m_bClosedV( 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), m_bTestMode( false)
{
SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ;
}
@@ -554,6 +554,8 @@ Tree::BuildTree_test( double dLinTol, double dSideMin, double dSideMax)
Split( 10) ;
m_vnLeaves.push_back( 20) ;
m_vnLeaves.push_back( 21) ;
// riempio anche la lista dei parent delle celle
m_vnParents = m_vnLeaves ;
return true ;
}
@@ -1496,9 +1498,9 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
reverse( vNeigh.begin(), vNeigh.end()) ;
// aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top
if ( ! vNeigh.empty() && vNeigh.size() != 1) {
// se la superficie è chiusa lungo il parametro U e la cella è sul lato top
// 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.
if ( m_bClosedU && m_mTree.at( nId).m_bOnTopEdge) {
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) ;
vVertices.push_back( pt) ;
@@ -1596,6 +1598,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
int nId = -1 ;
// se fallisce ritorna un vettore vuoto
// verifico che il punto sia all'interno dello spazio parametrico
// allargo i bordi in modo da tenere anche i punti sul bordo dello spazio parametrico
if ( ptToAssign.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptToAssign.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL||
ptToAssign.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptToAssign.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) {
//nCells.push_back( - 2) ;
@@ -1604,15 +1607,19 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
// se ho diviso preliminarmente le patches e in uno dei due parametri ho un numero dispari di patches devo individuare a mano la cella parent
// in cui individuare la foglia giusta
if ( m_bSplitPatches && ( m_nSpanU > 1 || m_nSpanV > 1)) {
if ( (m_bSplitPatches && ( m_nSpanU > 1 || m_nSpanV > 1)) || m_bTestMode) {
INTVECTOR nParents = FindCell( ptToAssign, clTrim, m_vnParents) ;
nId = nParents.back() ;
if ( m_bTestMode ) {
nCells.push_back(nId) ;
return nCells ;
}
}
// individuo la foglia in cui ho lo start del loop
while ( ! m_mTree.at( nId).IsLeaf()) {
if ( m_mTree.at( nId).IsSplitVert()) {
double dMid = ( m_mTree.at( nId).GetBottomLeft().x + m_mTree.at( nId).GetTopRight().x) / 2 ;
if ( ptToAssign.x < dMid + EPS_SMALL) {
if ( ptToAssign.x < dMid) {
nId = m_mTree.at( nId).m_nChild1 ;
}
else {
@@ -1621,7 +1628,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
}
else {
double dMid = ( m_mTree.at( nId).GetBottomLeft().y + m_mTree.at( nId).GetTopRight().y) / 2 ;
if ( ptToAssign.y < dMid + EPS_SMALL) {
if ( ptToAssign.y < dMid) {
nId = m_mTree.at( nId).m_nChild2 ;
}
else {
@@ -1638,23 +1645,29 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
if ( abs( ptToAssign.x - ptTl.x) < EPS_SMALL || abs( ptToAssign.x - ptBr.x) < EPS_SMALL ||
abs( ptToAssign.y - ptTl.y) < EPS_SMALL || abs( ptToAssign.y - ptBr.y) < EPS_SMALL)
{
Point3d ptToAssignPlus ;
double dParam ;
Vector3d vtDir ;
clTrim.GetParamAtPoint( ptToAssign, dParam, EPS_SMALL) ;
clTrim.GetPointTang( dParam + EPS_SMALL, ICurve::FROM_MINUS, ptToAssignPlus, vtDir) ;
clTrim.GetStartDir( vtDir) ;
// proseguo lungo la curva di trim di EPS_SMALL
Point3d ptToAssignPlus = ptToAssign + vtDir * EPS_SMALL ;
// se la curva di trim è praticamente parallela ad un lato allora giro a destra, perché voglio considerare intersecate le celle esterne ( sul bordo) al loop
if ( abs( vtDir.x) > 1 - EPS_SMALL || abs( vtDir.y) > 1 - EPS_SMALL) {
vtDir.Rotate( Z_AX, -90) ;
ptToAssignPlus = ptToAssignPlus + vtDir * 2 * EPS_SMALL ;
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 90) ;
ptToAssignPlus = ptToAssignPlus + vtDir * EPS_SMALL ;
// controllo di non essere uscito dallo spazio parametrico ed eventualmente giro a sinistra
if ( ptToAssignPlus.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptToAssignPlus.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL||
ptToAssignPlus.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptToAssignPlus.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) {
// rispetto al punto di partenza avanzo lungo la curva di trim
ptToAssignPlus = ptToAssign + vtDir * EPS_SMALL ;
Vector3d vtDirSX = vtDir ; vtDirSX.Rotate( Z_AX, -90) ;
// e poi giro a sinistra
ptToAssignPlus = ptToAssign + vtDir * EPS_SMALL ;
}
}
INTVECTOR nCellsSave = nCells ;
nCells = FindCell( ptToAssignPlus, clTrim, true) ;
if ( nCells.empty()) {
ptToAssignPlus = ptToAssignPlus - 2 * vtDir * EPS_SMALL ;
vtDir.Rotate( Z_AX, 90) ;
ptToAssignPlus = ptToAssignPlus + 10 * vtDir * EPS_SMALL ;
nCells = FindCell( ptToAssignPlus, clTrim, true) ;
if ( nCells.empty())
nCells.push_back( nId) ;
// se nonostante tutto non trovo nulla allora tengo il risultato ottenuto scorrendo l'albero
nCells = nCellsSave ;
}
}
}
@@ -1693,15 +1706,13 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
else if ( (int)nCells.size() >= 1 ) {
// la CurveLine è il segmento di trim su cui giace ptToAssign
Point3d ptIntersPlus ;
double dParam ;
Vector3d vDir ;
cl.GetParamAtPoint( ptToAssign, dParam, EPS_SMALL) ;
cl.GetStartDir( vDir) ;
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 prima di spostarmi
if ( abs( vDir.x) >= 1 - EPS_SMALL || abs( vDir.y) >= 1 - EPS_SMALL)
vDir.Rotate( Z_AX, -45) ;
ptIntersPlus = ptToAssign + vDir * EPS_SMALL ;
if ( abs( vtDir.x) >= 1 - EPS_SMALL || abs( vtDir.y) >= 1 - EPS_SMALL)
vtDir.Rotate( Z_AX, -45) ;
ptIntersPlus = ptToAssign + vtDir * EPS_SMALL ;
nCells = FindCell( ptIntersPlus, cl, vCells) ;
}
// se vuoto allora il punto non è in nessuna delle celle passate in input
@@ -2012,7 +2023,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
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
bool bIntersFound = false ;
Point3d ptInters ;
int nEdge2 ;
if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) {
@@ -2024,16 +2034,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
nEdge2 = 1 ;
clEdge2.Set( ptTl, ptBL) ;
}
//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 ;
@@ -2044,16 +2044,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
nEdge2 = 2 ;
clEdge2.Set( ptBL, ptBr) ;
}
//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 ;
@@ -2064,16 +2054,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
nEdge2 = 3 ;
clEdge2.Set( ptBr, ptTR) ;
}
//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 ;
@@ -2084,71 +2064,44 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
nEdge2 = 0 ;
clEdge2.Set( ptTR, ptTl) ;
}
//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) ;
IntCrvCrvInfo aInfo, aInfo2 ;
bool bIntersOn1Found = true ;
if ( ! illExit.GetIntCrvCrvInfo( aInfo)) {
bIntersOn1Found = false ;
if ( ! clEdge2.IsValid())
return false ;
}
//else if ( aInfo.bOverlap && ! bFirstInters) {
// ptInters = aInfo.IciA[1].ptI ;
// bIntersFound = true ;
//}
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
bIntersOn1Found = true ;
if ( clEdge2.IsValid() && ! bIntersOn1Found){
IntersLineLine illExit2( clTrim, clEdge2, true) ;
// verifico su quale dei due lati ho l'intersezione
if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)){
if ( bIntersOn1Found) {
// se ho intersezione su Edge1 con sovrapposizione, seleziono o il primo punto o il secondo.
if ( aInfo.bOverlap && ! bFirstInters)
ptInters = aInfo.IciA[1].ptI ;
else
ptInters = aInfo.IciA[0].ptI ;
}
else
return false ;
}
else {
//// solo intersezione sul lato 2
bIntersOn2Found = true ;
if ( aInfo2.bOverlap && ! bFirstInters)
ptInters = aInfo2.IciA[1].ptI ;
else
ptInters = aInfo2.IciA[0].ptI ;
}
}
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 {
if ( aInfo.bOverlap && ! bFirstInters)
ptInters = aInfo.IciA[1].ptI ;
bIntersFound = true ;
//// solo intersezione sul lato 2
if ( aInfo2.bOverlap)
ptInters = aInfo2.IciA[1].ptI ;
else
ptInters = aInfo.IciA[0].ptI ;
ptInters = aInfo2.IciA[0].ptI ;
}
}
if ( ! bIntersOn2Found)
OnWhichEdge( nId, ptInters, nEdge) ;
else
nEdge = nEdge2 ;
if ( ! bIntersFound)
return false ;
// determino il lato/vertice di uscita
OnWhichEdge( nId, ptInters, nEdge) ;
m_mTree[nId].m_vInters.back().nOut = nEdge ;
if ( (int)vptInters.size() == 0 || ! AreSamePointExact( ptInters , vptInters.back()))
vptInters.push_back( ptInters) ;
@@ -2290,11 +2243,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 6 ;
}
else {
else if (! vNeigh1.empty()) {
nId = vNeigh1.back() ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 7 ;
}
else
return false ;
}
}
else if ( nEdge == 5) {
@@ -2339,11 +2294,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 7 ;
}
else {
else if (! vNeigh1.empty()) {
nId = vNeigh1[0] ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 4 ;
}
else
return false ;
}
}
else if ( nEdge == 6) {
@@ -2388,11 +2345,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 4 ;
}
else {
else if (! vNeigh1.empty()) {
nId = vNeigh1[0] ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 5 ;
}
else
return false ;
}
}
else if ( nEdge == 7) {
@@ -2437,11 +2396,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 5 ;
}
else {
else if (! vNeigh1.empty()) {
nId = vNeigh1.back() ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 6 ;
}
else
return false ;
}
}
// aggiungo l'intersezione al vettore delle intersezioni della prossima cella
@@ -3427,14 +3388,6 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
Point3d ptTl ( ptBL.x, ptTR.y) ;
Point3d ptBr ( ptTR.x, ptBL.y) ;
if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptTR.y) < EPS_SMALL)
nEdge = 0 ;
else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptBL.x) < EPS_SMALL)
nEdge = 1 ;
else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptBL.y) < EPS_SMALL)
nEdge = 2 ;
else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL)
nEdge = 3 ;
if ( AreSamePointApprox( ptToAssign, ptTR))
nEdge = 7 ;
else if ( AreSamePointApprox( ptToAssign, ptTl))
@@ -3443,6 +3396,14 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
nEdge = 5 ;
else if ( AreSamePointApprox( ptToAssign, ptBr))
nEdge = 6 ;
else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptTR.y) < EPS_SMALL)
nEdge = 0 ;
else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptBL.x) < EPS_SMALL)
nEdge = 1 ;
else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptBL.y) < EPS_SMALL)
nEdge = 2 ;
else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL)
nEdge = 3 ;
else
return false ;
return true ;