diff --git a/Tree.cpp b/Tree.cpp index f64fdf3..eaf7ffd 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1198,28 +1198,37 @@ Tree::GetPolygons( std::vector& vPolygons) { // scorro sui poligoni delle celle non trimmate int nCells = (int)vPolygonsBasic.size() ; for ( int i = 0 ; i < nCells ; ++i ) { - // vettore dei poligoni ( loop) della cella nId - POLYLINEVECTOR vCellPolygons ; + // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps int nId = m_vnLeaves[i] ; - // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella - INTVECTOR vnParentChunk ; - //int nEdgeIn = -1 ; - // vettore in cui salvo i loop che non appartengono al poligono che sto cotruendo nel ciclo attuale e da cui ripasserò dopo - INTVECTOR vToCheck( (int) m_mTree[nId].m_vInters.size()) ; - std::generate_n( vToCheck.begin(), (int) m_mTree[nId].m_vInters.size(), generator()) ; - // numero di poligoni aggiunti - int nPoly = 0 ; - // scorro sui vettori intersezione della cella nId e sui suoi vertici - // in questo for analizzo solo i loop che tagliano la cella - while( nPoly == 0 || (int)vToCheck.size() != 0) { - int nPolyBefore = nPoly ; - CreateCellPolygons( i, vPolygons, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i]) ; - if ( nPolyBefore == nPoly) - break ; + if ( m_mTree[nId].m_nFlag == 4) { + // vettore dei poligoni ( loop) della cella nId + POLYLINEVECTOR vCellPolygons ; + vCellPolygons.push_back( vPolygonsBasic[i]) ; + vPolygons.push_back( vCellPolygons) ; + } + else if ( m_mTree[nId].m_nFlag == 0) + continue ; + else { + // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella + INTVECTOR vnParentChunk ; + //int nEdgeIn = -1 ; + // vettore in cui salvo i loop che non appartengono al poligono che sto cotruendo nel ciclo attuale e da cui ripasserò dopo + INTVECTOR vToCheck( (int) m_mTree[nId].m_vInters.size()) ; + std::generate_n( vToCheck.begin(), (int) m_mTree[nId].m_vInters.size(), generator()) ; + // numero di poligoni aggiunti + int nPoly = 0 ; + // scorro sui vettori intersezione della cella nId e sui suoi vertici + // in questo for analizzo solo i loop che tagliano la cella + while( nPoly == 0 || (int)vToCheck.size() != 0) { + int nPolyBefore = nPoly ; + CreateCellPolygons( i, vPolygons, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i]) ; + if ( nPolyBefore == nPoly) + break ; + } + // ora analizzo anche i loop che sono contenuti nella cella + CreateIslandAndHoles( i, vPolygons, nPoly, vnParentChunk) ; } - // ora analizzo anche i loop che sono contenuti nella cella - CreateIslandAndHoles( i, vPolygons, nPoly, vnParentChunk) ; } return true; } @@ -1608,6 +1617,7 @@ Tree::TraceLoopLabelCell( void) Point3d ptLast = m_mTree[nId].m_vInters.back().vpt.back() ; Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + int nLastId ; if ( AreSamePointApprox( m_mTree[nId].GetTopRight(), ptLast) || AreSamePointApprox( ptTl, ptLast) || AreSamePointApprox( m_mTree[nId].GetBottomLeft(), ptLast) || @@ -1618,12 +1628,14 @@ Tree::TraceLoopLabelCell( void) CurveLine clTrim ; clTrim.Set( ptStart, ptEnd) ; vptInters.clear() ; + nLastId = nId ; FindInters( nId, clTrim, vptInters, bVertex) ; + m_mTree[nLastId].m_vInters.back().vpt.push_back( vptInters[0]) ; } int nOut = m_mTree[nId].m_vInters[nPass].nOut ; m_mTree[nId].m_vInters.back().vpt.insert( m_mTree[nId].m_vInters.back().vpt.end(), - m_mTree[nId].m_vInters[nPass].vpt.begin(), - m_mTree[nId].m_vInters[nPass].vpt.end()) ; + m_mTree[nId].m_vInters[nPass].vpt.begin(), + m_mTree[nId].m_vInters[nPass].vpt.end()) ; m_mTree[nId].m_vInters[nPass] = m_mTree[nId].m_vInters.back() ; m_mTree[nId].m_vInters.pop_back() ; // sistemo il lato d'uscita @@ -1668,6 +1680,7 @@ Tree::TraceLoopLabelCell( void) } else { //categorizzo la cella/////////////////////////////////////////////////////////// m_mTree[nCell].m_nFlag2 = 1 ; + CategorizeCell( nCell) ; } if ( ! m_mTree[nCell].IsProcessed()) { @@ -1702,6 +1715,7 @@ Tree::TraceLoopLabelCell( void) if ( nCell == nLastLeft && m_mTree[nCell].IsProcessed() ) { // categorizzo//////////////////////////////////////////////////////////////////////////// m_mTree[nCell].m_nFlag2 = 1 ; + CategorizeCell( nCell) ; bAllDone = true ; break ; } @@ -1757,6 +1771,8 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert 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 ; if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) { nEdge = 0 ; // lato sopra @@ -1766,6 +1782,11 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert //else //if ( ptEnd.x < ptBL.x) if ( ptEnd.x < ptBL.x) clEdge2.Set( ptTl, ptBL) ; + else if ( AreSamePointExact( ptEnd, ptTl)) { + nEdge = 4 ; + ptInters = ptTl ; + bIntersFound = true ; + } } else if ( ptEnd.x <= ptBL.x && ptEnd.y <= ptTR.y) { nEdge = 1 ; @@ -1777,6 +1798,11 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert //else //if ( ptEnd.y < ptBL.y) if ( ptEnd.y < ptBL.y) clEdge2.Set( ptBL, ptBr) ; + else if ( AreSamePointExact( ptEnd, ptBL)) { + nEdge = 5 ; + ptInters = ptBL ; + bIntersFound = true ; + } } else if ( ptEnd.y <= ptBL.y && ptEnd.x >= ptBL.x) { nEdge = 2 ; @@ -1788,6 +1814,11 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert //else //if ( ptEnd.x > ptTR.x) if ( ptEnd.x > ptTR.x) clEdge2.Set( ptBr, ptTR) ; + else if ( AreSamePointExact( ptEnd, ptBr)) { + nEdge = 6 ; + ptInters = ptBr ; + bIntersFound = true ; + } } else if ( ptEnd.x >= ptTR.x && ptEnd.y >= ptBL.y) { nEdge = 3 ; @@ -1799,50 +1830,56 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert //else //if ( ptEnd.y > ptTR.y) if ( ptEnd.y > ptTR.y) clEdge2.Set( ptTR, ptTl) ; + else if ( AreSamePointExact( ptEnd, ptTR)) { + nEdge = 7 ; + ptInters = ptTR ; + bIntersFound = true ; + } } else return false ; - // intersezione e controlli - IntersLineLine illExit( clTrim, clEdge, true) ; - IntCrvCrvInfo aInfo, aInfo2 ; - Point3d ptInters ; - //if ( ! illExit.GetIntCrvCrvInfo( aInfo) ) - // return false ; - illExit.GetIntCrvCrvInfo( aInfo) ; - if ( clEdge2.IsValid()){ - IntersLineLine illExit2( clTrim, clEdge2, true) ; - //if ( ! illExit2.GetIntCrvCrvInfo( aInfo2) ) + if ( ! bIntersFound) { + // intersezione e controlli + IntersLineLine illExit( clTrim, clEdge, true) ; + IntCrvCrvInfo aInfo, aInfo2 ; + //if ( ! illExit.GetIntCrvCrvInfo( aInfo) ) // return false ; - // verifico su quale dei due lati ho l'intersezione - if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)) - ptInters = aInfo.IciA[0].ptI ; - else { - // solo intersezione sul lato 2 - if ( illExit.GetNumInters() == 0 ) { - ptInters = aInfo2.IciA[0].ptI ; - if ( nEdge > 3 && nEdge != 7) - nEdge = nEdge - 4 ; - else if ( nEdge < 3 ) - ++ nEdge ; - else - nEdge = 0 ; - } - // intersezione sul vertice della cella + illExit.GetIntCrvCrvInfo( aInfo) ; + if ( clEdge2.IsValid()){ + IntersLineLine illExit2( clTrim, clEdge2, true) ; + //if ( ! illExit2.GetIntCrvCrvInfo( aInfo2) ) + // return false ; + // verifico su quale dei due lati ho l'intersezione + if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)) + ptInters = aInfo.IciA[0].ptI ; else { - ptInters = aInfo2.IciA[0].ptI ; - bVertex = true ; - // la cella adiacente in diagonale a quel vertice - nEdge = nEdge + 4 ; + // solo intersezione sul lato 2 + if ( illExit.GetNumInters() == 0 ) { + ptInters = aInfo2.IciA[0].ptI ; + if ( nEdge > 3 && nEdge != 7) + nEdge = nEdge - 4 ; + else if ( nEdge < 3 ) + ++ nEdge ; + else + nEdge = 0 ; + } + // intersezione sul vertice della cella + else { + ptInters = aInfo2.IciA[0].ptI ; + bVertex = true ; + // la cella adiacente in diagonale a quel vertice + nEdge = nEdge + 4 ; + } } } + else + ptInters = aInfo.IciA[0].ptI ; } - else - ptInters = aInfo.IciA[0].ptI ; 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 - m_mTree[nId].m_vInters.back().vpt = vptInters ; + m_mTree[nId].m_vInters.back().vpt = vptInters ; // al posto di .vpt = vptInters metto un push_back //////////////////////////////////////////////// vptInters.clear() ; // setto la categoria della cella if ( m_mTree[nId].m_nFlag == -1) @@ -2356,7 +2393,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I plTrimmedPoly.Close() ; double dArea ; plTrimmedPoly.GetAreaXY( dArea) ; - if ( dArea > EPS_SMALL ) { + if ( dArea > SQ_EPS_SMALL) { vCellPolygons.push_back( plTrimmedPoly) ; vPolygons.push_back( vCellPolygons) ; ++ nPoly ; @@ -2481,6 +2518,7 @@ Tree::CheckIfBefore( PolyLine& pl, int nEdge) const bool Tree::CheckIfBefore( Inters& inA) const { + // controllo se l'ingresso è prima dell'uscita int nEdge1 = inA.nIn ; int nEdge2 = inA.nOut ; PolyLine pl ; @@ -2804,11 +2842,12 @@ Tree::SetRightEdgeIn( int nId) } // se non ho inters sul lato destro devo verificare se è tutto dentro o tutto fuori if ( ! bDone) { - // ciclo sulle inters e cerco se ho dei passaggi con un'uscita più bassa di un'entrata e se eventualmente è la più a destra! + // ciclo sulle inters e cerco quella più a destra, se ha un'uscita più bassa di un'entrata allora il right edge è compreso! bool bFound = false ; bool bRightMost = false ; int nEdgeIn = 6, nEdgeOut = 7, nLoop ; Point3d ptIn, ptOut ; + ptIn = ptOut = m_mTree[nId].GetBottomLeft() ; for ( int k = 0 ; k < nPass ; ++ k) { // trovo il loop che ha l'ingresso o l'uscita più a destra if ( CheckIfBefore( m_mTree[nId].m_vInters[k].nIn, m_mTree[nId].m_vInters[k].vpt[0], nEdgeIn, ptIn) || @@ -2842,16 +2881,111 @@ Tree::SetRightEdgeIn( int nId) bool Tree::CategorizeCell( int& nId) { - //if ( m_mTree[nId].m_nFlag != -1) { - // return true ; - //} - //INTVECTOR vNeigh ; - //GetLeftNeigh( nId, vNeigh) ; - //// mi servono i vicini di sinistra per capire se sono dentro il loop o fuori - //// 0 right edge fuori, 1 right edge dentro, 2 metà e metà - //if ( ) { + if ( m_mTree[nId].m_nFlag != -1) { + return true ; + } + INTVECTOR vNeigh, vNeigh1 ; + GetLeftNeigh( nId, vNeigh) ; + // mi servono i vicini di sinistra per capire se sono dentro il loop o fuori + // nRightEdgeIn // 0 right edge fuori, 1 right edge dentro, 2 metà e metà + // nFlag // 0 fuori, 1 intersecata, 2 contiene loop, 3 = 1 & 2, 4 dentro + if ( (int)vNeigh.size() == 0 ) { + m_mTree[nId].m_nFlag = 0 ; + } + else if ( (int)vNeigh.size() == 1) { + 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 ; + // 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 ) { + // guardo le intersezioni a mano + // + //int nPass = (int) m_mTree[vNeigh[0]].m_vInters.size() ; + //for ( int p = 0 ; p < nPass ; ++p ) { + // // se ho almeno un ingresso o un'uscita + // if ( ) { + + // } + // else { + // m_mTree[nId].m_nFlag == 0 ; + // } + //} + GetBottomNeigh( nId, vNeigh1) ; + int nNeigh = vNeigh1[0] ; + if ( m_mTree[nNeigh].m_nFlag == 0 || m_mTree[nNeigh].m_nFlag == 2) { + m_mTree[nId].m_nFlag = 0 ; + } + else if ( m_mTree[nNeigh].m_nFlag == 4) { + m_mTree[nId].m_nFlag = 4 ; + } + else if ( m_mTree[nNeigh].m_nFlag == 1 || m_mTree[nNeigh].m_nFlag == 3) { + if ( m_mTree[nNeigh].m_nRightEdgeIn == 0) + m_mTree[nId].m_nFlag = 0 ; + else if ( m_mTree[nNeigh].m_nRightEdgeIn == 1) + m_mTree[nId].m_nFlag = 4 ; + else if ( m_mTree[nNeigh].m_nRightEdgeIn == 2 ) { + // in questo caso devo verificare le intersezioni sul lato destro del vicino bottom + // scorro e cerco l'intersezione più alta, se è out la cella è dentro, se è in devo verificare l'out se è più a sinistra o a destra. + int nPass = (int) m_mTree[nNeigh].m_vInters.size() ; + bool bTopMost = false ; + bool bFound = false; + Point3d ptInters, ptBr( m_mTree[nNeigh].GetTopRight().x, m_mTree[nNeigh].GetBottomLeft().y) ; + ptInters = ptBr ; // inizializzato a vertice bottom right + int nEdgeIn = 3, nEdgeOut = 3, nLoop ; + 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))) { + 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)) { + nLoop = r ; + ptInters = m_mTree[nNeigh].m_vInters[r].vpt.back() ; + bFound = true ; + } + } + if ( bFound && CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) { + bTopMost = true ; + } + if ( bFound && bTopMost) { + if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) && AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nOut, 3) ) { + if ( CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) + m_mTree[nId].m_nFlag = 4 ; + else + m_mTree[nId].m_nFlag = 0 ; + } + else if ( AreSameEdge(m_mTree[nId].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 + Point3d ptOut = m_mTree[nNeigh].m_vInters[nLoop].vpt.back() ; + Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + if ( ptOut.x >= ptBr.x) + m_mTree[nId].m_nFlag = 4 ; + else + m_mTree[nId].m_nFlag = 0 ; + } + } + } + } + } + } + else { + for ( int r = 0 ; r < (int)vNeigh.size() ; ++ r) { + if ( m_mTree[vNeigh[r]].m_nRightEdgeIn == 1) { + m_mTree[nId].m_nFlag = 4 ; + break ; + } + else if ( m_mTree[vNeigh[r]].m_nRightEdgeIn == 0) { + m_mTree[nId].m_nFlag = 0 ; + break ; + } + } + } - //} - // m_mTree[nId].m_nFlag2 = 1 ; return true ; } diff --git a/Tree.h b/Tree.h index d3ab143..369acba 100644 --- a/Tree.h +++ b/Tree.h @@ -75,8 +75,8 @@ class Cell int m_nChild1 ; // prima cella figlio int m_nChild2 ; // seconda cella figlio int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim - int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling // 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop + int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà INTVECTOR m_vnLoop ; // indice dei loop contenuti nella cella std::vector m_vInters ; // vettore delle intersezioni della cella con i loop di trim