EgtGeomKernel :

- aggiunta funzione di proiezione a minima distanza di curva su superfcie
- migliorato LockAddErase per atomic_flag.
This commit is contained in:
Dario Sassi
2025-12-09 08:14:56 +01:00
parent 17fe5f0c9c
commit 11dd35af44
2 changed files with 156 additions and 23 deletions
+154 -22
View File
@@ -70,7 +70,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
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 < int( vPt5ax.size())) {
while ( nInd < ssize( vPt5ax)) {
if ( vPt5ax[nInd].nFlag == P5AX_CONC) {
// analizzo i punti appena precedenti
int nIpv = nInd - 1 ;
@@ -86,7 +86,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
}
// analizzo i punti appena successivi
int nInx = nInd + 1 ;
while ( nInx < int( vPt5ax.size())) {
while ( nInx < ssize( vPt5ax)) {
double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ;
if ( dSqLen < dSqMaxLen)
vPt5ax[nInx].nFlag = P5AX_TO_DELETE ;
@@ -104,7 +104,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
int nPrec = 0 ;
int nCurr = 1 ;
int nNext = 2 ;
while ( nNext < int( vPt5ax.size())) {
while ( nNext < ssize( vPt5ax)) {
bool bRemove = false ;
// lunghezza del segmento che unisce gli adiacenti
double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ;
@@ -161,6 +161,138 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
return true ;
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax)
{
// punto sulle supefici a minima distanza
int nSurfMin = -1 ;
int nTriaMin ;
Point3d ptMin ;
double dMinDist ;
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
// punto sulla superficie a minima distanza
DistPointSurfTm dPS( ptP, *vpStm[i]) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetMinDistTriaIndex ( nTriaMin) ;
dMinDist = dDist ;
}
}
// se trovato
if ( nSurfMin >= 0) {
// assegno il punto
Point3d ptInt = ptMin ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nSurfMin]->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.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)
{
// 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 metà della tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
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, vpSurfTm, 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) {
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) {
// punto medio
Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ;
double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptMid, vpSurfTm, dMid, Pt5ax)) {
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
-- i ;
}
}
}
}
// 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 ;
@@ -173,11 +305,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
Point3d ptL = GetToLoc( ptP, frRefLine) ;
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = int( vIntRes.size()) - 1 ;
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
@@ -231,7 +363,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -270,10 +402,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ;
for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) {
IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ;
if ( pIntPLSTM == nullptr) {
for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j)
for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j)
delete vpIntPLSTM[j] ;
return false ;
}
@@ -298,12 +430,12 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
}
// Libero oggetti per calcolo massivo
for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i)
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i)
delete vpIntPLSTM[i] ;
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
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
@@ -385,11 +517,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
// conservo l'intersezione più alta
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = int( vIntRes.size()) - 1 ;
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
@@ -444,7 +576,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -498,7 +630,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
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
@@ -540,11 +672,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
// conservo l'intersezione più alta
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = int( vIntRes.size()) - 1 ;
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
@@ -600,7 +732,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
{
// Sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -654,7 +786,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
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
@@ -748,11 +880,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
// intersezione della retta con le superfici (conservo l'intersezione più alta)
int nInd = -1 ;
IntLinStmInfo IntRes ;
for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
int nI = int( vIntRes.size()) - 1 ;
int nI = ssize( vIntRes) - 1 ;
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
--nI ;
// se trovata
@@ -814,7 +946,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) {
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
@@ -889,7 +1021,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
// se richiesto, inserimento punti intermedi in presenza di spigoli
if ( bSharpEdges) {
for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) {
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