EgtGeomKernel :

- migliormaneto della velocità di calcolo per la triangolazione di superfici di Bezier.
- irrobustimento della stessa triangolazione.
This commit is contained in:
Daniele Bariletti
2024-06-19 10:07:03 +02:00
parent 09220bfd68
commit 9d845179a4
3 changed files with 306 additions and 88 deletions
+255 -72
View File
@@ -1567,24 +1567,54 @@ Tree::GetDepth( int nId, int nRef = -2) const
//----------------------------------------------------------------------------
bool
Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
Tree::GetPolygons( POLYLINEMATRIX& vvPolygons)
{
POLYLINEMATRIX vvPolygonsBasic3d ;
return GetPolygons( vvPolygons, false, vvPolygonsBasic3d) ;
}
//----------------------------------------------------------------------------
bool
Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vPolygonsBasic3d)
{
return GetPolygons( vvPolygons, true, vPolygonsBasic3d) ;
}
//----------------------------------------------------------------------------
bool
Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d)
{
if ( (int) m_vPolygons.size() == 0) {
if ( ! m_bTrimmed) {
vPolygons.clear() ;
vvPolygons.clear() ;
POLYLINEVECTOR vPolygonsBasic ;
GetPolygonsBasic( vPolygonsBasic, true) ;
POLYLINEVECTOR vPolygonsBasic3d ;
if ( bForTriangulation)
GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ;
else
GetPolygonsBasic( vPolygonsBasic) ;
int c = 0;
for ( PolyLine pl : vPolygonsBasic) {
POLYLINEVECTOR vSinglePolygon ;
vSinglePolygon.push_back( pl) ;
vPolygons.push_back( vSinglePolygon) ;
vvPolygons.push_back( vSinglePolygon) ;
if ( bForTriangulation) {
POLYLINEVECTOR vSinglePolygon3d ;
vSinglePolygon3d.push_back( vPolygonsBasic3d[c]) ;
vvPolygons3d.push_back( vSinglePolygon3d) ;
}
++c ;
}
return true ;
}
// trimmata
else {
POLYLINEVECTOR vPolygonsBasic ;
GetPolygonsBasic( vPolygonsBasic) ;
POLYLINEVECTOR vPolygonsBasic3d ;
if ( bForTriangulation)
GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ;
else
GetPolygonsBasic( vPolygonsBasic) ;
// aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim
m_vCEdge2D.clear() ;
for ( int i = 0 ; i < 4 ; ++i) {
@@ -1603,7 +1633,17 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
// vettore dei poligoni ( loop) della cella nId
POLYLINEVECTOR vCellPolygons ;
vCellPolygons.push_back( vPolygonsBasic[i]) ;
vPolygons.push_back( vCellPolygons) ;
vvPolygons.push_back( vCellPolygons) ;
if ( bForTriangulation ) {
POLYLINEVECTOR vCellPolygons3d ;
PolyLine plPolygon3d ;
plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ;
plPolygon3d.AddUPoint( 1, m_mVert[nId][1]) ;
plPolygon3d.AddUPoint( 2, m_mVert[nId][2]) ;
plPolygon3d.AddUPoint( 3, m_mVert[nId][3]) ;
vCellPolygons3d.push_back( plPolygon3d) ;
vvPolygons3d.push_back( vCellPolygons3d) ;
}
}
else if ( m_mTree[nId].m_nFlag == 0)
continue ;
@@ -1620,26 +1660,41 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
// in questo for analizzo solo i loop che tagliano la cella
while( (int)vToCheck.size() != 0) {
int nPolyBefore = nPoly ;
CreateCellPolygons( i, vPolygons, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i]) ;
CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i], vPolygonsBasic3d[i]) ;
if ( nPolyBefore == nPoly)
break ;
}
// ora analizzo anche i loop che sono contenuti nella cella
CreateIslandAndHoles( i, vPolygons, nPoly, vnParentChunk) ;
CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk) ;
}
}
return true ;
}
}
else {
vPolygons = m_vPolygons ;
vvPolygons = m_vPolygons ;
return true ;
}
}
//----------------------------------------------------------------------------
bool
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVECTOR vCells)
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygons3d)
{
return GetPolygonsBasic( vPolygons, true, vPolygons3d) ;
}
//----------------------------------------------------------------------------
bool
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells)
{
POLYLINEVECTOR vPolygons3d ;
return GetPolygonsBasic( vPolygons, false, vPolygons3d, vCells) ;
}
//----------------------------------------------------------------------------
bool
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells)
{
// condizioni per il calcolo dei poligoni di base
if ( m_vPolygons.empty() || // se non li ho mai calcolati
@@ -1647,11 +1702,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size()) || // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle
bForTriangulation) { // oppure se sto chiedendo i poligoni per la triangolazione ( devo fare considerazioni particolari se ho dei poli sui lati del parametrico)
m_vPolygons.clear() ;
m_vPolygons3d.clear() ;
// se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie
if ( vCells.empty())
vCells = m_vnLeaves ;
PNTVECTOR vVertices ;
PNTVECTOR vVertices3d ;
INTVECTOR vNeigh ;
// setto le celle che sono sul LeftEdge e sul TopEdge
if ( m_bClosedU) {
@@ -1673,8 +1730,10 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
// N.B. :i poligoni sono costruiti a partire dal ptBL !!!
for ( int nId : vCells) {
vVertices.clear() ;
vVertices3d.clear() ;
vNeigh.clear() ;
vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ;
vVertices3d.push_back( m_mVert.at( nId)[0]) ;
INTVECTOR vnVert ;
BOOLVECTOR vbBonusVert(4) ;
fill( vbBonusVert.begin(), vbBonusVert.end(), false) ;
@@ -1688,11 +1747,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( j).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ;
vVertices.push_back( pt) ;
vVertices3d.push_back( m_mVert[j][1]) ;
}
}
else {
for ( int j : vNeigh)
for ( int j : vNeigh) {
vVertices.push_back( m_mTree.at( j).GetTopRight()) ;
vVertices3d.push_back( m_mVert[j][2]) ;
}
}
bBottomRight = true ;
vbBonusVert[2] = true ;
@@ -1710,11 +1772,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ;
vVertices.push_back( pt) ;
vVertices3d.push_back( m_mVert[j][1]) ;
}
}
else {
for ( int j : vNeigh)
for ( int j : vNeigh) {
vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ;
vVertices3d.push_back( m_mVert[j][0]) ;
}
}
vbBonusVert[3] = true ;
}
@@ -1722,10 +1787,12 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
else if ( ! bBottomRight) {
Point3d ptBr( m_mTree.at( nId).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ;
vVertices.push_back( ptBr) ;
vVertices3d.push_back( m_mVert[nId][1]) ;
vnVert.push_back( int(vVertices.size()) - 1) ;
}
vNeigh.clear() ;
vVertices.push_back( m_mTree.at( nId).GetTopRight()) ;
vVertices3d.push_back( m_mVert[nId][2]) ;
vnVert.push_back( int(vVertices.size()) - 1) ;
GetTopNeigh ( nId, vNeigh) ;
std::reverse( vNeigh.begin(), vNeigh.end()) ;
@@ -1738,11 +1805,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ;
vVertices.push_back( pt) ;
vVertices3d.push_back( m_mVert[j][3]) ;
}
}
else {
for ( int j : vNeigh)
for ( int j : vNeigh) {
vVertices.push_back( m_mTree.at( j).GetBottomLeft()) ;
vVertices3d.push_back( m_mVert[j][0]) ;
}
}
bTopLeft = true ;
vbBonusVert[0] = true ;
@@ -1761,11 +1831,14 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
for ( int j : vNeigh) {
Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ;
vVertices.push_back( pt) ;
vVertices3d.push_back( m_mVert[j][3]) ;
}
}
else {
for ( int j : vNeigh)
for ( int j : vNeigh) {
vVertices.push_back( m_mTree.at( j).GetTopRight()) ;
vVertices3d.push_back( m_mVert[j][2]) ;
}
}
vbBonusVert[1] = true ;
}
@@ -1773,10 +1846,12 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
else if ( ! bTopLeft) {
Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ;
vVertices.push_back( ptTl) ;
vVertices3d.push_back( m_mVert[nId][3]) ;
vnVert.push_back( int(vVertices.size()) - 1) ;
}
vNeigh.clear() ;
vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ;
vVertices3d.push_back( m_mVert[nId][0]) ;
vnVert.push_back( int(vVertices.size()) - 1) ;
if ( bForTriangulation){
@@ -1787,12 +1862,16 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
// se ho punti bonus su entrambi i lati non devo fare nulla
if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) {
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
if ( vbBonusVert[1] ) // lati contati a partire da quello sopra in senso CCW
if ( vbBonusVert[1] ) {// lati contati a partire da quello sopra in senso CCW
vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW
vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ;
}
else if ( vbBonusVert[3] ) {
// dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto
vVertices.pop_back() ;
vVertices[0] = vVertices.end()[-1] ;
vVertices3d.pop_back() ;
vVertices3d[0] = vVertices3d.end()[-1] ;
}
}
}
@@ -1800,20 +1879,28 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
// se ho punti bonus su entrambi i lati non devo fare nulla
if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) {
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
if ( vbBonusVert[0] ) // lati contati a partire da quello sopra in senso CCW
if ( vbBonusVert[0] ){ // lati contati a partire da quello sopra in senso CCW
vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW
else if ( vbBonusVert[2] )
vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ;
}
else if ( vbBonusVert[2] ){
vVertices.erase(vVertices.begin() + vnVert[2]) ;
vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ;
}
}
}
if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3)) && ( vbBonusVert[1] || vbBonusVert[3] ) ) {
// se ho punti bonus su entrambi i lati non devo fare nulla
if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) {
// sennò devo togliere l'estremo del lato su cui NON ho punti bonus
if ( vbBonusVert[1] ) // lati contati a partire da quello sopra in senso CCW
if ( vbBonusVert[1] ){ // lati contati a partire da quello sopra in senso CCW
vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW
else if ( vbBonusVert[3] )
vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ;
}
else if ( vbBonusVert[3] ) {
vVertices.erase(vVertices.begin() + vnVert[3]) ;
vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ;
}
}
}
if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0)) && ( vbBonusVert[0] || vbBonusVert[2] ) ) {
@@ -1824,9 +1911,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
// dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto
vVertices.pop_back() ;
vVertices[0] = vVertices.end()[-1] ;
vVertices3d.pop_back() ;
vVertices3d[0] = vVertices3d.end()[-1] ;
}
else if ( vbBonusVert[2] )
else if ( vbBonusVert[2] ) {
vVertices.erase(vVertices.begin() + vnVert[3]) ;
vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ;
}
}
}
}
@@ -1850,14 +1941,19 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
if ( Dist( ptP00P11, ptPSrf) + EPS_SMALL > Dist( ptP10P01, ptPSrf)) {
rotate( vVertices.begin(), vVertices.begin() + 1,vVertices.end()) ;
vVertices.back() = vVertices.at( 0) ;
rotate( vVertices3d.begin(), vVertices3d.begin() + 1,vVertices3d.end()) ;
vVertices3d.back() = vVertices3d.at( 0) ;
}
}
}
m_vPolygons.emplace_back() ;
m_vPolygons.back().emplace_back() ;
m_vPolygons3d.emplace_back() ;
m_vPolygons3d.back().emplace_back() ;
for ( int i = 0 ; i < (int) vVertices.size() ; ++i) {
m_vPolygons.back().back().AddUPoint( i, vVertices.at( i)) ;
m_vPolygons3d.back().back().AddUPoint( i, vVertices3d.at( i)) ;
}
}
@@ -1867,6 +1963,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, INTVE
for ( int t = 0 ; t < (int)m_vPolygons.size() ; ++ t) {
for ( int z = 0 ; z < (int)m_vPolygons[t].size() ; ++z) {
vPolygons.push_back( m_vPolygons[t][z]) ;
vPolygons3d.push_back( m_vPolygons3d[t][z]) ;
}
}
return true ;
@@ -2172,7 +2269,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// 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
if ( bEraseNextPoint) {
if ( bEraseNextPoint && vptInters.size() != 0) {
vptInters.pop_back() ;
bEraseNextPoint = false ;
}
@@ -2182,7 +2279,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// al precedente FindInters avrei dovuto passare di cella
if ( ! FindInters( nId, clTrim, vptInters, true)) {
// scarterò il punto molto vicino al lato e tengo solo l'intersezione del trim col lato
vptInters.pop_back() ;
if( vptInters.size() != 0)
vptInters.pop_back() ;
plLoop.GetPrevPoint( ptTEnd) ;
plLoop.GetPrevPoint( ptTStart) ;
plLoop.GetNextPoint( ptCurr) ;
@@ -2203,10 +2301,19 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ;
}
// aggiungo la fine del segmento nel vettore delle intersezioni
vptInters.push_back( ptCurr) ;
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ;
// VERSIONE NUOVA
// controllo di aggiungere un punto abbastanza distante dal precedente
if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 2 * 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() ;
@@ -2519,7 +2626,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
else if ( nEdge == 7)
ptInters = ptTR ;
// aggiungo il nuovo punto al vettore delle intersezioni
if ( (int)vptInters.size() == 0 || ! AreSamePointApprox( ptInters , vptInters.back()))
if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 2 * 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
@@ -2834,21 +2941,20 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
//----------------------------------------------------------------------------
bool
Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell)
Tree::CreateCellPolygons( int nLeafId, 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] ;
PNTMATRIX vEdgeVertex ;
Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
vEdgeVertex.emplace_back() ;
vEdgeVertex.back().push_back( m_mTree[nId].GetTopRight()) ;
vEdgeVertex.emplace_back() ;
vEdgeVertex.back().push_back( ptTl) ;
vEdgeVertex.emplace_back() ;
vEdgeVertex.back().push_back( m_mTree[nId].GetBottomLeft()) ;
vEdgeVertex.emplace_back() ;
vEdgeVertex.back().push_back( ptBr) ;
PNTMATRIX vEdgeVertex(4) ;
PNTMATRIX vEdgeVertex3d(4) ;
vEdgeVertex[0].push_back( m_mTree[nId].GetTopRight()) ;
vEdgeVertex[1].push_back( m_mTree[nId].GetTopLeft()) ;
vEdgeVertex[2].push_back( m_mTree[nId].GetBottomLeft()) ;
vEdgeVertex[3].push_back( m_mTree[nId].GetBottomRight()) ;
vEdgeVertex3d[0].push_back( m_mVert[nId][2]) ;
vEdgeVertex3d[1].push_back( m_mVert[nId][3]) ;
vEdgeVertex3d[2].push_back( m_mVert[nId][0]) ;
vEdgeVertex3d[3].push_back( m_mVert[nId][1]) ;
// la PolyLine è riempita a partire dal lato bottom
Point3d ptStart ;
plCell.GetFirstPoint( ptStart) ;
@@ -2868,8 +2974,10 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
INTVECTOR vToCheckNow = vToCheck ;
// vettore dei poligoni ( loop) della cella nId
POLYLINEVECTOR vCellPolygons ;
POLYLINEVECTOR vCellPolygons3d ;
// costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps
PolyLine plTrimmedPoly ;
PolyLine plTrimmedPoly3d ;
// numero di volte che la cella è stata attraversata da una curva di trim
int nPassToCheck = (int) vToCheckNow.size() ;
// numero di vertici aggiunti al nuovo poligono
@@ -2894,7 +3002,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
nFirstLoopInPoly = j ;
}
for ( Point3d ptInt : inA.vpt) {
AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptInt) ;
AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptInt, plTrimmedPoly3d) ;
}
vAddedLoops.push_back( j) ;
nEdge = inA.nOut ;
@@ -2948,6 +3056,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
vEdge.Set( 1,0,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 0 ;
}
}
@@ -2956,6 +3065,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
vEdge.Set( 0,-1,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 1 ;
}
}
@@ -2964,6 +3074,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
vEdge.Set( -1,0,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 2 ;
}
}
@@ -2972,6 +3083,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
vEdge.Set( 0,1,0) ;
if ( AreOppositeVectorApprox( vLast, vEdge)) {
plTrimmedPoly.EraseLastUPoint() ;
plTrimmedPoly3d.EraseLastUPoint() ;
nEdge = 3 ;
}
}
@@ -2980,6 +3092,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
// quindi salto al prossimo loop
if ( plTrimmedPoly.GetPointNbr() == 1) {
plTrimmedPoly.Clear() ;
plTrimmedPoly3d.Clear() ;
if ( j == nFirstLoopInPoly)
nEdgeIn = -1 ;
continue ;
@@ -3015,14 +3128,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
while ( ! ( bValidNextStart && bAtNextStart) && bNotCameBack) {
Point3d ptVert ;
if ( nEdge == 0)
ptVert = ptTl ;
ptVert = vEdgeVertex[1][0] ;
else if ( nEdge == 1)
ptVert = m_mTree[nId].GetBottomLeft() ;
ptVert = vEdgeVertex[2][0] ;
else if ( nEdge == 2)
ptVert = ptBr ;
ptVert = vEdgeVertex[3][0] ;
else if ( nEdge == 3)
ptVert = m_mTree[nId].GetTopRight() ;
AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ;
ptVert = vEdgeVertex[0][0] ;
AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ;
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge < 3)
@@ -3069,14 +3182,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
while ( bNotCameBack) {
Point3d ptVert ;
if ( nEdge == 0)
ptVert = ptTl ;
ptVert = vEdgeVertex[1][0] ;
else if ( nEdge == 1)
ptVert = m_mTree[nId].GetBottomLeft() ;
ptVert = vEdgeVertex[2][0] ;
else if ( nEdge == 2)
ptVert = ptBr ;
ptVert = vEdgeVertex[3][0] ;
else if ( nEdge == 3)
ptVert = m_mTree[nId].GetTopRight() ;
AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ;
ptVert = vEdgeVertex[0][0] ;
AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d) ;
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge < 3)
@@ -3095,6 +3208,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
}
plTrimmedPoly.Close() ;
plTrimmedPoly3d.Close() ;
// controllo sull'area del poligono, se è 0 ( quindi un segmento), non lo aggiungo
double dArea ;
plTrimmedPoly.GetAreaXY( dArea) ;
@@ -3102,13 +3216,17 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
if ( dArea > 0) {
vCellPolygons.push_back( plTrimmedPoly) ;
vPolygons.push_back( vCellPolygons) ;
vCellPolygons3d.push_back( plTrimmedPoly3d) ;
vPolygons3d.push_back( vCellPolygons3d) ;
++ nPoly ;
vnParentChunk.push_back( inA.nChunk) ;
vCellPolygons.clear() ;
vCellPolygons3d.clear() ;
}
c = 0 ;
plTrimmedPoly.Clear() ;
plTrimmedPoly3d.Clear() ;
nEdgeIn = -1 ;
// devo verificare se tra i loop che sono finiti in vToCheck in realtà qualcuno l'ho usato per fare un poligono
for ( int k = 0 ; k < (int)vToCheck.size() ; ++ k) {
@@ -3127,18 +3245,21 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vTo
//----------------------------------------------------------------------------
bool
Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk)
Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk)
{
// vettore dei poligoni ( loop) della cella nId
POLYLINEVECTOR vCellPolygons ;
POLYLINEVECTOR vCellPolygons3d ;
// costruisco i poligoni partendo dal vettore delle intersezioni
int nId = m_vnLeaves[nLeafId] ;
PolyLine plTrimmedPoly ;
//PolyLine plTrimmedPoly ;
//PolyLine plTrimmedPoly3d ;
// loop interni in una cella intersecata
int nChunkBiggestCW = -1 ;
if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) {
PolyLine plInLoop ;
PolyLine plInLoop3d ;
Inters inA ;
// se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW devo aggiungere il bordo
bool bAllContained = true ;
@@ -3175,18 +3296,24 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly,
// i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella
Point3d ptVert = m_mTree[nId].GetTopRight() ;
plInLoop.AddUPoint( 0, ptVert) ;
ptVert.x = m_mTree[nId].GetBottomLeft().x ;
ptVert.y = m_mTree[nId].GetTopRight().y ;
ptVert = m_mTree[nId].GetTopLeft() ;
plInLoop.AddUPoint( 1, ptVert) ;
ptVert = m_mTree[nId].GetBottomLeft() ;
plInLoop.AddUPoint( 2, ptVert) ;
ptVert.x = m_mTree[nId].GetTopRight().x ;
ptVert.y = m_mTree[nId].GetBottomLeft().y ;
ptVert = m_mTree[nId].GetBottomRight() ;
plInLoop.AddUPoint( 3, ptVert) ;
plInLoop.Close() ;
vCellPolygons.push_back( plInLoop) ;
vPolygons.push_back( vCellPolygons) ;
++ nPoly ;
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]);
vCellPolygons3d.push_back( plInLoop3d) ;
vPolygons3d.push_back( vCellPolygons3d) ;
vCellPolygons3d.clear() ;
plInLoop3d.Clear() ;
// imposto il chunk del loop CW più grande ( il primo che ho incontrato)
vnParentChunk.push_back( nChunkBiggestCW) ;
vCellPolygons.clear() ;
@@ -3199,9 +3326,12 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly,
int k = 0 ;
for ( Point3d ptInt : inA.vpt) {
plInLoop.AddUPoint( k, ptInt) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptInt.x / SBZ_TREG_COEFF, ptInt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plInLoop3d.AddUPoint( k, pt3d) ;
++ k ;
}
plInLoop.Close() ;
plInLoop3d.Close() ;
bool bAdded = false ;
// se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto
if ( ! inA.bCCW) {
@@ -3211,7 +3341,9 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly,
for ( int r = 0 ; r < nPoly ; ++r) {
if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk) {
vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ;
vPolygons3d[nOtherPoly - r - 1].push_back( plInLoop3d) ;
plInLoop.Clear() ;
plInLoop3d.Clear() ;
bAdded = true ;
break ;
}
@@ -3220,12 +3352,17 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly,
if ( ! bAdded) {
vCellPolygons.push_back( plInLoop) ;
vPolygons.push_back( vCellPolygons) ;
vCellPolygons3d.push_back( plInLoop3d) ;
vPolygons3d.push_back( vCellPolygons3d) ;
++ nPoly ;
vnParentChunk.push_back( inA.nChunk) ;
plInLoop.Clear() ;
vCellPolygons.clear() ;
plInLoop3d.Clear() ;
vCellPolygons3d.clear() ;
}
plInLoop.Clear() ;
plInLoop3d.Clear() ;
}
else
continue ;
@@ -3384,11 +3521,14 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const
//----------------------------------------------------------------------------
bool
Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const
Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d) const
{
// se è il primo punto della PolyLine lo aggiungo
if ( plTrimmedPoly.GetPointNbr() == 0) {
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ;
m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
return true ;
}
@@ -3403,20 +3543,37 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly,
if ( ! AreSamePointApprox( ptToAdd, ptLast))
vDir = ptToAdd - ptLast ;
else
return true ;
return false ;
// se non riesco a normalizzare perché sono troppo vicino ad un vertice allora aggiungo direttamente il vertice
if ( ! vDir.Normalize()) {
plTrimmedPoly.EraseLastUPoint() ;
if ( AreSamePointApprox( ptToAdd, ptBr))
plTrimmedPoly.AddUPoint( c, ptBr) ;
else if ( AreSamePointApprox( ptToAdd, ptTR))
plTrimmedPoly.AddUPoint( c, ptTR) ;
else if ( AreSamePointApprox( ptToAdd, ptTl))
plTrimmedPoly.AddUPoint( c, ptTl) ;
else if ( AreSamePointApprox( ptToAdd, ptBL))
plTrimmedPoly.AddUPoint( c, ptBL) ;
Point3d ptVert ;
int nVert = -1 ;
if ( AreSamePointApprox( ptToAdd, ptBr)){
ptVert = ptBr ;
nVert = 1 ;
}
else if ( AreSamePointApprox( ptToAdd, ptTR)) {
ptVert = ptTR ;
nVert = 2 ;
}
else if ( AreSamePointApprox( ptToAdd, ptTl)) {
ptVert = ptTl ;
nVert = 3 ;
}
else if ( AreSamePointApprox( ptToAdd, ptBL)) {
ptVert = ptBL ;
nVert = 0 ;
}
else
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
ptVert = ptToAdd ;
plTrimmedPoly.AddUPoint( c, ptVert) ;
Point3d pt3d ;
if ( nVert != -1)
pt3d = m_mVert.at(nId)[nVert] ;
else
m_pSrfBz->GetPointD1D2( ptVert.x, ptVert.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
return true ;
}
@@ -3428,10 +3585,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly,
Point3d ptIntermed = vEdgeVertex[0][t] ;
if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) {
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[0][t]) ;
++ c ;
}
}
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
}
// edge 1
@@ -3440,10 +3600,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly,
Point3d ptIntermed = vEdgeVertex[1][t] ;
if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) {
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[1][t]) ;
++ c ;
}
}
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
}
// edge 2
@@ -3452,10 +3615,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly,
Point3d ptIntermed = vEdgeVertex[2][t] ;
if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) {
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[2][t]) ;
++ c ;
}
}
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
}
// edge 3
@@ -3464,22 +3630,29 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly,
Point3d ptIntermed = vEdgeVertex[3][t] ;
if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) {
plTrimmedPoly.AddUPoint( c, ptIntermed) ;
plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[3][t]) ;
++ c ;
}
}
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
}
// sono allineato con un lato, ma NON sono su un lato
// aggiungo e basta
else {
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
}
}
// non su un edge, quindi aggiungo e basta
else {
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
Point3d pt3d ; m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
plTrimmedPoly3d.AddUPoint( c, pt3d) ;
++ c ;
}
return true ;
@@ -3899,13 +4072,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges)
// recupero i poligoni base delle celle sui bordi
POLYLINEMATRIX mPL ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[0], false, vEdges[0]) ;
GetPolygonsBasic( mPL[0], vEdges[0]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[1], false, vEdges[1]) ;
GetPolygonsBasic( mPL[1], vEdges[1]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[2], false, vEdges[2]) ;
GetPolygonsBasic( mPL[2], vEdges[2]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[3], false, vEdges[3]) ;
GetPolygonsBasic( mPL[3], vEdges[3]) ;
// scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato
for ( int i = 0 ; i < int( mPL.size()) ; ++i) {
@@ -4097,6 +4270,7 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts)
bool
Tree::AdjustCuts( void)
{
// correzione del verso dei tagli aperti
if ( int( m_mTree.at( -1).m_vInters.size()) == 1)
return true ;
// li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR
@@ -4138,10 +4312,19 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
pl.AddUPoint(2, m_mTree.at(nRoot).GetBottomLeft()) ;
pl.AddUPoint(3, m_mTree.at(nRoot).GetBottomRight()) ;
pl.Close() ;
PolyLine pl3d ;
pl3d.AddUPoint(0, m_mVert.at(nRoot)[2]) ;
pl3d.AddUPoint(1, m_mVert.at(nRoot)[3]) ;
pl3d.AddUPoint(2, m_mVert.at(nRoot)[0]) ;
pl3d.AddUPoint(3, m_mVert.at(nRoot)[1]) ;
pl3d.Close() ;
// ora posso creare il poligono della cella con i tagli
POLYLINEMATRIX vPolygons3d ;
while( (int)vToCheck.size() != 0) {
int nPolyBefore = nPoly ;
CreateCellPolygons( 0, vPolygons, vToCheck, nPoly, vnParentChunk, pl) ;
CreateCellPolygons( 0, vPolygons, vPolygons3d, vToCheck, nPoly, vnParentChunk, pl, pl3d) ; // l'aggiunta di vPolygons3d forse è un problema in questo punto.
// sarà da valutare quando si aggiungerà la funzione per aggiungere tagli aperti
// e se si vuole usare la funzione su uno spazio 2D ideale non collegato ad una sup di Bezier
if ( nPolyBefore == nPoly)
break ;
}