Files
EgtGeomKernel/PolyArc.cpp
T
Dario Sassi 07405f7de6 EgtGeomKernel 1.6b3 :
- aggiunta gestione buchi alle triangolazione di poligoni
- creazione suerfici trimesh da regioni con buchi.
2015-02-11 11:38:50 +00:00

505 lines
15 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : PolyArc.cpp Data : 14.08.14 Versione : 1.5h3
// Contenuto : Implementazione della classe PolyArc.
//
//
//
// Modifiche : 14.08.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkPolyArc.h"
#include "/EgtDev/Include/EGkFrame3d.h"
//----------------------------------------------------------------------------
PolyArc::PolyArc( void)
{
m_vtExtr = Z_AX ;
m_nRejected = 0 ;
m_nCount = 0 ;
m_iter = m_lUPointBs.end() ;
}
//----------------------------------------------------------------------------
PolyArc::~PolyArc( void)
{
}
//----------------------------------------------------------------------------
bool
PolyArc::Clear( void)
{
m_vtExtr = Z_AX ;
m_nRejected = 0 ;
m_nCount = 0 ;
m_lUPointBs.clear() ;
m_iter = m_lUPointBs.end() ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::SetExtrusion( const Vector3d& vtExtr)
{
if ( vtExtr.IsSmall())
return false ;
m_vtExtr = vtExtr ;
m_vtExtr.Normalize() ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
{
// se il punto è uguale al precedente (ignoro parametro e bulge), non lo inserisco ma ok
if ( m_nCount > 0 && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
++ m_nRejected ;
return true ;
}
try {
m_lUPointBs.emplace_back( dPar, ptP, dBulge) ;
}
catch (...) {
return false ;
}
m_nCount ++ ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Close( void)
{
// ci devono essere almeno 2 punti
if ( m_lUPointBs.size() < 2)
return false ;
// verifico non sia già chiuso
if ( AreSamePointApprox( m_lUPointBs.front().ptP, m_lUPointBs.back().ptP))
return false ;
// aggiungo un punto uguale al primo in coda
return AddUPoint( m_lUPointBs.front().dU, m_lUPointBs.front().ptP, m_lUPointBs.front().dB) ;
}
//----------------------------------------------------------------------------
bool
PolyArc::ModifyLastBulge( double dBulge)
{
// verifico esistano dei punti
if ( m_lUPointBs.empty())
return false ;
// eseguo la modifica
m_lUPointBs.back().dB = dBulge ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::EraseFirstUPoint( void)
{
if ( m_lUPointBs.empty())
return false ;
m_lUPointBs.pop_front() ;
m_nCount -- ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::EraseLastUPoint( void)
{
if ( m_lUPointBs.empty())
return false ;
m_lUPointBs.pop_back() ;
m_nCount -- ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::AddOffsetToU( double dOffset)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->dU += dOffset ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::ParamLinearTransform( double dStartU, double dEndU)
{
// ci devono essere almeno 2 punti
if ( m_lUPointBs.size() < 2)
return false ;
// recupero i vecchi estremi del parametro
double dOriStartU = m_lUPointBs.front().dU ;
double dOriEndU = m_lUPointBs.back().dU ;
// determino i coefficienti di riparametrizzazione
double dCoeff ;
if ( fabs( dEndU - dStartU) < EPS_ZERO)
dCoeff = 0 ;
else if ( fabs( dOriEndU - dOriStartU) > EPS_ZERO)
dCoeff = ( dEndU - dStartU) / ( dOriEndU - dOriStartU) ;
else
return false ;
// eseguo la riparametrizzazione
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->dU = dStartU + dCoeff * ( iter->dU - dOriStartU) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::SetElevation( double dZ)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.z = dZ ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::AddElevation( double dZ)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.z += dZ ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Translate( const Vector3d& vtMove)
{
// il vettore estrusione non subisce modifiche
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.Translate( vtMove) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
m_vtExtr.Rotate( vtAx, dCosAng, dSinAng) ;
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Scale( const Frame3d& frRef, double dCoeff)
{
m_vtExtr.Scale( frRef, dCoeff, dCoeff, dCoeff) ;
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.Scale( frRef, dCoeff, dCoeff, dCoeff) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{
m_vtExtr.Mirror( vtNorm) ;
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter) {
iter->ptP.Mirror( ptOn, vtNorm) ;
iter->dB *= - 1 ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::ToGlob( const Frame3d& frRef)
{
m_vtExtr.ToGlob( frRef) ;
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.ToGlob( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::ToLoc( const Frame3d& frRef)
{
m_vtExtr.ToLoc( frRef) ;
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.ToLoc( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
// ciclo sui punti
m_vtExtr.LocToLoc( frOri, frDest) ;
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.LocToLoc( frOri, frDest) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Join( PolyArc& PA, double dOffsetPar)
{
// se l'altro poliarco non contiene alcunchè, esco con ok
if ( PA.m_nCount == 0)
return true ;
// verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro
if ( m_nCount > 0 && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP))
return false ;
// cancello l'ultimo di questo
EraseLastUPoint() ;
// aggiungo eventuale offset all'altro
if ( fabs( dOffsetPar) > EPS_PARAM)
PA.AddOffsetToU( dOffsetPar) ;
// sposto i punti dall'altra polilinea a questa e aggiorno i contatori
m_lUPointBs.splice( m_lUPointBs.end(), PA.m_lUPointBs) ;
m_nCount += PA.GetPointNbr() ;
PA.m_nCount = 0 ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Split( double dU, PolyArc& PA)
{
// pulisco la polilinea destinazione
PA.Clear() ;
// ricerca del punto in cui dividere
UPNTBLIST::const_iterator iter ;
iter = m_lUPointBs.begin() ;
while ( iter != m_lUPointBs.end() && iter->dU < ( dU + EPS_PARAM))
++ iter ;
if ( iter == m_lUPointBs.end())
return false ;
// sposto i punti nell'altra polilinea
PA.m_lUPointBs.splice( PA.m_lUPointBs.end(), m_lUPointBs, iter, m_lUPointBs.end()) ;
PA.m_nCount = int( PA.m_lUPointBs.size()) ;
m_nCount -= PA.m_nCount ;
// prepongo l'ultimo punto rimasto
PA.m_lUPointBs.push_front( m_lUPointBs.back()) ;
++ PA.m_nCount ;
// annullo l'iteratore corrente
m_iter = m_lUPointBs.end() ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::IsClosed( void) const
{
if ( m_lUPointBs.size() < 3)
return false ;
return ( AreSamePointApprox( m_lUPointBs.front().ptP, m_lUPointBs.back().ptP)) ;
}
//----------------------------------------------------------------------------
bool
PolyArc::GetFirstUPoint( double* pdPar, Point3d* pptP, double* pdBulge, bool bNotLast) const
{
// cerco il primo punto
m_iter = m_lUPointBs.begin() ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( bNotLast && m_iter == -- ( m_lUPointBs.end()))
return false ;
// assegno i dati
if ( pdPar != nullptr)
*pdPar = m_iter->dU ;
if ( pptP != nullptr)
*pptP = m_iter->ptP ;
if ( pdBulge != nullptr)
*pdBulge = m_iter->dB ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::GetNextUPoint( double* pdPar, Point3d* pptP, double* pdBulge, bool bNotLast) const
{
// cerco il prossimo punto
if ( m_iter == m_lUPointBs.end())
return false ;
++ m_iter ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( bNotLast && m_iter == -- ( m_lUPointBs.end()))
return false ;
// assegno i dati
if ( pdPar != nullptr)
*pdPar = m_iter->dU ;
if ( pptP != nullptr)
*pptP = m_iter->ptP ;
if ( pdBulge != nullptr)
*pdBulge = m_iter->dB ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::GetFirstUArc( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin, double* pdBulge) const
{
// parametro e punto iniziali
m_iter = m_lUPointBs.begin() ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( pdIni != nullptr)
*pdIni = m_iter->dU ;
if ( pptIni != nullptr)
*pptIni = m_iter->ptP ;
// bulge dell'arco (è attaccato al punto iniziale)
if ( pdBulge != nullptr)
*pdBulge = m_iter->dB ;
// parametro e punto finali
++ m_iter ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( pdFin != nullptr)
*pdFin = m_iter->dU ;
if ( pptFin != nullptr)
*pptFin = m_iter->ptP ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::GetNextUArc( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin, double* pdBulge) const
{
// parametro e punto iniziali (è il precedente finale)
if ( m_iter == m_lUPointBs.end())
return false ;
if ( pdIni != nullptr)
*pdIni = m_iter->dU ;
if ( pptIni != nullptr)
*pptIni = m_iter->ptP ;
// bulge (è attaccato al punto iniziale)
if ( pdBulge != nullptr)
*pdBulge = m_iter->dB ;
// parametro e punto finali
++ m_iter ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( pdFin != nullptr)
*pdFin = m_iter->dU ;
if ( pptFin != nullptr)
*pptFin = m_iter->ptP ;
return true ;
}
//----------------------------------------------------------------------------
// L'eventuale piano deve essere perpendicolare al vettore estrusione
// Risultati :
// false + rank = 0 nessun punto, + rank = 1 punto allineati come estrusione, + rank = 3 percorso 3d;
// true + rank = 0 punti collassati, + rank = 2 percorso 2d.
//----------------------------------------------------------------------------
bool
PolyArc::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) const
{
// inizializzazioni
nRank = 0 ;
ptCen = ORIG ;
vtDir = m_vtExtr ;
// il primo punto fissa la proiezione di riferimento sull'asse di estrusione
double dBulge ;
Point3d ptStart ;
if ( ! GetFirstPoint( ptStart, dBulge))
return false ;
ptCen += ptStart ;
// ciclo sui punti per verificare il valore relativo della proiezione
Point3d ptP ;
while ( GetNextPoint( ptP, dBulge)) {
// componente della differenza tra i punti parallela al vettore estrusione
double dPar = ( ptP - ptStart) * m_vtExtr ;
// vettore componente della differenza perpendicolare al vettore estrusione
Vector3d vtPerp = ( ptP - ptStart) - dPar * m_vtExtr ;
// se il vettore componente perpendicolare è non nullo, punto non allineato su estrusione
if ( ! vtPerp.IsSmall()) {
if ( nRank == 0 || nRank == 1)
nRank += 2 ;
}
// se la componente parallela è non nulla, punto non nel piano
if ( fabs( dPar) > dToler) {
if ( nRank == 0 || nRank == 2)
nRank += 1 ;
}
// aggiorno la somma dei punti per calcolare il centro
ptCen += ptP ;
}
// aggiusto il centro
ptCen /= m_nCount ;
return ( nRank == 0 || nRank == 2) ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Invert( bool bInvertU)
{
// verifico non sia vuota
if ( m_lUPointBs.empty())
return true ;
// inverto la lista
m_lUPointBs.reverse() ;
// sposto il bulge all'estremo iniziale di ogni tratto (l'ultimo non conta)
for ( UPNTBLIST::iterator iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter) {
if ( next( iter) != m_lUPointBs.end())
iter->dB = next( iter)->dB ;
else
iter->dB = 0 ;
}
// se richiesto, inverto anche il parametro U
if ( bInvertU) {
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
double dUfin = m_lUPointBs.front().dU ;
// ciclo su tutti gli elementi
for ( UPNTBLIST::iterator iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter) {
iter->dU = dUfin - iter->dU ;
}
}
return true ;
}