6faae39afd
- correzioni a HashGrid2d e 3d (molto importanti) - correzioni a Intervals per operazioni booleane.
221 lines
6.9 KiB
C++
221 lines
6.9 KiB
C++
//----------------------------------------------------------------------------
|
|
// 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 <algorithm>
|
|
|
|
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 + m_dToler && dMax > iIter->first - m_dToler) {
|
|
// 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 - m_dToler) {
|
|
// 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 + m_dToler)
|
|
// 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 + m_dToler) && dMax < ( iIter->second - m_dToler)) {
|
|
iIter->first = dMax ;
|
|
// passo al successivo
|
|
++ iIter ;
|
|
}
|
|
// se devo limitarlo superiormente
|
|
else if ( dMin > ( iIter->first + m_dToler) && dMax >= ( iIter->second - m_dToler)) {
|
|
iIter->second = dMin ;
|
|
// passo al successivo
|
|
++ iIter ;
|
|
}
|
|
// se devo dividerlo in due parti
|
|
else if ( dMin > ( iIter->first + m_dToler) && dMax < ( iIter->second - m_dToler)) {
|
|
// 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 ;
|
|
}
|