EgtGeomKernel :

- risolti i problemi di trim su superfici di bezier
Problemi noti:
- mancano ancora delle celle
- si formano delle crack
This commit is contained in:
Daniele Bariletti
2023-06-07 17:43:23 +02:00
parent f3346fd1f1
commit 7cf933ec48
2 changed files with 177 additions and 51 deletions
+176 -50
View File
@@ -1561,8 +1561,6 @@ Tree::TraceLoopLabelCell( void)
}
else {
nId = nCells.back() ;
// qui devo scegliere da quale cella partire!! ///////////////////////////////////////////////////////////////////////////////////////////////////
// fatto
}
// trovo quali punti della polyline sono nella cella e l'intersezione
PNTVECTOR vptInters ;
@@ -1669,15 +1667,26 @@ Tree::TraceLoopLabelCell( void)
// categorizzo la cella
m_mTree[nCell].m_nFlag2 = 1 ;
CategorizeCell( nCell) ;
bool bDone = false ;
int nInProcessing = -1 ;
int c = 0 ;
int nDisplay = -1 ;
// fintanto che la cella ha tra i vicini a destra una cella non elaborata mi sposto a destra
// definisco una cella Processed se tutto il ramo a destra è categorizzato
while ( (int)vNeigh.size() > 0 || ! m_mTree[nCell].IsProcessed()) {
while ( ((int)vNeigh.size() > 0 && ! bDone) || ! m_mTree[nCell].IsProcessed()) {
// per debug
if ( nInProcessing != nCell) {
nInProcessing = nCell ;
c = 0 ;
}
else
++ c ;
// verso la cella a destra più in basso da cui non sono ancora passato
bool bProceeded = false ;
for ( int i = 0 ; i < (int)vNeigh.size(); ++ i) {
if ( m_mTree[vNeigh[i]].m_nFlag2 == 0 ) {
nCell = vNeigh[i] ;
nDisplay = m_mTree[nCell].m_nFlag ;
bProceeded = true ;
break ;
}
@@ -1694,14 +1703,33 @@ Tree::TraceLoopLabelCell( void)
// guardo i vicini a destra per passare alla prossima cella
vNeigh.clear() ;
GetRightNeigh( nCell, vNeigh) ;
bDone = true ;
// controllo che tra i vicini di destra ce ne sia almeno uno non processato
for ( int t: vNeigh) {
if ( ! m_mTree[t].IsProcessed()) {
bDone = false ;
break ;
}
}
}
// per debug
if ( c > 3)
break ;
}
vNeigh.clear() ;
GetRightNeigh( nCell, vNeigh) ;
// se non ho vicini a destra o se i vicini sono già tutti categorizzati
// torno indietro a sinistra alla cella già categorizzata più bassa
//bDone = true ;
c = 0 ;
while ( (int) vNeigh.size() == 0 || m_mTree[nCell].IsProcessed()) {
// per debug
if ( nInProcessing != nCell) {
nInProcessing = nCell ;
c = 0 ;
}
else
++ c ;
// trovo il vicino a sinistra, già categorizzato, più basso
vNeigh.clear() ;
GetLeftNeigh( nCell, vNeigh) ;
@@ -1738,8 +1766,16 @@ Tree::TraceLoopLabelCell( void)
break ;
}
}
if ( bDone)
if ( bDone) {
m_mTree[nCell].SetProcessed( bDone) ;
if ( m_mTree[nCell].m_nFlag2 == 0) {
m_mTree[nCell].m_nFlag2 = 1 ;
CategorizeCell( nCell) ;
}
}
// per debug
if ( c > 3)
break ;
}
vNeigh.clear() ;
GetRightNeigh( nCell, vNeigh) ;
@@ -1883,11 +1919,22 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert
else
ptInters = aInfo.IciA[0].ptI ;
}
// devo controllare se l'intersezione è in un vertice ed eventualmente correggere nEdge
if ( nEdge < 4) {
if ( AreSamePointExact( ptInters, ptTl))
nEdge = 4 ;
else if ( AreSamePointExact( ptInters, ptBL))
nEdge = 5 ;
else if ( AreSamePointExact( ptInters, ptBr))
nEdge = 6 ;
else if ( AreSamePointExact( ptInters, ptTR))
nEdge = 7 ;
}
m_mTree[nId].m_vInters.back().nOut = nEdge ;
vptInters.push_back( ptInters) ;
// salvo il vettore intersezione per la cella e capisco in quale altra cella passare
if ( (int)vptInters.size() == 1)
m_mTree[nId].m_vInters.back().vpt.push_back( vptInters[0]) ; // al posto di .vpt = vptInters metto un push_back ////////////////////////////////////////////////
m_mTree[nId].m_vInters.back().vpt.push_back( vptInters[0]) ;
else
m_mTree[nId].m_vInters.back().vpt = vptInters ;
vptInters.clear() ;
@@ -1987,13 +2034,27 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert
if ( ! nPossible.empty()) {
nId = nPossible[0] ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 2 ;
// controllo se entro in un vertice o a metà lato
Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
if ( AreSamePointExact( ptInters, ptBr))
m_mTree[nId].m_vInters.back().nIn = 6 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft()))
m_mTree[nId].m_vInters.back().nIn = 5 ;
else
m_mTree[nId].m_vInters.back().nIn = 2 ;
}
// ingresso da destra
else if ( ! nPossible1.empty()) {
nId = nPossible1.back() ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 3 ;
// controllo se entro in un vertice o a metà lato
Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
if ( AreSamePointExact( ptInters, ptBr))
m_mTree[nId].m_vInters.back().nIn = 6 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight()))
m_mTree[nId].m_vInters.back().nIn = 7 ;
else
m_mTree[nId].m_vInters.back().nIn = 3 ;
}
// ingresso in diagonale
else {
@@ -2022,13 +2083,27 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert
if ( ! nPossible.empty()) {
nId = nPossible[0] ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 3 ;
// controllo se entro in un vertice o a metà lato
Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
if ( AreSamePointExact( ptInters, ptBr))
m_mTree[nId].m_vInters.back().nIn = 6 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight()))
m_mTree[nId].m_vInters.back().nIn = 7 ;
else
m_mTree[nId].m_vInters.back().nIn = 3 ;
}
// ingresso dall'alto
else if ( ! nPossible1.empty()) {
nId = nPossible1[0] ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 0 ;
// controllo se entro in un vertice o a metà lato
Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
if ( AreSamePointExact( ptInters, ptTl))
m_mTree[nId].m_vInters.back().nIn = 4 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight()))
m_mTree[nId].m_vInters.back().nIn = 7 ;
else
m_mTree[nId].m_vInters.back().nIn = 0 ;
}
// ingresso in diagonale
else {
@@ -2057,13 +2132,27 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert
if ( ! nPossible.empty()) {
nId = nPossible.back() ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 0 ;
// controllo se entro in un vertice o a metà lato
Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
if ( AreSamePointExact( ptInters, ptTl))
m_mTree[nId].m_vInters.back().nIn = 4 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight()))
m_mTree[nId].m_vInters.back().nIn = 7 ;
else
m_mTree[nId].m_vInters.back().nIn = 0 ;
}
// ingresso da sinistra
else if ( ! nPossible1.empty()) {
nId = nPossible1[0] ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 1 ;
// controllo se entro in un vertice o a metà lato
Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
if ( AreSamePointExact( ptInters, ptTl))
m_mTree[nId].m_vInters.back().nIn = 4 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft()))
m_mTree[nId].m_vInters.back().nIn = 5 ;
else
m_mTree[nId].m_vInters.back().nIn = 1 ;
}
// ingresso in diagonale
else {
@@ -2093,13 +2182,27 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert
if ( ! nPossible.empty()) {
nId = nPossible.back() ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 1 ;
// controllo se entro in un vertice o a metà lato
Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
if ( AreSamePointExact( ptInters, ptTl))
m_mTree[nId].m_vInters.back().nIn = 4 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft()))
m_mTree[nId].m_vInters.back().nIn = 5 ;
else
m_mTree[nId].m_vInters.back().nIn = 1 ;
}
// ingresso dal basso
else if ( ! nPossible1.empty()) {
nId = nPossible1.back() ;
m_mTree[nId].m_vInters.emplace_back() ;
m_mTree[nId].m_vInters.back().nIn = 2 ;
// controllo se entro in un vertice o a metà lato
Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
if ( AreSamePointExact( ptInters, ptBr))
m_mTree[nId].m_vInters.back().nIn = 6 ;
else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft()))
m_mTree[nId].m_vInters.back().nIn = 5 ;
else
m_mTree[nId].m_vInters.back().nIn = 2 ;
}
// ingresso in diagonale
else {
@@ -2311,8 +2414,6 @@ Tree::CreateCellPolygons( int nLeafId, std::vector<POLYLINEVECTOR>& vPolygons, I
else if ( nEdge == 3)
ptVert = m_mTree[nId].GetTopRight() ;
AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ;
//plTrimmedPoly.AddUPoint( c, ptVert) ;
//++c ;
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge < 3 )
@@ -2371,6 +2472,17 @@ Tree::CreateIslandAndHoles( int nLeafId, std::vector<POLYLINEVECTOR>& vPolygons,
// numero dei loop interni passati
int n = 0 ;
Inters inA = m_mTree[nId].m_vInters[n] ;
// se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW
bool bAllCW = true ;
for ( Inters inB : m_mTree[nId].m_vInters) {
if ( inB.nIn == -1){
if ( inB.bCCW) {
bAllCW = false ;
break ;
}
}
}
// la seconda condizione è da cambiareeeeeeeeeeeeeeeeeeeee////////////////////////////////////////////////////////////////////////////////////////////
if ( m_mTree[nId].m_nFlag == 2 && ! inA.bCCW) {
// i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella
Point3d ptVert = m_mTree[nId].GetTopRight() ;
@@ -2395,7 +2507,7 @@ Tree::CreateIslandAndHoles( int nLeafId, std::vector<POLYLINEVECTOR>& vPolygons,
// numero di vertici aggiunti al nuovo poligono
int k = 0 ;
for ( Point3d ptInt : inA.vpt) {
plInLoop.AddUPoint( c, ptInt) ;
plInLoop.AddUPoint( k, ptInt) ;
++ k ;
}
plInLoop.Close();
@@ -2463,12 +2575,6 @@ Tree::CheckIfBefore( Inters& inA) const
int nEdge1 = inA.nIn ;
int nEdge2 = inA.nOut ;
PolyLine pl ;
//int c = 0 ;
//for ( int p = 0 ; p < (int)inA.vpt.size(); ++p ) {
// Point3d ptToAdd = inA.vpt[p] ;
// pl.AddUPoint( c, ptToAdd) ;
// ++ c ;
//}
pl.AddUPoint( 0, inA.vpt.back()) ;
pl.AddUPoint( 1, inA.vpt[0]) ;
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6} ;
@@ -2791,17 +2897,28 @@ Tree::SetRightEdgeIn( int nId)
int nPass = (int) m_mTree[nId].m_vInters.size() ;
bool bDone = false ;
for ( int k = 0 ; k < nPass ; ++ k) {
if ( m_mTree[nId].m_vInters[k].nIn == 3 || m_mTree[nId].m_vInters[k].nOut == 3 ) {
if ( m_mTree[nId].m_vInters[k].nIn == 3 || m_mTree[nId].m_vInters[k].nOut == 3) {
m_mTree[nId].m_nRightEdgeIn = 2 ;
bDone = true ;
break ;
}
// considero anche ingressi/ uscite dai vertici 6 e 7
if ( AreSameEdge( m_mTree[nId].m_vInters[k].nIn, 3) || AreSameEdge( m_mTree[nId].m_vInters[k].nOut, 3) ) {
m_mTree[nId].m_nRightEdgeIn = 2 ;
// controllo nei vertici
if ( m_mTree[nId].m_vInters[k].nOut == 6 && m_mTree[nId].m_vInters[k].nIn == 7) {
m_mTree[nId].m_nRightEdgeIn = 1 ;
bDone = true ;
break ;
}
if ( m_mTree[nId].m_vInters[k].nOut == 7 && m_mTree[nId].m_vInters[k].nIn == 6 ) {
m_mTree[nId].m_nRightEdgeIn = 0 ;
bDone = true ;
break ;
}
/*if ( AreSameEdge( m_mTree[nId].m_vInters[k].nIn, 3) || AreSameEdge( m_mTree[nId].m_vInters[k].nOut, 3) ) {
m_mTree[nId].m_nRightEdgeIn = 2 ;
bDone = true ;
break ;
}*/
}
// se non ho inters sul lato destro devo verificare se è tutto dentro o tutto fuori
if ( ! bDone) {
@@ -2859,7 +2976,17 @@ Tree::CategorizeCell( int& nId)
if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 1)
m_mTree[nId].m_nFlag = 4 ;
else if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 0)
m_mTree[nId].m_nFlag = 0 ;
// devo verificare se la cella è intersecata
if ( m_mTree[vNeigh[0]].m_nFlag == 1 || m_mTree[vNeigh[0]].m_nFlag == 3)
m_mTree[nId].m_nFlag = 0 ;
else {
if ( m_mTree[vNeigh[0]].m_nFlag == 4) {
m_mTree[nId].m_nFlag = 4 ;
}
else if ( m_mTree[vNeigh[0]].m_nFlag == 0) {
m_mTree[nId].m_nFlag = 0 ;
}
}
// se solo parte del right edge del vicino è compreso, allora devo verificare se la cella è contenuta o no
// guardando nFlag del vicino bottom, che è già categorizzato!
else if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 2 ) {
@@ -2888,16 +3015,28 @@ Tree::CategorizeCell( int& nId)
for ( int r = 0 ; r < nPass; ++ r ) {
// trovo il loop che ha l'ingresso o l'uscita più in alto sul lato destro
// verifico che o l'ingresso o l'uscita siano sul lato destro e che sia l'intersezione più alta su quel lato
if ( ( AreSameEdge( m_mTree[nNeigh].m_vInters[r].nIn, 3) && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nIn, m_mTree[nNeigh].m_vInters[r].vpt[0], nEdgeIn, ptInters))) {
if ( m_mTree[nNeigh].m_vInters[r].nIn == 3 && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nIn, m_mTree[nNeigh].m_vInters[r].vpt[0], ptInters)) {
nLoop = r ;
ptInters = m_mTree[nNeigh].m_vInters[r].vpt[0] ;
bFound = true ;
}
if ( AreSameEdge(m_mTree[nNeigh].m_vInters[r].nOut, 3) && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nOut, m_mTree[nNeigh].m_vInters[r].vpt.back(), nEdgeOut, ptInters)) {
if ( m_mTree[nNeigh].m_vInters[r].nOut == 3 && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nOut, m_mTree[nNeigh].m_vInters[r].vpt.back(), ptInters)) {
nLoop = r ;
ptInters = m_mTree[nNeigh].m_vInters[r].vpt.back() ;
bFound = true ;
}
// controllo nei vertici
if ( m_mTree[nNeigh].m_vInters[r].nOut == 7 || m_mTree[nNeigh].m_vInters[r].nIn == 7) {
nLoop = r ;
ptInters = m_mTree[nNeigh].GetTopRight() ;
bFound = true ;
break ;
}
if ( m_mTree[nNeigh].m_vInters[r].nOut == 6 || m_mTree[nNeigh].m_vInters[r].nIn == 6 ) {
nLoop = r ;
ptInters = ptBr ;
bFound = true ;
}
}
if ( bFound && CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) {
bTopMost = true ;
@@ -2909,7 +3048,7 @@ Tree::CategorizeCell( int& nId)
else
m_mTree[nId].m_nFlag = 0 ;
}
else if ( AreSameEdge(m_mTree[nId].m_vInters[nLoop].nOut, 3))
else if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nOut, 3))
m_mTree[nId].m_nFlag = 4 ;
else if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) ) {
// devo verificare se il l'uscita è più a sinistra o più a destra della cella
@@ -2949,11 +3088,6 @@ Tree::CheckIfBetween( Inters& inA, Inters& inB) const
// ( dall'end di A percorro i bordi della cella fino a tornare allo start e devo incontrare In e Out di B)
INTVECTOR vEdges ;
int nEdge = inA.nOut ;
//vEdges.push_back( nEdge) ;
//if ( nEdge == 3)
// nEdge = 0 ;
//else
// ++ nEdge ;
while ( nEdge != inA.nIn || (int) vEdges.size() == 0) {
vEdges.push_back( nEdge) ;
if ( nEdge == 3)
@@ -2965,8 +3099,8 @@ Tree::CheckIfBetween( Inters& inA, Inters& inB) const
vEdges.push_back( nEdge) ;
bool bFound = false ;
for ( int i : vEdges) {
if ( inB.nIn == i) {
if ( inB.nIn == inA.nIn && inA.nIn == inA.nOut ) {
if ( AreSameEdge(inB.nIn, i)) {
if ( AreSameEdge(inB.nIn, inA.nIn) && AreSameEdge(inA.nIn, inA.nOut)) {
nEdge = inA.nIn ;
//se l'inizio di A è prima della fine, allora devo controllare che B sia compreso tra Out e In (esterno)
if ( CheckIfBefore( nEdge, inA.vpt[0], inA.vpt.back()) ) {
@@ -2978,36 +3112,28 @@ Tree::CheckIfBetween( Inters& inA, Inters& inB) const
if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0]) && CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0]))
bFound = true ;
}
// alternativa
// percorrendo il lato in modo ciclico ( con condizioni al contorno che dalla fine mi riportano all'inizio)
// partendo da OutA devo incontrare InB e poi InA
//if ( CheckIfBefore( nEdge, inA.vpt.back(), nEdge, inB.vpt[0]) && CheckIfBefore( nEdge, inA.vpt.back(), nEdge, inB.vpt[0])) {
// bFound = true ;
//}
// mancano gli altri due casi da aggiungere alla ( condizione) || ( ) || ( )
}
else if ( inB.nIn == inA.nOut) {
else if ( AreSameEdge(inB.nIn, inA.nOut)) {
PolyLine pl ;
pl.AddUPoint( 0, inA.vpt[0]) ;
pl.AddUPoint( 1, inA.vpt.back()) ;
if ( CheckIfAfter( pl, inB.vpt[0], i))
bFound = true ;
}
else if ( inB.nIn == inA.nIn ) {
else if ( AreSameEdge(inB.nIn, inA.nIn)) {
//devo controllare il loop b sia prima dell'inizio di A
if ( CheckIfBefore(inA.nIn, inB.vpt[0], inA.nIn, inA.vpt[0]))
bFound = true ;
}
else
// devo controllare che inB sia prima di OutB
if ( inB.nOut == inB.nIn && CheckIfBefore( inB.nOut, inB.vpt[0], inB.vpt.back())) {
if ( AreSameEdge(inB.nOut, inB.nIn) && CheckIfBefore( inB.nOut, inB.vpt[0], inB.vpt.back())) {
bFound = true ;
}
else if ( inB.nOut != inB.nIn)
else if ( ! AreSameEdge(inB.nOut,inB.nIn))
bFound = true ;
}
if ( inB.nOut == i && ! bFound)
if ( AreSameEdge(inB.nOut, i) && ! bFound && CheckIfBefore(i, inA.vpt[0], inB.vpt.back()) && CheckIfBefore(i, inA.vpt.back(), inB.vpt.back()))
break ;
}
return bFound ;