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:
+188
-24
@@ -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 ;
|
||||
|
||||
Reference in New Issue
Block a user