From 67f3df353fa564202f0246f27514bb220a6c8544 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 12 Mar 2025 15:27:33 +0100 Subject: [PATCH 1/7] EgtGeomKernel 2.7c2 : - in CAvToolSurfTm caso singola posizione da controllare utilizzo HashGrid3d delle superfici tramite GetAllTriaOverlapBox. --- CAvToolSurfTm.cpp | 103 +++++++++++++++++++++++++++++++++++----------- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/CAvToolSurfTm.cpp b/CAvToolSurfTm.cpp index 3c7d1d7..e5bd9e4 100644 --- a/CAvToolSurfTm.cpp +++ b/CAvToolSurfTm.cpp @@ -24,6 +24,7 @@ using namespace std ; //---------------------------------------------------------------------------- const int STEP_PE = 50 ; +const double MAX_MOVE = 1000 ; //---------------------------------------------------------------------------- ICAvToolSurfTm* @@ -600,20 +601,46 @@ CAvToolSurfTm::MyTestMidPointHG( PNTULIST& lPntM, const PNTULIST::iterator& itPn double CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, Vector3d& vtTriaN) const { + // box dell'utensile con suo movimento + BBox3d b3Tool ; + // utensile + b3Tool.Add( ptT) ; + b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ; + if ( vtDir.IsX()) + b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ; + else if ( vtDir.IsY()) + b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ; + else if ( vtDir.IsZ()) + b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ; + else { + double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ; + double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ; + double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ; + b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ; + } + // aggiungo movimento + BBox3d b3Moved = b3Tool ; + b3Moved.Translate( MAX_MOVE * vtMove) ; + b3Tool.Add( b3Moved) ; + + // determino movimento minimo per evitare collisione con superfici double dTotDist = 0 ; vtTriaN = V_NULL ; for ( auto pStm : m_vSTM) { - Triangle3d Tria ; - for ( int nTria = pStm->GetFirstTriangle( Tria) ; - nTria != SVT_NULL ; - nTria = pStm->GetNextTriangle( nTria, Tria)) { - double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ; - if ( dDist < - EPS_SMALL) - return -1 ; - if ( dDist > EPS_SMALL) { - dTotDist += dDist ; - ptT += dDist * vtMove ; - vtTriaN = Tria.GetN() ; + INTVECTOR vTria ; + if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) { + for ( int nTria : vTria) { + Triangle3d Tria ; + if ( pStm->GetTriangle( nTria, Tria)) { + double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ; + if ( dDist < - EPS_SMALL) + return -1 ; + if ( dDist > EPS_SMALL) { + dTotDist += dDist ; + ptT += dDist * vtMove ; + vtTriaN = Tria.GetN() ; + } + } } } } @@ -624,24 +651,50 @@ CAvToolSurfTm::MyTestPosition( Point3d& ptT, const Vector3d& vtDir, const Vector double CAvToolSurfTm::MyTestPositionAdv( Point3d& ptT, const Vector3d& vtDir, const Vector3d& vtMove, VCT3DVECTOR& vVtTriaN) const { + // box dell'utensile con suo movimento + BBox3d b3Tool ; + // utensile + b3Tool.Add( ptT) ; + b3Tool.Add( ptT - vtDir * m_Tool.GetHeigth()) ; + if ( vtDir.IsX()) + b3Tool.Expand( 0, m_Tool.GetRadius(), m_Tool.GetRadius()) ; + else if ( vtDir.IsY()) + b3Tool.Expand( m_Tool.GetRadius(), 0, m_Tool.GetRadius()) ; + else if ( vtDir.IsZ()) + b3Tool.Expand( m_Tool.GetRadius(), m_Tool.GetRadius(), 0) ; + else { + double dExpandX = m_Tool.GetRadius() * sqrt( 1 - vtDir.x * vtDir.x) ; + double dExpandY = m_Tool.GetRadius() * sqrt( 1 - vtDir.y * vtDir.y) ; + double dExpandZ = m_Tool.GetRadius() * sqrt( 1 - vtDir.z * vtDir.z) ; + b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ; + } + // aggiungo movimento + BBox3d b3Moved = b3Tool ; + b3Moved.Translate( MAX_MOVE * vtMove) ; + b3Tool.Add( b3Moved) ; + + // determino movimento minimo per evitare collisione con superfici double dTotDist = 0 ; vVtTriaN.clear() ; for ( auto pStm : m_vSTM) { - Triangle3d Tria ; - for ( int nTria = pStm->GetFirstTriangle( Tria) ; - nTria != SVT_NULL ; - nTria = pStm->GetNextTriangle( nTria, Tria)) { - double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ; - if ( dDist < - EPS_SMALL) - return -1 ; - // se devo traslare il punto, c'è collisione - if ( dDist > EPS_SMALL) { - if ( dDist > 10 * EPS_SMALL) { - vVtTriaN.clear() ; - dTotDist += dDist ; - ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ; + INTVECTOR vTria ; + if ( pStm->GetAllTriaOverlapBox( b3Tool, vTria)) { + for ( int nTria : vTria) { + Triangle3d Tria ; + if ( pStm->GetTriangle( nTria, Tria)) { + double dDist = CAvToolTriangle( m_Tool, ptT, vtDir, Tria, vtMove) ; + if ( dDist < - EPS_SMALL) + return -1 ; + // se devo traslare il punto, c'è collisione + if ( dDist > EPS_SMALL) { + if ( dDist > 10 * EPS_SMALL) { + vVtTriaN.clear() ; + dTotDist += dDist ; + ptT += ( dDist - 5 * EPS_SMALL) * m_frMove.VersZ() ; + } + vVtTriaN.push_back( Tria.GetN()) ; + } } - vVtTriaN.push_back( Tria.GetN()) ; } } } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 77d8328e2295ecfc02f068b57f3978ef754d8843..59ac372c6f18bccf048187a6aedc503417d206aa 100644 GIT binary patch delta 236 zcmdlNy)SyhI%aKGhCGIJh8%`WhGK>c1_cHUhESkLCPN8BDnkm89}HwAf_cT0PijeT z{=m$}%xJXvyqqG4`lwjSxVewp10r;uY4S3`JfN_k6i~QJ7*lvJ3$os9QmsEYnTvVZ l Date: Thu, 13 Mar 2025 12:32:35 +0100 Subject: [PATCH 2/7] EgtGeomKernel : - aggiunto parametro in CalcPocketing. --- CalcPocketing.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index fad7a02..f8e3da4 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -8619,7 +8619,7 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, //---------------------------------------------------------------------------- bool CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, - int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders, + double dOpenMinSafe, int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders, bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // controllo dei parametri @@ -8640,6 +8640,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double myParams.bSmooth = bSmooth ; myParams.dAngle = dAngle ; myParams.dSideStep = dStep ; + myParams.dOpenMinSafe = dOpenMinSafe ; myParams.bInvert = bInvert ; myParams.bAvoidOpt = bAvoidOpt ; myParams.bCalcFeed = bCalcFeed ; From 65d826168b185add65a3e79bdc1a2c975b241687 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 17 Mar 2025 09:55:22 +0100 Subject: [PATCH 3/7] EgtGeomKernel : - In ConformalZigZag piccola modifica sulla tolleranza della regione limite. --- CalcPocketing.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index f8e3da4..74e943f 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -7390,7 +7390,7 @@ GetConformalIndices( const VICRVCOMPOPOVECTOR& vCrvOffs, int nMyInd0, int nMyInd //---------------------------------------------------------------------------- static bool -AdjustCloseEsgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParams& PockParams) +AdjustCloseEdgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParams& PockParams) { // controllo dei parametri if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) @@ -7403,7 +7403,7 @@ AdjustCloseEsgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParam // piccolo Offset per la superficie di classificazione PtrOwner pSfrLimit( CloneSurfFlatRegion( &PockParams.SfrLimit)) ; if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid() || - ! pSfrLimit->Offset( 100 * EPS_SMALL, ICurve::OFF_FILLET)) + ! pSfrLimit->Offset( 150 * EPS_SMALL, ICurve::OFF_FILLET)) return false ; // recupero le parti omogenee della curva @@ -7421,7 +7421,7 @@ AdjustCloseEsgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParam if ( IsNull( pMyCompo)) return false ; CRVCVECTOR ccClass ; - if ( pSfrLimit->GetCurveClassification( *vpCrvs[i], 125 * EPS_SMALL, ccClass)) { + if ( pSfrLimit->GetCurveClassification( *vpCrvs[i], EPS_SMALL, ccClass)) { for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { // recupero il tratto di curva PtrOwner pMyCurve( ConvertCurveToComposite( vpCrvs[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ; @@ -7443,9 +7443,8 @@ AdjustCloseEsgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParam } if ( pCrvFinal->IsValid()) pCrvCompo->CopyFrom( pCrvFinal) ; - + return ( pCrvCompo != nullptr && pCrvCompo->IsValid()) ; - } //---------------------------------------------------------------------------- @@ -7636,7 +7635,6 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketPara return false ; if ( vCrvOffs.empty()) return true ; - /* dalla superificie estesa presso i lati aperti, effettuo un Offset interno pari alla somma del raggio utensile e dell'offset radiale. La ricerca delle zone non svuotate avviene all'interno @@ -8260,7 +8258,7 @@ CombineClosedEdgesForConformalOffsets( const ISurfFlatRegion* pSfrChunk, const P ICRVCOMPOPOVECTOR vpCrvHomo ; PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() || - ! AdjustCloseEsgesForConformalGuide( pCrvExtLoop, PockParam) || + ! AdjustCloseEdgesForConformalGuide( pCrvExtLoop, PockParam) || ! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvHomo)) return false ; if ( ! bOk) @@ -8329,7 +8327,7 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS ICRVCOMPOPOVECTOR vpCrvs ; PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() || - ! AdjustCloseEsgesForConformalGuide( pCrvExtLoop, PockParam) || + ! AdjustCloseEdgesForConformalGuide( pCrvExtLoop, PockParam) || ! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvs)) return false ; if ( ! bOk) From 49340d2629adf038b41968d7116014cff6c9391f Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 17 Mar 2025 15:11:34 +0100 Subject: [PATCH 4/7] EgtGeomKernel : - in CollisionAvoid aumentato MAX_MOVE per calcoli con travi (elevazione su attacchi/uscite). --- CAvToolSurfTm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CAvToolSurfTm.cpp b/CAvToolSurfTm.cpp index e5bd9e4..4319869 100644 --- a/CAvToolSurfTm.cpp +++ b/CAvToolSurfTm.cpp @@ -24,7 +24,7 @@ using namespace std ; //---------------------------------------------------------------------------- const int STEP_PE = 50 ; -const double MAX_MOVE = 1000 ; +const double MAX_MOVE = 20000 ; //---------------------------------------------------------------------------- ICAvToolSurfTm* From b1acf7f4f0456fbb08cc19b444d0cb72f42c86b9 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 26 Mar 2025 11:26:36 +0100 Subject: [PATCH 5/7] EgtGeomKernel : - correzione a Inters3Planes (la linea deve essere infinita) - modifiche varie e correzioni a ProjectCurveOnSurf per gestire spigoli e per far funzionare l'eliminazione dei punti superflui. --- IntersPlanePlane.cpp | 2 +- ProjectCurveSurf.cpp | 771 +++++++++++++++++++++++++++++-------------- 2 files changed, 531 insertions(+), 242 deletions(-) diff --git a/IntersPlanePlane.cpp b/IntersPlanePlane.cpp index a4259a5..0b83506 100644 --- a/IntersPlanePlane.cpp +++ b/IntersPlanePlane.cpp @@ -42,5 +42,5 @@ Inters3Planes( const Plane3d& plPlane1, const Plane3d& plPlane2, const Plane3d& if ( IntersPlanePlane( plPlane1, plPlane2, ptL, vtL) != IPPT_YES) return IPPT_NO ; // intersezione della linea con il terzo piano - return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt) == ILPT_YES ? IPPT_YES : IPPT_NO) ; + return ( IntersLinePlane( ptL, vtL, 1, plPlane3, ptInt, false) == ILPT_YES ? IPPT_YES : IPPT_NO) ; } diff --git a/ProjectCurveSurf.cpp b/ProjectCurveSurf.cpp index 9da5bb9..d37054d 100644 --- a/ProjectCurveSurf.cpp +++ b/ProjectCurveSurf.cpp @@ -19,19 +19,187 @@ #include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Include/EGkIntersPlanePlane.h" +#include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkProjectCurveSurf.h" using namespace std ; //---------------------------------------------------------------------------- -// Angolo limite tra normale al triangolo e direzione di proiezione 89° +// 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 +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 + +//---------------------------------------------------------------------------- +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 ; +} + +//---------------------------------------------------------------------------- +static bool +RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir) +{ + // Parametri di riferimento + double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ; + double dSqTol = dLinTol * dLinTol ; + const double LENREF = 200 ; + 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())) { + if ( vPt5ax[nInd].nFlag == P5AX_CONC) { + // analizzo i punti appena precedenti + int nIpv = nInd - 1 ; + while ( nIpv >= 0) { + double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nIpv].ptP) ; + if ( dSqLen < dSqMaxLen) + vPt5ax[nIpv].nFlag = P5AX_TO_DELETE ; + else { + vPt5ax[nIpv].nFlag = P5AX_BEFORE_CONC ; + break ; + } + -- nIpv ; + } + // analizzo i punti appena successivi + int nInx = nInd + 1 ; + while ( nInx < int( vPt5ax.size())) { + double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ; + if ( dSqLen < dSqMaxLen) + vPt5ax[nInx].nFlag = P5AX_TO_DELETE ; + else { + vPt5ax[nInx].nFlag = P5AX_AFTER_CONC ; + break ; + } + ++ nInx ; + } + } + ++ nInd ; + } + // Rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo + int nCnt = 0 ; + int nPrec = 0 ; + int nCurr = 1 ; + int nNext = 2 ; + while ( nNext < int( vPt5ax.size())) { + bool bRemove = false ; + // lunghezza del segmento che unisce gli adiacenti + double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ; + // se rimovibile (Flag standard) e lunghezza inferiore al massimo, passo agli altri controlli + if ( vPt5ax[nCurr].nFlag == P5AX_STD && dSqLen <= dSqMaxLen) { + // distanza del punto corrente dal segmento che unisce gli adiacenti + DistPointLine dPL( vPt5ax[nCurr].ptP, vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ; + double dSqDist ; + // se distanza inferiore a tolleranza lineare + if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vPt5ax, nPrec, nCurr, nNext, dSqTol)) { + // verifico se errore angolare inferiore a limite + double dPar ; dPL.GetParamAtMinDistPoint( dPar) ; + if ( bTestDir) { + Vector3d vtNew = Media( vPt5ax[nPrec].vtDir1, vPt5ax[nNext].vtDir1, dPar) ; + if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir1 > dCosAngLim) + bRemove = true ; + } + else { + Vector3d vtNew = Media( vPt5ax[nPrec].vtDir2, vPt5ax[nNext].vtDir2, dPar) ; + if ( vtNew.Normalize() && vtNew * vPt5ax[nCurr].vtDir2 > dCosAngLim) + bRemove = true ; + } + } + } + // se da eliminare + if ( bRemove) { + // dichiaro da eliminare il punto + vPt5ax[nCurr].nFlag = P5AX_TO_DELETE ; + // avanzo con corrente e successivo + nCurr = nNext ; + ++ nNext ; + } + // altrimenti da tenere + else { + // avanzo il terzetto di uno step + nPrec = nCurr ; + nCurr = nNext ; + ++ nNext ; + // incremento contatore dei punti conservati + ++ nCnt ; + } + } + + // Copio i punti da conservare in un vettore temporaneo + PNT5AXVECTOR vMyPt5ax ; + vMyPt5ax.reserve( nCnt) ; + for ( const auto& Pt5ax : vPt5ax) { + if ( Pt5ax.nFlag != P5AX_TO_DELETE) + vMyPt5ax.emplace_back( Pt5ax) ; + } + // scambio i due vettori + vPt5ax.swap( vMyPt5ax) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const Frame3d& frRefLine, const IntersParLinesSurfTm& intPLSTM, + double dPar, Point5ax& Pt5ax) +{ + // intersezione retta di proiezione con superficie + 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 ; + // 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 = frRefLine.VersZ() ; + Pt5ax.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + // ritorno con successo + return true ; + } + return false ; +} //---------------------------------------------------------------------------- bool ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vtDir, - double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // sistemazioni per tipo di superficie const SurfTriMesh* pSurfTm = nullptr ; @@ -45,6 +213,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt case SRF_FLATRGN : pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ; + default : + break ; } if ( pSurfTm == nullptr) return false ; @@ -66,60 +236,143 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const Vector3d& vt return false ; IntersParLinesSurfTm intPLSTM( frRefLine, *pSurfTm) ; - // Vettore locale dei punti risultanti - PNT5AXVECTOR vMyPt5ax ; - vMyPt5ax.reserve( PL.GetPointNbr()) ; + // Pulisco e riservo spazio nel vettore dei punti risultanti + vPt5ax.clear() ; + vPt5ax.reserve( PL.GetPointNbr()) ; // proietto i punti della polilinea sulla superficie double dPar ; Point3d ptP ; bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ; while ( bFound) { - // intersezione retta di proiezione con superficie - 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 ; - // 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 ( ! pSurfTm->GetTriangle( vIntRes[nI].nT, trTria)) - return false ; - Vector3d vtN ; - if ( ! CalcNormal( ptInt, trTria, vtN)) - vtN = trTria.GetN() ; - // aggiungo al vettore dei proiettati - vMyPt5ax.emplace_back( ptInt, vtN, vtDir, dPar, 1) ; - } + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptP, *pSurfTm, frRefLine, intPLSTM, dPar, Pt5ax)) + vPt5ax.emplace_back( Pt5ax) ; + // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; } - // eventuale rimozione punti in eccesso rispetto alle tolleranze lasciata alla funzione chiamante - - // copio i punti nel vettore di ritorno - vPt5ax.clear() ; - for ( const auto& Pt5ax : vMyPt5ax) { - if ( Pt5ax.nFlag != -1) - vPt5ax.emplace_back( Pt5ax) ; + // 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 ; + // 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) { + // intersezione tra le due facce + Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ; + Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ; + Point3d ptEdge ; Vector3d vtEdge ; + if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) { + Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, ( vPt5ax[i].ptP - vPt5ax[j].ptP) ^ vtDir) ; + Point3d ptInt ; + if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { + // verifico se spigolo convesso o concavo + bool bConvex ; + if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP)) + bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ; + else + bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ; + // se convesso, metto due punti con direzione appena prima e appena dopo + if ( bConvex) { + Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; + Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; + if ( dLen1 > 2 * EPS_SMALL) { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ; + Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; + Pt5ax.vtDir2 = vtDir ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CVEX ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + if ( dLen2 > 2 * EPS_SMALL) { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; + Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; + Pt5ax.vtDir2 = vtDir ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CVEX ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + } + // altrimenti concavo, aggiungo un solo punto con la direzione media + else { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt ; + Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; + Pt5ax.vtDir2 = vtDir ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CONC ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + } + } + } + } } + // rimozione punti in eccesso rispetto alle tolleranze + RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; + return true ; } +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax) +{ + // 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, 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 ; + } + } + } + return false ; +} + //---------------------------------------------------------------------------- bool ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& gpRef, - double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // sistemazioni per tipo di superficie const SurfTriMesh* pSurfTm = nullptr ; @@ -133,6 +386,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& case SRF_FLATRGN : pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ; + default : + break ; } if ( pSurfTm == nullptr) return false ; @@ -141,7 +396,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& dLinTol = max( dLinTol, LIN_TOL_MIN) ; dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; - // approssimo la curva con una polilinea entro la metà della tolleranza + // 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 ; @@ -149,25 +404,67 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) return false ; - // Vettore locale dei punti risultanti - PNT5AXVECTOR vMyPt5ax ; - vMyPt5ax.reserve( PL.GetPointNbr()) ; + // Pulisco e riservo spazio nel vettore dei punti risultanti + vPt5ax.clear() ; + vPt5ax.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() ; + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptP, *pSurfTm, 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) { + for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ 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, *pSurfTm, gpRef, dMid, Pt5ax)) { + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + -- i ; + } + } + } + } + + // rimozione punti in eccesso rispetto alle tolleranze + RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, 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 Vector3d vtLine = ptP - ptMin ; double dLineLen = vtLine.Len() ; if ( dLineLen > EPS_SMALL) { vtLine /= dLineLen ; ILSIVECTOR vIntRes ; - if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *pSurfTm, vIntRes, false)) { - // cerco la prima intersezione valida a partire dall'ultima (è la più alta) + 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 ; @@ -181,37 +478,32 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const IGeoPoint3d& ptInt = vIntRes[nI].ptI ; // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) Triangle3dEx trTria ; - if ( ! pSurfTm->GetTriangle( vIntRes[nI].nT, trTria)) + if ( ! stmSurf.GetTriangle( vIntRes[nI].nT, trTria)) return false ; Vector3d vtN ; if ( ! CalcNormal( ptInt, trTria, vtN)) vtN = trTria.GetN() ; - // aggiungo al vettore dei proiettati - vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ; + // 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 ; } } } - bFound = PL.GetNextUPoint( &dPar, &ptP) ; } - - // eventuale rimozione punti in eccesso rispetto alle tolleranze lasciata alla funzione chiamante - - // copio i punti nel vettore di ritorno - vPt5ax.clear() ; - for ( const auto& Pt5ax : vMyPt5ax) { - if ( Pt5ax.nFlag != -1) - vPt5ax.emplace_back( Pt5ax) ; - } - - return true ; + return false ; } //---------------------------------------------------------------------------- bool ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRef, - double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { - // sistemazioni per tipo di superficie + // Sistemazioni per tipo di superficie const SurfTriMesh* pSurfTm = nullptr ; switch ( sfSurf.GetType()) { case SRF_TRIMESH : @@ -223,15 +515,17 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRe case SRF_FLATRGN : pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ; + default : + break ; } if ( pSurfTm == nullptr) return false ; - // controllo le tolleranze + // Controllo le tolleranze dLinTol = max( dLinTol, LIN_TOL_MIN) ; dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; - // approssimo la curva con una polilinea alla massima risoluzione + // Approssimo la curva con una polilinea alla massima risoluzione PolyLine PL ; if ( ! crCrv.ApproxWithLines( EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) return false ; @@ -239,71 +533,163 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ICurve& crRe if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) return false ; - // Vettore locale dei punti risultanti - PNT5AXVECTOR vMyPt5ax ; - vMyPt5ax.reserve( PL.GetPointNbr()) ; + // Pulisco e riservo spazio nel vettore dei punti risultanti + vPt5ax.clear() ; + vPt5ax.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 curva 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 - Vector3d vtLine = ptP - ptMin ; - double dLineLen = vtLine.Len() ; - if ( dLineLen > EPS_SMALL) { - vtLine /= dLineLen ; - ILSIVECTOR vIntRes ; - if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *pSurfTm, 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 ; + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptP, *pSurfTm, crRef, 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 < int( vPt5ax.size()) ; ++ 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) { + // intersezione tra le due facce + Plane3d plPlane1 ; plPlane1.Set( vPt5ax[j].ptP, vPt5ax[j].vtDir1) ; + Plane3d plPlane2 ; plPlane2.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir1) ; + Point3d ptEdge ; Vector3d vtEdge ; + if ( IntersPlanePlane( plPlane1, plPlane2, ptEdge, vtEdge) == IPPT_YES) { + Plane3d plPlane3 ; plPlane3.Set( vPt5ax[i].ptP, vPt5ax[i].vtDir2 ^ vPt5ax[j].vtDir2) ; + Point3d ptInt ; + if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) { + // verifico se spigolo convesso o concavo + bool bConvex ; + if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP)) + bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ; else - ptInt = vIntRes[nI].ptI ; - // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) - Triangle3dEx trTria ; - if ( ! pSurfTm->GetTriangle( vIntRes[nI].nT, trTria)) - return false ; - Vector3d vtN ; - if ( ! CalcNormal( ptInt, trTria, vtN)) - vtN = trTria.GetN() ; - // aggiungo al vettore dei proiettati - vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ; + bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ; + // se convesso, metto due punti con direzione appena prima e appena dopo + if ( bConvex) { + Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ; + Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ; + if ( dLen1 > 2 * EPS_SMALL) { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ; + Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; + Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CVEX ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + if ( dLen2 > 2 * EPS_SMALL) { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; + Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; + Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CVEX ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } + } + // altrimenti concavo, aggiungo un solo punto con la direzione media + else { + Point5ax Pt5ax ; + Pt5ax.ptP = ptInt ; + Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; + Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; + Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + Pt5ax.nFlag = P5AX_CONC ; + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + ++ i ; + } } } } } - bFound = PL.GetNextUPoint( &dPar, &ptP) ; } - // eventuale rimozione punti in eccesso rispetto alle tolleranze lasciata alla funzione chiamante - - // copio i punti nel vettore di ritorno - vPt5ax.clear() ; - for ( const auto& Pt5ax : vMyPt5ax) { - if ( Pt5ax.nFlag != -1) - vPt5ax.emplace_back( Pt5ax) ; - } + // rimozione punti in eccesso rispetto alle tolleranze + RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; return true ; } +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const SurfTriMesh& stmSurf, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax) +{ + // punto sulla superficie guida a minima distanza + DistPointSurfTm dPS( ptP, stmRef) ; + Point3d ptMin ; + int nTriaMin ; + if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) { + // recupero direzione della retta di minima distanza, altrimenti normale alla superficie + Vector3d vtLine = ptP - ptMin ; + double dLineLen = vtLine.Len() ; + if ( dLineLen > EPS_SMALL) + vtLine /= dLineLen ; + else { + // calcolo la normale della superficie guida + Triangle3dEx trGuide ; + if ( ! stmRef.GetTriangle( nTriaMin, trGuide)) + return false ; + if ( ! CalcNormal( ptMin, trGuide, vtLine)) + 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 ; + } + } + } + return false ; +} + //---------------------------------------------------------------------------- bool ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef, - double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax) + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) { // sistemazioni per tipo di superficie const SurfTriMesh* pSurfTm = nullptr ; @@ -317,6 +703,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef case SRF_FLATRGN : pSurfTm = GetBasicSurfFlatRegion( &sfSurf)->GetAuxSurf() ; break ; + default : + break ; } if ( pSurfTm == nullptr) return false ; @@ -333,6 +721,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef case SRF_FLATRGN : pRefTm = GetBasicSurfFlatRegion( &sfRef)->GetAuxSurf() ; break ; + default : + break ; } if ( pRefTm == nullptr) return false ; @@ -341,7 +731,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef dLinTol = max( dLinTol, LIN_TOL_MIN) ; dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; - // approssimo la curva con una polilinea entro la metà della tolleranza + // 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 ; @@ -349,147 +739,46 @@ ProjectCurveOnSurf( const ICurve& crCrv, const ISurf& sfSurf, const ISurf& sfRef if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) return false ; - // Vettore locale dei punti risultanti - PNT5AXVECTOR vMyPt5ax ; - vMyPt5ax.reserve( PL.GetPointNbr()) ; + // Pulisco e riservo spazio nel vettore dei punti risultanti + vPt5ax.clear() ; + vPt5ax.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, *pRefTm) ; - Point3d ptMin ; - int nTriaMin ; - if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) { - // recupero direzione della retta di minima distanza, altrimenti normale alla superficie - Vector3d vtLine = ptP - ptMin ; - double dLineLen = vtLine.Len() ; - if ( dLineLen > EPS_SMALL) - vtLine /= dLineLen ; - else { - // calcolo la normale della superficie guida - Triangle3dEx trGuide ; - if ( ! pRefTm->GetTriangle( nTriaMin, trGuide)) - return false ; - if ( ! CalcNormal( ptMin, trGuide, vtLine)) - vtLine = trGuide.GetN() ; - dLineLen = 100 ; - } - // intersezione della retta con la superficie - ILSIVECTOR vIntRes ; - if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *pSurfTm, 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 ( ! pSurfTm->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 ( ! pRefTm->GetTriangle( nTriaMin, trGuide)) - return false ; - Vector3d vtN2 ; - if ( ! CalcNormal( ptMin, trGuide, vtN2)) - vtN2 = trGuide.GetN() ; - // aggiungo al vettore dei proiettati - vMyPt5ax.emplace_back( ptInt, vtN, vtN2, dPar, 1) ; - } - } - } + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptP, *pSurfTm, *pRefTm, dPar, Pt5ax)) + vPt5ax.emplace_back( Pt5ax) ; + // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; } - // eventuale rimozione punti in eccesso rispetto alle tolleranze lasciata alla funzione chiamante - - // copio i punti nel vettore di ritorno - vPt5ax.clear() ; - for ( const auto& Pt5ax : vMyPt5ax) { - if ( Pt5ax.nFlag != -1) - vPt5ax.emplace_back( Pt5ax) ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -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 -RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, double dLinTol, double dMaxSegmLen, bool bTestDir) -{ - // rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo - double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ; - double dSqTol = dLinTol * dLinTol ; - const double LENREF = 100 ; - double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ; - 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) ; - if ( bTestDir) { - Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ; - if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > dCosAngLim) - bRemove = true ; - } - else { - Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir2, vMyPt5ax[nNext].vtDir2, dPar) ; - if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir2 > dCosAngLim) - bRemove = true ; + // se superfici con non troppi triangoli, inserimento punti intermedi in presenza di spigoli + if ( pSurfTm->GetFacetCount() < MAX_FACET_FOR_CORNER) { + for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ 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, *pSurfTm, *pRefTm, dMid, Pt5ax)) { + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + -- i ; } } } - // 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 ; - } } + + // rimozione punti in eccesso rispetto alle tolleranze + RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; + return true ; } From f0716e2727e3fc37f14871230ddca1985e61dcb1 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 27 Mar 2025 15:25:07 +0100 Subject: [PATCH 6/7] EgtGeomKernel 2.7c4 : - aggiunte funzioni GetSurfTriMeshPyramidFrustum e GetSurfTriMeshConeFrustum - modificata funzione GetSurfTriMeshPyramid per origine ora in centro alla base. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes StmStandard.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 59ac372c6f18bccf048187a6aedc503417d206aa..98218448fb3e1325028501f271f802aa1950aaac 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&P#&A-_cnHfzcD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-WjGrO delta 94 zcmdlNy)SyhFE&P_&A-_cnHh~HD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-Vf-5U diff --git a/StmStandard.cpp b/StmStandard.cpp index edc409a..40a1545 100644 --- a/StmStandard.cpp +++ b/StmStandard.cpp @@ -172,15 +172,15 @@ GetSurfTriMeshPyramid( double dDimX, double dDimY, double dHeight) return nullptr ; // creo la polilinea del contorno della base PolyLine PL ; - PL.AddUPoint( 0, ORIG) ; - PL.AddUPoint( 1, Point3d( dDimX, 0, 0)) ; - PL.AddUPoint( 2, Point3d( dDimX, dDimY, 0)) ; - PL.AddUPoint( 3, Point3d( 0, dDimY, 0)) ; - PL.AddUPoint( 4, ORIG) ; + PL.AddUPoint( 0, Point3d( -dDimX / 2, -dDimY / 2, 0)) ; + PL.AddUPoint( 1, Point3d( dDimX / 2, -dDimY / 2, 0)) ; + PL.AddUPoint( 2, Point3d( dDimX / 2, dDimY / 2, 0)) ; + PL.AddUPoint( 3, Point3d( -dDimX / 2, dDimY / 2, 0)) ; + PL.AddUPoint( 4, Point3d( -dDimX / 2, -dDimY / 2, 0)) ; if ( dHeight < 0) PL.Invert() ; // punto di vertice - Point3d ptTip( 0.5 * dDimX, 0.5 * dDimY, dHeight) ; + Point3d ptTip( 0, 0, dHeight) ; // creo e setto la superficie trimesh laterale PtrOwner pSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL)) @@ -257,6 +257,111 @@ GetSurfTriMeshSphere( double dRadius, double dLinTol) return GetSurfTriMeshByRevolve( &cArc, ORIG, Z_AX, true, dLinTol) ; } +//------------------------------------------------------------------------------- +ISurfTriMesh* +GetSurfTriMeshPyramidFrustum( double dBaseDimX, double dBaseDimY, double dTopDimX, double dTopDimY, double dHeight) +{ + // le dimensioni devono essere significative + if ( ( min( dBaseDimX, dBaseDimY) < EPS_SMALL && min( dTopDimX, dTopDimY) < EPS_SMALL) || abs( dHeight) < EPS_SMALL) + return nullptr ; + // se piramide + if ( min( dTopDimX, dTopDimY) < EPS_SMALL) + return GetSurfTriMeshPyramid( dBaseDimX, dBaseDimY, dHeight) ; + // se piramide inversa + if ( min( dBaseDimX, dBaseDimY) < EPS_SMALL) + return GetSurfTriMeshPyramid( dTopDimX, dTopDimY, -dHeight) ; + // se parallelepipedo + // continuo qui per avere l'origine in centro e non sullo spigolo in basso a sinistra + // creo la polilinea del contorno della base + PolyLine PL1 ; + PL1.AddUPoint( 0, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ; + PL1.AddUPoint( 1, Point3d( dBaseDimX / 2, -dBaseDimY / 2, 0)) ; + PL1.AddUPoint( 2, Point3d( dBaseDimX / 2 , dBaseDimY / 2, 0)) ; + PL1.AddUPoint( 3, Point3d( -dBaseDimX / 2, dBaseDimY / 2, 0)) ; + PL1.AddUPoint( 4, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ; + if ( dHeight < 0) + PL1.Invert() ; + // creo la polilinea del contorno di sopra + PolyLine PL2 ; + PL2.AddUPoint( 0, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ; + PL2.AddUPoint( 1, Point3d( dTopDimX / 2, -dTopDimY / 2, dHeight)) ; + PL2.AddUPoint( 2, Point3d( dTopDimX / 2, dTopDimY / 2, dHeight)) ; + PL2.AddUPoint( 3, Point3d( -dTopDimX / 2, dTopDimY / 2, dHeight)) ; + PL2.AddUPoint( 4, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ; + if ( dHeight < 0) + PL2.Invert() ; + // creo e setto la superficie trimesh laterale + PtrOwner pSTM( CreateBasicSurfTriMesh()) ; + if ( IsNull( pSTM) || ! pSTM->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR_SMOOTH)) + return nullptr ; + // creo la superficie di base e ne inverto la normale + SurfTriMesh STM1 ; + if ( ! STM1.CreateByFlatContour( PL1)) + return nullptr ; + STM1.Invert() ; + // la unisco alla superficie del fianco + if ( ! pSTM->DoSewing( STM1)) + return nullptr ; + // creo la superficie sopra + SurfTriMesh STM2 ; + if ( ! STM2.CreateByFlatContour( PL2)) + return nullptr ; + // la unisco alla superficie del fianco + if ( ! pSTM->DoSewing( STM2)) + return nullptr ; + // restituisco la superficie + return Release( pSTM) ; +} + +//------------------------------------------------------------------------------- +ISurfTriMesh* +GetSurfTriMeshConeFrustum( double dBaseRad, double dTopRad, double dHeight, double dLinTol) +{ + // le dimensioni devono essere significative + if ( ( dBaseRad < EPS_SMALL && dTopRad < EPS_SMALL) || abs( dHeight) < EPS_SMALL) + return nullptr ; + // se cono + if ( dTopRad < EPS_SMALL) + return GetSurfTriMeshCone( dBaseRad, dHeight, dLinTol) ; + // se cono rovescio + if ( dBaseRad < EPS_SMALL) + return GetSurfTriMeshCone( dTopRad, -dHeight, dLinTol) ; + // se cilindro + if ( abs( dTopRad - dBaseRad) < EPS_SMALL) + return GetSurfTriMeshCylinder( dBaseRad, dHeight, dLinTol) ; + // creo la circonferenza sotto + CurveArc cArc1 ; + cArc1.Set( ORIG, Z_AX, dBaseRad) ; + if ( dHeight < 0) + cArc1.Invert() ; + // creo la circonferenza sopra + CurveArc cArc2 ; + cArc2.Set( Point3d( 0, 0, dHeight), Z_AX, dTopRad) ; + if ( dHeight < 0) + cArc2.Invert() ; + // creo la superficie laterale del cono + PtrOwner pSTM( GetSurfTriMeshRuled( &cArc1, &cArc2, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ; + if ( IsNull( pSTM)) + return nullptr ; + // creo la superficie sotto e la inverto + PtrOwner pSTM1( GetSurfTriMeshByFlatContour( &cArc1, dLinTol)) ; + if ( IsNull( pSTM1)) + return nullptr ; + pSTM1->Invert() ; + // la unisco alla superficie del fianco + if ( ! pSTM->DoSewing( *pSTM1)) + return nullptr ; + // creo la superficie sopra + PtrOwner pSTM2( GetSurfTriMeshByFlatContour( &cArc2, dLinTol)) ; + if ( IsNull( pSTM2)) + return nullptr ; + // la unisco alla superficie del fianco + if ( ! pSTM->DoSewing( *pSTM2)) + return nullptr ; + // restituisco la superficie + return Release( pSTM) ; +} + //------------------------------------------------------------------------------- ISurfTriMesh* GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt) From b7a4f0bff3e686f02169e80ac2476a87dc05a887 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Fri, 28 Mar 2025 20:17:50 +0100 Subject: [PATCH 7/7] EgtGeomKernel : - a SurfTriMesh aggiunto metodo CreateByPolygonWithHoles. --- SfrCreate.cpp | 6 ++---- SurfTriMesh.cpp | 11 +++++++++++ SurfTriMesh.h | 5 +++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/SfrCreate.cpp b/SfrCreate.cpp index 4d576d8..cc18437 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -577,10 +577,8 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId) bool CalcRegionPolyLines( const POLYLINEVECTOR& vPL, Vector3d& vtN, INTMATRIX& vnPLIndMat, BOOLVECTOR& vbInvert) { - // matrice di interi : ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle - // successive i loop interni - //INTMATRIX vnPLIndMat ; - // vettore di bool : riferito al vettore originale delle polyline, riporta true se la polyline è stata invertita + // vnPLIndMat : ogni riga corrisponde ad un chunk, in posizione 0 c'è il loop esterno e nelle successive i loop interni + // vbInvert : riferito al vettore delle polyline, riporta true se la polyline è stata invertita // ricavo versore normale Plane3d plPlane ; double dArea ; diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 3b22004..87e5ffb 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -2091,6 +2091,17 @@ SurfTriMesh::CreateByFlatContour( const PolyLine& PL) return AdjustTopology() ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL) +{ + INTMATRIX vnPLIndMat ; + vnPLIndMat.push_back( { 0}) ; + for ( int i = 1 ; i < int( vPL.size()) ; ++ i) + vnPLIndMat[0].push_back( i) ; + return CreateByRegion( vPL, vnPLIndMat) ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL, const INTMATRIX& vnPLIndMat) diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 135ea7e..96bdd43 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2023 +// EgalTech 2014-2025 //---------------------------------------------------------------------------- -// File : SurfTriMesh.h Data : 09.12.23 Versione : 2.5l2 +// File : SurfTriMesh.h Data : 28.03.25 Versione : 2.7c4 // Contenuto : Dichiarazione della classe Superficie TriMesh. // // @@ -251,6 +251,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool RemoveTriangle( int nId) override ; bool AdjustTopology( void) override ; bool CreateByFlatContour( const PolyLine& PL) override ; + bool CreateByPolygonWithHoles( const POLYLINEVECTOR& vPL) override ; bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) override ; bool CreateByPointCurve( const Point3d& ptP, const PolyLine& PL) override ; bool CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2, int nRuledType) override ;