//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : Intervals.cpp Data : 03.08.15 Versione : 1.6h1 // Contenuto : Implementazione della classe insieme di intervalli Intervals. // // // // Modifiche : 03.08.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "\EgtDev\Include\EGkGeoConst.h" #include "\EgtDev\Include\EGkIntervals.h" #include using namespace std ; //---------------------------------------------------------------------------- void Intervals::Reset( void) { m_lInts.clear() ; m_Iter = m_lInts.end() ; } //---------------------------------------------------------------------------- void Intervals::Set( double dMin, double dMax) { Reset() ; // verifico ordine if ( dMin > dMax) swap( dMin, dMax) ; // aggiungo m_lInts.emplace_back( dMin, dMax) ; } //---------------------------------------------------------------------------- void Intervals::Add( double dMin, double dMax) { // verifico ordine if ( dMin > dMax) swap( dMin, dMax) ; // aggiungo, tenendo conto di interazioni con eventuali intervalli già presenti auto iInsert = m_lInts.end() ; auto iIter = m_lInts.begin() ; while ( iIter != m_lInts.end()) { // se interseca l'intervallo corrente if ( dMin < iIter->second + EPS_SMALL && dMax > iIter->first - EPS_SMALL) { // se ha già interessato un intervallo precedente if ( iInsert != m_lInts.end()) { // aggiorno il massimo dell'intervallo già interessato iInsert->second = max( dMax, iIter->second) ; // cancello il corrente iIter = m_lInts.erase( iIter) ; // il nuovo iteratore è già il successivo } // altrimenti modifico il corrente else { // salvo l'intervallo di inserimento iInsert = iIter ; // lo modifico iInsert->first = min( iInsert->first, dMin) ; iInsert->second = max( iInsert->second, dMax) ; // passo al successivo ++ iIter ; } } // se il nuovo intervallo finisce prima else if ( dMax <= iIter->first - EPS_SMALL) { // se non già inserito, lo faccio ora if ( iInsert == m_lInts.end()) iInsert = m_lInts.emplace( iIter, dMin, dMax) ; // termino break ; } // se il nuovo intervallo inizia dopo else if ( dMin > iIter->second + EPS_SMALL) // passo al successivo ++ iIter ; } // se non ancora inserito, va aggiunto alla fine if ( iInsert == m_lInts.end()) m_lInts.emplace_back( dMin, dMax) ; } //---------------------------------------------------------------------------- void Intervals::Subtract( double dMin, double dMax) { // verifico ordine if ( dMin > dMax) swap( dMin, dMax) ; // scorro gli intervalli auto iIter = m_lInts.begin() ; while ( iIter != m_lInts.end()) { // se interseca l'intervallo corrente if ( dMin < iIter->second && dMax > iIter->first) { // se devo limitarlo inferiormente if ( dMin < ( iIter->first + EPS_SMALL) && dMax < ( iIter->second - EPS_SMALL)) { iIter->first = dMax ; // passo al successivo ++ iIter ; } // se devo limitarlo superiormente else if ( dMin > ( iIter->first + EPS_SMALL) && dMax > ( iIter->second - EPS_SMALL)) { iIter->second = dMin ; // passo al successivo ++ iIter ; } // se devo dividerlo in due parti else if ( dMin > ( iIter->first + EPS_SMALL) && dMax < ( iIter->second - EPS_SMALL)) { // inserisco il nuovo intervallo che corrisponde alla parte inferiore iIter = m_lInts.emplace( iIter, iIter->first, dMin) ; // modifico l'intervallo successivo ++ iIter ; iIter->first = dMax ; // passo al successivo ++ iIter ; } // altrimenti devo eliminarlo else { iIter = m_lInts.erase( iIter) ; // il nuovo iteratore è già il successivo } } // se è tutto minore dell'intervallo corrente, ho finito else if ( dMax <= iIter->first) break ; // altrimenti è tutto maggiore dell'intervallo corrente, passo al successivo else // dMin >= iIter->second ++ iIter ; } } //---------------------------------------------------------------------------- void Intervals::Add( const Intervals& Other) { // aggiungo tutti gli intervalli dell'altro for ( auto& Interv : Other.m_lInts) Add( Interv.first, Interv.second) ; } //---------------------------------------------------------------------------- void Intervals::Subtract( const Intervals& Other) { // sottraggo tutti gli intervalli dell'altro for ( auto& Interv : Other.m_lInts) Subtract( Interv.first, Interv.second) ; } //---------------------------------------------------------------------------- void Intervals::Intersect( const Intervals& Other) { // se l'insieme è vuoto non devo fare alcunché if ( m_lInts.empty()) return ; // Insieme di intervalli ausiliario ampio come il corrente Intervals Aux ; Aux.Set( m_lInts.front().first, m_lInts.back().second) ; // Sottraggo Other da Aux Aux.Subtract( Other) ; // Sottraggo Aux dal corrente Subtract( Aux) ; } //---------------------------------------------------------------------------- bool Intervals::GetMinMax( double& dMin, double& dMax) { // verifico ci siano intervalli if ( m_lInts.empty()) return false ; // l'estensione va dall'inizio del primo intervallo alla fine dell'ultimo dMin = m_lInts.front().first ; dMax = m_lInts.back().second ; return true ; } //---------------------------------------------------------------------------- bool Intervals::GetFirst( double& dMin, double& dMax) { // vado all'inizio m_Iter = m_lInts.begin() ; // verifico sia definito if ( m_Iter == m_lInts.end()) return false ; // recupero i dati dMin = m_Iter->first ; dMax = m_Iter->second ; return true ; } //---------------------------------------------------------------------------- bool Intervals::GetNext( double& dMin, double& dMax) { // vado al successivo if ( m_Iter == m_lInts.end()) return false ; ++ m_Iter ; // verifico sia definito if ( m_Iter == m_lInts.end()) return false ; // recupero i dati dMin = m_Iter->first ; dMax = m_Iter->second ; return true ; }