diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index fec77c9..5e622f4 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/ProjectCurveSurfTm.cpp b/ProjectCurveSurfTm.cpp index ad40f56..053cf10 100644 --- a/ProjectCurveSurfTm.cpp +++ b/ProjectCurveSurfTm.cpp @@ -15,8 +15,9 @@ #include "stdafx.h" #include "DistPointLine.h" #include "GeoConst.h" -#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkProjectCurveSurfTm.h" using namespace std ; @@ -33,6 +34,53 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, return true ; } +//---------------------------------------------------------------------------- +static bool +RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, double dLinTol, double dMaxSegmLen) +{ + // 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 ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen, @@ -92,45 +140,7 @@ ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vec } // 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 ; - } - } + RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ; // copio i punti rimasti nel vettore di ritorno vPt5ax.clear() ; @@ -144,8 +154,82 @@ ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vec //---------------------------------------------------------------------------- bool -ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICurve& crRef, double dLinTol, double dMaxSegmLen, - PNT5AXVECTOR& vPt5ax) +ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const IGeoPoint3d& gpRef, + 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 ; + + // Vettore locale dei punti risultanti + PNT5AXVECTOR vMyPt5ax ; + vMyPt5ax.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) { + // punto di riferimento + Point3d ptMin = gpRef.GetPoint() ; + // intersezione della retta di minima distanza con la superficie + Vector3d vtLine = ptP - ptMin ; + double dLineLen = vtLine.Len() ; + if ( dLineLen > EPS_SMALL) { + vtLine /= dLineLen ; + ILSIVECTOR vIntRes ; + if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, 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, vtLine, dPar, 1) ; + } + } + } + bFound = PL.GetNextUPoint( &dPar, &ptP) ; + } + + // rimuovo i punti allineati entro la tolleranza e non pił lontani tra loro del massimo + RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ; + + // 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 ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICurve& crRef, + double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) { // controllo le tolleranze dLinTol = max( dLinTol, LIN_TOL_MIN) ; @@ -208,45 +292,95 @@ ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICu } // 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 ; - } - } + RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ; + + // 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 ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ISurfTriMesh& tmRef, + 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 ; + + // Vettore locale dei punti risultanti + PNT5AXVECTOR vMyPt5ax ; + vMyPt5ax.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) { + // punto sulla superficie guida a minima distanza + DistPointSurfTm dPS( ptP, tmRef) ; + Point3d ptMin ; + int nTriaMin ; + if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) { + // intersezione della retta di minima distanza con la superficie + Vector3d vtLine = ptP - ptMin ; + double dLineLen = vtLine.Len() ; + if ( dLineLen > EPS_SMALL) { + vtLine /= dLineLen ; + ILSIVECTOR vIntRes ; + if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, 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() ; + // calcolo la normale della superficie guida + Triangle3dEx trGuide ; + if ( ! tmRef.GetTriangle( nTriaMin, trGuide)) + return false ; + Vector3d vtN2 ; + double dU2, dV2, dW2 ; + if ( BarycentricCoord( ptMin, trGuide, dU2, dV2, dW2)) + vtN2 = dU2 * trGuide.GetVertexNorm( 0) + dV2 * trGuide.GetVertexNorm( 1) + dW2 * trGuide.GetVertexNorm( 2) ; + if ( ! vtN2.Normalize()) + vtN2 = trGuide.GetN() ; + // aggiungo al vettore dei proiettati + vMyPt5ax.emplace_back( ptInt, vtN, vtN2, dPar, 1) ; + } + } + } + } + bFound = PL.GetNextUPoint( &dPar, &ptP) ; + } + + // rimuovo i punti allineati entro la tolleranza e non pił lontani tra loro del massimo + RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ; // copio i punti rimasti nel vettore di ritorno vPt5ax.clear() ;