Files
EgtGeomKernel/ChainCurves.cpp
T
Dario Sassi e2eb379aa2 EgtGeomKernel :
- modifiche a chain
- correzioni a PointGrid3d.
2015-03-17 11:06:28 +00:00

352 lines
11 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : ChainCurves.cpp Data : 20.07.14 Versione : 1.5g3
// Contenuto : Implementazione della funzione ChainCurves, per creare una o più
// curve composite a partire dalle curve date.
//
//
// Modifiche : 20.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EgkChainCurves.h"
#include "/EgtDev/Include/EgkGeomDB.h"
#include "/EgtDev/Include/EgkCurve.h"
//----------------------------------------------------------------------------
bool
ChainCurves::Init( bool bAllowInvert, double dToler, int nCrvNbrHint)
{
m_bAllowInvert = bAllowInvert ;
m_dToler = dToler ;
m_sCrvId.clear() ;
m_sCrvId.rehash( nCrvNbrHint) ;
m_vCrvData.clear() ;
m_vCrvData.reserve( nCrvNbrHint) ;
const double DIM_CELL = 5.0 ;
m_PointGrid.Init( 2 * nCrvNbrHint, DIM_CELL) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::AddCurve( int nId, const Point3d& ptStart, const Vector3d& vtStart,
const Point3d& ptEnd, const Vector3d& vtEnd)
{
// verifico validità Id
if ( nId <= 0)
return false ;
// verifico non sia già stata aggiunta la stessa entità
if ( ! m_sCrvId.insert( nId).second)
return true ;
// inserisco i dati della curva nel vettore
m_vCrvData.emplace_back( nId, ptStart, vtStart, ptEnd, vtEnd) ;
int nV = int( m_vCrvData.size()) ;
// li inserisco nel PointGrid3d
m_PointGrid.InsertPoint( ptStart, nV) ;
m_PointGrid.InsertPoint( ptEnd, - nV) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::GetChainFromNear( const Point3d& ptStart, bool bHaltOnFork, INTVECTOR& vIds)
{
// pulisco il risultato
vIds.clear() ;
m_bIsFork = false ;
m_vFork.clear() ;
// recupero l'entità più vicina al punto di start
int nStart ;
INTVECTOR vStart ;
if ( ! m_PointGrid.FindNearest( ptStart, vStart) ||
! ChooseStart( ptStart, vStart, nStart))
return false ;
// recupero indice e verso
int nId = abs( nStart) - 1 ;
bool bEquiv = true ;
// tolgo dal grid
RemoveEntityFromGrid( nId) ;
// concateno dopo la fine dell'entità di partenza
INTVECTOR vIdsAfter ;
bool bClosed ;
if ( ! GetChainFromPoint( m_vCrvData[nId].ptEnd, m_vCrvData[nId].vtEnd,
m_vCrvData[nId].ptStart, bHaltOnFork, vIdsAfter, bClosed))
return false ;
// se non ho già chiuso l'anello, concateno prima dell'inizio dell'entità di partenza
INTVECTOR vIdsBefore ;
if ( ! bClosed) {
bool bRevClosed ;
if ( ! GetReverseChainFromPoint( m_vCrvData[nId].ptStart, m_vCrvData[nId].vtStart,
m_vCrvData[nId].ptEnd, bHaltOnFork, vIdsBefore, bRevClosed))
return false ;
// inverto l'ordine
reverse( vIdsBefore.begin(), vIdsBefore.end()) ;
}
// inserisco i risultati nel vettore complessivo
vIds.reserve( vIdsBefore.size() + 1 + vIdsAfter.size()) ;
vIds.insert( vIds.end(), vIdsBefore.begin(), vIdsBefore.end()) ;
AddToChain( nId, bEquiv, vIds) ;
vIds.insert( vIds.end(), vIdsAfter.begin(), vIdsAfter.end()) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
const Point3d& ptStop, bool bHaltOnFork,
INTVECTOR& vIds, bool& bStopped)
{
// pulisco il risultato
vIds.clear() ;
bStopped = false ;
m_bIsFork = false ;
m_vFork.clear() ;
// concateno in senso normale
Point3d ptCurr = ptStart ;
Vector3d vtCurr = vtStart ;
int nNext ;
INTVECTOR vNext ;
while ( m_PointGrid.Find( ptCurr, m_dToler, vNext) &&
ChooseNext( vtCurr, vNext, bHaltOnFork, nNext)) {
// recupero indice e verso
int nId = abs( nNext) - 1 ;
bool bEquiv = ( nNext > 0) ;
// inserisco nella concatenazione
AddToChain( nId, bEquiv, vIds) ;
// tolgo dal grid
RemoveEntityFromGrid( nId) ;
// determino il prossimo inizio
ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
// verifico se sono arrivato al punto di chiusura
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
bStopped = true ;
break ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::GetReverseChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
const Point3d& ptStop, bool bHaltOnFork,
INTVECTOR& vIds, bool& bStopped)
{
// pulisco il risultato
vIds.clear() ;
bStopped = false ;
m_bIsFork = false ;
m_vFork.clear() ;
// concateno in senso invertito
Point3d ptCurr = ptStart ;
Vector3d vtCurr = vtStart ;
int nPrev ;
INTVECTOR vPrev ;
while ( m_PointGrid.Find( ptCurr, m_dToler, vPrev) &&
ChoosePrev( vtCurr, vPrev, bHaltOnFork, nPrev)) {
// recupero indice e verso
int nId = abs( nPrev) - 1 ;
bool bEquiv = ( nPrev < 0) ;
// inserisco nella concatenazione
AddToChain( nId, bEquiv, vIds) ;
// tolgo dal grid
RemoveEntityFromGrid( nId) ;
// determino il prossimo inizio
ptCurr = bEquiv ? m_vCrvData[nId].ptStart : m_vCrvData[nId].ptEnd ;
vtCurr = bEquiv ? m_vCrvData[nId].vtStart : - m_vCrvData[nId].vtEnd ;
// verifico se sono arrivato al punto di stop
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
bStopped = true ;
break ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::AddToChain( int nId, bool bEquiv, INTVECTOR& vIds)
{
try { vIds.push_back( ( bEquiv ? m_vCrvData[nId].nId : - m_vCrvData[nId].nId)) ; }
catch (...) { return false ; }
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::RemoveEntityFromGrid( int nId)
{
bool bOk = m_PointGrid.RemovePoint( m_vCrvData[nId].ptStart, ( nId + 1)) ;
bOk = m_PointGrid.RemovePoint( m_vCrvData[nId].ptEnd, - ( nId + 1)) && bOk ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::ChooseStart( const Point3d& ptStart, const INTVECTOR& vStart, int& nStart)
{
// numero di entità candidate
int nSize = int( vStart.size()) ;
// se nessuna, errore
if ( nSize == 0)
return false ;
// se una, la ritorno
if ( nSize == 1) {
nStart = vStart[0] ;
return true ;
}
// altrimenti, cerco la migliore
int nI = - 1 ;
double dSqDistMin = INFINITO * INFINITO ;
for ( int i = 0 ; i < nSize ; ++ i) {
// recupero indice e verso
int nId = abs( vStart[i]) - 1 ;
bool bEquiv = ( vStart[i] > 0) ;
// calcolo un punto vicino all'estremo lungo la tangente
Point3d ptNear = ( bEquiv ? m_vCrvData[nId].ptStart + m_vCrvData[nId].vtStart :
m_vCrvData[nId].ptEnd - m_vCrvData[nId].vtEnd) ;
double dSqDist = SqDist( ptStart, ptNear) ;
if ( dSqDist < dSqDistMin) {
dSqDistMin = dSqDist ;
nI = i ;
}
}
// se non trovato
if ( nI < 0)
return false ;
// altrimenti assegno il migliore
nStart = vStart[nI] ;
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::ChooseNext( const Vector3d& vtCurr, const INTVECTOR& vNext, bool bHaltOnFork, int& nNext)
{
// cerco la direzione più vicina
int nI = - 1 ;
int nF = 0 ;
double dProScaMax = - 1.1 ;
for ( int i = 0 ; i < int( vNext.size()) ; ++ i) {
// recupero indice e verso
int nId = abs( vNext[i]) - 1 ;
bool bEquiv = ( vNext[i] > 0) ;
// se vietata inversione, salto se controverso
if ( ! m_bAllowInvert && ! bEquiv)
continue ;
// incremento contatore indice entità tra cui scegliere
++ nF ;
if ( bHaltOnFork)
m_vFork.push_back( vNext[i]) ;
// determino scarto angolare
Vector3d vtDir = ( bEquiv ? m_vCrvData[nId].vtStart : - m_vCrvData[nId].vtEnd) ;
double dProSca = vtCurr * vtDir ;
if ( dProSca > dProScaMax) {
dProScaMax = dProSca ;
nI = i ;
}
}
// se non trovato
if ( nI < 0) {
m_bIsFork = false ;
return false ;
}
// se richiesto arresto su biforcazione e trovata biforcazione
if ( bHaltOnFork && nF > 1) {
m_bIsFork = true ;
return false ;
}
// altrimenti assegno il migliore
nNext = vNext[nI] ;
m_bIsFork = false ;
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::ChoosePrev( const Vector3d& vtCurr, const INTVECTOR& vPrev, bool bHaltOnFork, int& nPrev)
{
// cerco la direzione più vicina
int nI = - 1 ;
int nF = 0 ;
double dProScaMax = - 1.1 ;
for ( int i = 0 ; i < int( vPrev.size()) ; ++ i) {
// recupero indice e verso
int nId = abs( vPrev[i]) - 1 ;
bool bEquiv = ( vPrev[i] < 0) ;
// se vietata inversione, salto se controverso
if ( ! m_bAllowInvert && ! bEquiv)
continue ;
// incremento contatore indice entità tra cui scegliere
++ nF ;
if ( bHaltOnFork)
m_vFork.push_back( vPrev[i]) ;
// determino scarto angolare
Vector3d vtDir = ( bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart) ;
double dProSca = vtCurr * vtDir ;
if ( dProSca > dProScaMax) {
dProScaMax = dProSca ;
nI = i ;
}
}
// se non trovato
if ( nI < 0) {
m_bIsFork = false ;
return false ;
}
// se richiesto arresto su biforcazione e trovata biforcazione
if ( bHaltOnFork && nF > 1) {
m_bIsFork = true ;
return false ;
}
// altrimenti assegno il migliore
nPrev = vPrev[nI] ;
m_bIsFork = false ;
return true ;
}
//----------------------------------------------------------------------------
bool
ChainCurves::GetForkIds( INTVECTOR& vForkIds)
{
// pulisco il risultato
vForkIds.clear() ;
// verifico di essere su una diramazione
if ( ! m_bIsFork || m_vFork.empty())
return false ;
// assegno gli Id del GeomDB
for ( int i = 0 ; i < int( m_vFork.size()) ; ++ i) {
int nId = abs( m_vFork[i]) - 1 ;
vForkIds.push_back( m_vCrvData[nId].nId) ;
}
return true ;
}