Files
EgtGeomKernel/ProjectCurveSurf.cpp
Dario Sassi 6942f5fc23 EgtGeomKernel :
- nella proiezione di curve su superfici aggiunto paramtetro bFromVsTo.
2026-04-15 08:54:32 +02:00

1104 lines
42 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2023-2026
//----------------------------------------------------------------------------
// File : ProjectCurveSurfTm.cpp Data : 03.01.26 Versione : 3.1a1
// Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh.
//
//
//
// Modifiche : 31.08.23 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkProjectCurveSurf.h"
using namespace std ;
//----------------------------------------------------------------------------
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
const double COS_ANG_LIM = 0.0175 ;
// Angolo massimo tra normali per effettuare bisezione su spigolo
const double COS_ANG_MAX_CORNER = 0.8660 ;
// Tipologia di punto
const int P5AX_TO_DELETE = -1 ; // da cancellare
const int P5AX_OUT = 0 ; // aggiunto prima di inizio o dopo fine
const int P5AX_STD = 1 ; // standard
const int P5AX_CVEX = 2 ; // su angolo convesso
const int P5AX_CONC = 3 ; // in angolo concavo
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
//----------------------------------------------------------------------------
static double
GetSurfBezierTol( double dLinTol)
{
return max( dLinTol / 10, EPS_SMALL) ;
}
//----------------------------------------------------------------------------
static bool
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
{
for ( int i = nPrec + 1 ; i < nCurr ; ++ i) {
double dSqDist ;
if ( ! DistPointLine( vPt5ax[i].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP).GetSqDist( dSqDist) || dSqDist > dSqTol)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
{
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
// precedente
int j = i - 1 ;
// se normali tra corrente e precedente oltre limite e punti abbastanza lontani
if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER &&
SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) {
// intersezione tra le due facce
Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ;
Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ;
Point3d ptEdge ; Vector3d vtEdge ;
if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) {
Plane3d plPlane3 ; plPlane3.Set(vPt5ax[i].ptP, (vPt5ax[i].ptP - vPt5ax[j].ptP) ^ ( vPt5ax[i].vtDir1 + vPt5ax[j].vtDir1)) ;
Point3d ptInt ;
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
// verifico se spigolo convesso o concavo
bool bConvex ;
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
else
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
// se convesso, metto due punti con direzione appena prima e appena dopo
if ( bConvex) {
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
if ( dLen1 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
Pt5ax.vtDirV = vPt5ax[j].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
else
vPt5ax[j].nFlag = P5AX_CVEX ;
if ( dLen2 > 2 * EPS_SMALL) {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
Pt5ax.vtDirV = vPt5ax[i].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
else
vPt5ax[i].nFlag = P5AX_CVEX ;
}
// altrimenti concavo, aggiungo un solo punto con la direzione media
else {
Point5ax Pt5ax ;
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ;
Pt5ax.vtDirU = Media( vPt5ax[i].vtDirU, vPt5ax[j].vtDirU) ; Pt5ax.vtDirU.Normalize() ;
Pt5ax.vtDirV = Media( vPt5ax[i].vtDirV, vPt5ax[j].vtDirV) ; Pt5ax.vtDirV.Normalize() ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
++ i ;
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
static bool
RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir)
{
// Parametri di riferimento
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
double dSqTol = dLinTol * dLinTol ;
const double LENREF = 200 ;
double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ;
// Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo
int nInd = 0 ;
while ( nInd < ssize( vPt5ax)) {
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
// analizzo i punti appena precedenti
int nIpv = nInd - 1 ;
while ( nIpv >= 0) {
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nIpv].ptP) ;
if ( dSqLen < dSqMaxLen)
vPt5ax[nIpv].nFlag = P5AX_TO_DELETE ;
else {
vPt5ax[nIpv].nFlag = P5AX_BEFORE_CONC ;
break ;
}
-- nIpv ;
}
// analizzo i punti appena successivi
int nInx = nInd + 1 ;
while ( nInx < ssize( vPt5ax)) {
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
if ( dSqLen < dSqMaxLen)
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
else {
vPt5ax[nInx].nFlag = P5AX_AFTER_CONC ;
break ;
}
++ nInx ;
}
}
++ nInd ;
}
// Rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
int nCnt = 0 ;
int nPrec = 0 ;
int nCurr = 1 ;
int nNext = 2 ;
while ( nNext < ssize( vPt5ax)) {
bool bRemove = false ;
// lunghezza del segmento che unisce gli adiacenti
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
// se rimovibile (Flag standard) e lunghezza inferiore al massimo, passo agli altri controlli
if ( vPt5ax[nCurr].nFlag == P5AX_STD && dSqLen <= dSqMaxLen) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( vPt5ax[nCurr].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
double dSqDist ;
// se distanza inferiore a tolleranza lineare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vPt5ax, nPrec, nCurr, nNext, dSqTol)) {
// verifico se errore angolare inferiore a limite
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
if ( bTestDir) {
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir1, vPt5ax[nNext].vtDir1, dPar) ;
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir1 > dCosAngLim)
bRemove = true ;
}
else {
Vector3d vtNew = Media( vPt5ax[nPrec].vtDir2, vPt5ax[nNext].vtDir2, dPar) ;
if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir2 > dCosAngLim)
bRemove = true ;
}
}
}
// se da eliminare
if ( bRemove) {
// dichiaro da eliminare il punto
vPt5ax[nCurr].nFlag = P5AX_TO_DELETE ;
// avanzo con corrente e successivo
nCurr = nNext ;
++ nNext ;
}
// altrimenti da tenere
else {
// avanzo il terzetto di uno step
nPrec = nCurr ;
nCurr = nNext ;
++ nNext ;
// incremento contatore dei punti conservati
++ nCnt ;
}
}
// Copio i punti da conservare in un vettore temporaneo
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( nCnt) ;
for ( const auto& Pt5ax : vPt5ax) {
if ( Pt5ax.nFlag != P5AX_TO_DELETE)
vMyPt5ax.emplace_back( Pt5ax) ;
}
// scambio i due vettori
vPt5ax.swap( vMyPt5ax) ;
return true ;
}
//----------------------------------------------------------------------------
static const SurfTriMesh*
MyGetAuxSurf( const ISurf* pSrf)
{
if ( pSrf == nullptr)
return nullptr ;
switch ( pSrf->GetType()) {
case SRF_TRIMESH :
return GetBasicSurfTriMesh( pSrf) ;
case SRF_FLATRGN :
return GetBasicSurfFlatRegion( pSrf)->GetAuxSurf() ;
case SRF_BEZIER :
return GetBasicSurfBezier( pSrf)->GetAuxSurf() ;
default :
return nullptr ;
}
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar, Point5ax& Pt5ax)
{
// punto sulle superfici a minima distanza
int nSurfMin = -1 ;
int nTriaMin = -1 ;
double dUMin = -1, dVMin = -1 ;
Point3d ptMin ;
double dMinDist = NAN ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
// punto sulla superficie a minima distanza
int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetMinDistTriaIndex ( nTriaMin) ;
dMinDist = dDist ;
}
}
else if ( nSrfType == SRF_BEZIER) {
DistPointSurfBz dPS( ptP, *GetBasicSurfBezier( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetParamsAtMinDistPoint( dUMin, dVMin) ;
dMinDist = dDist ;
}
}
}
// se trovato
if ( nSurfMin >= 0) {
// assegno il punto
Point3d ptInt = ptMin ;
// calcolo gli altri dati
int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
// recupero superficie trimesh
const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! pSurfTm->GetTriangle( nTriaMin, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
else if ( nSrfType == SRF_BEZIER) {
Point3d ptSB ;
Vector3d vtN, vtDerU, vtDerV ;
if ( ! GetBasicSurfBezier( vpSurf[nSurfMin])->GetPointNrmD1D2( dUMin, dVMin, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS,
ptSB, vtN, &vtDerU, &vtDerV))
return false ;
vtDerU.Normalize() ;
vtDerV.Normalize() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = vtDerU ;
Pt5ax.vtDirV = vtDerV ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
// ritorno con successo
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
// --- vettore di oggetti intersezione massiva rette parallele SurfTM --------
typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
double dPar, bool bFromVsTo, Point5ax& Pt5ax)
{
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
Point3d ptL = GetToLoc( ptP, frRefLine) ;
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
// se dalla direzione
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso la direzione
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
}
// se trovata
if ( nInd >= 0) {
// calcolo il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptInt, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = frRefLine.VersZ() ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Oggetti per calcolo massivo intersezioni tra linee di proiezione e superfici
Frame3d frRefLine ;
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) {
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
if ( pIntPLSTM == nullptr) {
for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j)
delete vpIntPLSTM[j] ;
return false ;
}
vpIntPLSTM.emplace_back( pIntPLSTM) ;
}
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// Libero oggetti per calcolo massivo
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i)
delete vpIntPLSTM[i] ;
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, bool bFromVsTo,
Point5ax& Pt5ax)
{
// punto di riferimento
Point3d ptMin = gpRef.GetPoint() ;
// intersezione della retta di minima distanza con le superfici
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
// conservo l'intersezione più alta
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se dal punto
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso il punto
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
}
// se trovata
if ( nInd >= 0) {
// calcolo il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptInt, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, bool bFromVsTo,
Point5ax& Pt5ax)
{
// punto a minima distanza
DistPointCurve dPC( ptP, crRef) ;
Point3d ptMin ;
int nFlag ;
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
// intersezione della retta di minima distanza con le superfici
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
// conservo l'intersezione più alta
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se dalla curva
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso la curva
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
}
// se trovata
if ( nInd >= 0) {
// assegno il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptInt, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = ( bFromVsTo ? vtLine : -vtLine) ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
}
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// Sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// Controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// Approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, bool bFromVsTo,
Point5ax& Pt5ax)
{
// punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, stmRef) ;
Point3d ptMin ;
int nTriaMin ;
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
// recupero direzione della retta di minima distanza, altrimenti normale alla superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL)
vtLine /= dLineLen ;
else {
// calcolo la normale della superficie guida
Triangle3dEx trGuide ;
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
return false ;
if ( ! CalcNormal( ptMin, trGuide, vtLine))
vtLine = trGuide.GetN() ;
dLineLen = 100 ;
}
// intersezione della retta con le superfici (conservo l'intersezione più alta)
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// se dalla superficie
if ( bFromVsTo) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
if ( nI >= 0) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
if ( dU > dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
// altrimenti verso la superficie
else {
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
int nI = 0 ;
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
++nI ;
// se trovata
if ( nI < ssize( vIntRes)) {
if ( nInd < 0) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
else {
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
if ( dU < dUref) {
IntRes = vIntRes[nI] ;
nInd = i ;
}
}
}
}
}
}
// se trovata
if ( nInd >= 0) {
// calcolo il punto
Point3d ptInt ;
if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE)
ptInt = IntRes.ptI2 ;
else
ptInt = IntRes.ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN))
vtN = trTria.GetN() ;
// calcolo la normale della superficie guida
Triangle3dEx trGuide ;
if ( ! stmRef.GetTriangle( nTriaMin, trGuide))
return false ;
Vector3d vtN2 ;
if ( ! CalcNormal( ptMin, trGuide, vtN2))
vtN2 = trGuide.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
return true ;
}
}
return false ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// sistemazioni per tipo di superficie di riferimento
const SurfTriMesh* pRefTm = nullptr ;
switch ( sfRef.GetType()) {
case SRF_TRIMESH :
pRefTm = GetBasicSurfTriMesh( &sfRef) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pRefTm = GetBasicSurfBezier( &sfRef)->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pRefTm = GetBasicSurfFlatRegion( &sfRef)->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pRefTm == nullptr)
return false ;
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
! PL.RemoveAlignedPoints( dLinTol, false) )
return false ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Pulisco e riservo spazio nel vettore dei punti risultanti
vPt5ax.clear() ;
vPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, bFromVsTo, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges)
AddPointsOnCorners( vPt5ax) ;
// rimozione punti in eccesso rispetto alle tolleranze
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
return true ;
}