Compare commits

...

5 Commits

Author SHA1 Message Date
Riccardo Elitropi 6bfb5c619f Merge commit 'fae6a7cd78972d7b91457994d525dba16d4e5945' into Douglas-Peucker 2024-02-21 16:55:28 +01:00
Riccardo Elitropi 8be2246249 Merge commit '47e79756d17ae312d89d3617289bccabcb4bcf66' into Douglas-Peucker 2024-02-13 12:37:57 +01:00
Riccardo Elitropi 56cff98cf3 EgtGeomKernel :
- miglioria codice.
2024-02-06 13:15:13 +01:00
Riccardo Elitropi 3168bee865 Merge commit '7cd83efd97d2ab771362e2b18eb3db62bd9fb6e4' into Douglas-Peucker 2024-02-06 10:24:43 +01:00
Riccardo Elitropi 3d2f8c1495 EgtGeomKernel :
- approsimazione PolyLine con Douglas-Peucker.
2024-02-06 10:23:22 +01:00
+88 -51
View File
@@ -733,6 +733,45 @@ PointsInTolerance( const PNTVECTOR& vRPT, const Point3d& ptP1, const Point3d& pt
return true ;
}
//-----------------------------------------------------------------------------
static bool
douglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart,
const int nIndEnd, PNTUVECTOR& vPtU_simple)
{
// se indici uguali, ritorno
if ( nIndStart == nIndEnd)
return true ;
// distanza massima e indice del punto associato
double dMaxSqDist = 0. ;
int nMaxInd = 0 ;
// scorro i punti intermedi tra nIndStart e nIndEnd
for ( int i = nIndStart + 1 ; i < nIndEnd ; ++ i) {
double dCurrSqDist = 0. ;
// distanza tra il punto attuale e la retta tra i punti di indici nIndStart ed nIndEnd
DistPointLine DPL( vPtU[i].first, vPtU[nIndStart].first, vPtU[nIndEnd].first) ;
if ( DPL.GetSqDist( dCurrSqDist) && dCurrSqDist > dMaxSqDist) {
// aggiorno i parametri
dMaxSqDist = dCurrSqDist ;
nMaxInd = i ;
}
}
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
if ( dMaxSqDist > dSqTol) {
// inserisco il punto
vPtU_simple.push_back( vPtU[nMaxInd]) ;
// split
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vPtU_simple) ||
! douglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vPtU_simple))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::RemoveAlignedPoints( double dToler)
@@ -743,59 +782,57 @@ PolyLine::RemoveAlignedPoints( double dToler)
// controllo minimo valore di tolleranza
dToler = max( dToler, LIN_TOL_MIN) ;
double dSqTol = dToler * dToler ;
// si analizza la distanza di un punto dal segmento che unisce precedente e successivo
// punto precedente
auto precP = m_lUPoints.begin() ;
// punto corrente
auto currP = next( precP) ;
// punto successivo
auto nextP = next( currP) ;
// lista dei punti appena rimossi
PNTVECTOR vRPT ; vRPT.reserve( 20) ;
// mentre esiste un successivo
while ( nextP != m_lUPoints.end()) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist ;
// se da eliminare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
// aggiungo il punto nella lista dei rimossi
vRPT.emplace_back( currP->first) ;
// elimino il punto
m_lUPoints.erase( currP) ;
// avanzo con corrente e successivo
currP = nextP ;
++ nextP ;
}
// altrimenti da tenere
else {
// cancello la lista dei rimossi
vRPT.clear() ;
// avanzo il terzetto di uno step
precP = currP ;
currP = nextP ;
++ nextP ;
}
// vettore contenente i punti della polyline
PNTUVECTOR vPtU ; vPtU.resize( int( m_lUPoints.size())) ;
// interatore primo punto
auto ptAct = m_lUPoints.begin() ;
for ( int i = 0 ; i < int( m_lUPoints.size()) ; ++ i) {
vPtU[i] = *ptAct;
ptAct = next( ptAct) ; // incremento iteratore
}
// se curva chiusa con almeno 4 punti, devo analizzare il terzetto attorno alla chiusura
if ( IsClosed() && m_lUPoints.size() >= 4) {
// precP e currP sono già corretti
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
auto firstP = m_lUPoints.begin() ;
// questo è il vero successivo
nextP = next( firstP) ;
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist ;
// se da eliminare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
// faccio coincidere il primo punto con il precedente
firstP->first = precP->first ;
// elimino il punto corrente
m_lUPoints.erase( currP) ;
}
// vettore indice dei punti semplificati
PNTUVECTOR vPtU_simple ;
// POLYLINE APERTA
if ( ! IsClosed()) {
// considero tutti i punti della PolyLine
vPtU_simple.push_back( vPtU.front()) ;
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vPtU_simple))
return false ;
vPtU_simple.push_back( vPtU.back()) ;
}
// POLYLINE 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
vPtU_simple.push_back( vPtU.front()) ;
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vPtU_simple))
return false ;
vPtU_simple.push_back( vPtU[ nMaxInd]) ;
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vPtU_simple))
return false ;
vPtU_simple.push_back( vPtU.back()) ;
}
// ordino
sort( vPtU_simple.begin(), vPtU_simple.end(),
[]( const POINTU& a , const POINTU& b) { return ( a.second < b.second) ; }) ;
// pulisco e aggiungo i parametri ricavati
m_lUPoints.clear() ;
for ( int i = 0 ; i < int( vPtU_simple.size()) ; ++ i)
m_lUPoints.push_back( vPtU_simple[i]) ;
return true ;
}