EgtGeomKernel :

- miglioramento delle superfici di bezier.
- aggiunta di una funzione per l'eliminazione delle span collassate e di una per l'inversione dei paramettri di una superficie.
This commit is contained in:
Daniele Bariletti
2025-12-19 15:03:19 +01:00
parent d27fdb9904
commit 91ca84f77a
4 changed files with 311 additions and 46 deletions
+65 -34
View File
@@ -474,7 +474,8 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
}
if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11))
if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitVert = false ;
}
if( bGoodSplitHoriz) {
@@ -490,7 +491,8 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
}
if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11))
if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitHoriz = false ;
}
@@ -786,6 +788,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
nCToSplit = pcToSplit->m_nChild1 ;
pcToSplit = &m_mTree[nCToSplit] ;
}
else
return false ;
}
else {
// sono arrivato ad una cella Leaf, quindi salvo la cella
@@ -899,6 +903,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
nCToSplit = pcToSplit->m_nChild1 ;
pcToSplit = &m_mTree[nCToSplit] ;
}
else
return false ;
}
else {
// sono arrivato ad una cella Leaf, quindi salvo la cella
@@ -1435,19 +1441,20 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
if ( ! TraceLoopLabelCell( vPolygonsBasic))
return false ;
// scorro sulle celle e costruisco i poligoni
int nCells = int( vPolygonsBasic.size()) ;
for ( int i = 0 ; i < nCells ; ++ i) {
int nPoly = 0 ;
for ( int nId: m_vnLeaves) {
// costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps
int nId = m_vnLeaves[i] ;
if ( m_mTree[nId].m_nFlag == 4) {
// vettore dei poligoni ( loop) della cella nId
vvPolygons.emplace_back() ;
vvPolygons.back().push_back(std::move(vPolygonsCorrected[i])) ;
vvPolygons.back().push_back(std::move(vPolygonsCorrected[nPoly])) ;
vvPolygons3d.emplace_back() ;
vvPolygons3d.back().push_back(std::move(vPolygonsBasic3d[i])) ;
vvPolygons3d.back().push_back(std::move(vPolygonsBasic3d[nPoly])) ;
}
else if ( m_mTree[nId].m_nFlag == 0)
continue ;
else if( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
continue ;
else {
// vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella
INTVECTOR vnParentChunk ;
@@ -1461,13 +1468,14 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
while ( ! vToCheck.empty()) {
int nPolyBefore = nPoly ;
PolyLine pl3d ;
CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsCorrected[i], vPolygonsBasic3d[i]) ;
CreateCellPolygons( nId, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsCorrected[nPoly], vPolygonsBasic3d[nPoly]) ;
if ( nPolyBefore == nPoly)
break ;
}
// ora analizzo anche i loop che sono contenuti nella cella
CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, vPolygonsCorrected[i], vPolygonsBasic3d[i]) ;
CreateIslandAndHoles( nId, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, vPolygonsCorrected[nPoly], vPolygonsBasic3d[nPoly]) ;
}
++ nPoly ;
}
}
@@ -1910,10 +1918,9 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs
nCells.push_back( nId) ;
if ( ! bRecurs) {
// se sono in un vertice o su un lato devo controllare di aver trovato la cella giusta
Point3d ptBr( m_mTree.at( nId).GetTopRight().x , m_mTree.at( nId).GetBottomLeft().y) ;
Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x , m_mTree.at( nId).GetTopRight().y) ;
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) {
int nEdge = - 2 ;
OnWhichEdge( nId, ptToAssign, nEdge) ;
if ( nEdge != - 2) {
Vector3d vtDir ;
clTrim.GetStartDir( vtDir) ;
// proseguo lungo la curva di trim di EPS_SMALL
@@ -1964,12 +1971,16 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
}
// se non ho trovato nulla vuol dire che sono su un vertice o su un lato
if ( nCells.empty() && ! bRecurs) {
int nEdge = -1 ;
int nEdge = -2 ;
for ( int nCell : vCells) {
OnWhichEdge( nCell,ptToAssign, nEdge) ;
if ( nEdge != -1)
break ;
OnWhichEdge( nCell, ptToAssign, nEdge) ;
if ( nEdge != -2 && (m_mTree.at(nCell).m_nCollapsed == Cell::Collapsed::NO_COLLAPSE || m_mTree.at(nCell).m_nCollapsed == Cell::Collapsed::TO_VERIFY))
nCells.push_back( nCell) ;
nEdge = -2 ;
}
if( ssize( nCells) == 1)
return nCells ;
Vector3d vtDir ;
cl.GetStartDir( vtDir) ;
Point3d ptIntersPlus = ptToAssign ;
@@ -1977,7 +1988,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
// potrei essere su un lato
if ( nEdge == 0 || nEdge == 1 || nEdge == 2 || nEdge == 3) {
// se è orientato con il lato mi sposto a destra
if ( ( nEdge == 0 || nEdge == 2 ) && abs(vtDir.x) > 1 - EPS_SMALL/100 ) {
if ( ( nEdge == 0 || nEdge == 2 ) && abs(vtDir.x) > 1 - EPS_SMALL/100) {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -90) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
}
@@ -1996,10 +2007,17 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 )
ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ;
// altrimenti ruoto a destra
else {
else if( ( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
}
// altrimenti ruoto a sinistra
else /*if( ( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
}
}
//
else
@@ -2011,7 +2029,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
ptIntersPlus = ptToAssign + vtDirSX * EPS_SMALL ;
}
// rilancio la rigida ricerca
nCells = FindCell( ptIntersPlus, cl, vCells, true) ;
nCells = FindCell( ptIntersPlus, cl, nCells, true) ;
}
return nCells ;
@@ -2117,9 +2135,10 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
pCell->m_vInters.back().nChunk = m_mChunk[i] ;
bool bLoopInside = true ;
Point3d ptCurr ;
auto iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
int nIdPolygon = distance( m_vnLeaves.begin(), iter) ;
if ( nIdPolygon > int( vplPolygons.size()) - 1)
int nIdPolygon = - 1;
if( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ;
else
return false ;
bool bEraseNextPoint = false ;
while ( plLoop.GetNextPoint( ptCurr)) {
@@ -2128,6 +2147,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
plLoop.GetNextPoint( ptTEnd) ;
CurveLine clTrim ;
clTrim.Set( ptTStart, ptTEnd) ;
Point3d ptLastInters = P_INVALID ;
int nInfiniteLoopCount = 0 ;
// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva
while ( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) {
// sto uscendo dalla cella, quindi cerco l'intersezione
@@ -2153,13 +2174,23 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
return false ;
bEraseNextPoint = true ;
}
// ricalcolo la posizione di nId nel vettore delle foglie
iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
nIdPolygon = distance( m_vnLeaves.begin(), iter) ;
if ( nIdPolygon > int( vplPolygons.size()) - 1)
return false ;
// se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito
// se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto
if( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
++ nInfiniteLoopCount ;
if( nInfiniteLoopCount == 4) {
LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell")
return false ;
}
}
ptLastInters = vptInters.back() ;
// aggiorno il puntatore alla cella
pCell = &m_mTree[nId] ;
// recupero l'indice del poligono base associato alla cella
if( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ;
else
return false ;
// salvo il verso del loop
pCell->m_vInters.back().bCCW = bCCW ;
// salvo il chunk del loop
@@ -2783,11 +2814,10 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon,
//----------------------------------------------------------------------------
bool
Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly,
Tree::CreateCellPolygons( int nId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly,
INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d)
{
// conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato
int nId = m_vnLeaves[nLeafId] ;
Cell& cCell = m_mTree[nId] ;
PNTMATRIX vEdgeVertex(4) ;
PNTMATRIX vEdgeVertex3d(4) ;
@@ -2795,7 +2825,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
Point3d ptTR = cCell.GetTopRight() ;
Point3d ptTl = cCell.GetTopLeft() ;
Point3d ptBr = cCell.GetBottomRight() ;
int nVertToErase = m_mTree.at(nId).m_nVertToErase ;
int nVertToErase = cCell.m_nVertToErase ;
if ( nVertToErase != 2)
vEdgeVertex[0].push_back( ptTR) ;
if ( nVertToErase != 3)
@@ -3116,11 +3146,10 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX
//----------------------------------------------------------------------------
bool
Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
Tree::CreateIslandAndHoles( int nId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk,
const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d)
{
// costruisco i poligoni partendo dal vettore delle intersezioni
int nId = m_vnLeaves[nLeafId] ;
Cell& cCell = m_mTree[nId] ;
//capisco se sono in modalità ForTriangulation
@@ -3994,7 +4023,9 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
Point3d ptTl ( ptBL.x, ptTR.y) ;
Point3d ptBr ( ptTR.x, ptBL.y) ;
if ( AreSamePointXYApprox( ptToAssign, ptTR))
if( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL)
return false ;
else if ( AreSamePointXYApprox( ptToAssign, ptTR))
nEdge = 7 ;
else if ( AreSamePointXYApprox( ptToAssign, ptTl))
nEdge = 4 ;