From ff2cc4f999e2d4314229a32287d255625ff0b2af Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 7 Aug 2025 11:22:43 +0200 Subject: [PATCH] EgtGeomKernel : - prima versione del VM5 assi con superfici di bezier 3x1. --- VolZmapVolume.cpp | 1391 +++++++++++++++++---------------------------- 1 file changed, 534 insertions(+), 857 deletions(-) diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index 2215e98..742461c 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -16,6 +16,7 @@ #include "stdafx.h" #include "CurveLine.h" #include "CurveArc.h" +#include "CurveBezier.h" #include "VolZmap.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkStringUtils3d.h" @@ -1331,39 +1332,45 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt int nStepCnt = int( ptS.size()) ; // vettori di riferimento per trovare i punti ausiliari - int nDegU = 1 ; int nDegV = 1 ; + int nDegU = 3 ; int nDegV = 1 ; int nSpanU = 1 ; int nSpanV = 1 ; bool bRat = false ; - int nSub = 4 ; // numero di bilineari con cui approssimare il (quasi) semi-cilindro ellissoide che descrive il volume della punta e della cima del tool + int nSub = 2 ; // numero di bezier di grado 3x1 con cui approssimare il (quasi) semi-cilindro ellissoide che descrive il volume della punta e della cima del tool PNTVECTOR d ; Vector3d q = Z_AX ; - DBLVECTOR A1, B1, C1, A2, B2, C2 ; + int nTotSurf = 4; if ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS) - nTotSurf = 2 * nStepCnt + nSub * 2 * nStepCnt + nSub * 2 ; // sup laterali, sup superiori e inferiori, superfici verticali di inizio e fine + nTotSurf = 2 * nStepCnt + nSub * 2 * nStepCnt + nSub * 2 + 8 ; // sup laterali, sup superiori e inferiori, superfici verticali di inizio e fine, superfici di base dei tool else if( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX || n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE) - nTotSurf = 2 * nStepCnt + nSub * 2 * nStepCnt + nStepCnt + nSub * 2 + nSub * 2 ; // ..come sopra.. + verticali esterne + verticali interne + nTotSurf = 2 * nStepCnt + nSub * 2 * nStepCnt + nStepCnt + nSub * 2 + 12 ; // ..come sopra.. else if( n5AxisType == VolZmap::Move5Axis::ACROSS) - nTotSurf = 2 * nStepCnt + nSub * 4 * nStepCnt + nSub * 4 ; // come caso ALONG + nTotSurf = 2 * nStepCnt + nSub * 4 * nStepCnt + nSub * 2 + 16 ; // come caso ALONG + + VCT3DVECTOR a3( nTotSurf) ; + VCT3DVECTOR a2( nTotSurf) ; + VCT3DVECTOR a1( nTotSurf) ; + VCT3DVECTOR a0( nTotSurf) ; + VCT3DVECTOR b3( nTotSurf) ; + VCT3DVECTOR b2( nTotSurf) ; + VCT3DVECTOR b1( nTotSurf) ; + VCT3DVECTOR b0( nTotSurf) ; int nSurfInd = 0 ; ISURFBEZPOVECTOR vSurfBez( nTotSurf * nStepCnt) ; BOXVECTOR vSurfBox( nTotSurf * nStepCnt) ; double dSide = 0 ; // punti per le bilineari, sulle posizioni del tool alle estremità del movimento - PNTVECTOR vPntTipStartEx ; - PNTVECTOR vPntTipEndEx ; - PNTVECTOR vPntTopStartEx ; - PNTVECTOR vPntTopEndEx ; - PNTVECTOR vPntTipStartEx2 ; - PNTVECTOR vPntTipEndEx2 ; - PNTVECTOR vPntTopStartEx2 ; - PNTVECTOR vPntTopEndEx2 ; - Vector3d vtDirTopStartEx ; - Vector3d vtDirTopEndEx ; - Vector3d vtDirTipStartEx ; - Vector3d vtDirTipEndEx ; + PNTVECTOR vPntTipStartExF ; + PNTVECTOR vPntTipEndExF ; + PNTVECTOR vPntTopStartExF ; + PNTVECTOR vPntTopEndExF ; + PNTVECTOR vPntTipStartExB ; + PNTVECTOR vPntTipEndExB ; + PNTVECTOR vPntTopStartExB ; + PNTVECTOR vPntTopEndExB ; + Point3d ptP1TEx, ptP2TEx ; #ifdef TEST //debug @@ -1419,28 +1426,24 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt ptBottom2e = ptP2T - vtAuxBottomE ; // punti sul top e tip del tool che servono per costruire le bilineare di congiunzione tra step - PNTVECTOR vPntTipStart ; - PNTVECTOR vPntTipEnd ; - PNTVECTOR vPntTopStart ; - PNTVECTOR vPntTopEnd ; + PNTVECTOR vPntTipStartFront ; + PNTVECTOR vPntTipEndFront ; + PNTVECTOR vPntTopStartFront ; + PNTVECTOR vPntTopEndFront ; // punti addizionali che servono nei casi che rischiedono più superfici bilineari ( tutti tranne NO_BASE_INTERS) - PNTVECTOR vPntTipStart2 ; - PNTVECTOR vPntTipEnd2 ; - PNTVECTOR vPntTopStart2 ; - PNTVECTOR vPntTopEnd2 ; + PNTVECTOR vPntTipStartBack ; + PNTVECTOR vPntTipEndBack ; + PNTVECTOR vPntTopStartBack ; + PNTVECTOR vPntTopEndBack ; if ( nSub > 1) { // determino in che modo collegare il cilindro iniziale con quello finale Vector3d vtTopBaseEnd = vtDirTop - ( (vtDirTop * vtLe[s]) * vtLe[s]) ; vtTopBaseEnd.Normalize() ; vtTopBaseEnd *= dMaxRad ; - if ( s == nStepCnt - 1) - vtDirTopEndEx = vtTopBaseEnd ; Point3d ptRefEnd = ptE[s] - vtTopBaseEnd ; Vector3d vtTopBaseStart = vtDirTop - ( ( vtDirTop * vtLs[s]) * vtLs[s]) ; vtTopBaseStart.Normalize() ; vtTopBaseStart *= dMaxRad ; - if ( s == 0) - vtDirTopStartEx = vtTopBaseStart ; Point3d ptRefStart = ptS[s] + vtTopBaseStart ; dSide = (ptRefEnd - ptRefStart) * vtLs[s] ; @@ -1453,97 +1456,86 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Vector3d vtTipBaseStart = - (vtLs[s] ^ vtDirTip) ; vtTipBaseStart.Normalize() ; vtTipBaseStart *= dMinRad ; - if ( s == 0) { - vtDirTipStartEx = vtTipBaseStart ; - vtDirTipStartEx.Rotate( vtLs[s], 90) ; - } Vector3d vtTipBaseEnd = - (vtLe[s] ^ vtDirTip) ; vtTipBaseEnd.Normalize() ; vtTipBaseEnd *= dMinRad ; - if ( s == nStepCnt - 1) { - vtDirTipEndEx = vtTipBaseEnd ; - vtDirTipEndEx.Rotate( vtLe[s], 90) ; - } // aggiungo il primo punto per ognuno dei gruppi vtTopBaseStart.Rotate( vtLs[s], 90) ; vtTopBaseEnd.Rotate( vtLe[s], 90) ; - vPntTopStart.emplace_back( ptS[s] + vtTopBaseStart) ; - vPntTopEnd.emplace_back( ptE[s] + vtTopBaseEnd) ; - vPntTipStart.emplace_back( ptP1T + vtTipBaseStart) ; - vPntTipEnd.emplace_back( ptP2T + vtTipBaseEnd) ; + vPntTopStartFront.emplace_back( ptS[s] - vtTopBaseStart) ; + vPntTopEndFront.emplace_back( ptE[s] - vtTopBaseEnd) ; + vPntTipStartFront.emplace_back( ptP1T + vtTipBaseStart) ; + vPntTipEndFront.emplace_back( ptP2T + vtTipBaseEnd) ; // punti addizionali per superfici bilineari - vPntTopStart2.emplace_back( ptS[s] + vtTopBaseStart) ; - vPntTopEnd2.emplace_back( ptE[s] + vtTopBaseEnd) ; - vPntTipStart2.emplace_back( ptP1T + vtTipBaseStart) ; - vPntTipEnd2.emplace_back( ptP2T + vtTipBaseEnd) ; - double dSubAng = 180. / nSub ; - // se dSide si discosta da zero allora devo usare più di una superficie per definire la parte superiore e inferiore del volume spazzata dal tool - for ( int i = 0 ; i < nSub ; ++i) { + vPntTopStartBack.emplace_back( ptS[s] + vtTopBaseStart) ; + vPntTopEndBack.emplace_back( ptE[s] + vtTopBaseEnd) ; + vPntTipStartBack.emplace_back( ptP1T - vtTipBaseStart) ; + vPntTipEndBack.emplace_back( ptP2T - vtTipBaseEnd) ; + double dSubAng = 90 ; + // girano tutti in verso CCW rispetto alla normale del tool + for ( int i = 0 ; i < 2 ; ++i) { // punti sulla base superiore dei cilindri - vPntTopStart.emplace_back( vPntTopStart.back()) ; - vPntTopStart2.emplace_back( vPntTopStart2.back()) ; - if ( dSide > 0){ - vPntTopStart.back().Rotate(ptS[s], vtLs[s], dSubAng) ; - vPntTopStart2.back().Rotate(ptS[s], vtLs[s], -dSubAng) ; - } - else{ - vPntTopStart.back().Rotate(ptS[s], vtLs[s], -dSubAng) ; - vPntTopStart2.back().Rotate(ptS[s], vtLs[s], dSubAng) ; - } - vPntTopEnd.emplace_back( vPntTopEnd.back()) ; - vPntTopEnd2.emplace_back( vPntTopEnd2.back()) ; - if ( dSide > 0){ - vPntTopEnd.back().Rotate(ptE[s], vtLe[s], dSubAng) ; - vPntTopEnd2.back().Rotate(ptE[s], vtLe[s], -dSubAng) ; - } - else{ - vPntTopEnd.back().Rotate(ptE[s], vtLe[s], -dSubAng) ; - vPntTopEnd2.back().Rotate(ptE[s], vtLe[s], dSubAng) ; - } + // start + //// frontale + vPntTopStartFront.emplace_back( vPntTopStartFront.back()) ; + vPntTopStartFront.back().Rotate(ptS[s], vtLs[s], dSubAng) ; + //// posteriore + vPntTopStartBack.emplace_back( vPntTopStartBack.back()) ; + vPntTopStartBack.back().Rotate(ptS[s], vtLs[s], dSubAng) ; + // end + //// frontale + vPntTopEndFront.emplace_back( vPntTopEndFront.back()) ; + vPntTopEndFront.back().Rotate(ptE[s], vtLe[s], dSubAng) ; + //// posteriore + vPntTopEndBack.emplace_back( vPntTopEndBack.back()) ; + vPntTopEndBack.back().Rotate(ptE[s], vtLe[s], dSubAng) ; // punti sulla base inferiore dei cilindri - vPntTipStart.emplace_back( vPntTipStart.back()) ; - vPntTipStart2.emplace_back( vPntTipStart2.back()) ; - if ( dSide > 0){ - vPntTipStart.back().Rotate(ptP1T, vtLs[s], dSubAng) ; - vPntTipStart2.back().Rotate(ptP1T, vtLs[s], -dSubAng) ; - } - else{ - vPntTipStart.back().Rotate(ptP1T, vtLs[s], -dSubAng) ; - vPntTipStart2.back().Rotate(ptP1T, vtLs[s], dSubAng) ; - } - vPntTipEnd.emplace_back( vPntTipEnd.back()) ; - vPntTipEnd2.emplace_back( vPntTipEnd2.back()) ; - if ( dSide > 0){ - vPntTipEnd.back().Rotate(ptP2T, vtLe[s], dSubAng) ; - vPntTipEnd2.back().Rotate(ptP2T, vtLe[s], -dSubAng) ; - } - else{ - vPntTipEnd.back().Rotate(ptP2T, vtLe[s], -dSubAng) ; - vPntTipEnd2.back().Rotate(ptP2T, vtLe[s], dSubAng) ; - } + vPntTipStartFront.emplace_back( vPntTipStartFront.back()) ; + vPntTipStartFront.back().Rotate(ptP1T, vtLs[s], dSubAng) ; + vPntTipStartBack.emplace_back( vPntTipStartBack.back()) ; + vPntTipStartBack.back().Rotate(ptP1T, vtLs[s], dSubAng) ; + + vPntTipEndFront.emplace_back( vPntTipEndFront.back()) ; + vPntTipEndFront.back().Rotate(ptP2T, vtLe[s], dSubAng) ; + vPntTipEndBack.emplace_back( vPntTipEndBack.back()) ; + vPntTipEndBack.back().Rotate(ptP2T, vtLe[s], dSubAng) ; } } // mi salvo i punti ausiliari per la posizione iniziale e finale del tool if ( s == 0) { - vPntTipStartEx = vPntTipStart ; - vPntTopStartEx = vPntTopStart ; - vPntTipStartEx2 = vPntTipStart2 ; - vPntTopStartEx2 = vPntTopStart2 ; + vPntTipStartExF = vPntTipStartFront ; + vPntTopStartExF = vPntTopStartFront ; + vPntTipStartExB = vPntTipStartBack ; + vPntTopStartExB = vPntTopStartBack ; + ptP1TEx = ptP1T ; } if ( s == nStepCnt - 1) { - vPntTipEndEx = vPntTipEnd ; - vPntTopEndEx = vPntTopEnd ; - vPntTipEndEx2 = vPntTipEnd2 ; - vPntTopEndEx2 = vPntTopEnd2 ; + vPntTipEndExF = vPntTipEndFront ; + vPntTopEndExF = vPntTopEndFront ; + vPntTipEndExB = vPntTipEndBack ; + vPntTopEndExB = vPntTopEndBack ; + ptP2TEx = ptP2T ; } vector vvPtCtrl ; // superficie laterale sinistra - vvPtCtrl.emplace_back( PNTVECTOR({ ptBottom1s, ptTop1s, ptBottom1e, ptTop1e})) ; + CurveLine cLineLeftStart ; cLineLeftStart.Set( ptBottom1s, ptTop1s) ; + PtrOwner cBezLeftStart( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftStart, nDegU, bRat))) ; + CurveLine cLineLeftEnd ; cLineLeftEnd.Set( ptBottom1e, ptTop1e) ; + PtrOwner cBezLeftEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftEnd, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezLeftStart->GetAllControlPoints()) ; + PNTVECTOR vPntLeft = cBezLeftEnd->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ; // superficie laterale destra - vvPtCtrl.emplace_back( PNTVECTOR({ ptTop2s, ptBottom2s, ptTop2e, ptBottom2e})) ; + CurveLine cLineRightStart ; cLineRightStart.Set( ptTop2s, ptBottom2s) ; + PtrOwner cBezRightStart( GetBasicCurveBezier( LineToBezierCurve( &cLineRightStart, nDegU, bRat))) ; + CurveLine cLineRightEnd ; cLineRightEnd.Set( ptTop2e, ptBottom2e) ; + PtrOwner cBezRightEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineRightEnd, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezRightStart->GetAllControlPoints()) ; + PNTVECTOR vPntRight = cBezRightEnd->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ; if ( nSub == 1) { // superficie inferiore vvPtCtrl.emplace_back( PNTVECTOR({ ptBottom2s, ptBottom1s, ptBottom2e, ptBottom1e})) ; @@ -1552,113 +1544,356 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt } else { if( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS || n5AxisType == VolZmap::Move5Axis::ACROSS){ - // superfici inferiori - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart[i], vPntTipStart[i+1], vPntTipEnd[i], vPntTipEnd[i+1]})) ; + CurveArc cArcTipStart1, cArcTipEnd1, cArcTipStart2,cArcTipEnd2 ; + if ( dSide > 0) { + cArcTipStart1.SetC2PN( ptP1T, vPntTipStartFront[0], vPntTipStartFront[1], vtLs[s]) ; + cArcTipEnd1.SetC2PN( ptP2T, vPntTipEndFront[0], vPntTipEndFront[1], vtLe[s]) ; + cArcTipStart2.SetC2PN( ptP1T, vPntTipStartFront[1], vPntTipStartFront[2], vtLs[s]) ; + cArcTipEnd2.SetC2PN( ptP2T, vPntTipEndFront[1], vPntTipEndFront[2], vtLe[s]) ; } - // superfici superiori - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTopStart[i], vPntTopStart[i+1], vPntTopEnd[i], vPntTopEnd[i+1]})) ; + else { + cArcTipStart1.SetC2PN( ptP1T, vPntTipStartBack[1], vPntTipStartBack[0], vtLs[s]) ; + cArcTipEnd1.SetC2PN( ptP2T, vPntTipEndBack[1], vPntTipEndBack[0], vtLe[s]) ; + cArcTipStart2.SetC2PN( ptP1T, vPntTipStartBack[2], vPntTipStartBack[1], vtLs[s]) ; + cArcTipEnd2.SetC2PN( ptP2T, vPntTipEndBack[2], vPntTipEndBack[1], vtLe[s]) ; } - // chiudo il volume con le superici verticali all'ultimo step - if( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && s == nStepCnt - 1) { - for ( int i = 0 ; i < nSub ; ++i ) - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStartEx[i+1], vPntTipStartEx[i], vPntTopStartEx[nSub - i - 1], vPntTopStartEx[nSub - i]})) ; - for ( int i = 0 ; i < nSub ; ++i ) - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipEndEx[i], vPntTipEndEx[i+1], vPntTopEndEx[nSub - i], vPntTopEndEx[nSub - i- 1]})) ; + // superfici inferiori 1 + PtrOwner cBezTipStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart1, nDegU, bRat))) ; + PtrOwner cBezTipEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart1->GetAllControlPoints()) ; + PNTVECTOR vPntTipEnd1 = cBezTipEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd1.begin(), vPntTipEnd1.end()) ; + // superfici inferiori 2 + PtrOwner cBezTipStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart2, nDegU, bRat))) ; + PtrOwner cBezTipEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart2->GetAllControlPoints()) ; + PNTVECTOR vPntTipEnd2 = cBezTipEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEnd2.begin(), vPntTipEnd2.end()) ; + // superfici superiori 1 + CurveArc cArcTopStart1, cArcTopEnd1, cArcTopStart2, cArcTopEnd2 ; + if ( dSide > 0) { + cArcTopStart1.SetC2PN( ptS[s], vPntTopStartBack[0], vPntTopStartBack[1], vtLs[s]) ; + cArcTopEnd1.SetC2PN( ptE[s], vPntTopEndBack[0], vPntTopEndBack[1], vtLe[s]) ; + cArcTopStart2.SetC2PN( ptS[s], vPntTopStartBack[1], vPntTopStartBack[2], vtLs[s]) ; + cArcTopEnd2.SetC2PN( ptE[s], vPntTopEndBack[1], vPntTopEndBack[2], vtLe[s]) ; } + else { + cArcTopStart1.SetC2PN( ptS[s], vPntTopStartFront[1], vPntTopStartFront[0], vtLs[s]) ; + cArcTopEnd1.SetC2PN( ptE[s], vPntTopEndFront[1], vPntTopEndFront[0], vtLe[s]) ; + cArcTopStart2.SetC2PN( ptS[s], vPntTopStartFront[2], vPntTopStartFront[1], vtLs[s]) ; + cArcTopEnd2.SetC2PN( ptE[s], vPntTopEndFront[2], vPntTopEndFront[1], vtLe[s]) ; + } + PtrOwner cBezTopStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart1, nDegU, bRat))) ; + PtrOwner cBezTopEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart1->GetAllControlPoints()) ; + PNTVECTOR vPntTopEnd1 = cBezTopEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd1.begin(), vPntTopEnd1.end()) ; + // superfici superiori 2 + PtrOwner cBezTopStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart2, nDegU, bRat))) ; + PtrOwner cBezTopEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart2->GetAllControlPoints()) ; + PNTVECTOR vPntTopEnd2 = cBezTopEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEnd2.begin(), vPntTopEnd2.end()) ; // aggiungo le superfici bilineari anche nell'altro verso sia per il top che per il tip if( n5AxisType == VolZmap::Move5Axis::ACROSS) { - // inferiori - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart2[i], vPntTipStart2[i+1], vPntTipEnd2[i], vPntTipEnd2[i+1]})) ; + CurveArc cArcTipStart1, cArcTipEnd1, cArcTipStart2, cArcTipEnd2 ; + if ( dSide > 0) { + cArcTipStart1.SetC2PN( ptP1T, vPntTipStartBack[1], vPntTipStartBack[0], vtLs[s]) ; + cArcTipEnd1.SetC2PN( ptP2T, vPntTipEndBack[1], vPntTipEndBack[0], vtLe[s]) ; + cArcTipStart2.SetC2PN( ptP1T, vPntTipStartBack[2], vPntTipStartBack[1], vtLs[s]) ; + cArcTipEnd2.SetC2PN( ptP2T, vPntTipEndBack[2], vPntTipEndBack[1], vtLe[s]) ; } - // superfici superiori - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTopStart2[i], vPntTopStart2[i+1], vPntTopEnd2[i], vPntTopEnd2[i+1]})) ; + else { + cArcTipStart1.SetC2PN( ptP1T, vPntTipStartFront[0], vPntTipStartFront[1], vtLs[s]) ; + cArcTipEnd1.SetC2PN( ptP2T, vPntTipEndFront[0], vPntTipEndFront[1], vtLe[s]) ; + cArcTipStart2.SetC2PN( ptP1T, vPntTipStartFront[1], vPntTipStartFront[2], vtLs[s]) ; + cArcTipEnd2.SetC2PN( ptP2T, vPntTipEndFront[1], vPntTipEndFront[2], vtLe[s]) ; } - // all'ultimo step chiudo i volumi delimitati dalle bilineari - if( s == nStepCnt - 1) { - // chiudo il volume con le superici verticali, 1o volume, interne - for ( int i = 0 ; i < nSub ; ++i) - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStartEx[i+1], vPntTipStartEx[i], vPntTopStartEx2[nSub - i - 1], vPntTopStartEx2[nSub - i]})) ; - // chiudo il volume con le superici verticali, 2o volume, interne - for ( int i = 0 ; i < nSub ; ++i) - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipEndEx2[i], vPntTipEndEx2[i+1], vPntTopEndEx[nSub - i], vPntTopEndEx[nSub - i -1]})) ; - // chiudo il volume con le superici verticali, 1o volume, esterne - for ( int i = 0 ; i < nSub ; ++i) - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipEndEx[i], vPntTipEndEx[i+1], vPntTopEndEx2[nSub - i], vPntTopEndEx2[nSub - i - 1]})) ; - // chiudo il volume con le superici verticali, 2o volume, esterne - for ( int i = 0 ; i < nSub ; ++i) - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStartEx2[i+1], vPntTipStartEx2[i], vPntTopStartEx[nSub - i - 1], vPntTopStartEx[nSub - i]})) ; + // inferiori 1 + PtrOwner cBezTipStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart1, nDegU, bRat))) ; + PtrOwner cBezTipEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart1->GetAllControlPoints()) ; + PNTVECTOR vPntTip1 = cBezTipEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ; + // inferiori 2 + PtrOwner cBezTipStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart2, nDegU, bRat))) ; + PtrOwner cBezTipEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart2->GetAllControlPoints()) ; + PNTVECTOR vPntTip2 = cBezTipEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ; + + CurveArc cArcTopStart1, cArcTopEnd1, cArcTopStart2, cArcTopEnd2 ; + if ( dSide > 0) { + cArcTopStart1.SetC2PN( ptS[s], vPntTopStartFront[1], vPntTopStartFront[0], vtLs[s]) ; + cArcTopEnd1.SetC2PN( ptE[s], vPntTopEndFront[1], vPntTopEndFront[0], vtLe[s]) ; + cArcTopStart2.SetC2PN( ptS[s], vPntTopStartFront[2], vPntTopStartFront[1], vtLs[s]) ; + cArcTopEnd2.SetC2PN( ptE[s], vPntTopEndFront[2], vPntTopEndFront[1], vtLe[s]) ; } + else { + cArcTopStart1.SetC2PN( ptS[s], vPntTopStartBack[0], vPntTopStartBack[1], vtLs[s]) ; + cArcTopEnd1.SetC2PN( ptE[s], vPntTopEndBack[0], vPntTopEndBack[1], vtLe[s]) ; + cArcTopStart2.SetC2PN( ptS[s], vPntTopStartBack[1], vPntTopStartBack[2], vtLs[s]) ; + cArcTopEnd2.SetC2PN( ptE[s], vPntTopEndBack[1], vPntTopEndBack[2], vtLe[s]) ; + } + // superfici superiori 1 + PtrOwner cBezTopStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart1, nDegU, bRat))) ; + PtrOwner cBezTopEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart1->GetAllControlPoints()) ; + PNTVECTOR vPntTop1 = cBezTopEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.begin(), vPntTop1.end()) ; + // superfici superiori 2 + PtrOwner cBezTopStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart2, nDegU, bRat))) ; + PtrOwner cBezTopEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart2->GetAllControlPoints()) ; + PNTVECTOR vPntTop2 = cBezTopEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.begin(), vPntTop2.end()) ; } } else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX) { - // superfici superiori - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTopStart[i], vPntTopStart[i+1], vPntTopEnd[i], vPntTopEnd[i+1]})) ; - } - // superfici superiori nell'altro verso - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTopStart2[i], vPntTopStart2[i+1], vPntTopEnd2[i], vPntTopEnd2[i+1]})) ; - } - // superfici inferiori semplici - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart.front(), vPntTipStart.back(), vPntTipEnd.front(), vPntTipEnd.back()})) ; + // superfici superiori 1 + CurveArc cArcTopStart1, cArcTopEnd1, cArcTopStart2, cArcTopEnd2 ; + cArcTopStart1.SetC2PN( ptS[s], vPntTopStartExF[1], vPntTopStartExF[0], vtLs[s]) ; + cArcTopEnd1.SetC2PN( ptE[s], vPntTopEndExF[1], vPntTopEndExF[0], vtLe[s]) ; + cArcTopStart2.SetC2PN( ptS[s], vPntTopStartExF[2], vPntTopStartExF[1], vtLs[s]) ; + cArcTopEnd2.SetC2PN( ptE[s], vPntTopEndExF[2], vPntTopEndExF[1], vtLe[s]) ; + PtrOwner cBezTopStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart1, nDegU, bRat))) ; + PtrOwner cBezTopEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart1->GetAllControlPoints()) ; + PNTVECTOR vPntTop1 = cBezTopEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop1.begin(), vPntTop1.end()) ; + // superfici superiori 2 + PtrOwner cBezTopStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart2, nDegU, bRat))) ; + PtrOwner cBezTopEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart2->GetAllControlPoints()) ; + PNTVECTOR vPntTop2 = cBezTopEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop2.begin(), vPntTop2.end()) ; + // superfici superiori indietro 1 + CurveArc cArcTopStart3, cArcTopEnd3, cArcTopStart4, cArcTopEnd4 ; + cArcTopStart3.SetC2PN( ptS[s], vPntTopStartExB[0], vPntTopStartExB[1], vtLs[s]) ; + cArcTopEnd3.SetC2PN( ptE[s], vPntTopEndExB[0], vPntTopEndExB[1], vtLe[s]) ; + cArcTopStart4.SetC2PN( ptS[s], vPntTopStartExB[1], vPntTopStartExB[2], vtLs[s]) ; + cArcTopEnd4.SetC2PN( ptE[s], vPntTopEndExB[1], vPntTopEndExB[2], vtLe[s]) ; + PtrOwner cBezTopStart3( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart3, nDegU, bRat))) ; + PtrOwner cBezTopEnd3( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd3, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart3->GetAllControlPoints()) ; + PNTVECTOR vPntTop3 = cBezTopEnd3->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop3.begin(), vPntTop3.end()) ; + // superfici superiori indietro 2 + PtrOwner cBezTopStart4( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart4, nDegU, bRat))) ; + PtrOwner cBezTopEnd4( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd4, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart4->GetAllControlPoints()) ; + PNTVECTOR vPntTop4 = cBezTopEnd4->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop4.begin(), vPntTop4.end()) ; - if( s == nStepCnt - 1) { - // calcolo i punti di split dei diametri - PNTVECTOR vSplitDiamStart ; - PNTVECTOR vSplitDiamEnd ; - Vector3d vDirDiamStart = (vPntTipStartEx.back() - vPntTipStartEx.front()) / nSub ; - Vector3d vDirDiamEnd = (vPntTipEndEx.back() - vPntTipEndEx.front()) / nSub ; - for ( int i = 0 ; i <= nSub ; ++i) { - vSplitDiamStart.push_back( vPntTipStartEx.front() + i * vDirDiamStart) ; - vSplitDiamEnd.push_back( vPntTipEndEx.front() + i * vDirDiamEnd) ; - } - // aggiungo le superfici verticali esterne - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamStart[i+1], vSplitDiamStart[i], vPntTopStartEx[nSub - i - 1], vPntTopStartEx[nSub - i]})) ; - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamEnd[i], vSplitDiamEnd[i+1], vPntTopEndEx2[nSub - i], vPntTopEndEx2[nSub - i- 1]})) ; - } - // aggiungo le superfici verticali interne - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamStart[i+1], vSplitDiamStart[i], vPntTopStartEx2[nSub - i - 1], vPntTopStartEx2[nSub - i]})) ; - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamEnd[i], vSplitDiamEnd[i+1], vPntTopEndEx[nSub - i], vPntTopEndEx[nSub - i- 1]})) ; - } - } + // superfici inferiori semplici + CurveLine cLineStart ; cLineStart.Set( vPntTipStartBack[s], vPntTipStartBack[s]) ; + PtrOwner cBezTipStart( GetBasicCurveBezier( LineToBezierCurve( &cLineStart, nDegU, bRat))) ; + CurveLine cLineEnd ; cLineEnd.Set( vPntTipEndBack[s], vPntTipEndBack[s]) ; + PtrOwner cBezTipEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineEnd, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart->GetAllControlPoints()) ; + PNTVECTOR vPntTip = cBezTipEnd->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip.begin(), vPntTip.end()) ; } else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE) { - // superfici inferiori - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart[i], vPntTipStart[i+1], vPntTipEnd[i], vPntTipEnd[i+1]})) ; - } - // superfici inferiori nell'altro verso - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTipStart2[i], vPntTipStart2[i+1], vPntTipEnd2[i], vPntTipEnd2[i+1]})) ; - } - // superfici superiori semplici - vvPtCtrl.emplace_back( PNTVECTOR({ vPntTopStart.front(), vPntTopStart.back(), vPntTopEnd.front(), vPntTopEnd.back()})) ; + // inferiori 1 + CurveArc cArcTipStart1, cArcTipEnd1, cArcTipStart2, cArcTipEnd2 ; + cArcTipStart1.SetC2PN( ptP1T, vPntTipStartFront[0], vPntTipStartFront[1], vtLs[s]) ; + cArcTipEnd1.SetC2PN( ptP2T, vPntTipEndFront[0], vPntTipEndFront[1], vtLe[s]) ; + cArcTipStart2.SetC2PN( ptP1T, vPntTipStartFront[1], vPntTipStartFront[2], vtLs[s]) ; + cArcTipEnd2.SetC2PN( ptP2T, vPntTipEndFront[1], vPntTipEndFront[2], vtLe[s]) ; + PtrOwner cBezTipStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart1, nDegU, bRat))) ; + PtrOwner cBezTipEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart1->GetAllControlPoints()) ; + PNTVECTOR vPntTip1 = cBezTipEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip1.begin(), vPntTip1.end()) ; + // inferiori 2 + PtrOwner cBezTipStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart2, nDegU, bRat))) ; + PtrOwner cBezTipEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart2->GetAllControlPoints()) ; + PNTVECTOR vPntTip2 = cBezTipEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip2.begin(), vPntTip2.end()) ; + // inferiori indietro 1 + CurveArc cArcTipStart3, cArcTipEnd3, cArcTipStart4, cArcTipEnd4 ; + cArcTipStart3.SetC2PN( ptP1T, vPntTipStartBack[1], vPntTipStartBack[0], vtLs[s]) ; + cArcTipEnd3.SetC2PN( ptP2T, vPntTipEndBack[1], vPntTipEndBack[0], vtLe[s]) ; + cArcTipStart4.SetC2PN( ptP1T, vPntTipStartBack[2], vPntTipStartBack[1], vtLs[s]) ; + cArcTipEnd4.SetC2PN( ptP2T, vPntTipEndBack[2], vPntTipEndBack[1], vtLe[s]) ; + PtrOwner cBezTipStart3( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart3, nDegU, bRat))) ; + PtrOwner cBezTipEnd3( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd3, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart3->GetAllControlPoints()) ; + PNTVECTOR vPntTip3 = cBezTipEnd3->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip3.begin(), vPntTip3.end()) ; + // inferiori indietro 2 + PtrOwner cBezTipStart4( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart4, nDegU, bRat))) ; + PtrOwner cBezTipEnd4( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd4, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart4->GetAllControlPoints()) ; + PNTVECTOR vPntTip4 = cBezTipEnd4->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTip4.begin(), vPntTip4.end()) ; - if( s == nStepCnt - 1) { - // calcolo i punti di split dei diametri - PNTVECTOR vSplitDiamStart ; - PNTVECTOR vSplitDiamEnd ; - Vector3d vDirDiamStart = (vPntTopStartEx.back() - vPntTopStartEx.front()) / nSub ; - Vector3d vDirDiamEnd = (vPntTopEndEx.back() - vPntTopEndEx.front()) / nSub ; - for ( int i = 0 ; i <= nSub ; ++i) { - vSplitDiamStart.push_back( vPntTopStartEx.front() + i * vDirDiamStart) ; - vSplitDiamEnd.push_back( vPntTopEndEx.front() + i * vDirDiamEnd) ; + // superfici superiori semplici + CurveLine cLineStart ; cLineStart.Set( vPntTopStartBack[s], vPntTopStartBack[s]) ; + PtrOwner cBezTopStart( GetBasicCurveBezier( LineToBezierCurve( &cLineStart, nDegU, bRat))) ; + CurveLine cLineEnd ; cLineEnd.Set( vPntTopEndBack[s], vPntTopEndBack[s]) ; + PtrOwner cBezTopEnd( GetBasicCurveBezier( LineToBezierCurve( &cLineEnd, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTopStart->GetAllControlPoints()) ; + PNTVECTOR vPntTop = cBezTopEnd->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTop.begin(), vPntTop.end()) ; + } + + // all'ultimo step chiudo il volume con le superfici verticali e le basi dei tool + if ( s == nStepCnt - 1) { + // chiudo il volume con le superici verticali end 1 + CurveArc cArcTipEnd1, cArcTopEnd1, cArcTipEnd2, cArcTopEnd2 ; + cArcTipEnd1.SetC2PN( ptP2TEx, vPntTipEndExF[0], vPntTipEndExF[1], vtLe.back()) ; + cArcTopEnd1.SetC2PN( ptE.back(), vPntTopEndExF[0], vPntTopEndExF[1], vtLe.back()) ; + cArcTipEnd2.SetC2PN( ptP2TEx, vPntTipEndExF[1], vPntTipEndExF[2], vtLe.back()) ; + cArcTopEnd2.SetC2PN( ptE.back(), vPntTopEndExF[1], vPntTopEndExF[2], vtLe.back()) ; + PtrOwner cBezTipEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd1, nDegU, bRat))) ; + PtrOwner cBezTopEnd1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipEnd1->GetAllControlPoints()) ; + PNTVECTOR vPntEnd1 = cBezTopEnd1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd1.begin(), vPntEnd1.end()) ; + // chiudo il volume con le superici verticali end 2 + PtrOwner cBezTipEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEnd2, nDegU, bRat))) ; + PtrOwner cBezTopEnd2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEnd2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipEnd2->GetAllControlPoints()) ; + PNTVECTOR vPntEnd2 = cBezTopEnd2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEnd2.begin(), vPntEnd2.end()) ; + + // chiudo il volume con le superici verticali start 1 + CurveArc cArcTipStart1, cArcTopStart1, cArcTipStart2, cArcTopStart2 ; + cArcTipStart1.SetC2PN( ptP1TEx, vPntTipStartExB[0], vPntTipStartExB[1], vtLs.front()) ; + cArcTopStart1.SetC2PN( ptS.front(), vPntTopStartExB[0], vPntTopStartExB[1], vtLs.front()) ; + cArcTipStart2.SetC2PN( ptP1TEx, vPntTipStartExB[1], vPntTipStartExB[2], vtLs.front()) ; + cArcTopStart2.SetC2PN( ptS.front(), vPntTopStartExB[1], vPntTopStartExB[2], vtLs.front()) ; + PtrOwner cBezTipStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart1, nDegU, bRat))) ; + PtrOwner cBezTopStart1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart1, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart1->GetAllControlPoints()) ; + PNTVECTOR vPntStart1 = cBezTopStart1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart1.begin(), vPntStart1.end()) ; + // chiudo il volume con le superfici verticali start 2 + PtrOwner cBezTipStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStart2, nDegU, bRat))) ; + PtrOwner cBezTopStart2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStart2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( cBezTipStart2->GetAllControlPoints()) ; + PNTVECTOR vPntStart2 = cBezTopStart2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStart2.begin(), vPntStart2.end()) ; + + // superfici di base dei tool + if ( (! ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && dSide < 0)) || + n5AxisType != VolZmap::Move5Axis::ALONG_CONCAVE) { + // start back tip + CurveArc cArcTipStartBack1, cArcTipStartBack2 ; + cArcTipStartBack1.SetC2PN( ptP1TEx, vPntTipStartExB[0], vPntTipStartExB[1], vtLs.front()) ; + cArcTipStartBack2.SetC2PN( ptP1TEx, vPntTipStartExB[1], vPntTipStartExB[2], vtLs.front()) ; + PtrOwner cBezTipStartBack1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStartBack1, nDegU, bRat))) ; + PtrOwner cBezTipStartBack2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStartBack2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T}) ; + PNTVECTOR vPntTipStartBack1 = cBezTipStartBack1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartBack1.begin(), vPntTipStartBack1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T}) ; + PNTVECTOR vPntTipStartBack2 = cBezTipStartBack2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartBack2.begin(), vPntTipStartBack2.end()) ; + if( n5AxisType != VolZmap::Move5Axis::ALONG_CONVEX) { + // start front tip + CurveArc cArcTipStartFront1, cArcTipStartFront2 ; + cArcTipStartFront1.SetC2PN( ptP1TEx, vPntTipStartExF[0], vPntTipStartExF[1], vtLs.front()) ; + cArcTipStartFront2.SetC2PN( ptP1TEx, vPntTipStartExF[1], vPntTipStartExF[2], vtLs.front()) ; + PtrOwner cBezTipStartFront1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStartFront1, nDegU, bRat))) ; + PtrOwner cBezTipStartFront2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipStartFront2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T}) ; + PNTVECTOR vPntTipStartFront1 = cBezTipStartFront1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartFront1.begin(), vPntTipStartFront1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP1T, ptP1T, ptP1T, ptP1T}) ; + PNTVECTOR vPntTipStartFront2 = cBezTipStartFront2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipStartFront2.begin(), vPntTipStartFront2.end()) ; } - // aggiungo le superfici verticali esterne - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamStart[i+1], vSplitDiamStart[i], vPntTipStartEx[nSub - i - 1], vPntTipStartEx[nSub - i]})) ; - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamEnd[i], vSplitDiamEnd[i+1], vPntTipEndEx2[nSub - i], vPntTipEndEx2[nSub - i- 1]})) ; + } + if ( ! ( ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && dSide > 0) || + ( n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE))) { + // end front tip + CurveArc cArcTipEndFront1, cArcTipEndFront2 ; + cArcTipEndFront1.SetC2PN( ptP2TEx, vPntTipEndExF[0], vPntTipEndExF[1], vtLe.back()) ; + cArcTipEndFront2.SetC2PN( ptP2TEx, vPntTipEndExF[1], vPntTipEndExF[2], vtLe.back()) ; + PtrOwner cBezTipEndFront1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEndFront1, nDegU, bRat))) ; + PtrOwner cBezTipEndFront2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEndFront2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T}) ; + PNTVECTOR vPntTipEndFront1 = cBezTipEndFront1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndFront1.begin(), vPntTipEndFront1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T}) ; + PNTVECTOR vPntTipEndFront2 = cBezTipEndFront2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndFront2.begin(), vPntTipEndFront2.end()) ; + if( n5AxisType != VolZmap::Move5Axis::ALONG_CONVEX) { + // end back tip + CurveArc cArcTipEndBack1, cArcTipEndBack2 ; + cArcTipEndBack1.SetC2PN( ptP2TEx, vPntTipEndExB[0], vPntTipEndExB[1], vtLe.back()) ; + cArcTipEndBack2.SetC2PN( ptP2TEx, vPntTipEndExB[1], vPntTipEndExB[2], vtLe.back()) ; + PtrOwner cBezTipEndBack1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEndBack1, nDegU, bRat))) ; + PtrOwner cBezTipEndBack2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTipEndBack2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T}) ; + PNTVECTOR vPntTipEndBack1 = cBezTipEndBack1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndBack1.begin(), vPntTipEndBack1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptP2T, ptP2T, ptP2T, ptP2T}) ; + PNTVECTOR vPntTipEndBack2 = cBezTipEndBack2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTipEndBack2.begin(), vPntTipEndBack2.end()) ; } - // aggiungo le superfici verticali interne - for ( int i = 0 ; i < nSub ; ++i) { - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamStart[i+1], vSplitDiamStart[i], vPntTipStartEx2[nSub - i - 1], vPntTipStartEx2[nSub - i]})) ; - vvPtCtrl.emplace_back( PNTVECTOR({ vSplitDiamEnd[i], vSplitDiamEnd[i+1], vPntTipEndEx[nSub - i], vPntTipEndEx[nSub - i- 1]})) ; + } + + if ( (! ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && dSide > 0)) || + n5AxisType != VolZmap::Move5Axis::ALONG_CONVEX) { + // start back top + CurveArc cArcTopStartBack1, cArcTopStartBack2 ; + cArcTopStartBack1.SetC2PN( ptS.front(), vPntTopStartExB[1], vPntTopStartExB[0], vtLs.front()) ; + cArcTopStartBack2.SetC2PN( ptS.front(), vPntTopStartExB[2], vPntTopStartExB[1], vtLs.front()) ; + PtrOwner cBezTopStartBack1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStartBack1, nDegU, bRat))) ; + PtrOwner cBezTopStartBack2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStartBack2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptS[s], ptS[s], ptS[s], ptS[s]}) ; + PNTVECTOR vPntTopStartBack1 = cBezTopStartBack1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartBack1.begin(), vPntTopStartBack1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptS[s], ptS[s], ptS[s], ptS[s]}) ; + PNTVECTOR vPntTopStartBack2 = cBezTopStartBack2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartBack2.begin(), vPntTopStartBack2.end()) ; + if( n5AxisType != VolZmap::Move5Axis::ALONG_CONCAVE) { + // start front top + CurveArc cArcTopStartFront1, cArcTopStartFront2 ; + cArcTopStartFront1.SetC2PN( ptS.front(), vPntTopStartExF[1], vPntTopStartExF[0], vtLs.front()) ; + cArcTopStartFront2.SetC2PN( ptS.front(), vPntTopStartExF[2], vPntTopStartExF[1], vtLs.front()) ; + PtrOwner cBezTopStartFront1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStartFront1, nDegU, bRat))) ; + PtrOwner cBezTopStartFront2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopStartFront2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptS[s], ptS[s], ptS[s], ptS[s]}) ; + PNTVECTOR vPntTopStartFront1 = cBezTopStartFront1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartFront1.begin(), vPntTopStartFront1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptS[s], ptS[s], ptS[s], ptS[s]}) ; + PNTVECTOR vPntTopStartFront2 = cBezTopStartFront2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopStartFront2.begin(), vPntTopStartFront2.end()) ; + } + } + if ( ! ( ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && dSide < 0) || + ( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX))) { + // end front top + CurveArc cArcTopEndFront1, cArcTopEndFront2 ; + cArcTopEndFront1.SetC2PN( ptE.back(), vPntTopEndExF[1], vPntTopEndExF[0], vtLe.back()) ; + cArcTopEndFront2.SetC2PN( ptE.back(), vPntTopEndExF[2], vPntTopEndExF[1], vtLe.back()) ; + PtrOwner cBezTopEndFront1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEndFront1, nDegU, bRat))) ; + PtrOwner cBezTopEndFront2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEndFront2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptE[s], ptE[s], ptE[s], ptE[s]}) ; + PNTVECTOR vPntTopEndFront1 = cBezTopEndFront1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndFront1.begin(), vPntTopEndFront1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptE[s], ptE[s], ptE[s], ptE[s]}) ; + PNTVECTOR vPntTopEndFront2 = cBezTopEndFront2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndFront2.begin(), vPntTopEndFront2.end()) ; + if( n5AxisType != VolZmap::Move5Axis::ALONG_CONCAVE) { + // end back top + CurveArc cArcTopEndBack1, cArcTopEndBack2 ; + cArcTopEndBack1.SetC2PN( ptE.back(), vPntTopEndExB[1], vPntTopEndExB[0], vtLe.back()) ; + cArcTopEndBack2.SetC2PN( ptE.back(), vPntTopEndExB[2], vPntTopEndExB[1], vtLe.back()) ; + PtrOwner cBezTopEndBack1( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEndBack1, nDegU, bRat))) ; + PtrOwner cBezTopEndBack2( GetBasicCurveBezier(ArcToBezierCurve( &cArcTopEndBack2, nDegU, bRat))) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptE[s], ptE[s], ptE[s], ptE[s]}) ; + PNTVECTOR vPntTopEndBack1 = cBezTopEndBack1->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndBack1.begin(), vPntTopEndBack1.end()) ; + vvPtCtrl.emplace_back( PNTVECTOR{ ptE[s], ptE[s], ptE[s], ptE[s]}) ; + PNTVECTOR vPntTopEndBack2 = cBezTopEndBack2->GetAllControlPoints() ; + vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntTopEndBack2.begin(), vPntTopEndBack2.end()) ; } } } @@ -1672,19 +1907,30 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt vSurfBez[nSurfInd]->SetControlPoint( 1, vvPtCtrl[z][1]) ; vSurfBez[nSurfInd]->SetControlPoint( 2, vvPtCtrl[z][2]) ; vSurfBez[nSurfInd]->SetControlPoint( 3, vvPtCtrl[z][3]) ; + vSurfBez[nSurfInd]->SetControlPoint( 4, vvPtCtrl[z][4]) ; + vSurfBez[nSurfInd]->SetControlPoint( 5, vvPtCtrl[z][5]) ; + vSurfBez[nSurfInd]->SetControlPoint( 6, vvPtCtrl[z][6]) ; + vSurfBez[nSurfInd]->SetControlPoint( 7, vvPtCtrl[z][7]) ; vSurfBox[nSurfInd].Add( vvPtCtrl[z]) ; - Vector3d a = vvPtCtrl[z][3] - vvPtCtrl[z][1] + ( vvPtCtrl[z][0] - vvPtCtrl[z][2]) ; - Vector3d b = vvPtCtrl[z][1] - vvPtCtrl[z][0] ; - Vector3d c = vvPtCtrl[z][2] - vvPtCtrl[z][0] ; - d.push_back( vvPtCtrl[z][0]) ; + Vector3d A = vvPtCtrl[z][4] - vvPtCtrl[z][0] ; + Vector3d B = vvPtCtrl[z][5] - vvPtCtrl[z][1] ; + Vector3d C = vvPtCtrl[z][6] - vvPtCtrl[z][2] ; + Vector3d D = vvPtCtrl[z][7] - vvPtCtrl[z][3] ; + Vector3d E = vvPtCtrl[z][0] - ORIG ; + Vector3d F = vvPtCtrl[z][1] - ORIG ; + Vector3d G = vvPtCtrl[z][2] - ORIG; + Vector3d H = vvPtCtrl[z][3] - ORIG ; - A1.push_back( a.x * q.z - a.z * q.x) ; - B1.push_back( b.x * q.z - b.z * q.x) ; - C1.push_back( c.x * q.z - c.z * q.x) ; - A2.push_back( a.y * q.z - a.z * q.y) ; - B2.push_back( b.y * q.z - b.z * q.y) ; - C2.push_back( c.y * q.z - c.z * q.y) ; + a3[nSurfInd] = -A + 3*B - 3*C + D ; + a2[nSurfInd] = 3*A - 6*B + 3*C ; + a1[nSurfInd] = -3*A +3*B ; + a0[nSurfInd] = A ; + + b3[nSurfInd] = -E + 3*F - 3*G + H ; + b2[nSurfInd] = 3*E - 6*F + 3*G ; + b1[nSurfInd] = -3*E + 3*F ; + b0[nSurfInd] = E ; #ifdef TEST if ( nGrid == 0) @@ -1705,681 +1951,112 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt #endif - BBox3d bbStartCyl = GetCylMoveBBox( ptS[0], ptS[0], vtLs[0], dMaxRad, dHeight) ; - BBox3d bbEndCyl = GetCylMoveBBox( ptE.back(), ptE.back(), vtLe.back(), dMaxRad, dHeight) ; + //BBox3d bbStartCyl = GetCylMoveBBox( ptS[0], ptS[0], vtLs[0], dMaxRad, dHeight) ; + //BBox3d bbEndCyl = GetCylMoveBBox( ptE.back(), ptE.back(), vtLe.back(), dMaxRad, dHeight) ; - // se sono nel caso di un cono calcolo già i parametri utili - Point3d ptVS, ptVE ; - double dTan = 0, dMinH, dMaxH ; - Point3d ptP1T = ptS[0] - vtLs[0] * dHeight ; - Point3d ptP2T = ptE.back() - vtLe.back() * dHeight ; - if ( dMinRad < EPS_SMALL) { - ptVS = ptP1T ; - ptVE = ptP2T ; - dMinH = 0 ; - dMaxH = dHeight ; - dTan = dMaxRad / dHeight ; - } - else { - dTan = (dMaxRad - dMinRad) / dHeight ; - dMaxH = dMaxRad * dTan ; - dMinH = dMaxH - dHeight ; - ptVS = ptS[0] - vtLs[0] * dMaxH ; - ptVE = ptE.back() - vtLe.back() * dMaxH ; - } - - Vector3d vtDirTop = ptE.back() - ptS.front() ; - Vector3d vtDirTip = ptP2T - ptP1T ; - VCT3DVECTOR vvtTipStartAux( nSub + 1) ; - VCT3DVECTOR vvtTipEndAux( nSub + 1) ; - VCT3DVECTOR vvtTopStartAux( nSub + 1) ; - VCT3DVECTOR vvtTopEndAux( nSub + 1) ; - vvtTipStartAux.front() = vPntTipStartEx.front() - ptP1T ; - vvtTipEndAux.front() = vPntTipEndEx.front() - ptP2T ; - vvtTopStartAux.front() = vPntTopStartEx.front() - ptS.front() ; - vvtTopEndAux.front() = vPntTopEndEx.front() - ptE.back() ; - - double dMinRadApprox = 0 ; - double dMaxRadApprox = 0 ; - for ( int i = 1 ; i <= nSub ; ++i) { - vvtTipStartAux[i] = Media( vPntTipStartEx[i-1],vPntTipStartEx[i]) - ptP1T ; - if ( i == nSub) - dMinRadApprox = vvtTipStartAux[i].Len() ; - vvtTipStartAux[i].Normalize() ; - vvtTipEndAux[i] = Media( vPntTipEndEx[i-1],vPntTipEndEx[i]) - ptP2T ; - vvtTipEndAux[i].Normalize() ; - vvtTopStartAux[i] = Media( vPntTopStartEx[i-1],vPntTopStartEx[i]) - ptS[0] ; - if ( i == nSub) - dMaxRadApprox = vvtTopStartAux[i].Len() ; - vvtTopStartAux[i].Normalize() ; - vvtTopEndAux[i] = Media( vPntTopEndEx[i-1],vPntTopEndEx[i]) - ptE.back() ; - vvtTopEndAux[i].Normalize() ; - } + //// se sono nel caso di un cono calcolo già i parametri utili + //Point3d ptVS, ptVE ; + //double dTan = 0, dMinH, dMaxH ; + //Point3d ptP1T = ptS[0] - vtLs[0] * dHeight ; + //Point3d ptP2T = ptE.back() - vtLe.back() * dHeight ; + //if ( dMinRad < EPS_SMALL) { + // ptVS = ptP1T ; + // ptVE = ptP2T ; + // dMinH = 0 ; + // dMaxH = dHeight ; + // dTan = dMaxRad / dHeight ; + //} + //else { + // dTan = (dMaxRad - dMinRad) / dHeight ; + // dMaxH = dMaxRad * dTan ; + // dMinH = dMaxH - dHeight ; + // ptVS = ptS[0] - vtLs[0] * dMaxH ; + // ptVE = ptE.back() - vtLe.back() * dMaxH ; + //} // scorro tutti gli spilloni interessati int nAllStepsSurfs = nTotSurf * nStepCnt ; - vector vvnSurf ; - if( n5AxisType != VolZmap::Move5Axis::ACROSS) { - vvnSurf.emplace_back() ; - vvnSurf[0].resize( nAllStepsSurfs) ; - iota( vvnSurf[0].begin(), vvnSurf[0].end(), 0) ; - } - else { - vvnSurf.resize( 2) ; - // superfici laterali - int nSurf = 0 ; - for( int s = 0 ; s < nStepCnt ; ++s) { - //superifici laterali - for ( int i = 0 ; i < 2 ; ++i, ++nSurf) { - vvnSurf[0].push_back( nSurf) ; - vvnSurf[1].push_back( nSurf) ; - } - // superfici inferiori in avanti - for ( int i = 0 ; i < nSub ; ++i, ++nSurf) - vvnSurf[0].push_back( nSurf) ; - //superfici superiori indietro - for ( int i = 0 ; i < nSub ; ++i, ++nSurf) - vvnSurf[1].push_back( nSurf) ; - //superfici inferiori indietro - for ( int i = 0 ; i < nSub ; ++i, ++nSurf) - vvnSurf[1].push_back( nSurf) ; - //superfici superiori in avanti - for ( int i = 0 ; i < nSub ; ++i, ++nSurf) - vvnSurf[0].push_back( nSurf) ; - } - // superfici verticali in avanti interne - for ( int i = 0 ; i < nSub ; ++i, ++nSurf ) - vvnSurf[0].push_back( nSurf) ; - // superfici verticali indietro interne - for ( int i = 0 ; i < nSub ; ++i, ++nSurf) - vvnSurf[1].push_back( nSurf) ; - // superfici verticali in avanti esterne - for ( int i = 0 ; i < nSub ; ++i, ++nSurf ) - vvnSurf[0].push_back( nSurf) ; - // superfici verticali indietro esterne - for ( int i = 0 ; i < nSub ; ++i, ++nSurf) - vvnSurf[1].push_back( nSurf) ; - - // N.B. : avanti e indietro sono riferiti al caso dSide >0 , in caso dSide <0 si invertono - // ai fini della divisione in due volumi diversi non importa chi sia il primo e chi il secondo volume - } for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d r( dX, dY, 0) ; - vector vvInters( vvnSurf.size()) ; - vector vvStartEnds( vvnSurf.size()) ; + PNTVEC3DVECTOR vInters ; + INTINTVECTOR vStartEnds ; + //debug INTVECTOR vSurfInters ; - for(int v = 0 ; v < int(vvnSurf.size()) ; ++v) { - // interseco con le bilineari - for( int s : vvnSurf[v]) { - // verifico che lo spillone faccia interferenza con il box della superficie - if ( vSurfBox[s].SqDistFromPointXY( r) < EPS_ZERO) { - double D1 = ( d[s].x - r.x) * q.z - ( d[s].z - r.z) * q.x ; - double D2 = ( d[s].y - r.y) * q.z - ( d[s].z - r.z) * q.y ; + // interseco con le bilineari + for( int s = 0 ; s < int( vSurfBez.size()) ; ++s) { + // verifico che lo spillone faccia interferenza con il box della superficie + if ( vSurfBox[s].SqDistFromPointXY( r) < EPS_ZERO) { + DBLVECTOR vdCoeff, vdRoots ; + // coefficienti dal grado più basso al grado più alto + vdCoeff = { - a0[s].y * b0[s].x + r.x * a0[s].y + a0[s].x * b0[s].y - r.y * a0[s].x, + - a1[s].y * b0[s].x - a0[s].y * b1[s].x + r.x * a1[s].y + a1[s].x * b0[s].y + a0[s].x * b1[s].y - r.y * a1[s].x, + - a2[s].y * b0[s].x - a1[s].y * b1[s].x - a0[s].y * b2[s].x + r.x * a2[s].y + a2[s].x * b0[s].y + a1[s].x * b1[s].y + a0[s].x * b2[s].y - r.y * a2[s].x, + - a3[s].y * b0[s].x - a2[s].y * b1[s].x - a1[s].y * b2[s].x - a0[s].y * b3[s].x + r.x * a3[s].y + a3[s].x * b0[s].y + a2[s].x * b1[s].y + a1[s].x * b2[s].y + a0[s].x * b3[s].y - r.y * a3[s].x, + - a3[s].y * b1[s].x - a2[s].y * b2[s].x - a1[s].y * b3[s].x + a3[s].x * b1[s].y + a2[s].x * b2[s].y + a1[s].x * b3[s].y, + - a3[s].y * b2[s].x - a2[s].y * b3[s].x + a3[s].x * b2[s].y + a2[s].x * b3[s].y, + - a3[s].y * b3[s].x + a3[s].x * b3[s].y} ; + int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ; + for( int w = 0 ; w < nRoots ; ++w) { + double dU = 0, dV = 0 ; + if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) { + dU = vdRoots[w] ; + Vector3d vAlpha = a3[s] * pow(dU, 3) + a2[s] * pow( dU, 2) + a1[s] * dU + a0[s] ; + Vector3d vBeta = b3[s] * pow(dU, 3) + b2[s] * pow( dU, 2) + b1[s] * dU + b0[s] ; + dV = - ( vBeta.x - r.x) / vAlpha.x ; + if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) { + Point3d ptBez ; + Vector3d vtN ; + vSurfBez[s]->GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez, vtN) ; + vtN *= -1 ; + UpdateMaxMin( ptBez, vtN, vInters) ; - DBLVECTOR vdCoeff, vdRoots ; - vdCoeff = { (B2[s] * D1 - B1[s] * D2), ( A2[s] * D1 - A1[s] * D2 + B2[s] * C1[s] - B1[s] * C2[s]), ( A2[s] * C1[s] - A1[s] * C2[s])} ; - int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ; - if ( nRoots != 0) { - double dU1 = 0, dV1 = 0 ; - double dU2 = 0, dV2 = 0 ; - if ( vdRoots[0] > 0 - EPS_ZERO && vdRoots[0] < 1 + EPS_ZERO) { - dV1 = vdRoots[0] ; - dU1 = (dV1 * (C1[s] - C2[s]) + ( D1 - D2)) / ( dV1 * ( A2[s] - A1[s]) + ( B2[s] - B1[s])) ; - if ( dU1 > - EPS_ZERO && dU1 < 1 + EPS_ZERO) { - Point3d ptBez1 ; - Vector3d vtN1 ; - vSurfBez[s]->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez1, vtN1) ; - vtN1 *= -1 ; - UpdateMaxMin( ptBez1, vtN1, vvInters[v]) ; - - //debug - vSurfInters.push_back( s) ; - } - } - if ( nRoots > 1 && vdRoots[1] > 0 - EPS_ZERO && vdRoots[1] < 1 + EPS_ZERO) { - dV2 = vdRoots[1] ; - dU2 = (dV2 * (C1[s] - C2[s]) + ( D1 - D2)) / ( dV2 * ( A2[s] - A1[s]) + ( B2[s] - B1[s])) ; - if ( dU2 > - EPS_ZERO && dU2 < 1 + EPS_ZERO) { - Point3d ptBez2 ; - Vector3d vtN2 ; - vSurfBez[s]->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez2, vtN2) ; - vtN2 *= -1 ; - UpdateMaxMin( ptBez2, vtN2, vvInters[v]) ; - - //debug - vSurfInters.push_back( s) ; - } + //debug + vSurfInters.push_back( s) ; } } } } - - if ( vvInters[v].size() > 2 ) { - sort( vvInters[v].begin(), vvInters[v].end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.z < b.first.z ; }) ; - INTINT pStartEnd ; - bool bDirStart = vvInters[v].front().second * Z_AX > 0 ; - bool bFirstEndFound = false ; - pStartEnd.first = 0 ; - for ( int w = 1 ; w < int( vvInters[v].size()) ; ++w) { - bool bDir = vvInters[v][w].second * Z_AX > 0 ; - // se è l'ultimo punto esco - if ( w == int( vvInters[v].size() - 1) && bDirStart != bDir) { - pStartEnd.second = w ; - vvStartEnds[v].push_back(pStartEnd) ; - break ; - } - // sennò scorro finché non trovo l'uscita più lontana ( prima di un altro ingresso o eventualmente l'ultima inters) - else if( bDirStart != bDir) - bFirstEndFound = true ; - // se trovo di nuovo un'intersezione orientata come la prima dello spillone allora ho un nuovo start e posso chiudere l'intervallo precedente - else if( bFirstEndFound && bDirStart == bDir) { - pStartEnd.second = w - 1 ; - bFirstEndFound = false ; - vvStartEnds[v].push_back(pStartEnd) ; - pStartEnd.first = w ; - pStartEnd.second = -1 ; - } - } - for( auto p : vvStartEnds[v] ) - SubtractIntervals(nGrid, i, j, vvInters[v][p.first].first.z, vvInters[v][p.second].first.z, vvInters[v][p.first].second, vvInters[v][p.second].second, nToolNum) ; - } - else if ( vvInters[v].size() == 2){ - vvStartEnds[v].push_back(INTINT(0, 1)) ; - SubtractIntervals( nGrid, i, j, vvInters[v].front().first.z, vvInters[v].back().first.z, vvInters[v].front().second, vvInters[v].back().second, nToolNum) ; - } - else if ( vvInters[v].size() == 1) - return false ; - } - - // interseco con la prima metà del tool in posizione iniziale e con la seconda metà del tool in posizione finale - PNTVEC3DVECTOR vIntersTool ; - BOOLVECTOR vbUpdate( 2) ; - PNTVECTOR vPntInters( 2) ; - VCT3DVECTOR vVtIntersNorm( 2) ; - // ciclo sulle due posizioni del tool : start e end della passata - for( int t = 0 ; t < 2 ; ++t) { - // prima di calcolare l'intersezione verifico che ci sia interferenza con i box - bool bBoxInters = false ; - if( t == 0) - bBoxInters = bbStartCyl.SqDistFromPointXY( r) < EPS_ZERO ; - else if ( t == 1) - bBoxInters = bbEndCyl.SqDistFromPointXY( r) < EPS_ZERO ; - - if( bBoxInters) { - Frame3d frTool ; - if ( t == 0) - frTool.Set( ptP1T, vtLs.front()) ; - else if ( t == 1) - frTool.Set( ptP2T, vtLe.back()) ; - - bool bIntersFound = false ; - // calcolo le intersezioni in base alla forma del tool: cilindro o cono - if ( dMaxRad - dMinRad < EPS_SMALL) - bIntersFound = IntersLineCylinder( r, Z_AX, frTool, dHeight, dMaxRad, false, false, vPntInters[0], vVtIntersNorm[0], vPntInters[1], vVtIntersNorm[1]) ; - else - bIntersFound = IntersLineConus( r, Z_AX, frTool, dTan, dMinH, dMaxH, false, false, vPntInters[0], vVtIntersNorm[0], vPntInters[1], vVtIntersNorm[1]) ; - - if ( bIntersFound) { - // ciclo sulle due intersezioni - fill( vbUpdate.begin(), vbUpdate.end(), false) ; - for( int p = 0 ; p < 2 ; ++p) { - bool bOnTopBase = ( vPntInters[p] - frTool.Orig() ) * frTool.VersZ() > dHeight - EPS_SMALL ; - bool bOnBottomBase = ( vPntInters[p] - frTool.Orig() ) * frTool.VersZ() < EPS_SMALL ; - // se ho un'intersezione su una base devo verificare se la devo considerare o no - if ( bOnBottomBase || bOnTopBase) { - // verifico se sono nella metà della base il cui contorno è in contatto con le bilineari - //base inferiore - double dSectorAng = 0 ; - bool bApproxedSideBottom = false ; - bool bApproxedSideTop = false ; - double dBottomBaseSide = 0 ; - if ( t == 0) - dBottomBaseSide = ( vPntInters[p] - frTool.Orig()) * vtDirTipStartEx ; - else if ( t == 1) - dBottomBaseSide = ( vPntInters[p] - frTool.Orig()) * vtDirTipEndEx ; - double dTopBaseSide = 0 ; - if ( t == 0) - dTopBaseSide = ( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight)) * vtDirTopStartEx ; - else if ( t == 1) - dTopBaseSide = ( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight)) * vtDirTopEndEx ; - - if ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS) { - if ( dSide < 0) { - bApproxedSideBottom = dBottomBaseSide < 0 ; - bApproxedSideTop = dTopBaseSide > 0 ; - } - else { - bApproxedSideBottom = dBottomBaseSide > 0 ; - bApproxedSideTop = dTopBaseSide < 0 ; - } - } - else if ( n5AxisType == VolZmap::Move5Axis::ACROSS) { - bApproxedSideBottom = true ; - bApproxedSideTop = true ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX){ - if ( bOnBottomBase) { - if ( t == 0) - vbUpdate[p] = dBottomBaseSide < 0 ; - else if ( t == 1) - vbUpdate[p] = dBottomBaseSide > 0 ; - } - else if ( bOnTopBase) - bApproxedSideTop = true ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE) { - if ( bOnBottomBase) - bApproxedSideBottom = true ; - else if ( bOnTopBase) { - if ( t == 0) - vbUpdate[p] = dTopBaseSide < 0 ; - else if( t == 1) - vbUpdate[p] = dTopBaseSide > 0 ; - } - } - if ( bOnBottomBase && bApproxedSideBottom) { - if ( t == 0) - vvtTipStartAux.front().GetAngle( vPntInters[p] - frTool.Orig(), dSectorAng) ; - else if( t == 1) - vvtTipEndAux.front().GetAngle( vPntInters[p] - frTool.Orig(), dSectorAng) ; - // determino in quale settore del semicerchio approssimato mi trovo - int nSector = int( dSectorAng / ( 180. / nSub) + 1) ; - // verifico se l'intersezione linea-base è interna o esterna - if ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS) { - double dDist = 0 ; - if ( t == 0) - dDist = ( vPntInters[p] - frTool.Orig() ) * vvtTipStartAux[nSector] ; - else if( t == 1) - dDist = ( vPntInters[p] - frTool.Orig() ) * vvtTipEndAux[nSector] ; - - if ( (dSide > 0 && t == 0) || (dSide < 0 && t == 1)) - vbUpdate[p] = dDist < dMinRadApprox - EPS_SMALL ; - else - vbUpdate[p] = dDist > dMinRadApprox - EPS_SMALL && dDist < dMinRad ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE) { - double dDist = 0 ; - // per il caso ALONG_CONCAVE dovrei avere dSide < 0, quindi sulla base bottom avere i punti ausiliari nella parte posteriore del cerchio di base - if ( dBottomBaseSide > 0) { - if ( t == 0) { - // in questo caso devo prendere il vettore Aux dell'angolo supplementare e con segno opposto - dDist = ( vPntInters[p] - frTool.Orig() ) * ( -vvtTipStartAux[( nSub + 1 ) - nSector] ) ; - vbUpdate[p] = dDist < dMinRadApprox - EPS_SMALL ; - } - else if ( t == 1) - vbUpdate[p] = true ; - } - else { - if ( t == 0) - vbUpdate[p] = true ; - else if ( t == 1 ) { - dDist = (vPntInters[p] - frTool.Orig()) * vvtTipEndAux[nSector] ; - vbUpdate[p] = dDist < dMinRadApprox - EPS_SMALL ; - } - } - } - else if ( n5AxisType == VolZmap::Move5Axis::ACROSS) { - double dDist = 0 ; - // con dSide < 0 sulla base bottom/top ho i punti ausiliari nella parte posteriore/anteriore del cerchio di base - // con dSide > 0 sulla base bottom/top ho i punti ausiliari nella parte anteriore/posteriore del cerchio di base - - if ( dBottomBaseSide > 0) { - if ( t == 0) { - if ( dSide < 0) { - // in questo caso devo prendere il vettore Aux dell'angolo supplementare e con segno opposto - dDist = ( vPntInters[p] - frTool.Orig() ) * ( -vvtTipStartAux[( nSub + 1 ) - nSector] ) ; - } - else { - dDist = ( vPntInters[p] - frTool.Orig() ) * vvtTipStartAux[nSector] ; - } - vbUpdate[p] = dDist < dMinRadApprox - EPS_SMALL ; - } - else if ( t == 1) - vbUpdate[p] = true ; - } - else { - if ( t == 0) - vbUpdate[p] = true ; - else if ( t == 1) { - if ( dSide < 0) { - dDist = ( vPntInters[p] - frTool.Orig() ) * vvtTipStartAux[nSector] ; - } - else { - // in questo caso devo prendere il vettore Aux dell'angolo supplementare e con segno opposto - dDist = ( vPntInters[p] - frTool.Orig() ) * ( -vvtTipStartAux[( nSub + 1 ) - nSector] ) ; - } - vbUpdate[p] = dDist < dMinRadApprox - EPS_SMALL ; - } - } - } - } - // base superiore - else if( bOnTopBase && bApproxedSideTop) { - if ( t == 0) - vvtTopStartAux.front().GetAngle( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight ), dSectorAng) ; - else if( t == 1) - vvtTopEndAux.front().GetAngle( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight ), dSectorAng) ; - // determino in quale settore del semicerchio approssimato mi trovo - int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; - // verifico se l'intersezione linea-base è interna o esterna - if ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS) { - double dDist = 0 ; - if ( t == 0) - dDist = ( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight)) * vvtTopStartAux[nSector] ; - else if( t == 1) - dDist = ( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight)) * vvtTopEndAux[nSector] ; - - if ( (dSide < 0 && t == 0) || (dSide > 0 && t == 1)) - vbUpdate[p] = dDist < dMaxRadApprox - EPS_SMALL ; - else - vbUpdate[p] = dDist > dMaxRadApprox - EPS_SMALL && dDist < dMaxRad ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX) { - double dDist = 0 ; - // per il caso ALONG_CONVEX dovrei avere dSide > 0, quindi sulla base top avere i punti ausiliari nella parte posteriore del cerchio di base - if ( dTopBaseSide > 0) { - // in questo caso devo prendere il vettore Aux dell'angolo supplementare e con segno opposto - if ( t == 0) - dDist = ( vPntInters[p] - frTool.Orig()) * ( -vvtTopStartAux[( nSub + 1 ) - nSector]) ; - else if( t == 1) - dDist = ( vPntInters[p] - frTool.Orig()) * ( -vvtTopEndAux[( nSub + 1 ) - nSector]) ; - vbUpdate[p] = dDist < dMaxRadApprox - EPS_SMALL ; - } - else - vbUpdate[p] = true ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ACROSS) { - double dDist = 0 ; - // con dSide < 0 sulla base bottom/top ho i punti ausiliari nella parte posteriore/anteriore del cerchio di base - // con dSide > 0 sulla base bottom/top ho i punti ausiliari nella parte anteriore/posteriore del cerchio di base - if ( dTopBaseSide > 0) { - if ( t == 0) { - if ( dSide < 0) { - dDist = ( vPntInters[p] - frTool.Orig()) * vvtTopStartAux[nSector] ; - } - else { - // in questo caso devo prendere il vettore Aux dell'angolo supplementare e con segno opposto - dDist = ( vPntInters[p] - frTool.Orig()) * ( -vvtTopStartAux[( nSub + 1 ) - nSector] ) ; - } - vbUpdate[p] = dDist < dMaxRadApprox - EPS_SMALL ; - } - else if ( t == 1) - vbUpdate[p] = true ; - } - else { - if ( t == 0) - vbUpdate[p] = true ; - else if ( t == 1) { - if ( dSide < 0) { - // in questo caso devo prendere il vettore Aux dell'angolo supplementare e con segno opposto - dDist = ( vPntInters[p] - frTool.Orig()) * ( -vvtTopStartAux[( nSub + 1 ) - nSector] ) ; - } - else { - dDist = ( vPntInters[p] - frTool.Orig()) * vvtTopStartAux[nSector] ; - } - vbUpdate[p] = dDist < dMaxRadApprox - EPS_SMALL ; - } - } - } - } - else if ( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && - (( t == 0 && ((bOnTopBase && dSide < 0) || ( bOnBottomBase && dSide > 0))) || - ( t == 1 && ((bOnTopBase && dSide > 0) || ( bOnBottomBase && dSide < 0))))) - vbUpdate[p] = true ; - } - // superficie laterale - else { - double dHInters = 0 ; - if ( t == 0) - dHInters = (vPntInters[p] - ptP1T) * vtLs.front() ; - else if( t == 1) - dHInters = (vPntInters[p] - ptP2T) * vtLe.back() ; - Vector3d vtDir = Media( vtDirTip, vtDirTop, dHInters / dHeight) ; - if ( t == 0) - vbUpdate[p] = vVtIntersNorm[p] * vtDir > 0 ; // le normali dei punti di intersezione sul cilindro sono rivolte verso l'interno del cilindro - else if ( t == 1) - vbUpdate[p] = vVtIntersNorm[p] * vtDir < 0 ; - if ( ! vbUpdate[p]) { - //calcolo in che settore sono - double dTopSectorAng = 0 ; - double dBottomSectorAng = 0 ; - // settore top - if ( t == 0) - vvtTopStartAux.front().GetAngle( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight ), dTopSectorAng) ; - else if( t == 1) - vvtTopEndAux.front().GetAngle( vPntInters[p] - ( frTool.Orig() + frTool.VersZ() * dHeight ), dTopSectorAng) ; - // settore bottom - if ( t == 0) - vvtTipStartAux.front().GetAngle( vPntInters[p] - frTool.Orig(), dBottomSectorAng) ; - else if( t == 1) - vvtTipEndAux.front().GetAngle( vPntInters[p] - frTool.Orig(), dBottomSectorAng) ; - - int nTopSector = int( dTopSectorAng / ( 180. / nSub) + 1) ; - int nBottomSector = int( dBottomSectorAng / ( 180. / nSub) + 1) ; - bool bUnderTop = false ; - bool bOverBottom = false ; - if( n5AxisType != VolZmap::Move5Axis::ALONG_CONCAVE) { - // controllo la posizione del punto rispetto alla superificie bilineare di quel settore - int nSurf = 0 ; - if( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS) { - if ( (dSide < 0 && t == 0)) - nSurf = ( 2 + nSub + nTopSector) - 1 ; - else if( (dSide > 0 && t == 1)) - nSurf = ( 2 + nSub * 2) * (nStepCnt - 1) + ( 2 + nSub + nTopSector) - 1 ; // devo tenere conto anche delle superfici aggiunte negli step precedenti - else - bUnderTop = true ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX) { - // dovrebbe avere dSide > 0 - if ( t == 0) { - if ( dSide > 0) - nSurf = ( 2 + nSub + nTopSector) - 1 ; - else - nSurf = ( 2 + nTopSector) - 1 ; - } - else if ( t == 1) { - if ( dSide > 0) - nSurf = ( 2 + nSub * 2) * (nStepCnt - 1) + ( 2 + nTopSector) - 1 ; - else - nSurf = ( 2 + nSub * 2) * (nStepCnt - 1) + ( 2 + nSub + nTopSector) - 1 ; - } - } - else if ( n5AxisType == VolZmap::Move5Axis::ACROSS) { - if ( t == 0) { - if ( dSide > 0) - nSurf = ( 2 + 3*nSub + nTopSector) - 1 ; - else - nSurf = ( 2 + nSub + nTopSector) - 1 ; - } - else if ( t == 1) { - if ( dSide > 0) - nSurf = ( 2 + nSub * 4) * (nStepCnt - 1) + ( 2 + nSub + nTopSector) - 1 ; - else - nSurf = ( 2 + nSub * 4) * (nStepCnt - 1) + ( 2 + 3*nSub + nTopSector) - 1 ; - } - } - - if( ! bUnderTop) { - Point3d ptCTop ; - Vector3d vtNTop ; - Point3d P00 = vSurfBez[nSurf]->GetControlPoint( 0, nullptr) ; - Point3d P10 = vSurfBez[nSurf]->GetControlPoint( 1, nullptr) ; - Point3d P01 = vSurfBez[nSurf]->GetControlPoint( 2, nullptr) ; - Point3d P11 = vSurfBez[nSurf]->GetControlPoint( 3, nullptr) ; - double dV = - 1 ; - double dU = - 1 ; - // stimo i parametri del punto più vicino sulla superficie tramite una media baricentrica - double w00 = 1 / ( Dist( vPntInters[p], P00) + EPS_SMALL) ; - double w10 = 1 / ( Dist( vPntInters[p], P10) + EPS_SMALL) ; - double w01 = 1 / ( Dist( vPntInters[p], P01) + EPS_SMALL) ; - double w11 = 1 / ( Dist( vPntInters[p], P11) + EPS_SMALL) ; - double dSum = w00 + w10 + w01 + w11 ; - w00 /= dSum ; - w10 /= dSum ; - w01 /= dSum ; - w11 /= dSum ; - dU = w10 + w11 ; - dV = w01 + w11 ; - vSurfBez[nSurf]->GetPointNrmD1D2( dU, dV, ISurfBezier::Side::FROM_MINUS,ISurfBezier::Side::FROM_MINUS, ptCTop, vtNTop) ; - Vector3d vtIntTop = vPntInters[p] - ptCTop ; - bUnderTop = vtIntTop * vtNTop < 0 ; - } - } - if ( n5AxisType != VolZmap::Move5Axis::ALONG_CONVEX) { - int nSurf = 0 ; - if( n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS) { - if ( ( dSide > 0 && t == 0)) - nSurf = ( 2 + nBottomSector) - 1 ; - else if( ( dSide < 0 && t == 1)) - nSurf = ( 2 + nSub * 2) * (nStepCnt - 1) + ( 2 + nBottomSector) - 1 ; - else - bOverBottom = true ; - } - else if ( n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE) { - // dovrebbe avere dSide < 0 - if( t == 0) { - if ( dSide < 0) - nSurf = ( 2 + nSub + nBottomSector) - 1 ; - else - nSurf = ( 2 + nBottomSector) - 1 ; - } - else if ( t == 1 ) { - if ( dSide < 0) - nSurf = ( 2 + nSub * 2) * (nStepCnt - 1) + ( 2 + nBottomSector) - 1 ; - else - nSurf = ( 2 + nSub * 2) * (nStepCnt - 1) + ( 2 + nSub + nBottomSector) - 1 ; - } - } - else if ( n5AxisType == VolZmap::Move5Axis::ACROSS) { - if( t == 0) { - if ( dSide < 0) - nSurf = ( 2 + 2 * nSub + nBottomSector) - 1 ; - else - nSurf = ( 2 + nBottomSector) - 1 ; - } - else if ( t == 1 ) { - if ( dSide < 0) - nSurf = ( 2 + nSub * 4) * (nStepCnt - 1) + ( 2 + nBottomSector) - 1 ; - else - nSurf = ( 2 + nSub * 4) * (nStepCnt - 1) + ( 2 + 2 * nSub + nBottomSector) - 1 ; - } - } - - if( ! bOverBottom) { - Point3d ptCBottom ; - Vector3d vtNBottom ; - Point3d P00 = vSurfBez[nSurf]->GetControlPoint( 0, nullptr) ; - Point3d P10 = vSurfBez[nSurf]->GetControlPoint( 1, nullptr) ; - Point3d P01 = vSurfBez[nSurf]->GetControlPoint( 2, nullptr) ; - Point3d P11 = vSurfBez[nSurf]->GetControlPoint( 3, nullptr) ; - double dV = - 1 ; - double dU = - 1 ; - // stimo i parametri del punto più vicino sulla superficie tramite una media baricentrica - double w00 = 1 / ( Dist( vPntInters[p], P00) + EPS_SMALL) ; - double w10 = 1 / ( Dist( vPntInters[p], P10) + EPS_SMALL) ; - double w01 = 1 / ( Dist( vPntInters[p], P01) + EPS_SMALL) ; - double w11 = 1 / ( Dist( vPntInters[p], P11) + EPS_SMALL) ; - double dSum = w00 + w10 + w01 + w11 ; - w00 /= dSum ; - w10 /= dSum ; - w01 /= dSum ; - w11 /= dSum ; - dU = w10 + w11 ; - dV = w01 + w11 ; - vSurfBez[nSurf]->GetPointNrmD1D2( dU, dV, ISurfBezier::Side::FROM_MINUS,ISurfBezier::Side::FROM_MINUS, ptCBottom, vtNBottom) ; - Vector3d vtIntBottom = vPntInters[p] - ptCBottom ; - bOverBottom = vtIntBottom * vtNBottom < 0 ; - } - } - - bool bNo_inters = n5AxisType == VolZmap::Move5Axis::NO_BASE_INTERS && (( dSide < 0 && (( t == 0 && bUnderTop) || ( t == 1 && bOverBottom))) || - ( dSide > 0 && (( t == 0 && bOverBottom) || ( t == 1 && bUnderTop)))) ; - bool bAlong_Convex = n5AxisType == VolZmap::Move5Axis::ALONG_CONVEX && bUnderTop ; - bool bAlong_Concave = n5AxisType == VolZmap::Move5Axis::ALONG_CONCAVE && bOverBottom ; - bool bAcross = n5AxisType == VolZmap::Move5Axis::ACROSS && bUnderTop && bOverBottom ; - - if ( bNo_inters || bAlong_Convex || bAlong_Concave || bAcross) - vbUpdate[p] = true ; - } - } - } - - // se solo una delle due intersezioni è da scartare, allora la sostituisco con un punto all'interno della più vicina intersezione con - // il volume identificato dalle bilineari - int nPointToAdjust = -1 ; - if( vbUpdate[0] && ! vbUpdate[1]) - nPointToAdjust = 1 ; - if( ! vbUpdate[0] && vbUpdate[1]) - nPointToAdjust = 0 ; - if ( nPointToAdjust != -1) { - // se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari - // se non ho neanche questa intersezione allora posso buttare via tutto - int nVol = -1 ; - bool bStartOrEndPair = false ; // true = start ; false = end - double dMinDist = INFINITO ; - int nClosePair = -1 ; // coppia più vicina - for( int v = 0 ; v < int( vvnSurf.size()) ; ++v) { - // se sto per buttare via l'intersezione, la sposto invece all'interno dell'intervallo di intersezione fatto dal volume definito dalle bilineari - // se non ho neanche questa intersezione allora posso buttare via tutto - if ( vvInters[v].size() != 0 ) { - int c = 0 ; - for ( auto& pair : vvStartEnds[v]) { - double dDist = Dist( vPntInters[nPointToAdjust], vvInters[v][pair.first].first) ; - if ( dDist < dMinDist ) { - dMinDist = dDist ; - bStartOrEndPair = true ; - nClosePair = c ; - nVol = v ; - } - dDist = Dist( vPntInters[nPointToAdjust], vvInters[v][pair.second].first) ; - if ( dDist < dMinDist) { - dMinDist = dDist ; - bStartOrEndPair = false ; - nClosePair = c ; - nVol = v ; - } - ++c ; - } - } - } - if( nClosePair != -1) { - if( bStartOrEndPair) - vPntInters[nPointToAdjust] = vvInters[nVol][vvStartEnds[nVol][nClosePair].first].first ; - else - vPntInters[nPointToAdjust] = vvInters[nVol][vvStartEnds[nVol][nClosePair].second].first ; - vbUpdate[nPointToAdjust] = true ; - } - // se non ho trovato intersezioni con la bilineare allora provo a tenere il punto originale - else - vbUpdate[nPointToAdjust] = true ; - } - - - if ( vbUpdate[0]) { - UpdateMaxMin( vPntInters[0], vVtIntersNorm[0], vIntersTool) ; - - //debug - vSurfInters.push_back( t == 0 ? -1 : -2) ; - } - if ( vbUpdate[1]) { - UpdateMaxMin( vPntInters[1], vVtIntersNorm[1], vIntersTool) ; - - //debug - vSurfInters.push_back( t == 0 ? -1 : -2) ; - } - } - - if ( vIntersTool.size() == 2) { - sort( vIntersTool.begin(), vIntersTool.end(), []( PNTVEC3D& a, PNTVEC3D& b){ return a.first.z < b.first.z ;}) ; - SubtractIntervals( nGrid, i, j, vIntersTool.front().first.z, vIntersTool.back().first.z, vIntersTool.front().second, vIntersTool.back().second, nToolNum) ; - vIntersTool.clear() ; - } - } } + + if ( vInters.size() > 2) { + sort( vInters.begin(), vInters.end(), [](PNTVEC3D& a, PNTVEC3D& b) { return a.first.z < b.first.z ; }) ; + INTINT pStartEnd ; + bool bDirStart = vInters.front().second * Z_AX > 0 ; + bool bFirstEndFound = false ; + pStartEnd.first = 0 ; + for ( int w = 1 ; w < int( vInters.size()) ; ++w) { + bool bDir = vInters[w].second * Z_AX > 0 ; + // se è l'ultimo punto esco + if ( w == int( vInters.size() - 1) && bDirStart != bDir) { + pStartEnd.second = w ; + vStartEnds.push_back(pStartEnd) ; + break ; + } + // sennò scorro finché non trovo l'uscita più lontana ( prima di un altro ingresso o eventualmente l'ultima inters) + else if( bDirStart != bDir) + bFirstEndFound = true ; + // se trovo di nuovo un'intersezione orientata come la prima dello spillone allora ho un nuovo start e posso chiudere l'intervallo precedente + else if( bFirstEndFound && bDirStart == bDir) { + pStartEnd.second = w - 1 ; + bFirstEndFound = false ; + vStartEnds.push_back(pStartEnd) ; + pStartEnd.first = w ; + pStartEnd.second = -1 ; + } + } + for( auto p : vStartEnds ) + SubtractIntervals(nGrid, i, j, vInters[p.first].first.z, vInters[p.second].first.z, vInters[p.first].second, vInters[p.second].second, nToolNum) ; + } + else if ( vInters.size() == 2){ + vStartEnds.push_back(INTINT(0, 1)) ; + SubtractIntervals( nGrid, i, j, vInters.front().first.z, vInters.back().first.z, vInters.front().second, vInters.back().second, nToolNum) ; + } + else if ( vInters.size() == 1) + return false ; } }