diff --git a/PolyLine.cpp b/PolyLine.cpp index dff395c..a1ba656 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -737,7 +737,7 @@ PolyLine::AdjustForMaxSegmentLen( double dMaxLen) //----------------------------------------------------------------------------- static bool DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart, - const int nIndEnd, INTVECTOR& vInd, double dMaxLen) + const int nIndEnd, INTVECTOR& vInd) { // se indici uguali, ritorno if ( nIndStart == nIndEnd) @@ -745,7 +745,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const // distanza massima e indice del punto associato double dMaxSqDist = 0. ; - int nMaxInd = nIndStart + 1 ; + int nMaxInd = 0 ; // scorro i punti intermedi tra nIndStart e nIndEnd for ( int i = nIndStart + 1 ; i < nIndEnd ; ++ i) { @@ -761,15 +761,12 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const // se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra // (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd) - bool bSplit = dMaxSqDist > dSqTol ; - if ( dMaxLen < INFINITO) - bSplit = bSplit || ( nIndEnd - nIndStart > 1 && Dist( vPtU[nIndStart].first, vPtU[nIndEnd].first) > dMaxLen) ; - if ( bSplit) { + if ( dMaxSqDist > dSqTol) { // inserisco il punto vInd.push_back( nMaxInd) ; // split - if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vInd, dMaxLen) || - ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vInd, dMaxLen)) + if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vInd) || + ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vInd)) return false ; } @@ -795,34 +792,65 @@ PolyLine::RemoveAlignedPoints( double dToler, bool bStartEnd, double dMaxLen) // vettore indici dei punti rimanenti INTVECTOR vInd ; vInd.reserve( vPtU.size()) ; - // se aperta - if ( ! IsClosed()) { - // considero tutti i punti della PolyLine - vInd.push_back( 0) ; - if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd, dMaxLen)) - return false ; - vInd.push_back( int( vPtU.size()) - 1) ; - } - // altrimenti chiusa - else { - // cerco il punto più distante dal primo - double dMaxDist = 0. ; - int nMaxInd = 0 ; - for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) { - double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ; - if ( dCurrDist > dMaxDist) { - dMaxDist = dCurrDist ; - nMaxInd = i ; - } + if ( dMaxLen > INFINITO - 1) { + // se aperta + if ( ! IsClosed()) { + // considero tutti i punti della PolyLine + vInd.push_back( 0) ; + if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd)) + return false ; + vInd.push_back( int( vPtU.size()) - 1) ; + } + // altrimenti chiusa + else { + // cerco il punto più distante dal primo + double dMaxDist = 0. ; + int nMaxInd = 0 ; + for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) { + double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ; + if ( dCurrDist > dMaxDist) { + dMaxDist = dCurrDist ; + nMaxInd = i ; + } + } + // recupero due PolyLine di approssimazione + vInd.push_back( 0) ; + if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd)) + return false ; + vInd.push_back( nMaxInd) ; + if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd)) + return false ; + vInd.push_back( int( vPtU.size()) - 1) ; + } + } + else { + // raggruppo i punti della polyline a gruppi che stanno entro la lunghezza massima e ad ognuno applico Douglas + vInd.push_back(0) ; + + int i = 0 ; + while ( i < ssize(vPtU) - 1) { + int nLast = i + 1 ; + while ( nLast < ssize( vPtU) && Dist( vPtU[i].first, vPtU[nLast].first) <= dMaxLen) + ++nLast ; + + // l'ultimo punto era oltre il limite + --nLast ; + + // sicurezza: almeno un passo avanti + if ( nLast == i) + nLast = i + 1 ; + + // mantieni l'estremo del tratto + if ( vInd.back() != nLast) + vInd.push_back( nLast) ; + + // semplifica il tratto interno + if ( nLast - i > 1) { + if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, i, nLast, vInd)) + return false ; + } + i = nLast ; } - // recupero due PolyLine di approssimazione - vInd.push_back( 0) ; - if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd, dMaxLen)) - return false ; - vInd.push_back( nMaxInd) ; - if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd, dMaxLen)) - return false ; - vInd.push_back( int( vPtU.size()) - 1) ; } // ordino in senso crescente