EgtGeomKernel 1.6t3 :

- migliorata velocità di esecuzione di FindNearest di PointGrid3d per ChainCurves
- a PolyLine aggiunte GetConvexHullXY e GetMinAreaRectangleXY.
This commit is contained in:
Dario Sassi
2016-08-25 15:59:32 +00:00
parent 8e7b54e3d5
commit e78697e557
12 changed files with 273 additions and 77 deletions
+91 -60
View File
@@ -27,11 +27,11 @@ struct IBox {
int nYmin, nYmax ;
int nZmin, nZmax ;
IBox( void) : nXmin( INT_MAX), nXmax( INT_MIN),
nYmin( INT_MAX), nYmax( INT_MIN),
nZmin( INT_MAX), nZmax( INT_MIN) {}
nYmin( INT_MAX), nYmax( INT_MIN),
nZmin( INT_MAX), nZmax( INT_MIN) {}
void Reset( void)
{ nXmin = nYmin = nZmin = INT_MAX ;
nXmax = nYmax = nZmax = INT_MIN ; }
nXmax = nYmax = nZmax = INT_MIN ; }
bool Encloses( int nX, int nY, int nZ)
{ return ( nX >= nXmin && nX <= nXmax &&
nY >= nYmin && nY <= nYmax &&
@@ -255,72 +255,103 @@ bool
PointGrid3d::FindNearest( const Point3d& ptTest, INTVECTOR& vnIds)
{
const double NEAR_TOL = 100 * EPS_SMALL ;
const int SIZE_LIMIT = 1000 ;
// pulisco il risultato
vnIds.clear() ;
// raggio di ricerca
double dRad = max( m_BBox.DistFromPoint( ptTest), NEAR_TOL) ;
// delta di incremento per raggio di ricerca
const int N_CELL = 10 ;
double dDelta = N_CELL * m_dCellDim ;
// massimo numero di step di ricerca basato su raggio box di ingombro
double dBoxRad ;
if ( ! m_BBox.GetRadius( dBoxRad))
return false ;
int nMaxSteps = int( 2 * ceil( dBoxRad / dDelta)) ;
nMaxSteps = max( nMaxSteps, 1) ;
// ciclo di ricerca con raggio crescente
IBox iBoxPrev ;
IBox ibR[N_SUBIBOX] ;
bool bFound = false ;
double dMinDist ;
double dSqMinDist ;
for ( int m = 0 ; m <= nMaxSteps ; ++ m) {
// determino il range di celle sui tre assi
IBox iBox ;
if ( ! Get3dRangeNbr( ptTest, dRad, iBox))
continue ;
// tolgo il range precedente
SubtractIBox( iBox, iBoxPrev, ibR) ;
// ciclo su tutte le celle dei range rimanenti
for ( int l = 0 ; l < N_SUBIBOX ; ++ l) {
for ( int i = ibR[l].nXmin ; i <= ibR[l].nXmax ; ++ i) {
for ( int j = ibR[l].nYmin ; j <= ibR[l].nYmax ; ++ j) {
for ( int k = ibR[l].nZmin ; k <= ibR[l].nZmax ; ++ k) {
// ciclo sui punti della cella
IPNTI_UMMAP_CRANGE MMrange = m_MMap.equal_range( PointHash( i, j, k)) ;
for ( ; MMrange.first != MMrange.second ; ++ MMrange.first) {
// se distanza inferiore al minimo, aggiorno...
double dSqDist = SqDist( (*MMrange.first).second.first, ptTest) ;
// altro punto con la stessa minima distanza già trovata
if ( bFound && fabs( dSqDist - dSqMinDist) < 2 * dMinDist * NEAR_TOL + NEAR_TOL * NEAR_TOL) {
// inserisco il punto nel vettore dei risultati
vnIds.push_back( (*MMrange.first).second.second) ;
}
// primo punto o punto con minima distanza più bassa
else if ( ! bFound || dSqDist < dSqMinDist) {
bFound = true ;
// aggiorno i minimi
dSqMinDist = dSqDist ;
dMinDist = sqrt( dSqMinDist) ;
// pulisco il vettore dei risultati ed inserisco questo
vnIds.clear() ;
vnIds.push_back( (*MMrange.first).second.second) ;
// se ci sono pochi elementi, eseguo direttamente la ricerca sugli stessi
if ( m_MMap.size() < SIZE_LIMIT) {
// ciclo di ricerca sugli elementi
bool bFound = false ;
double dMinDist ;
double dSqMinDist ;
for each ( const auto& PntI in m_MMap) {
// quadrato della distanza
double dSqDist = SqDist( ptTest, PntI.second.first) ;
// altro punto con la stessa minima distanza già trovata
if ( bFound && fabs( dSqDist - dSqMinDist) < 2 * dMinDist * NEAR_TOL + NEAR_TOL * NEAR_TOL) {
// inserisco il punto nel vettore dei risultati
vnIds.push_back( PntI.second.second) ;
}
// primo punto o punto con minima distanza più bassa
else if ( ! bFound || dSqDist < dSqMinDist) {
bFound = true ;
// aggiorno i minimi
dSqMinDist = dSqDist ;
dMinDist = sqrt( dSqMinDist) ;
// pulisco il vettore dei risultati ed inserisco questo
vnIds.clear() ;
vnIds.push_back( PntI.second.second) ;
}
}
return bFound ;
}
// altrimenti, verifico cerchi concentrici di celle
else {
// raggio di ricerca
double dRad = max( m_BBox.DistFromPoint( ptTest), NEAR_TOL) ;
// delta di incremento per raggio di ricerca
const int N_CELL = 10 ;
double dDelta = N_CELL * m_dCellDim ;
// massimo numero di step di ricerca basato su raggio box di ingombro
double dBoxRad ;
if ( ! m_BBox.GetRadius( dBoxRad))
return false ;
int nMaxSteps = int( 2 * ceil( dBoxRad / dDelta)) ;
nMaxSteps = max( nMaxSteps, 1) ;
// ciclo di ricerca con raggio crescente
IBox iBoxPrev ;
IBox ibR[N_SUBIBOX] ;
bool bFound = false ;
double dMinDist ;
double dSqMinDist ;
for ( int m = 0 ; m <= nMaxSteps ; ++ m) {
// determino il range di celle sui tre assi
IBox iBox ;
if ( ! Get3dRangeNbr( ptTest, dRad, iBox))
continue ;
// tolgo il range precedente
SubtractIBox( iBox, iBoxPrev, ibR) ;
// ciclo su tutte le celle dei range rimanenti
for ( int l = 0 ; l < N_SUBIBOX ; ++ l) {
for ( int i = ibR[l].nXmin ; i <= ibR[l].nXmax ; ++ i) {
for ( int j = ibR[l].nYmin ; j <= ibR[l].nYmax ; ++ j) {
for ( int k = ibR[l].nZmin ; k <= ibR[l].nZmax ; ++ k) {
// ciclo sui punti della cella
IPNTI_UMMAP_CRANGE MMrange = m_MMap.equal_range( PointHash( i, j, k)) ;
for ( ; MMrange.first != MMrange.second ; ++ MMrange.first) {
// se distanza inferiore al minimo, aggiorno...
double dSqDist = SqDist( (*MMrange.first).second.first, ptTest) ;
// altro punto con la stessa minima distanza già trovata
if ( bFound && fabs( dSqDist - dSqMinDist) < 2 * dMinDist * NEAR_TOL + NEAR_TOL * NEAR_TOL) {
// inserisco il punto nel vettore dei risultati
vnIds.push_back( (*MMrange.first).second.second) ;
}
// primo punto o punto con minima distanza più bassa
else if ( ! bFound || dSqDist < dSqMinDist) {
bFound = true ;
// aggiorno i minimi
dSqMinDist = dSqDist ;
dMinDist = sqrt( dSqMinDist) ;
// pulisco il vettore dei risultati ed inserisco questo
vnIds.clear() ;
vnIds.push_back( (*MMrange.first).second.second) ;
}
}
}
}
}
}
// se trovato, inutile continuare perchè ci si allontanerà
if ( bFound)
return true ;
// incremento il raggio di ricerca
dRad += dDelta ;
// salvo box di precedente ricerca
iBoxPrev = iBox ;
}
// se trovato, inutile continuare perchè ci si allontanerà
if ( bFound)
return true ;
// incremento il raggio di ricerca
dRad += dDelta ;
// salvo box di precedente ricerca
iBoxPrev = iBox ;
}
return bFound ;
return bFound ;
}
}
//----------------------------------------------------------------------------