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
+1 -1
View File
@@ -27,7 +27,7 @@ ChainCurves::Init( bool bAllowInvert, double dToler, int nCrvNbrHint)
m_sCrvId.rehash( nCrvNbrHint) ;
m_vCrvData.clear() ;
m_vCrvData.reserve( nCrvNbrHint) ;
const double DIM_CELL = 5.0 ;
const double DIM_CELL = 10.0 ;
m_PointGrid.Init( 2 * nCrvNbrHint, DIM_CELL) ;
return true ;
}
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -32,8 +32,8 @@ const double ANG_TOL_APPROX_DEG = 45 ;
const double LIN_TOL_STD = 0.1 ;
// deviazione angolare standard (in gradi)
const double ANG_TOL_STD_DEG = 15 ;
// tolleranza lineare per visualizzazione di superfici regioni piane
const double LIN_TOL_SFR = 0.01 ;
// tolleranza lineare affinata (tipica per superfici regioni piane)
const double LIN_TOL_FINE = 0.01 ;
// lunghezza minima feature lineare
const double LIN_FEA_LEN_STD = 20 ;
+1 -1
View File
@@ -61,6 +61,6 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
[]( const IntLinStmInfo& a, const IntLinStmInfo&b) { return a.dU < b.dU ; }) ;
[]( const IntLinStmInfo& a, const IntLinStmInfo& b) { return ( a.dU < b.dU) ; }) ;
return true ;
}
+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 ;
}
}
//----------------------------------------------------------------------------
+166 -1
View File
@@ -941,4 +941,169 @@ PolyLine::Flatten( double dZ)
}
}
return true ;
}
}
//----------------------------------------------------------------------------
bool
PolyLine::GetConvexHullXY( PNTVECTOR& vConvHull) const
{
int nSize = int( m_lUPoints.size()) ;
if ( nSize == 0)
return false ;
// inserisco i punti in un array ( considero solo x e y, annullo le z)
PNTVECTOR vPnt( nSize) ;
int k = 0 ;
for each ( const auto& Pnt in m_lUPoints)
vPnt[k++] = Point3d( Pnt.first.x, Pnt.first.y, 0) ;
// ordino secondo le X crescenti
std::sort( vPnt.begin(), vPnt.end(),
[]( const Point3d& a, const Point3d& b) { return ( a.x < b.x) ; }) ;
// elimino eventuali punti coincidenti
for ( int i = 0 ; i < nSize ; ++ i) {
for ( int j = i + 1 ; j < nSize ; ++ j) {
if ( ( vPnt[j].x - vPnt[i].x) > EPS_SMALL)
break ;
else if ( AreSamePointXYApprox( vPnt[i], vPnt[j])) {
vPnt.erase( vPnt.begin() + j) ;
-- nSize ;
}
}
}
// applico l'algoritmo di Andrew
int j = 0 ;
vConvHull.resize( 2 * nSize) ;
// costruisco la parte inferiore
for ( int i = 0 ; i < nSize ; ++ i) {
while ( j >= 2 && CrossXY( vConvHull[j-1] - vConvHull[j-2], vPnt[i] - vConvHull[j-2]) <= 0)
-- j ;
vConvHull[j++] = vPnt[i] ;
}
// costruisco la parte superiore
for ( int i = nSize - 2, t = j + 1 ; i >= 0 ; -- i) {
while ( j >= t && CrossXY( vConvHull[j-1] - vConvHull[j-2], vPnt[i] - vConvHull[j-2]) <= 0)
-- j ;
vConvHull[j++] = vPnt[i] ;
}
vConvHull.resize( j - 1) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::GetMinAreaRectangleXY( Point3d& ptCen, Vector3d& vtAx, double& dLen, double& dHeight) const
{
// Convex Hull
PNTVECTOR vConvHull ;
if ( ! GetConvexHullXY( vConvHull))
return false ;
// all points in ConvexHull are different, minimum a segment
int nCount = int( vConvHull.size()) ;
if ( nCount < 2)
return false ;
// Starting edge nCount-1 -> 0
int l = 0, m = 0, n = 0 ;
double dMinArea = INFINITO * INFINITO ;
{
// Edge indexes
int i = 0 ;
int j = nCount - 1 ;
// Edge versor
Vector3d vtE0 = vConvHull[i] - vConvHull[j] ;
vtE0.Normalize() ;
// Edge perpendicular versor
Vector3d vtE1 = Vector3d( -vtE0.y, vtE0.x, 0) ;
// Loop through all points to get maximum extents
double dMin0 = INFINITO, dMax0 = - INFINITO, dMin1 = 0, dMax1 = - INFINITO ;
for ( int k = 0 ; k < nCount ; ++ k) {
// Project points onto axes vtE0 and vtE1 and keep track
// of minimum and maximum values along both axes
Vector3d vtDiff = vConvHull[k] - vConvHull[j] ;
double dSca = ScalarXY( vtDiff, vtE0) ;
if ( dSca < dMin0) {
dMin0 = dSca ;
l = k ;
}
if ( dSca > dMax0) {
dMax0 = dSca ;
m = k ;
}
dSca = ScalarXY( vtDiff, vtE1) ;
if ( dSca > dMax1) {
dMax1 = dSca ;
n = k ;
}
}
// Remember area, center and axes
dMinArea = ( dMax0 - dMin0) * ( dMax1 - dMin1) ;
ptCen = vConvHull[j] + 0.5 * (( dMin0 + dMax0) * vtE0 + ( dMin1 + dMax1) * vtE1) ;
vtAx = vtE0 ;
dLen = dMax0 - dMin0 ;
dHeight = dMax1 - dMin1 ;
}
// Loop through all other edges (j trails i by 1)
for ( int i = 1, j = 0 ; i < nCount ; j = i, ++ i) {
// Get current edge, normalized
Vector3d vtE0 = vConvHull[i] - vConvHull[j] ;
vtE0.Normalize() ;
// Get an axis vtE1 orthogonal to edge vtE0
Vector3d vtE1 = Vector3d( -vtE0.y, vtE0.x, 0) ;
// Find new min on vtE0
double dMin0 = ScalarXY( ( vConvHull[l] - vConvHull[j]), vtE0) ;
for ( int k = 0 ; k < nCount ; ++ k) {
int lnext = ( l + 1) % nCount ;
double dMin0next = ScalarXY( (vConvHull[lnext] - vConvHull[j]), vtE0) ;
if ( dMin0next < dMin0) {
dMin0 = dMin0next ;
l = lnext ;
}
else
break ;
}
// Find new max on vtE0
double dMax0 = ScalarXY( ( vConvHull[m] - vConvHull[j]), vtE0) ;
for ( int k = 0 ; k < nCount ; ++ k) {
int mnext = ( m + 1) % nCount ;
double dMax0next = ScalarXY( (vConvHull[mnext] - vConvHull[j]), vtE0) ;
if ( dMax0next > dMax0) {
dMax0 = dMax0next ;
m = mnext ;
}
else
break ;
}
// Find new min on vtE1
double dMin1 = 0 ;
// Find new max on vtE1
double dMax1 = ScalarXY( ( vConvHull[n] - vConvHull[j]), vtE1) ;
for ( int k = 0 ; k < nCount ; ++ k) {
int nnext = ( n + 1) % nCount ;
double dMax1next = ScalarXY( (vConvHull[nnext] - vConvHull[j]), vtE1) ;
if ( dMax1next > dMax1) {
dMax1 = dMax1next ;
n = nnext ;
}
else
break ;
}
double dArea = ( dMax0 - dMin0) * ( dMax1 - dMin1) ;
// If best so far, remember area, center, and axes
if ( dArea < dMinArea) {
dMinArea = dArea ;
ptCen = vConvHull[j] + 0.5 * (( dMin0 + dMax0) * vtE0 + ( dMin1 + dMax1) * vtE1) ;
vtAx = vtE0 ;
dLen = dMax0 - dMin0 ;
dHeight = dMax1 - dMin1 ;
}
}
// Axis aligned with max dimension
if ( dHeight > dLen) {
vtAx.Rotate( Z_AX, 0, 1) ;
swap( dLen, dHeight) ;
}
return true ;
}
+3 -3
View File
@@ -134,7 +134,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
// se curva chiusa
if ( pCompo1->IsClosed()) {
// fondo le curve allineate
pCompo1->MergeCurves( LIN_TOL_SFR, ANG_TOL_STD_DEG) ;
pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ;
// ne faccio una copia e la inverto
PtrOwner<ICurveComposite> pCompo2( GetCurveComposite( pCompo1->Clone())) ;
if ( IsNull( pCompo2) || ! pCompo2->Invert())
@@ -166,7 +166,7 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
pCompo1->ExtendEndByLen( dRadius) ;
}
// fondo le curve allineate
pCompo1->MergeCurves( LIN_TOL_SFR, ANG_TOL_STD_DEG) ;
pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ;
// ne faccio una copia e la inverto
PtrOwner<ICurveComposite> pCompo2( GetCurveComposite( pCompo1->Clone())) ;
if ( IsNull( pCompo2) || ! pCompo2->Invert())
@@ -284,7 +284,7 @@ SurfFlatRegionByContours::Prepare( void)
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ;
[]( const INDAREA& a, const INDAREA& b) { return ( fabs( a.second) > fabs( b.second)) ; }) ;
return true ;
}
+4 -4
View File
@@ -267,10 +267,10 @@ MySimpleCDSurfFrMove::TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const
// altrimenti confronto le approssimazioni con linee delle curve
// determino le due polilinee
PolyLine PL1 ;
if ( ! pCrv1->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL1))
if ( ! pCrv1->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL1))
return false ;
PolyLine PL2 ;
if ( ! pCrv2->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL2))
if ( ! pCrv2->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL2))
return false ;
// ciclo sulle linee della prima polilinea
Point3d ptStart1, ptEnd1 ;
@@ -437,10 +437,10 @@ MySimpleCDSurfFrMove::RotateCurveNoCollisionCurve( const ICurve* pCrv1, const IC
// altrimenti confronto le approssimazioni con linee delle curve
// determino le due polilinee
PolyLine PL1 ;
if ( ! pCrv1->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL1))
if ( ! pCrv1->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL1))
return false ;
PolyLine PL2 ;
if ( ! pCrv2->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL2))
if ( ! pCrv2->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL2))
return false ;
// ciclo sulle linee della prima polilinea
Point3d ptStart1, ptEnd1 ;
+1 -1
View File
@@ -365,7 +365,7 @@ CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
vArea.emplace_back( i, - dArea) ;
}
sort( vArea.begin(), vArea.end(),
[]( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ;
[]( const INDAREA& a, const INDAREA& b) { return ( fabs( a.second) > fabs( b.second)) ; }) ;
// sposto le polilinee nel vettore da restituire secondo l'ordine
vPL.clear() ;
vPL.resize( vPLtmp.size()) ;
+2 -2
View File
@@ -991,7 +991,7 @@ SurfFlatRegion::GetAuxSurf( void) const
ICurve* pLoop = GetMyLoop( i, j) ;
while ( pLoop != nullptr) {
// approssimo con linee a destra per non avere problemi in punti di contatto tra esterni e interni
if ( ! pLoop->ApproxWithLines( LIN_TOL_SFR, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, vPL[j]))
if ( ! pLoop->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, vPL[j]))
return nullptr ;
pLoop = GetMyLoop( i, ++j) ;
}
@@ -1163,7 +1163,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass
bFound = inTOnM.GetNext( dMin, dMax) ;
}
sort( ccClass.begin(), ccClass.end(),
[]( const CrvClass& a, const CrvClass& b) { return a.dParS < b.dParS ; }) ;
[]( const CrvClass& a, const CrvClass& b) { return ( a.dParS < b.dParS) ; }) ;
return true ;
}
+1 -1
View File
@@ -376,7 +376,7 @@ SurfFlatRegion::MyNewSurfFromLoops( PCRV_DEQUE& vpLoop)
}
// ordino in senso decrescente sull'area
sort( vArea.begin(), vArea.end(),
[]( const INDAREA& a, const INDAREA&b) { return a.second > b.second ; }) ;
[]( const INDAREA& a, const INDAREA& b) { return ( a.second > b.second) ; }) ;
// determino quanti sono i nuovi cicli esterni (area positiva)
int nLoopCount = int( vArea.size()) ;
+1 -1
View File
@@ -716,7 +716,7 @@ Triangulate::SortInternalLoops( const POLYLINEVECTOR& vPL, INTVECTOR& vOrd)
}
// ordino vettore in senso decrescente rispetto al massimo
sort( vMax.begin() + 1, vMax.end(),
[]( const INDMAX& a, const INDMAX&b) { return a.second > b.second ; }) ;
[]( const INDMAX& a, const INDMAX& b) { return ( a.second > b.second) ; }) ;
// copio indice nel vettore di ordine
vOrd.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i)