diff --git a/OffsetCurve3d.cpp b/OffsetCurve3d.cpp index 12b1946..678ac65 100644 --- a/OffsetCurve3d.cpp +++ b/OffsetCurve3d.cpp @@ -61,7 +61,7 @@ OffsetCurve3d::Reset( void) //---------------------------------------------------------------------------- bool -OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOffDist, int nType) +OffsetCurve3d::Make( const PNT5AXVECTOR& vPnt5Ax, double dOffDist, int nType) { // la funzione è pensata per lavorare con il risultato dell'operazione ProjectCurveOnSurf @@ -70,6 +70,18 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff // pulisco tutto Reset() ; + + INTVECTOR vFlag ; + VCT3DVECTOR vOffDir ; + PolyLine PL ; + for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) { + PL.AddUPoint( i, vPnt5Ax[i].ptP) ; + vOffDir.push_back( vPnt5Ax[i].vtDir1) ; + if ( vPnt5Ax[i].nFlag > 0) + vFlag.push_back( vPnt5Ax[i].nFlag) ; + else + return false ; + } PtrOwner pCrv( CreateBasicCurveComposite()) ; if ( ! pCrv->FromPolyLine( PL)) return false ; @@ -116,25 +128,6 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff bool bClosed = pCrv->IsClosed() ; - INTVECTOR vFlag ; - vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ; - const ICurve* pSubCrv = pCrv->GetFirstCurve() ; - const double dSinAngSmall = sin( 1 * DEGTORAD) ; - for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) { - pSubCrv = pCrv->GetNextCurve() ; - Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ; - vtDirCurr.Normalize() ; - int nFlag ; - double dProj = vtDirCurr * vOffDir[i-1] ; - if ( dProj > dSinAngSmall) - nFlag = OffsetCurve3d::AngType::ANG_SMOOTH_CONC ; - else if ( dProj > - dSinAngSmall) - nFlag = OffsetCurve3d::AngType::ANG_STR ; - else - nFlag = OffsetCurve3d::AngType::ANG_CVEX ; - vFlag.push_back( nFlag) ; - } - for ( int i = 1 ; i < ssize( vFlag) - 1 ; ++i) { if ( vFlag[i-1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC && vFlag[i+1] == OffsetCurve3d::AngType::ANG_SMOOTH_CONC && @@ -148,12 +141,23 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff Vector3d vtCorrPrev ; Vector3d vtTangPrev ; Vector3d vtDirPrev ; pCrv->GetStartDir( vtDirPrev) ; + if ( bClosed) { + Vector3d vtDirLast ; pCrv->GetEndDir( vtDirLast) ; + if ( vFlag[0] != OffsetCurve3d::AngType::ANG_CVEX) + vtTangPrev = Media( vtDirLast, vtDirPrev) ; + else if ( vFlag[0] == OffsetCurve3d::AngType::ANG_CVEX && vFlag.back() != OffsetCurve3d::AngType::ANG_CVEX) + vtTangPrev = vtDirLast ; + else + vtTangPrev = vtDirPrev ; + } const ICurve* pCrvPrev = pCrv->GetFirstCurve() ; const ICurve* pCrvCurr ; OFFSETSEGVEC vOffsetCrvs ; Vector3d vtDirPrevOff = V_INVALID ; - for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) { + for ( int i = 1 ; i <= pCrv->GetCurveCount() ; ++i) { pCrvCurr = pCrv->GetNextCurve() ; + if ( pCrvCurr == nullptr && bClosed && vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX) + pCrvCurr = pCrv->GetFirstCurve() ; Vector3d vtOffDir = vOffDir[i] ; Vector3d vtDirCurr ; pCrvCurr->GetStartDir( vtDirCurr) ; pCrvPrev->GetStartDir( vtDirPrev) ; @@ -239,7 +243,8 @@ OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOff Point3d ptP ; vOffsetCrvs.front().pCrv->GetStartPoint( ptP) ; ICurveLine* pCL = CreateBasicCurveLine() ; pCL->Set( ptPrev, ptP) ; - vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ; + if ( pCL->IsValid()) + vOffsetCrvs.emplace_back( pCL, OffsetCurve3d::AngType::ANG_STR, -1) ; } // qui faccio la correzione per gli angoli interni @@ -400,7 +405,10 @@ CalcAdjustConcavePartsInPath( const ICurveComposite* pCrv, const OFFSETSEGVEC& v while ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) { vLines.push_back( i) ; ++i ; - nFlag = vOffsetCrvs[i].nFlag ; + if ( i < ssize( vOffsetCrvs)) + nFlag = vOffsetCrvs[i].nFlag ; + else + nFlag = OffsetCurve3d::AngType::ANG_STR ; } CYLVECT vCyl ; // creo un cilindro della dimensione del raggio diff --git a/ProjectCurveSurf.cpp b/ProjectCurveSurf.cpp index 30151ef..f767a8c 100644 --- a/ProjectCurveSurf.cpp +++ b/ProjectCurveSurf.cpp @@ -32,15 +32,6 @@ using namespace std ; 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 -const int P5AX_SMOOTH_CONC = 6 ; // zona concava curva, senza spigolo netto //---------------------------------------------------------------------------- static double @@ -65,7 +56,7 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, static bool AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) { - const double dSinSmallAngle = sin( 0 * DEGTORAD) ; + const double dSinSmallAngle = sin( 0.5 * DEGTORAD) ; for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { // precedente int j = i - 1 ; @@ -160,7 +151,10 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) // guardo se la proiezione il tratto successivo, lungo la normale precedente + maggiore di un angolo minimo ( angolo interno smooth) Vector3d vtDirNext = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtDirNext.Normalize() ; - if ( vtDirNext * vPt5ax[j].vtDir1 > dSinSmallAngle) { + double dProj1 = vtDirNext * vPt5ax[j].vtDir1 ; + double dProj2 = ( - vtDirNext) * vPt5ax[i].vtDir1 ; + + if ( ( abs( dProj1) > abs( dProj2) ? dProj1 > dSinSmallAngle : dProj2 > dSinSmallAngle)) { // se concavo senza spigolo netto segnalo zona concava smooth vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ; } @@ -382,7 +376,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar //---------------------------------------------------------------------------- bool ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, - double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax, bool bNormOrTang) { // controllo le tolleranze dLinTol = max( dLinTol, LIN_TOL_MIN) ; @@ -402,16 +396,47 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, 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) ; + double dPar, dParNext ; + Point3d ptP, ptPNext ; + Vector3d vtDirPrev = V_INVALID ; + if ( PL.IsClosed()) { + Point3d pt1, pt2 ; + PL.GetLastLine( pt1, pt2) ; + vtDirPrev = pt2 - pt1 ; + } + bool bFound = PL.GetFirstULine( &dPar, &ptP, &dParNext, &ptPNext) ; + Vector3d vtFirst = ptPNext - ptP ; + bool bClosed = PL.IsClosed() ; + bool bLast = false ; 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 richiesta la tangente anziché la normale allora modifico il vettore associato al punto + Vector3d vtDir ; + if ( ! bNormOrTang) { + Vector3d vtNorm = vPt5ax.back().vtDir1 ; + if ( ! bLast) + vtDir = ptPNext - ptP ; + else if ( bClosed) + vtDir = vtFirst ; + else + vtDir = vtDirPrev ; + vtDirPrev = vtDir ; + if ( vtDirPrev.IsValid()) + vtDir = Media( vtDir, vtDirPrev) ; + Vector3d vtTang = vtDir ^ vtNorm ; vtTang.Normalize() ; + vPt5ax.back().vtDir1 = vtTang ; + vPt5ax.back().vtDir2 = vtTang ; + } + // passo al successivo + bFound = PL.GetNextULine( &dPar, &ptP, &dParNext, &ptPNext) ; + // se sono arrivato alla fine aggiungo l'ultimo punto + if ( ! bFound && ! bLast) { + bLast = true ; + bFound = true ; + } } // se richiesto, inserimento punti intermedi in presenza di spigoli diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 4ed21ea..ccad9ef 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -29,11 +29,24 @@ #include "/EgtDev/Include/EGkRotationXplaneFrame.h" #include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkProjectCurveSurf.h" +#include "/EgtDev/Include/EGkOffsetCurve3d.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; +#define SAVEEXTEND 0 + +#if SAVEEXTEND +vector vGeo ; +vector> vvGeo ; +#include "/EgtDev/Include/EGkColor.h" +vector vCol ; +#include "/EgtDev/Include/EGkGeoObjSave.h" +#include "/EgtDev/Include/EGkGeoVector3d.h" +#endif + //------------------------------------------------------------------------------- // costanti per SurfTmRectSwept @@ -2135,3 +2148,102 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do // restituisco la superficie return Release( pSTM) ; } + +//------------------------------------------------------------------------------- +ISurfTriMesh* +GetSurfExtension( const ISurfTriMesh* pSrfTM, double dExtLen, int nLoop, int nSubCrv, int nType, double dLinTol) +{ + // controlli sui parametri in input + if ( pSrfTM == nullptr || nLoop < 0 || nSubCrv < -1) + return nullptr ; + + POLYLINEVECTOR vLoops ; + if ( ! pSrfTM->GetLoops( vLoops)) + return nullptr ; + PtrOwner pLoop( CreateBasicCurveComposite()) ; + if ( ! pLoop->FromPolyLine( vLoops[nLoop]) || nSubCrv >= pLoop->GetCurveCount()) + return nullptr ; + + // ricavo il tratto di bordo da estendere, con le tangenti della superficie + PtrOwner pEdge ; + if ( nSubCrv == - 1) + pEdge.Set( pLoop) ; + else + pEdge.Set( pLoop->GetCurve( nSubCrv)->Clone()) ; + + double dMaxLen = 2.5 ; + PNT5AXVECTOR vPnt5Ax ; + CISURFPVECTOR vSurf ; vSurf.push_back( pSrfTM) ; + bool bClosed = pEdge->IsClosed() ; + ProjectCurveOnSurf( *pEdge, vSurf, dLinTol, dMaxLen, true, vPnt5Ax, false) ; + //PolyLine PL ; + //VCT3DVECTOR vOffDir ; + //bool bClosed = pEdge->IsClosed() ; + /////////// versione con calcolo della tangente + //for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) { + // PL.AddUPoint( i, vPnt5Ax[i].ptP) ; + // Vector3d vtDir ; + // if ( ( i == 0 || i == ssize( vPnt5Ax) - 1) && bClosed) + // vtDir = Media( vPnt5Ax.end()[-1].ptP - vPnt5Ax.end()[-2].ptP, vPnt5Ax[1].ptP - vPnt5Ax[0].ptP) ; + // else if ( i > 0 && i < ssize( vPnt5Ax) - 1) + // vtDir = Media( vPnt5Ax[i].ptP - vPnt5Ax[i-1].ptP, vPnt5Ax[i+1].ptP - vPnt5Ax[i].ptP) ; + // else if ( i < ssize( vPnt5Ax) - 1) + // vtDir = vPnt5Ax[i+1].ptP - vPnt5Ax[i].ptP ; + // else + // vtDir = vPnt5Ax[i].ptP - vPnt5Ax[i-1].ptP ; + // Vector3d& vtN = vPnt5Ax[i].vtDir1 ; + // Vector3d vtOffDir = vtDir ^ vtN ; vtOffDir.Normalize() ; + // vOffDir.push_back( vtOffDir) ; + //} + + //////////// qui la tangente è già stata calcolata da ProjectCurveOnSurf + //for ( int i = 0 ; i < ssize( vPnt5Ax) ; ++i) { + // PL.AddUPoint( i, vPnt5Ax[i].ptP) ; + // vOffDir.push_back( vPnt5Ax[i].vtDir1) ; + //} + + OffsetCurve3d off3d ; + if ( ! off3d.Make( vPnt5Ax, dExtLen, nType)) + return nullptr ; + + PtrOwner pOffEdge( CreateBasicCurveComposite()) ; + for ( int i = 0 ; i < off3d.GetCurveCount() ; ++i) { + if ( ! pOffEdge->AddCurve( off3d.GetLongerCurve())) + return nullptr ; + } +#if SAVEEXTEND + vvGeo.clear() ; + vCol.clear() ; + vvGeo.emplace_back() ; + vvGeo.back().push_back( pEdge->Clone()) ; + vvGeo.back().push_back( pOffEdge->Clone()) ; + vCol.push_back( AQUA) ; + vvGeo.emplace_back() ; + for ( int i = 0 ; i < ssize( vOffDir) ; ++i) { + IGeoVector3d* pGV = CreateGeoVector3d() ; + pGV->Set( vOffDir[i] * dExtLen, vPnt5Ax[i].ptP) ; + vvGeo.back().push_back( pGV) ; + } + vCol.push_back( LIME) ; + SaveGeoObj( vvGeo, vCol, "C:\\Temp\\curve offset 3d\\surfExtend_insight.nge") ; + + vGeo.clear() ; + vCol.clear() ; + for ( int i = 1 ; i < ssize( vPnt5Ax) ; ++i) { + ICurveLine* pCL = CreateBasicCurveLine() ; + pCL->Set( vPnt5Ax[i-1].ptP, vPnt5Ax[i].ptP) ; + vGeo.push_back( pCL) ; + if ( vPnt5Ax[i].nFlag == 6) + vCol.push_back( GREEN) ; + else if ( vPnt5Ax[i].nFlag == 2) + vCol.push_back( RED) ; + else + vCol.push_back( PURPLE) ; + } + SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\surfExtend_con-cvx.nge") ; +#endif + + PtrOwner pSurfExt( GetSurfTriMeshRuled( pEdge, pOffEdge, ISurfTriMesh::RuledType::RLT_MINDIST, dLinTol)) ; + + return Release( pSurfExt) ; +} \ No newline at end of file