650540e573
- semplificata e ottimizzata creazione di superficie trimesh box standard - miglioramenti sintattici vari.
677 lines
22 KiB
C++
677 lines
22 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 "DistPointLine.h"
|
|
#include "GeoConst.h"
|
|
#include "CurveArc.h"
|
|
#include "/EgtDev/Include/EGkPolyArc.h"
|
|
#include "/EgtDev/Include/EGkFrame3d.h"
|
|
#include <algorithm>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
PolyArc::PolyArc( void)
|
|
{
|
|
m_vtExtr = Z_AX ;
|
|
m_nRejected = 0 ;
|
|
m_iter = m_lUPointBs.end() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
PolyArc::~PolyArc( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::Clear( void)
|
|
{
|
|
m_vtExtr = Z_AX ;
|
|
m_nRejected = 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_lUPointBs.size() > 0 && AreSamePointApprox( ptP, m_lUPointBs.back().ptP)) {
|
|
// assegno parametro e bulge
|
|
m_lUPointBs.back().dU = dPar ;
|
|
m_lUPointBs.back().dB = dBulge ;
|
|
// incremento contatore rifiutati ed esco
|
|
++ m_nRejected ;
|
|
return true ;
|
|
}
|
|
// aggiungo il punto
|
|
try {
|
|
m_lUPointBs.emplace_back( dPar, ptP, dBulge) ;
|
|
}
|
|
catch (...) {
|
|
return false ;
|
|
}
|
|
|
|
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::ModifyLastParam( double dPar)
|
|
{
|
|
// verifico esistano dei punti
|
|
if ( m_lUPointBs.empty())
|
|
return false ;
|
|
// eseguo la modifica
|
|
m_lUPointBs.back().dU = dPar ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::EraseLastUPoint( void)
|
|
{
|
|
if ( m_lUPointBs.empty())
|
|
return false ;
|
|
|
|
m_lUPointBs.pop_back() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::AddOffsetToU( double dOffset)
|
|
{
|
|
for ( auto 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 ( abs( dEndU - dStartU) < EPS_PARAM)
|
|
dCoeff = 0 ;
|
|
else if ( abs( dOriEndU - dOriStartU) > EPS_PARAM)
|
|
dCoeff = ( dEndU - dStartU) / ( dOriEndU - dOriStartU) ;
|
|
else
|
|
return false ;
|
|
// eseguo la riparametrizzazione
|
|
for ( auto iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
|
|
iter->dU = dStartU + dCoeff * ( iter->dU - dOriStartU) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::SetElevation( double dZ)
|
|
{
|
|
for ( auto iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
|
|
iter->ptP.z = dZ ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::AddElevation( double dZ)
|
|
{
|
|
for ( auto 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
|
|
for ( auto 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) ;
|
|
for ( auto 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) ;
|
|
for ( auto 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) ;
|
|
for ( auto 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) ;
|
|
for ( auto 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) ;
|
|
for ( auto 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) ;
|
|
for ( auto 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_lUPointBs.size() == 0)
|
|
return true ;
|
|
// verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro
|
|
if ( m_lUPointBs.size() > 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 ( abs( 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) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::Split( double dU, PolyArc& PA)
|
|
{
|
|
// pulisco la polilinea destinazione
|
|
PA.Clear() ;
|
|
// ricerca del punto in cui dividere
|
|
auto 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()) ;
|
|
// prepongo l'ultimo punto rimasto
|
|
PA.m_lUPointBs.push_front( m_lUPointBs.back()) ;
|
|
// 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::IsRectangleXY( BBox3d& b3Rect) const
|
|
{
|
|
b3Rect.Reset() ;
|
|
// Deve essere chiusa
|
|
if ( ! IsClosed())
|
|
return false ;
|
|
// Verifico presenza di archi e linee oblique e calcolo il box
|
|
Point3d ptIni, ptFin ; double dBulge ;
|
|
bool bNext = GetFirstArc( ptIni, ptFin, dBulge) ;
|
|
while ( bNext) {
|
|
// non sono ammessi archi
|
|
double dLeftDeflection = - dBulge * DistXY( ptIni, ptFin) / 2 ;
|
|
if ( abs( dLeftDeflection) > 10 * EPS_SMALL)
|
|
return false ;
|
|
// non sono ammesse linee oblique
|
|
if ( abs( ptFin.y - ptIni.y) > 10 * EPS_SMALL && abs( ptFin.x - ptIni.x) > 10 * EPS_SMALL)
|
|
return false ;
|
|
// la Z deve essere costante
|
|
if ( abs( ptFin.z - ptIni.z) > 10 * EPS_SMALL)
|
|
return false ;
|
|
// aggiorno il box
|
|
b3Rect.Add( ptIni) ;
|
|
b3Rect.Add( ptFin) ;
|
|
// passo alla curva successiva
|
|
bNext = GetNextArc( ptIni, ptFin, dBulge) ;
|
|
}
|
|
// Verifico che tutte le linee stiano sulla frontiera del box
|
|
bNext = GetFirstArc( ptIni, ptFin, dBulge) ;
|
|
while ( bNext) {
|
|
// verifico che l'inizio stia sulla frontiera del rettangolo
|
|
if ( abs( ptIni.x - b3Rect.GetMin().x) > 10 * EPS_SMALL && abs( ptIni.x - b3Rect.GetMax().x) > 10 * EPS_SMALL &&
|
|
abs( ptIni.y - b3Rect.GetMin().y) > 10 * EPS_SMALL && abs( ptIni.y - b3Rect.GetMax().y) > 10 * EPS_SMALL)
|
|
return false ;
|
|
// verifico che la fine stia sulla frontiera del rettangolo
|
|
if ( abs( ptFin.x - b3Rect.GetMin().x) > 10 * EPS_SMALL && abs( ptFin.x - b3Rect.GetMax().x) > 10 * EPS_SMALL &&
|
|
abs( ptFin.y - b3Rect.GetMin().y) > 10 * EPS_SMALL && abs( ptFin.y - b3Rect.GetMax().y) > 10 * EPS_SMALL)
|
|
return false ;
|
|
// passo alla curva successiva
|
|
bNext = GetNextArc( ptIni, ptFin, dBulge) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::IsCircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const
|
|
{
|
|
// Deve essere chiusa
|
|
if ( ! IsClosed())
|
|
return false ;
|
|
// Devono essere presenti solo archi con lo stesso centro, raggio e direzione
|
|
bool bFirst = true ;
|
|
Point3d ptIni, ptFin ; double dBulge ;
|
|
bool bNext = GetFirstArc( ptIni, ptFin, dBulge) ;
|
|
while ( bNext) {
|
|
// non ammessi segmenti di retta
|
|
double dLeftDeflection = - dBulge * DistXY( ptIni, ptFin) / 2 ;
|
|
if ( abs( dLeftDeflection) < 10 * EPS_SMALL)
|
|
return false ;
|
|
// calcolo l'arco
|
|
CurveArc cArc ;
|
|
if ( ! cArc.Set2PNB( ptIni, ptFin, m_vtExtr, dBulge))
|
|
return false ;
|
|
if ( bFirst) {
|
|
bFirst = false ;
|
|
ptCen = cArc.GetCenter() ;
|
|
vtN = cArc.GetNormVersor() ;
|
|
dRad = cArc.GetRadius() ;
|
|
bCCW = ( cArc.GetAngCenter() > 0) ;
|
|
}
|
|
else {
|
|
if ( ! AreSamePointEpsilon( ptCen, cArc.GetCenter(), dLinTol))
|
|
return false ;
|
|
if ( ! AreSameVectorApprox( vtN, cArc.GetNormVersor()))
|
|
return false ;
|
|
if ( abs( dRad - cArc.GetRadius()) > dLinTol)
|
|
return false ;
|
|
if ( bCCW != ( cArc.GetAngCenter() > 0))
|
|
return false ;
|
|
}
|
|
// passo alla curva successiva
|
|
bNext = GetNextArc( ptIni, ptFin, dBulge) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 ( abs( dPar) > dToler) {
|
|
if ( nRank == 0 || nRank == 2)
|
|
nRank += 1 ;
|
|
}
|
|
// aggiorno la somma dei punti per calcolare il centro
|
|
ptCen += ptP ;
|
|
}
|
|
// aggiusto il centro
|
|
ptCen /= double( m_lUPointBs.size()) ;
|
|
|
|
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) e lo inverto
|
|
for ( auto 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 ( auto iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter) {
|
|
iter->dU = dUfin - iter->dU ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
PointsInTolerance( const PNTVECTOR& vRPT, const Point3d& ptP1, const Point3d& ptP2, double dSqTol)
|
|
{
|
|
for ( const auto& ptQ : vRPT) {
|
|
double dSqDist ;
|
|
if ( ! DistPointLine( ptQ, ptP1, ptP2).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
PolyArc::RemoveAlignedPoints( double dToler)
|
|
{
|
|
// se non ci sono almeno 3 punti, esco subito
|
|
if ( m_lUPointBs.size() < 3)
|
|
return true ;
|
|
// controllo minimo valore di tolleranza
|
|
dToler = max( dToler, LIN_TOL_MIN) ;
|
|
double dSqTol = dToler * dToler ;
|
|
// si analizza la distanza di un punto dal segmento che unisce precedente e successivo
|
|
// punto precedente
|
|
auto precP = m_lUPointBs.begin() ;
|
|
// punto corrente
|
|
auto currP = next( precP) ;
|
|
// punto successivo
|
|
auto nextP = next( currP) ;
|
|
// lista dei punti appena rimossi
|
|
PNTVECTOR vRPT ; vRPT.reserve( 20) ;
|
|
// mentre esiste un successivo
|
|
while ( nextP != m_lUPointBs.end()) {
|
|
double dSqDist = 2 * dSqTol ;
|
|
// se precedente e corrente non hanno bulge (non sono archi i due tratti)
|
|
if ( abs( precP->dB) < EPS_SMALL && abs( currP->dB) < EPS_SMALL) {
|
|
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
|
DistPointLine( currP->ptP, precP->ptP, nextP->ptP).GetSqDist( dSqDist) ;
|
|
}
|
|
// se da eliminare e gli altri eliminati stanno nella tolleranza
|
|
if ( dSqDist < dSqTol && PointsInTolerance( vRPT, precP->ptP, nextP->ptP, dSqTol)) {
|
|
// aggiungo il punto nella lista dei rimossi
|
|
vRPT.emplace_back( currP->ptP) ;
|
|
// elimino il punto
|
|
m_lUPointBs.erase( currP) ;
|
|
// avanzo con corrente e successivo
|
|
currP = nextP ;
|
|
++ nextP ;
|
|
}
|
|
// altrimenti da tenere
|
|
else {
|
|
// cancello la lista dei rimossi
|
|
vRPT.clear() ;
|
|
// avanzo il terzetto di uno step
|
|
precP = currP ;
|
|
currP = nextP ;
|
|
++ nextP ;
|
|
}
|
|
}
|
|
// se curva chiusa con almeno 4 punti, devo analizzare il terzetto attorno alla chiusura
|
|
if ( IsClosed() && m_lUPointBs.size() >= 4) {
|
|
// precP e currP sono già corretti
|
|
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
|
|
auto firstP = m_lUPointBs.begin() ;
|
|
// questo è il vero successivo
|
|
nextP = next( firstP) ;
|
|
double dSqDist = 2 * dSqTol ;
|
|
// se precedente e corrente non hanno bulge (non sono archi i due tratti)
|
|
if ( abs( precP->dB) < EPS_SMALL && abs( firstP->dB) < EPS_SMALL) {
|
|
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
|
DistPointLine( currP->ptP, precP->ptP, nextP->ptP).GetSqDist( dSqDist) ;
|
|
}
|
|
// se da eliminare
|
|
if ( dSqDist < dSqTol && PointsInTolerance( vRPT, precP->ptP, nextP->ptP, dSqTol)) {
|
|
// faccio coincidere il primo punto con il precedente
|
|
firstP->ptP = precP->ptP ;
|
|
// elimino il punto corrente
|
|
m_lUPointBs.erase( currP) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|