//---------------------------------------------------------------------------- // EgalTech 2023-2023 //---------------------------------------------------------------------------- // File : ProjectCurveSurfTm.cpp Data : 16.11.23 Versione : 2.5kh3 // Contenuto : Implementazione funzioni proiezione curve su superficie Trimesh. // // // // Modifiche : 31.08.23 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DistPointLine.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkProjectCurveSurfTm.h" using namespace std ; //---------------------------------------------------------------------------- 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 ; } //---------------------------------------------------------------------------- bool ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen, 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 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, 1.) ; if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) return false ; // Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie Frame3d frRefLine ; if ( ! frRefLine.Set( ORIG, vtDir)) return false ; IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ; // Vettore locale dei punti risultanti PNT5AXVECTOR vMyPt5ax ; vMyPt5ax.reserve( PL.GetPointNbr()) ; // proietto i punti della polilinea sulla superficie double dU ; Point3d ptP ; bool bFound = PL.GetFirstUPoint( &dU, &ptP) ; while ( bFound) { Point3d ptL = GetToLoc( ptP, frRefLine) ; ILSIVECTOR vIntRes ; intPLSTM.GetInters( ptL, 1, vIntRes, false) ; if ( vIntRes.size() > 0) { // calcolo il punto int nI = int( vIntRes.size()) - 1 ; 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 ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria)) return false ; Vector3d vtN ; double dU, dV, dW ; if ( BarycentricCoord( ptInt, trTria, dU, dV, dW)) vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ; if ( ! vtN.Normalize()) vtN = trTria.GetN() ; // aggiungo al vettore dei proiettati vMyPt5ax.emplace_back( ptInt, vtN, dU, 1) ; } bFound = PL.GetNextUPoint( &dU, &ptP) ; } // rimuovo i punti allineati entro la tolleranza e non pił lontani tra loro del massimo double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ; double dSqTol = dLinTol * dLinTol ; int nPrec = 0 ; int nCurr = 1 ; int nNext = 2 ; while ( nNext < int( vMyPt5ax.size())) { bool bRemove = false ; // lunghezza del segmento che unisce gli adiacenti double dSqLen = SqDist( vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ; // se lunghezza inferiore al massimo, passo agli altri controlli if ( dSqLen <= dSqMaxLen) { // distanza del punto corrente dal segmento che unisce gli adiacenti DistPointLine dPL( vMyPt5ax[nCurr].ptP, vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ; double dSqDist ; // se distanza inferiore a tolleranza lineare if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vMyPt5ax, nPrec, nCurr, nNext, dSqTol)) { // verifico se errore angolare inferiore a limite double dPar ; dPL.GetParamAtMinDistPoint( dPar) ; Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ; if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > cos( 2 * DEGTORAD)) bRemove = true ; } } // se da eliminare if ( bRemove) { // dichiaro da eliminare il punto vMyPt5ax[nCurr].nFlag = -1 ; // avanzo con corrente e successivo nCurr = nNext ; ++ nNext ; } // altrimenti da tenere else { // avanzo il terzetto di uno step nPrec = nCurr ; nCurr = nNext ; ++ nNext ; } } // copio i punti rimasti nel vettore di ritorno vPt5ax.clear() ; for ( const auto& Pt5ax : vMyPt5ax) { if ( Pt5ax.nFlag != -1) vPt5ax.emplace_back( Pt5ax) ; } return true ; }