From 563697f84083f19837d14e6cdeb07400f4168f1e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 26 Sep 2025 10:47:06 +0200 Subject: [PATCH] EgtGeomKernel : - correzione al box del volume spazzato VM 5assi - modificata gestione conversione curve a bezier. --- CurveAux.cpp | 51 ++++++++++++++++--------- VolZmapVolume.cpp | 96 +++++------------------------------------------ 2 files changed, 43 insertions(+), 104 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 938a5e3..ce190e1 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -544,6 +544,13 @@ ArcToBezierCurve( const ICurveArc* pArc, int nDeg, bool bMakeRatOrNot) PtrOwner pCrvBez( CreateBasicCurveBezier()) ; if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( *pArc)) return nullptr ; + if ( ! bMakeRatOrNot) { + Point3d ptCen = pArc->GetCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + pCrvBez.Set( ApproxArcCurveBezierWithSingleCubic( pCrvBez, ptCen, vtN)) ; + } + if ( IsNull( pCrvBez)) + return nullptr ; // aumento il grado della curva come richiesto while ( pCrvBez->GetDegree() < nDeg) pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; @@ -926,10 +933,8 @@ ApproxBezierWithCubics(const ICurve* pCrv, double dTol) Vector3d vtStartDir, vtEndDir ; pCrvBezier->GetPointD1D2( 0, ICurve::FROM_MINUS, ptStart, &vtStartDir) ; pCrvBezier->GetPointD1D2( 1, ICurve::FROM_PLUS, ptEnd, &vtEndDir) ; - Plane3d plPLane ; - plPLane.Set( ptStart, ptCtrl, ptEnd) ; - vtStartDir.Rotate( plPLane.GetVersN(), 90) ; - vtEndDir.Rotate( plPLane.GetVersN(), 90) ; + vtStartDir.Rotate( vtN, 90) ; + vtEndDir.Rotate( vtN, 90) ; Point3d ptAux1 = ptStart + vtStartDir ; Point3d ptAux2 = ptEnd + vtEndDir ; PtrOwner pCL1( CreateBasicCurveLine()) ; @@ -944,7 +949,7 @@ ApproxBezierWithCubics(const ICurve* pCrv, double dTol) double dDist2 = Dist( ptEnd, ptCen) ; if ( abs(dDist1 - dDist2) < EPS_SMALL ) { CurveArc cArc ; - cArc.SetC2PN( ptCen, ptStart, ptEnd, plPLane.GetVersN()) ; + cArc.SetC2PN( ptCen, ptStart, ptEnd, vtN) ; // controllo se il raggio della circonferenza risultante coincide con quello calcolato prima // impongo inoltre che l'angolo al centro sia minore di 90 gradi if ( abs( cArc.GetRadius() - dDist1) < EPS_SMALL && cArc.GetAngCenter() < 90 + EPS_SMALL) @@ -988,7 +993,7 @@ ApproxBezierWithCubics(const ICurve* pCrv, double dTol) if ( ! bIsArc) pCrvCubic.Set( ApproxCurveBezierWithSingleCubic( pCrvPart)) ; else { - pCrvCubic.Set( ApproxArcCurveBezierWithSingleCubic( pCrvPart, ptCen)) ; + pCrvCubic.Set( ApproxArcCurveBezierWithSingleCubic( pCrvPart, ptCen, vtN)) ; if ( IsNull( pCrvCubic)) { // se fallisce allora riprovo usando più di una bezier bIsArc = false ; @@ -1062,12 +1067,21 @@ ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) //---------------------------------------------------------------------------- ICurveBezier* -ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen) +ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen, const Vector3d& vtN) { - // verifico sia una bezier - const CurveBezier* pCrvBez = GetBasicCurveBezier( pCrv) ; - if ( pCrvBez == nullptr) - return nullptr ; + // verifico sia una bezier + const CurveBezier* pCrvBez = GetBasicCurveBezier( pCrv) ; + if ( pCrvBez == nullptr) + return nullptr ; + + // mi metto nel frame della curva ( lavoro nel piano XY) + Point3d ptStart = pCrvBez->GetControlPoint( 0) ; + Point3d ptEnd = pCrvBez->GetControlPoint( 2) ; + Frame3d frCrv; frCrv.Set( ptStart, vtN) ; + ptStart = ORIG ; + ptEnd.ToLoc( frCrv) ; + Point3d ptCenLoc = ptCen ; + ptCenLoc.ToLoc( frCrv) ; // converto una curva di bezier che definisce un arco perfetto di circonferenza // dato il centro( della circonferenza), inizio e fine @@ -1077,9 +1091,7 @@ ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen) bool bRat = pCrvBez->IsRational() ; if ( nDeg != 2 || ! bRat) return nullptr ; - - Point3d ptStart = pCrvBez->GetControlPoint( 0) ; - Point3d ptEnd = pCrvBez->GetControlPoint( 2) ; + if ( AreSamePointEpsilon( ptStart, ptEnd, EPS_SMALL * 50)) return nullptr ; nDeg = 3 ; @@ -1089,10 +1101,10 @@ ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen) pCrvCubic->SetControlPoint( 3, ptEnd) ; // from the article of Aleksas Riškus "Approximation of a cubic bezier curve by circular arcs and vice versa" // with corrections from "Hans Muller's Flex Blog", page "More About Approximating Circular Arcs With a Cubic Bezier Path" - double ax = ptStart.x - ptCen.x ; - double ay = ptStart.y - ptCen.y ; - double bx = ptEnd.x - ptCen.x ; - double by = ptEnd.y - ptCen.y ; + double ax = ptStart.x - ptCenLoc.x ; + double ay = ptStart.y - ptCenLoc.y ; + double bx = ptEnd.x - ptCenLoc.x ; + double by = ptEnd.y - ptCenLoc.y ; double q1 = ax * ax + ay * ay ; double q2 = q1 + ax * bx + ay * by ; double k2 = 4. / 3 * ( sqrt( 2 * q1 * q2) - q2) / ( ax * by - ay * bx) ; @@ -1104,6 +1116,9 @@ ApproxArcCurveBezierWithSingleCubic( const ICurve* pCrv, const Point3d& ptCen) pCrvCubic->SetControlPoint( 1, ptCtrl1) ; pCrvCubic->SetControlPoint( 2, ptCtrl2) ; + // ritorno nel frame originale + pCrvCubic->ToGlob( frCrv) ; + return Release( pCrvCubic) ; } diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index 412a668..20d1825 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -857,66 +857,16 @@ GetCylMoveBBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, d inline BBox3d GetCylMoveRotBBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV1, const Vector3d& vtV2, double dRad, double dH) { - // Determinazione dei punti più laterali del tool, rispetto alla direzione di movimento - // per la testa e per la punta del tool - Point3d ptP1T = ptP1 - dH * vtV1 ; - Point3d ptP2T = ptP2 - dH * vtV2 ; + // costruisco gli archi che definiscono il top e bottom del tool di partenza nel loro riferimento e li porto nel frame + BBox3d bbStart = GetCylMoveBBox( ptP1, ptP1, vtV1, dRad, dH) ; + BBox3d bbEnd = GetCylMoveBBox( ptP2, ptP2, vtV2, dRad, dH) ; + + // sommo i due box e li restituisco + BBox3d bbVol ; + bbVol.Add( bbStart) ; + bbVol.Add( bbEnd) ; - Vector3d vtDirTop = ptP2 - ptP1 ; - Vector3d vtDirTip = ptP2T - ptP1T ; - vtDirTop.Normalize() ; - vtDirTip.Normalize() ; - - // determino i punti laterali del top e del bottom(tip), nella posizione di partenza - Vector3d vtAuxTopS = vtV1 ^ vtDirTop ; - vtAuxTopS.Normalize() ; - vtAuxTopS *= dRad ; - Point3d ptPTop1 = ptP1 + vtAuxTopS ; - Point3d ptPTop2 = ptP1 - vtAuxTopS ; - - Vector3d vtAuxBottomS = vtV1 ^ vtDirTip ; - vtAuxBottomS.Normalize() ; - vtAuxBottomS *= dRad ; - Point3d ptPBottom1 = ptP1T + vtAuxBottomS ; - Point3d ptPBottom2 = ptP1T - vtAuxBottomS ; - - // determino i punti laterali del top e del bottom(tip), nella posizione di arrivo - Vector3d vtAuxTopE = vtV2 ^ vtDirTop ; - vtAuxTopE.Normalize() ; - vtAuxTopE *= dRad ; - Point3d ptPTop3 = ptP2 + vtAuxTopE ; - Point3d ptPTop4 = ptP2 - vtAuxTopE ; - - Vector3d vtAuxBottomE = vtV2 ^ vtDirTip ; - vtAuxBottomE.Normalize() ; - vtAuxBottomE *= dRad ; - Point3d ptPBottom3 = ptP2T + vtAuxBottomE ; - Point3d ptPBottom4 = ptP2T - vtAuxBottomE ; - - // calcolo anche i punti estremi iniziali e finali dei cilindri - Point3d ptTopEnd, ptBottomEnd, ptTopStart, ptBottomStart ; - ptTopEnd = ptP2 + vtDirTop * dRad ; - ptBottomEnd = ptP2T + vtDirTip * dRad ; - ptTopStart = ptP1 - vtDirTop * dRad ; - ptBottomStart = ptP1T - vtDirTip * dRad ; - - // Calcolo del box del volume spazzato dal tool - BBox3d b3Box ; - b3Box.Add( ptPTop1) ; - b3Box.Add( ptPTop2) ; - b3Box.Add( ptPBottom1) ; - b3Box.Add( ptPBottom2) ; - b3Box.Add( ptPTop3) ; - b3Box.Add( ptPTop4) ; - b3Box.Add( ptPBottom3) ; - b3Box.Add( ptPBottom4) ; - b3Box.Add( ptTopEnd) ; - b3Box.Add( ptBottomEnd) ; - b3Box.Add( ptTopStart) ; - b3Box.Add( ptBottomStart) ; - - // Restituisco il box calcolato - return b3Box ; + return bbVol ; } //---------------------------------------------------------------------------- @@ -1599,10 +1549,6 @@ Reiterate : return true ; } -#if true - #define TEST -#endif - //---------------------------------------------------------------------------- bool VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtLs, const Vector3d& vtLe, @@ -1999,11 +1945,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c } } -#ifdef TEST - vector vGeo ; - vector vCol( nTotSurf) ; -#endif - // inizializzo le superfici bilineari e i parametri per le intersezioni for ( int z = 0 ; z < int( vvPtCtrl.size()) ; ++z) { vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; @@ -2070,23 +2011,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c vSurfBez[nSurfInd].bbSurfY.Add( vPtCtrlLoc) ; } -#ifdef TEST - //debug - if ( nGrid == 0) - vGeo.push_back( vSurfBez[nSurfInd].sBez.Clone()) ; - //debug -#endif - - ++nSurfInd ; - } - -#ifdef TEST - if ( false) { - fill( vCol.begin(), vCol.end(), Color( 255, 128, 0)) ; - SaveGeoObj( vGeo, vCol, "D:/Temp/VirtualMilling/5axisAdvanced/finalApprox.nge", 2) ; - } -#endif - // scorro tutti gli spilloni interessati int j = 0 ; int nLastForwardJ = -1 ; @@ -2499,7 +2423,7 @@ VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, co InitializePointsAndVectors( ptSti, ptEni, vtDSi, vtDEi, ptLs, ptLe, vtLs, vtLe); // Standard è multithread - constexpr bool MULTITHREAD = true; + constexpr bool MULTITHREAD = true ; if ( MULTITHREAD) { // Ciclo sulle mappe vector> vRes( m_nMapNum) ;