EgtGeomKernel 1.6f3 :

- ApproxWithLines per Curve con possibilità di forzare un lato
- aggiunta MergeCurves a CurveComposite
- a PolyLine aggiunte RemoveAlignedPoints e ApproxOnSide
- corretta ExtendEndByLen e ExtendStartByLen per CurveArc quando è elica.
This commit is contained in:
Dario Sassi
2015-06-21 16:56:18 +00:00
parent af49f942d3
commit 82195db8cc
22 changed files with 470 additions and 153 deletions
+188 -24
View File
@@ -13,18 +13,21 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveLine.h"
#include "DistPointLine.h"
#include "IntersLineLine.h"
#include "PolygonPlane.h"
#include "PointsPCA.h"
#include "\EgtDev\Include\EGkPolyLine.h"
#include "\EgtDev\Include\EGkPlane3d.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGnStringUtils.h"
using namespace std ;
//----------------------------------------------------------------------------
PolyLine::PolyLine( void)
{
m_nRejected = 0 ;
m_nCount = 0 ;
m_iter = m_lUPoints.end() ;
}
@@ -38,7 +41,6 @@ bool
PolyLine::Clear( void)
{
m_nRejected = 0 ;
m_nCount = 0 ;
m_lUPoints.clear() ;
m_iter = m_lUPoints.end() ;
return true ;
@@ -49,7 +51,7 @@ bool
PolyLine::AddUPoint( double dPar, const Point3d& ptP)
{
// se il punto è uguale al precedente (ignoro parametro), non lo inserisco ma ok
if ( m_nCount > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
++ m_nRejected ;
return true ;
}
@@ -61,8 +63,6 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP)
return false ;
}
++ m_nCount ;
return true ;
}
@@ -88,7 +88,6 @@ PolyLine::EraseFirstUPoint( void)
return false ;
m_lUPoints.pop_front() ;
-- m_nCount ;
return true ;
}
@@ -101,7 +100,6 @@ PolyLine::EraseLastUPoint( void)
return false ;
m_lUPoints.pop_back() ;
-- m_nCount ;
return true ;
}
@@ -214,20 +212,18 @@ bool
PolyLine::Join( PolyLine& PL, double dOffsetPar)
{
// se l'altra polilinea non contiene alcunchè, esco con ok
if ( PL.m_nCount == 0)
if ( PL.m_lUPoints.size() == 0)
return true ;
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
if ( m_nCount > 0 && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
if ( m_lUPoints.size() > 0 && ! AreSamePointApprox( m_lUPoints.back().first, PL.m_lUPoints.front().first))
return false ;
// cancello l'ultimo di questa
EraseLastUPoint() ;
// aggiungo eventuale offset all'altra
if ( fabs( dOffsetPar) > EPS_PARAM)
PL.AddOffsetToU( dOffsetPar) ;
// sposto i punti dall'altra polilinea a questa e aggiorno i contatori
// sposto i punti dall'altra polilinea a questa
m_lUPoints.splice( m_lUPoints.end(), PL.m_lUPoints) ;
m_nCount += PL.GetPointNbr() ;
PL.m_nCount = 0 ;
return true ;
}
@@ -247,11 +243,8 @@ PolyLine::Split( double dU, PolyLine& PL)
return false ;
// sposto i punti nell'altra polilinea
PL.m_lUPoints.splice( PL.m_lUPoints.end(), m_lUPoints, iter, m_lUPoints.end()) ;
PL.m_nCount = int( PL.m_lUPoints.size()) ;
m_nCount -= PL.m_nCount ;
// prepongo l'ultimo punto rimasto
PL.m_lUPoints.push_front( m_lUPoints.back()) ;
++ PL.m_nCount ;
// annullo l'iteratore corrente
m_iter = m_lUPoints.end() ;
@@ -606,8 +599,8 @@ PolyLine::GetAreaXY( double& dArea) const
//----------------------------------------------------------------------------
bool
PolyLine::GetMaxDistanceFromLine( double& dMaxDist, const Point3d& ptAx,
const Vector3d& vtAx, double dLen, bool bIsSegment) const
PolyLine::GetMaxDistanceFromLine( const Point3d& ptLine, const Vector3d& vtLine, double dLen,
double& dMaxDist, bool bIsSegment) const
{
// Verifico che la polilinea esista
if ( GetPointNbr() < 1)
@@ -616,7 +609,7 @@ PolyLine::GetMaxDistanceFromLine( double& dMaxDist, const Point3d& ptAx,
dMaxDist = 0 ;
Point3d ptP ;
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
DistPointLine dstPL( ptP, ptAx, vtAx, dLen, bIsSegment) ;
DistPointLine dstPL( ptP, ptLine, vtLine, dLen, bIsSegment) ;
double dDist ;
if ( dstPL.GetDist( dDist) && dDist > dMaxDist)
dMaxDist = dDist ;
@@ -627,7 +620,7 @@ PolyLine::GetMaxDistanceFromLine( double& dMaxDist, const Point3d& ptAx,
//----------------------------------------------------------------------------
bool
PolyLine::AdjustForMaxSegmentLen( double& dMaxLen)
PolyLine::AdjustForMaxSegmentLen( double dMaxLen)
{
PNTULIST::iterator iter = m_lUPoints.begin() ;
// se non ci sono punti, esco subito
@@ -655,7 +648,6 @@ PolyLine::AdjustForMaxSegmentLen( double& dMaxLen)
double dCoeff = double( i) / nStep ;
m_lUPoints.insert( iter, POINTU( Media( ptPprec, ptPcurr, dCoeff),
(( 1 - dCoeff) * dUprec + dCoeff * dUcurr))) ;
++ m_nCount ;
}
}
// passo al successivo
@@ -671,6 +663,178 @@ PolyLine::AdjustForMaxSegmentLen( double& dMaxLen)
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::RemoveAlignedPoints( double dToler)
{
// se non ci sono almeno 3 punti, esco subito
if ( m_lUPoints.size() < 3)
return true ;
// coefficiente deduzione tolleranza
const double COEFF_TOL = 0.7 ;
// si analizza la distanza di un punto dal segmento che unisce precente e successivo
// punto precedente
auto precP = m_lUPoints.begin() ;
// punto corrente
auto currP = next( precP) ;
// punto successivo
auto nextP = next( currP) ;
// assegno la tolleranza corrente
double dCurrToler = dToler ;
// mentre esiste un successivo
while ( nextP != m_lUPoints.end()) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist ;
// se da eliminare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dCurrToler * dCurrToler) {
// diminuisco la tolleranza corrente dell'errore attuale
dCurrToler -= COEFF_TOL * sqrt( dSqDist) ;
// elimino il punto
m_lUPoints.erase( currP) ;
// avanzo con corrente e successivo
currP = nextP ;
++ nextP ;
}
// altrimenti da tenere
else {
// ripristino la tolleranza corrente
dCurrToler = dToler ;
// 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_lUPoints.size() >= 4) {
// precP e currP sono già corretti
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
auto firstP = m_lUPoints.begin() ;
// questo è il vero successivo
nextP = next( firstP) ;
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist ;
// se da eliminare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dCurrToler * dCurrToler) {
// faccio coincidere il primo punto con il precedente
firstP->first = precP->first ;
// elimino il punto corrente
m_lUPoints.erase( currP) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::ApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler)
{
// se non ci sono almeno 3 punti, esco subito
if ( m_lUPoints.size() < 3)
return true ;
// coefficienti deduzione tolleranza
const double COEFF_TOL = 0.7 ;
// punto precedente
auto precP = m_lUPoints.begin() ;
// punto corrente
auto currP = next( precP) ;
// punto successivo
auto nextP = next( currP) ;
// assegno la tolleranza corrente
double dCurrToler = dToler ;
// mentre esiste un successivo
while ( nextP != m_lUPoints.end()) {
// --- si verifica se possibile eliminare il punto corrente rimanendo dal lato voluto e in tolleranza ---
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist = INFINITO * INFINITO ;
dPL.GetSqDist( dSqDist) ;
// se punti allineati
if ( dSqDist < EPS_SMALL * EPS_SMALL) {
// ripristino la tolleranza corrente
dCurrToler = dToler ;
// elimino il corrente
m_lUPoints.erase( currP) ;
// avanzo con corrente e successivo
currP = nextP ;
++ nextP ;
continue ;
}
// se lato sinistro e gira a sinistra o lato destro e gira a destra
double dCrossXY = ( ( currP->first - precP->first) ^ ( nextP->first - currP->first)) * vtN ;
if ( ( bLeftSide && dCrossXY > 0) || ( ! bLeftSide && dCrossXY < 0)) {
// se eliminabile
if ( dSqDist < dCurrToler * dCurrToler) {
// diminuisco la tolleranza corrente dell'errore attuale
dCurrToler -= COEFF_TOL * sqrt( dSqDist) ;
// elimino il punto corrente
m_lUPoints.erase( currP) ;
// avanzo con corrente e successivo
currP = nextP ;
++ nextP ;
continue ;
}
}
// --- si verifica se possibile elimare segmento da corrente a successivo rimanendo in tolleranza e dal lato voluto ---
// punto successivo del successivo
auto nex2P = next( nextP) ;
if ( nex2P != m_lUPoints.end()) {
double dCros2XY = ( ( nextP->first - currP->first) ^ ( nex2P->first - nextP->first)) * vtN ;
// se lato sinistro e 2 giri a destra o lato destro e 2 giri a sinistra
if ( ( bLeftSide && dCrossXY < 0 && dCros2XY < 0) ||
( ! bLeftSide && dCrossXY > 0 && dCros2XY > 0)) {
// calcolo del punto di intersezione tra i segmenti precP-currP e nextP-next2P, allungati al centro
CurveLine Line1, Line2 ;
if ( Line1.Set( precP->first, currP->first) && Line1.ExtendEndByLen( 1000) &&
Line2.Set( nextP->first, nex2P->first) && Line2.ExtendStartByLen( 1000)) {
// se la normale non coincide con l'asse Z, devo portare le linee nel riferimento OCS di questa
Frame3d frNorm ;
if ( ! vtN.IsZplus() && ! vtN.IsZminus())
frNorm.Set( ORIG, vtN) ;
Line1.ToLoc( frNorm) ;
Line2.ToLoc( frNorm) ;
IntersLineLine IntLL( Line1, Line2) ;
IntCrvCrvInfo IntInfo ;
if ( IntLL.GetIntCrvCrvInfo( IntInfo) && ! IntInfo.bOverlap) {
Point3d ptInt = 0.5 * ( IntInfo.IciA[0].ptI + IntInfo.IciB[0].ptI) ;
ptInt.ToGlob( frNorm) ;
// verifico che distanza dell'intersezione dal segmento currP-nextP sia inferiore a tolleranza corrente
DistPointLine dIL( ptInt, currP->first, nextP->first) ;
double dSqDist2 = INFINITO * INFINITO ;
dIL.GetSqDist( dSqDist2) ;
// se eliminabile
if ( dSqDist2 < dCurrToler * dCurrToler) {
// diminuisco la tolleranza corrente dell'errore attuale
dCurrToler -= COEFF_TOL * sqrt( dSqDist2) ;
// sposto il successivo sull'intersezione e ne aggiorno il parametro
nextP->first = ptInt ;
nextP->second = 0.5 * ( currP->second + nextP->second) ;
// elimino il punto corrente
m_lUPoints.erase( currP) ;
// avanzo con corrente e successivo
currP = nextP ;
nextP = nex2P ;
continue ;
}
}
}
}
}
// non è stato eliminato alcunché
// ripristino la tolleranza corrente
dCurrToler = dToler ;
// avanzo il terzetto di uno step
precP = currP ;
currP = nextP ;
++ nextP ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::Invert( bool bInvertU)
@@ -685,8 +849,8 @@ PolyLine::Invert( bool bInvertU)
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
double dUfin = m_lUPoints.front().second ;
// ciclo su tutti gli elementi
for ( PNTULIST::iterator iter = m_lUPoints.begin() ; iter != m_lUPoints.end() ; ++ iter) {
iter->second = dUfin - iter->second ;
for ( auto& UPoint : m_lUPoints) {
UPoint.second = dUfin - UPoint.second ;
}
}
return true ;