From b65800843ab185291716ef09bacd2f445467b1fb Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 23 Apr 2025 12:18:16 +0200 Subject: [PATCH] =?UTF-8?q?EgtGeomKernel=20:=20-=20proiezione=20curve=20su?= =?UTF-8?q?=20superficie=20ora=20accetta=20pi=C3=B9=20superfici.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProjectCurveSurf.cpp | 490 ++++++++++++++++++++++++++----------------- SurfTriMesh.h | 7 + 2 files changed, 306 insertions(+), 191 deletions(-) diff --git a/ProjectCurveSurf.cpp b/ProjectCurveSurf.cpp index d37054d..9944cdd 100644 --- a/ProjectCurveSurf.cpp +++ b/ProjectCurveSurf.cpp @@ -29,8 +29,6 @@ using namespace std ; //---------------------------------------------------------------------------- // Angolo limite tra normale al triangolo e direzione di proiezione 89° const double COS_ANG_LIM = 0.0175 ; -// Massimo numero di triangoli per raffinare ricerca su spigoli -const int MAX_FACET_FOR_CORNER = 1000 ; // Angolo massimo tra normali per effettuare bisezione su spigolo const double COS_ANG_MAX_CORNER = 0.8660 ; // Tipologia di punto @@ -156,30 +154,52 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, return true ; } +typedef std::vector INTPARLINESTMPVECTOR ; // vettore di oggetti intersezione massiva rette parallele SurfTM + //---------------------------------------------------------------------------- static bool -ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3d& frRefLine, const IntersParLinesSurfTm& intPLSTM, +ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM, double dPar, Point5ax& Pt5ax) { - // intersezione retta di proiezione con superficie + // intersezione retta di proiezione con superfici (conservo l'intersezione più alta) Point3d ptL = GetToLoc( ptP, frRefLine) ; - ILSIVECTOR vIntRes ; - intPLSTM.GetInters( ptL, 1, vIntRes, false) ; - // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; - while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) - --nI ; + int nInd = -1 ; + IntLinStmInfo IntRes ; + for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ 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 ; + 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 ; + } + } + } + } + } // se trovata - if ( nI >= 0) { + if ( nInd >= 0) { // calcolo il punto Point3d ptInt ; - if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) - ptInt = vIntRes[nI].ptI2 ; + if ( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) + ptInt = IntRes.ptI2 ; else - ptInt = vIntRes[nI].ptI ; + ptInt = IntRes.ptI ; // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) Triangle3dEx trTria ; - if ( ! stmSurf.GetTriangle( vIntRes[nI].nT, trTria)) + if ( ! vpStm[nInd]->GetTriangle( IntRes.nT, trTria)) return false ; Vector3d vtN ; if ( ! CalcNormal( ptInt, trTria, vtN)) @@ -198,26 +218,30 @@ ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3 //---------------------------------------------------------------------------- bool -ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vtDir, +ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // sistemazioni per tipo di superficie - const SurfTriMesh* pSurfTm = nullptr ; - switch ( sfSurf.GetType()) { - case SRF_TRIMESH : - pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; - break ; - case SRF_BEZIER : - pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; - break ; - case SRF_FLATRGN : - pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; - break ; - default : - break ; + CISRFTMPVECTOR vpSurfTm ; + for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + const SurfTriMesh* pSurfTm = nullptr ; + switch ( vpSurf[i]->GetType()) { + case SRF_TRIMESH : + pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ; + break ; + case SRF_BEZIER : + pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ; + break ; + case SRF_FLATRGN : + pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ; + break ; + default : + break ; + } + if ( pSurfTm == nullptr) + return false ; + vpSurfTm.emplace_back( pSurfTm) ; } - if ( pSurfTm == nullptr) - return false ; // controllo le tolleranze dLinTol = max( dLinTol, LIN_TOL_MIN) ; @@ -230,11 +254,20 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) return false ; - // Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie + // Oggetti per calcolo massivo intersezioni tra linee di proiezione e superfici Frame3d frRefLine ; if ( ! frRefLine.Set( ORIG, vtDir)) return false ; - IntersParLinesSurfTm intPLSTM( frRefLine, *pSurfTm) ; + INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ; + for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) { + IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ; + if ( pIntPLSTM == nullptr) { + for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j) + delete vpIntPLSTM[j] ; + return false ; + } + vpIntPLSTM.emplace_back( pIntPLSTM) ; + } // Pulisco e riservo spazio nel vettore dei punti risultanti vPt5ax.clear() ; @@ -247,12 +280,16 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt while ( bFound) { // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptP, *pSurfTm, frRefLine, intPLSTM, dPar, Pt5ax)) + if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax)) vPt5ax.emplace_back( Pt5ax) ; // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; } + // Libero oggetti per calcolo massivo + for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) + delete vpIntPLSTM[i] ; + // se richiesto, inserimento punti intermedi in presenza di spigoli if ( bSharpEdges) { for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { @@ -325,72 +362,96 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt //---------------------------------------------------------------------------- static bool -ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax) +ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax) { // punto di riferimento Point3d ptMin = gpRef.GetPoint() ; - // intersezione della retta di minima distanza con la superficie + // intersezione della retta di minima distanza con le superfici Vector3d vtLine = ptP - ptMin ; double dLineLen = vtLine.Len() ; if ( dLineLen > EPS_SMALL) { vtLine /= dLineLen ; - ILSIVECTOR vIntRes ; - if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) { - // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; - while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) - --nI ; - // se trovata - if ( nI >= 0) { - // calcolo il punto - Point3d ptInt ; - if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) - ptInt = vIntRes[nI].ptI2 ; - else - ptInt = vIntRes[nI].ptI ; - // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) - Triangle3dEx trTria ; - if ( ! stmSurf.GetTriangle( vIntRes[nI].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.dPar = dPar ; - Pt5ax.nFlag = P5AX_STD ; - // ritorno con successo - return true ; + // conservo l'intersezione più alta + int nInd = -1 ; + IntLinStmInfo IntRes ; + for ( int i = 0 ; i < int( vpStm.size()) ; ++ 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 ; + 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 ; + } + } + } } } + // 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.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + // ritorno con successo + return true ; + } } return false ; } //---------------------------------------------------------------------------- bool -ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& gpRef, +ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef, double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // sistemazioni per tipo di superficie - const SurfTriMesh* pSurfTm = nullptr ; - switch ( sfSurf.GetType()) { - case SRF_TRIMESH : - pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; - break ; - case SRF_BEZIER : - pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; - break ; - case SRF_FLATRGN : - pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; - break ; - default : - break ; + CISRFTMPVECTOR vpSurfTm ; + for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + const SurfTriMesh* pSurfTm = nullptr ; + switch ( vpSurf[i]->GetType()) { + case SRF_TRIMESH : + pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ; + break ; + case SRF_BEZIER : + pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ; + break ; + case SRF_FLATRGN : + pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ; + break ; + default : + break ; + } + if ( pSurfTm == nullptr) + return false ; + vpSurfTm.emplace_back( pSurfTm) ; } - if ( pSurfTm == nullptr) - return false ; // controllo le tolleranze dLinTol = max( dLinTol, LIN_TOL_MIN) ; @@ -415,14 +476,14 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& while ( bFound) { // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptP, *pSurfTm, gpRef, dPar, Pt5ax)) + if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax)) vPt5ax.emplace_back( Pt5ax) ; // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; } - // se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli - if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) { + // se richiesto, inserimento punti intermedi in presenza di spigoli + if ( bSharpEdges) { for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { // precedente int j = i - 1 ; @@ -434,7 +495,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptMid, *pSurfTm, gpRef, dMid, Pt5ax)) { + if ( ProjectPointOnSurf( ptMid, vpSurfTm, gpRef, dMid, Pt5ax)) { vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; -- i ; } @@ -450,49 +511,69 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& //---------------------------------------------------------------------------- static bool -ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const ICurve& crRef, double dPar, Point5ax& Pt5ax) +ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, 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 la superficie + // intersezione della retta di minima distanza con le superfici Vector3d vtLine = ptP - ptMin ; double dLineLen = vtLine.Len() ; if ( dLineLen > EPS_SMALL) { vtLine /= dLineLen ; - ILSIVECTOR vIntRes ; - if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) { - // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; - while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) - --nI ; - // se trovata - if ( nI >= 0) { - // calcolo il punto - Point3d ptInt ; - if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) - ptInt = vIntRes[nI].ptI2 ; - else - ptInt = vIntRes[nI].ptI ; - // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) - Triangle3dEx trTria ; - if ( ! stmSurf.GetTriangle( vIntRes[nI].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.dPar = dPar ; - Pt5ax.nFlag = P5AX_STD ; - // ritorno con successo - return true ; + // conservo l'intersezione più alta + int nInd = -1 ; + IntLinStmInfo IntRes ; + for ( int i = 0 ; i < int( vpStm.size()) ; ++ 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 ; + 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 ; + } + } + } } } + // 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 = vtLine ; + Pt5ax.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + // ritorno con successo + return true ; + } } } return false ; @@ -500,26 +581,30 @@ ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const ICurve //---------------------------------------------------------------------------- bool -ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRef, +ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef, double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // Sistemazioni per tipo di superficie - const SurfTriMesh* pSurfTm = nullptr ; - switch ( sfSurf.GetType()) { - case SRF_TRIMESH : - pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; - break ; - case SRF_BEZIER : - pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; - break ; - case SRF_FLATRGN : - pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; - break ; - default : - break ; + CISRFTMPVECTOR vpSurfTm ; + for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + const SurfTriMesh* pSurfTm = nullptr ; + switch ( vpSurf[i]->GetType()) { + case SRF_TRIMESH : + pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ; + break ; + case SRF_BEZIER : + pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ; + break ; + case SRF_FLATRGN : + pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ; + break ; + default : + break ; + } + if ( pSurfTm == nullptr) + return false ; + vpSurfTm.emplace_back( pSurfTm) ; } - if ( pSurfTm == nullptr) - return false ; // Controllo le tolleranze dLinTol = max( dLinTol, LIN_TOL_MIN) ; @@ -544,7 +629,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRe while ( bFound) { // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptP, *pSurfTm, crRef, dPar, Pt5ax)) + if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax)) vPt5ax.emplace_back( Pt5ax) ; // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; @@ -622,7 +707,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRe //---------------------------------------------------------------------------- static bool -ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax) +ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax) { // punto sulla superficie guida a minima distanza DistPointSurfTm dPS( ptP, stmRef) ; @@ -643,71 +728,94 @@ ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const SurfTr vtLine = trGuide.GetN() ; dLineLen = 100 ; } - // intersezione della retta con la superficie - ILSIVECTOR vIntRes ; - if ( IntersLineSurfTm( ptP, vtLine, dLineLen, stmSurf, vIntRes, false)) { - // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; - while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) - --nI ; - // se trovata - if ( nI >= 0) { - // calcolo il punto - Point3d ptInt ; - if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) - ptInt = vIntRes[nI].ptI2 ; - else - ptInt = vIntRes[nI].ptI ; - // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) - Triangle3dEx trTria ; - if ( ! stmSurf.GetTriangle( vIntRes[nI].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.dPar = dPar ; - Pt5ax.nFlag = P5AX_STD ; - // ritorno con successo - return true ; + // 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) { + 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 ; + 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 ; + } + } + } } } + // 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.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + // ritorno con successo + return true ; + } } return false ; } //---------------------------------------------------------------------------- bool -ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef, +ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef, double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // sistemazioni per tipo di superficie - const SurfTriMesh* pSurfTm = nullptr ; - switch ( sfSurf.GetType()) { - case SRF_TRIMESH : - pSurfTm = GetBasicSurfTriMesh( &sfSurf) ; - break ; - case SRF_BEZIER : - pSurfTm = GetBasicSurfBezier( &sfSurf)->GetAuxSurf() ; - break ; - case SRF_FLATRGN : - pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; - break ; - default : - break ; + CISRFTMPVECTOR vpSurfTm ; + for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + const SurfTriMesh* pSurfTm = nullptr ; + switch ( vpSurf[i]->GetType()) { + case SRF_TRIMESH : + pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ; + break ; + case SRF_BEZIER : + pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurf() ; + break ; + case SRF_FLATRGN : + pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ; + break ; + default : + break ; + } + if ( pSurfTm == nullptr) + return false ; + vpSurfTm.emplace_back( pSurfTm) ; } - if ( pSurfTm == nullptr) - return false ; // sistemazioni per tipo di superficie di riferimento const SurfTriMesh* pRefTm = nullptr ; @@ -750,14 +858,14 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef while ( bFound) { // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptP, *pSurfTm, *pRefTm, dPar, Pt5ax)) + if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax)) vPt5ax.emplace_back( Pt5ax) ; // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; } - // se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli - if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) { + // se richiesto, inserimento punti intermedi in presenza di spigoli + if ( bSharpEdges) { for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { // precedente int j = i - 1 ; @@ -769,7 +877,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptMid, *pSurfTm, *pRefTm, dMid, Pt5ax)) { + if ( ProjectPointOnSurf( ptMid, vpSurfTm, *pRefTm, dMid, Pt5ax)) { vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; -- i ; } diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 96bdd43..5fbec74 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -483,3 +483,10 @@ inline SurfTriMesh* GetBasicSurfTriMesh( IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != SRF_TRIMESH) return nullptr ; return ( static_cast( pGObj)) ; } + +//---------------------------------------------------------------------------- +// Raccolte di puntatori a SurfTriMesh +typedef std::vector CISRFTMPVECTOR ; // vettore di puntatori a const SurfTriMesh +typedef std::vector ISRFTMPVECTOR ; // vettore di puntatori a SurfTriMesh +typedef std::list ISRFTMPLIST ; // lista di puntatori a SurfTriMesh +typedef std::vector> ISRFTMPOVECTOR ; // vettore di puntatori esclusivi a SurfTriMesh