diff --git a/VolZmap.h b/VolZmap.h index 5ddb4d5..9c31e9e 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -394,7 +394,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ; bool TestIntersPlaneZmapBBox( const Plane3d& plPlane) const ; // aggiornamento intersezioni - bool UpdateMaxMin( Point3d ptBez, Vector3d vtN, double& dMin, double& dMax, Point3d& ptMin, Point3d& ptMax, Vector3d& vtMin, Vector3d& vtMax) const ; + bool UpdateMaxMin( Point3d ptBez, Vector3d vtN, PNTVECTVECTOR& vInters) const ; // Voxel: esistenza e passaggio da N a ijk per i voxel bool IsValidVoxel( int nN) const ; bool IsValidVoxel( int nI, int nJ, int nK) const ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index f912546..e7a652d 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -1120,18 +1120,10 @@ GetAlongAcrossRotation( const Vector3d& vtDir1, const Vector3d& vtDir2, const Ve //---------------------------------------------------------------------------- bool -VolZmap::UpdateMaxMin( Point3d ptBez, Vector3d vtN, double& dMin, double& dMax, Point3d& ptMin, Point3d& ptMax, Vector3d& vtMin, Vector3d& vtMax) const +VolZmap::UpdateMaxMin( Point3d ptBez, Vector3d vtN, PNTVECTVECTOR& vInters) const { - if ( ptBez.z > dMax) { - dMax = ptBez.z ; - ptMax = ptBez ; - vtMax = -vtN ; // inverto il segno della normale, perché devo passare la normale della supercie tagliata, non di quella di taglio - } - if ( ptBez.z < dMin) { - dMin = ptBez.z ; - ptMin = ptBez ; - vtMin = -vtN ; // inverto il segno della normale, perché devo passare la normale della supercie tagliata, non di quella di taglio - } + if ( ! AreSameVectorExact( vtN, V_NULL)) + vInters.emplace_back( PNTVECT( ptBez, vtN)) ; return true ; } @@ -1297,7 +1289,7 @@ VolZmap::GenTool_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& //debug static vector vGeo ; -static int nCount = 0 ; +//static int nCount = 0 ; //debug //---------------------------------------------------------------------------- @@ -1321,12 +1313,12 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt 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 - ISURFBEZPOVECTOR vSurfBez ; PNTVECTOR d ; Vector3d q = Z_AX ; DBLVECTOR A1, B1, C1, A2, B2, C2 ; int nTotSurf = 2 + nSub * 2 ; - BOXVECTOR vSurfBox( nTotSurf) ; + 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 ; @@ -1392,7 +1384,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Vector3d vtTopBaseEnd = vtDirTop - ( (vtDirTop * vtLe[s]) * vtLe[s]) ; vtTopBaseEnd.Normalize() ; vtTopBaseEnd *= dMaxRad ; - if ( s == nStepCnt) + if ( s == nStepCnt - 1) vtDirTopEndEx = vtTopBaseEnd ; Point3d ptRefEnd = ptE[s] - vtTopBaseEnd ; Vector3d vtTopBaseStart = vtDirTop - ( ( vtDirTop * vtLs[s]) * vtLs[s]) ; @@ -1411,7 +1403,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Vector3d vtTipBaseEnd = - (vtLe[s] ^ vtDirTip) ; vtTipBaseEnd.Normalize() ; vtTipBaseEnd *= dMinRad ; - if ( s == nStepCnt) + if ( s == nStepCnt - 1) vtDirTipEndEx = vtTipBaseEnd ; // aggiungo il primo punto per ognuno dei gruppi vtTopBaseStart.Rotate( vtLs[s], 90) ; @@ -1482,13 +1474,14 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt // inizializzo le superfici bilineari e i parametri per le intersezioni for( int z = 0 ; z < nTotSurf ; ++z) { - vSurfBez.emplace_back( CreateSurfBezier()) ; - vSurfBez.back()->Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ; - vSurfBez.back()->SetControlPoint( 0, vvPtCtrl[z][0]) ; - vSurfBez.back()->SetControlPoint( 1, vvPtCtrl[z][1]) ; - vSurfBez.back()->SetControlPoint( 2, vvPtCtrl[z][2]) ; - vSurfBez.back()->SetControlPoint( 3, vvPtCtrl[z][3]) ; - vSurfBox[z].Add( vvPtCtrl[z]) ; + int nSurfInd = s * nTotSurf + z ; + vSurfBez[nSurfInd].Set( CreateSurfBezier()) ; + vSurfBez[nSurfInd]->Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ; + vSurfBez[nSurfInd]->SetControlPoint( 0, vvPtCtrl[z][0]) ; + vSurfBez[nSurfInd]->SetControlPoint( 1, vvPtCtrl[z][1]) ; + vSurfBez[nSurfInd]->SetControlPoint( 2, vvPtCtrl[z][2]) ; + vSurfBez[nSurfInd]->SetControlPoint( 3, vvPtCtrl[z][3]) ; + 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] ; @@ -1502,17 +1495,15 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt B2.push_back( b.y * q.z - b.z * q.y) ; C2.push_back( c.y * q.z - c.z * q.y) ; if ( nGrid == 0) - vGeo.push_back( vSurfBez[z]->Clone()) ; + vGeo.push_back( vSurfBez[nSurfInd]->Clone()) ; } } - ////debug - //if ( nGrid == 0) { - // if ( nCount == 20) - // SaveGeoObj( vGeo, "D:/Temp/VirtualMilling/5axisAdvanced/finalApprox.nge", 2) ; - // ++nCount ; - //} - ////debug + //debug + if ( nGrid == 0) { + SaveGeoObj( vGeo, "D:/Temp/VirtualMilling/5axisAdvanced/finalApprox.nge", 2) ; + } + //debug BBox3d bbStartCyl = GetCylMoveBBox( ptS[0], ptS[0], vtLs[0], dMaxRad, dHeight) ; BBox3d bbEndCyl = GetCylMoveBBox( ptE.back(), ptE.back(), vtLe.back(), dMaxRad, dHeight) ; @@ -1561,14 +1552,23 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt // frTopStart.Set( ptS[0], ) ; // frTopEnd.Set( ptE.back(), ) ; //} - for ( int i = 1 ; i <= nSub ; ++i) { - vvtTipStartAux[i] = Media( vPntTipStartEx[i-1],vPntTipStartEx[i]) - ptP1T; - vvtTipEndAux[i] = Media( vPntTipEndEx[i-1],vPntTipEndEx[i]) - ptP2T ; - vvtTopStartAux[i] = Media( vPntTopStartEx[i-1],vPntTopStartEx[i]) - ptS[0] ; - vvtTopEndAux[i] = Media( vPntTopEndEx[i-1],vPntTopEndEx[i]) - ptE.back() ; - } + double dMinRadApprox = 0 ; + double dMaxRadApprox = 0 ; - double dRadApprox = vvtTipStartAux.back().Len() ; + 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() ; + } //// creo le quattro superficie quadrate per fare i cap della giunzione tra cilindri e bilineari //PNTMATRIX vvPntSq( 4) ; @@ -1599,17 +1599,15 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt //} // scorro tutti gli spilloni interessati + int nAllStepsSurfs = nTotSurf * nStepCnt ; 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) ; - Point3d ptMin, ptMax ; - double dMin = INFINITO, dMax = -10 ; - Vector3d vtMin, vtMax ; - + PNTVECTVECTOR vInters ; // interseco con le bilineari - for( int s = 0 ; s < nTotSurf ; ++s) { + for( int s = 0 ; s < nAllStepsSurfs ; ++s) { // 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 ; @@ -1628,7 +1626,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Point3d ptBez1 ; Vector3d vtN1 ; vSurfBez[s]->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez1, vtN1) ; - UpdateMaxMin( ptBez1, vtN1, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( ptBez1, -vtN1, vInters) ; } } if ( nRoots > 1 && vdRoots[1] > 0 - EPS_ZERO && vdRoots[1] < 1 + EPS_ZERO) { @@ -1638,7 +1636,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Point3d ptBez2 ; Vector3d vtN2 ; vSurfBez[s]->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptBez2, vtN2) ; - UpdateMaxMin( ptBez2, vtN2, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( ptBez2, -vtN2, vInters) ; } } } @@ -1657,68 +1655,88 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt if ( IntersLineCylinder( r, Z_AX, frStartCyl, dHeight, dMaxRad, false, false, pt1, vt1, pt2, vt2)) { bool bUpdate1 = false ; bool bUpdate2 = false ; - if ( dSide > 0) { - double dPerp = abs( vtDirTip * vtLs[0]) ; - double dDirTip = vtDirTip.Len() ; - double dParall = sqrt( pow( dDirTip,2) - pow( dPerp,2)) ; - double dDistOverlap = dMinRad / dParall * dDirTip ; - bUpdate1 = Dist( ptP1T, pt1) < dDistOverlap && vt1 * vtDirTip > 0 ; - bUpdate2 = Dist( ptP1T, pt2) < dDistOverlap && vt2 * vtDirTip > 0 ; - } - else { - double dPerp = abs( vtDirTop * vtLs[0]) ; - double dDirTop = vtDirTop.Len() ; - double dParall = sqrt( pow( dDirTop,2) - pow( dPerp,2)) ; - double dDistOverlap = dMinRad / dParall * dDirTop ; - bUpdate1 = Dist(ptS[0], pt1) < dDistOverlap && vt1 * vtDirTop > 0 ; - bUpdate2 = Dist(ptS[0], pt2) < dDistOverlap && vt2 * vtDirTop > 0 ; - } + bool bOnTopBase1 = ( pt1 - frStartCyl.Orig()) * frStartCyl.VersZ() > dHeight - EPS_SMALL ; + bool bOnBottomBase1 = ( pt1 - frStartCyl.Orig()) * frStartCyl.VersZ() < EPS_SMALL ; + bool bOnTopBase2 = ( pt2 - frStartCyl.Orig()) * frStartCyl.VersZ() > dHeight - EPS_SMALL ; + bool bOnBottomBase2 = ( pt2 - frStartCyl.Orig()) * frStartCyl.VersZ() < EPS_SMALL ; // se ho un'intersezione su una base devo verificare se la devo considerare o no - if ( ! bUpdate1 && (( pt1 - frStartCyl.Orig()) * frStartCyl.VersZ() < EPS_SMALL || ( pt1 - frStartCyl.Orig()) * frStartCyl.VersZ() > dHeight - EPS_SMALL)) { + if ( bOnBottomBase1 || bOnTopBase1) { // verifico se sono nella metà della base il cui contorno è in contatto con le bilineari //base inferiore double dSectorAng = 0 ; - if ( ( pt1 - frStartCyl.Orig()) * vtDirTipEndEx > 0) { + if ( bOnBottomBase1 && ( pt1 - frStartCyl.Orig()) * vtDirTipStartEx > 0) { vvtTipStartAux.front().GetAngle(pt1 - frStartCyl.Orig(), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub) + 1) ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate1 = (pt1 - frStartCyl.Orig()) * vvtTipStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = (pt1 - frStartCyl.Orig()) * vvtTipStartAux[nSector] ; + if ( dSide > 0) + bUpdate1 = dDist < dMinRadApprox - EPS_SMALL ; + else + bUpdate1 = dDist > dMinRadApprox - EPS_SMALL && dDist < dMinRad ; } // base superiore - else if(( pt1 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight ) )* vtDirTopEndEx > 0) { - vvtTopStartAux.front().GetAngle(pt1 - frStartCyl.Orig(), dSectorAng) ; + else if( bOnTopBase1 && ( pt1 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight))* vtDirTopStartEx > 0) { + vvtTopStartAux.front().GetAngle( pt1 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate1 = (pt1 - frStartCyl.Orig()) * vvtTopStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = ( pt1 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight)) * vvtTopStartAux[nSector] ; + if( dSide < 0) + bUpdate1 = dDist < dMaxRadApprox - EPS_SMALL ; + else + bUpdate1 = dDist > dMaxRadApprox - EPS_SMALL && dDist < dMaxRad ; } + else + bUpdate1 = true ; + } + else { + double dHInters1 = (pt1 - ptP1T) * vtLs.front() ; + Vector3d vtDir1 = Media( vtDirTip, vtDirTop, dHInters1 / dHeight) ; + bUpdate1 = vt1 * vtDir1 > 0 ; } // se ho un'intersezione su una base devo verificare se la devo considerare o no - if ( ! bUpdate2 && (( pt2 - frStartCyl.Orig()) * frStartCyl.VersZ() < EPS_SMALL || ( pt2 - frStartCyl.Orig()) * frStartCyl.VersZ() > dHeight - EPS_SMALL)) { + if ( bOnBottomBase2 || bOnTopBase2) { // verifico se sono nella metà della base il cui contorno è in contatto con le bilineari //base inferiore double dSectorAng = 0 ; - if ( ( pt2 - frStartCyl.Orig()) * vtDirTipEndEx > 0) { - vvtTipStartAux.front().GetAngle(pt2 - frStartCyl.Orig(), dSectorAng) ; + if ( bOnBottomBase2 && ( pt2 - frStartCyl.Orig()) * vtDirTipStartEx > 0) { + vvtTipStartAux.front().GetAngle( pt2 - frStartCyl.Orig(), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate2 = (pt2 - frStartCyl.Orig()) * vvtTipStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = ( pt2 - frStartCyl.Orig()) * vvtTipStartAux[nSector] ; + if ( dSide > 0) + bUpdate2 = dDist < dMinRadApprox - EPS_SMALL ; + else + bUpdate2 = dDist > dMinRadApprox - EPS_SMALL && dDist < dMinRad ; + } // base superiore - else if(( pt2 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight ) )* vtDirTopEndEx > 0) { - vvtTopStartAux.front().GetAngle(pt2 - frStartCyl.Orig(), dSectorAng) ; + else if( bOnTopBase2 && ( pt2 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight))* vtDirTopStartEx > 0) { + vvtTopStartAux.front().GetAngle( pt2 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate2 = (pt2 - frStartCyl.Orig()) * vvtTopStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = ( pt2 - ( frStartCyl.Orig() + frStartCyl.VersZ() * dHeight)) * vvtTopStartAux[nSector] ; + if ( dSide < 0) + bUpdate2 = dDist < dMaxRadApprox - EPS_SMALL ; + else { + bUpdate2 = dDist > dMaxRadApprox - EPS_SMALL && dDist < dMaxRad ; + } } + else + bUpdate2 = true ; + } + else { + double dHInters2 = ( pt2 - ptP1T) * vtLs.front() ; + Vector3d vtDir2 = Media( vtDirTip, vtDirTop, dHInters2 / dHeight) ; + bUpdate2 = vt2 * vtDir2 > 0 ; } if ( bUpdate1) - UpdateMaxMin( pt1, -vt1, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( pt1, vt1, vInters) ; if ( bUpdate2) - UpdateMaxMin( pt2, -vt2, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( pt2, vt2, vInters) ; } } if ( bbEndCyl.SqDistFromPointXY( r) < EPS_ZERO) { @@ -1729,68 +1747,86 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt if ( IntersLineCylinder( r, Z_AX, frEndCyl, dHeight, dMaxRad, false, false, pt1, vt1, pt2, vt2)){ bool bUpdate1 = false ; bool bUpdate2 = false ; - if ( dSide > 0) { - double dPerp = abs( vtDirTop * vtLs[0]) ; - double dDirTop = vtDirTop.Len() ; - double dParall = sqrt( pow( dDirTop,2) - pow( dPerp,2)) ; - double dDistOverlap = dMinRad / dParall * dDirTop ; - bUpdate1 = Dist( ptE.back(), pt1) < dDistOverlap && vt1 * vtDirTop < 0 ; - bUpdate2 = Dist( ptE.back(), pt2) < dDistOverlap && vt2 * vtDirTop < 0 ; - } - else { - double dPerp = abs( vtDirTip * vtLs[0]) ; - double dDirTip = vtDirTip.Len() ; - double dParall = sqrt( pow( dDirTip,2) - pow( dPerp,2)) ; - double dDistOverlap = dMinRad / dParall * dDirTip ; - bUpdate1 = Dist( ptP2T, pt1) < dDistOverlap && vt1 * vtDirTip < 0 ; - bUpdate2 = Dist( ptP2T, pt2) < dDistOverlap && vt2 * vtDirTip < 0 ; - } + bool bOnTopBase1 = ( pt1 - frEndCyl.Orig()) * frEndCyl.VersZ() > dHeight - EPS_SMALL ; + bool bOnBottomBase1 = ( pt1 - frEndCyl.Orig()) * frEndCyl.VersZ() < EPS_SMALL ; + bool bOnTopBase2 = ( pt2 - frEndCyl.Orig()) * frEndCyl.VersZ() > dHeight - EPS_SMALL ; + bool bOnBottomBase2 = ( pt2 - frEndCyl.Orig()) * frEndCyl.VersZ() < EPS_SMALL ; // se ho un'intersezione su una base devo verificare se la devo considerare o no - if ( ! bUpdate1 && (( pt1 - frEndCyl.Orig()) * frEndCyl.VersZ() < EPS_SMALL || ( pt1 - frEndCyl.Orig()) * frEndCyl.VersZ() > dHeight - EPS_SMALL)) { + if ( bOnBottomBase1 || bOnTopBase1) { // verifico se sono nella metà della base il cui contorno è in contatto con le bilineari //base inferiore double dSectorAng = 0 ; - if ( ( pt1 - frEndCyl.Orig()) * vtDirTipEndEx > 0) { + if ( bOnBottomBase1 && ( pt1 - frEndCyl.Orig()) * vtDirTipEndEx > 0) { vvtTipStartAux.front().GetAngle(pt1 - frEndCyl.Orig(), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate1 = (pt1 - frEndCyl.Orig()) * vvtTipStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = (pt1 - frEndCyl.Orig()) * vvtTipStartAux[nSector] ; + if ( dSide < 0) + bUpdate1 = dDist < dMinRadApprox - EPS_SMALL ; + else + bUpdate1 = dDist > dMinRadApprox - EPS_SMALL && dDist < dMinRad ; } // base superiore - else if(( pt1 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight ) )* vtDirTopEndEx > 0) { - vvtTopStartAux.front().GetAngle(pt1 - frEndCyl.Orig(), dSectorAng) ; + else if( bOnTopBase1 && ( pt1 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight))* vtDirTopEndEx > 0) { + vvtTopStartAux.front().GetAngle( pt1 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate1 = (pt1 - frEndCyl.Orig()) * vvtTopStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = ( pt1 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight)) * vvtTopStartAux[nSector] ; + if ( dSide > 0) + bUpdate1 = dDist < dMaxRadApprox - EPS_SMALL ; + else + bUpdate1 = dDist > dMaxRadApprox - EPS_SMALL && dDist < dMaxRad ; } + else + bUpdate1 = true ; + } + else { + double dHInters1 = (pt1 - ptP2T) * vtLe.back() ; + Vector3d vtDir1 = Media( vtDirTip, vtDirTop, dHInters1 / dHeight) ; + bUpdate1 = vt1 * vtDir1 < 0 ; } // se ho un'intersezione su una base devo verificare se la devo considerare o no - if ( ! bUpdate2 && (( pt2 - frEndCyl.Orig()) * frEndCyl.VersZ() < EPS_SMALL || ( pt2 - frEndCyl.Orig()) * frEndCyl.VersZ() > dHeight - EPS_SMALL)) { + if ( bOnBottomBase2 || bOnTopBase2) { // verifico se sono nella metà della base il cui contorno è in contatto con le bilineari //base inferiore double dSectorAng = 0 ; - if ( ( pt2 - frEndCyl.Orig()) * vtDirTipEndEx > 0) { + if ( bOnBottomBase2 && ( pt2 - frEndCyl.Orig()) * vtDirTipEndEx > 0) { vvtTipStartAux.front().GetAngle(pt2 - frEndCyl.Orig(), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate2 = (pt2 - frEndCyl.Orig()) * vvtTipStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = (pt2 - frEndCyl.Orig()) * vvtTipStartAux[nSector] ; + if ( dSide < 0) + bUpdate2 = dDist < dMinRadApprox - EPS_SMALL ; + else + bUpdate2 = dDist > dMinRadApprox - EPS_SMALL && dDist < dMinRad ; } // base superiore - else if(( pt2 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight ) )* vtDirTopEndEx > 0) { - vvtTopStartAux.front().GetAngle(pt2 - frEndCyl.Orig(), dSectorAng) ; + else if( bOnTopBase2 && ( pt2 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight))* vtDirTopEndEx > 0) { + vvtTopStartAux.front().GetAngle( pt2 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight), dSectorAng) ; // determino in quale settore del semicerchio approssimato mi trovo - int nSector = dSectorAng / ( 180. / nSub) + 1 ; + int nSector = int( dSectorAng / ( 180. / nSub)) + 1 ; // verifico se l'intersezione linea-base è interna o esterna - bUpdate2 = (pt2 - frEndCyl.Orig()) * vvtTopStartAux[nSector] < dRadApprox - EPS_SMALL ; + double dDist = ( pt2 - ( frEndCyl.Orig() + frEndCyl.VersZ() * dHeight)) * vvtTopStartAux[nSector] ; + if ( dSide > 0) + bUpdate2 = dDist < dMaxRadApprox - EPS_SMALL ; + else + bUpdate2 = dDist > dMaxRadApprox - EPS_SMALL && dDist < dMaxRad ; } + else + bUpdate2 = true ; + } + else { + double dHInters2 = (pt2 - ptP2T) * vtLe.back() ; + Vector3d vtDir2 = Media( vtDirTip, vtDirTop, dHInters2 / dHeight) ; + bUpdate2 = vt2 * vtDir2 < 0 ; } if ( bUpdate1) - UpdateMaxMin( pt1, -vt1, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( pt1, vt1, vInters) ; if ( bUpdate2) - UpdateMaxMin( pt2, -vt2, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( pt2, vt2, vInters) ; } } } @@ -1802,8 +1838,8 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Point3d pt1, pt2 ; Vector3d vt1, vt2 ; if ( IntersLineConus( r, Z_AX, frStartCon, dTan, dMinH, dMaxH, false, false, pt1, vt1, pt2, vt2)) { - UpdateMaxMin( pt1, -vt1, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; - UpdateMaxMin( pt2, -vt2, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( pt1, vt1, vInters) ; + UpdateMaxMin( pt2, vt2, vInters) ; } } if ( bbEndCyl.SqDistFromPointXY( r) < EPS_ZERO) { @@ -1812,16 +1848,61 @@ VolZmap::Comp_5AxisMilling( int nGrid, const PNTVECTOR& ptS, const PNTVECTOR& pt Point3d pt1, pt2 ; Vector3d vt1, vt2 ; if ( IntersLineConus( r, Z_AX, frEndCon, dTan, dMinH, dMaxH, false, false, pt1, vt1, pt2, vt2)) { - UpdateMaxMin( pt1, -vt1, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; - UpdateMaxMin( pt2, -vt2, dMin, dMax, ptMin, ptMax, vtMin, vtMax) ; + UpdateMaxMin( pt1, vt1, vInters) ; + UpdateMaxMin( pt2, vt2, vInters) ; } } } // interseco con le basi trimmate dei cilindri ( che tengono conto dell'approssimazione fatta con bilineari del volume spazzato da top e tip) - if ( dMax > 0 && dMin < dMax) - SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax, nToolNum) ; + if ( vInters.size() != 0 ) { + // se ho un numero dispari di intersezioni devo migliorare la gestione + + // riordino le intersezioni rispetto alla loro z + sort( vInters.begin(), vInters.end(), []( PNTVECT& a, PNTVECT& b){ return a.first.z < b.first.z ;}) ; + if ( vInters.size() > 2) { + INTVECTOR vErase ; + bool bStartNewInterval = true ; + // elimino eventuali doppioni di punti + for ( int w = 0 ; w < int( vInters.size()) ; ++w) { + // se è l'ultimo punto esco + if ( w == int( vInters.size() - 1)) + break ; + // se sono due punti vicino tolgo il secondo se sto cercando l'inizio di un intervallo + // mentre se sto cercando la fine tolgo il primo + if ( vInters[w + 1].first.z - vInters[w].first.z < 1) { + if ( bStartNewInterval) { + // se sto cercando l'inizio, ma sono gli ultimi due punti e sono vicini allora tolgo entrambi ed esco + if ( w == int( vInters.size() - 2)) { + // serve che siano in quest'ordine + vErase.push_back( w) ; + vErase.push_back( w + 1) ; + break ; + } + else + vErase.push_back( w + 1) ; + ++w ; + } + else { + vErase.push_back( w) ; + ++w ; + } + } + bStartNewInterval = ! bStartNewInterval ; + } + + // elimino i doppioni + for ( int w = vErase.size() - 1 ; w >= 0 ; --w) + vInters.erase( vInters.begin() + vErase[w]) ; + } + if ( vInters.size() % 2 == 0) { + for( int z = 0 ; z < int( vInters.size()) ; z += 2) + SubtractIntervals( nGrid, i, j, vInters[z].first.z, vInters[z+1].first.z, vInters[z].second, vInters[z+1].second, nToolNum) ; + } + else if ( vInters.size() == 3) + SubtractIntervals( nGrid, i, j, vInters.front().first.z, vInters.back().first.z, vInters.front().second, vInters.back().second, nToolNum) ; + } } } @@ -2054,14 +2135,14 @@ VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, co Point3d ptSti = ptPs ; Vector3d vtDSi = vtDs ; double dCorr = 0.05 * 1. / nStepCnt ; // creo una sovrapposizone tra uno step e il successivo - dCorr = 0. ; - BIPNTVECTOR vPntStep( nStepCnt) ; - vector> vDirStep( nStepCnt) ; + //dCorr = 0. ; // annullo la sovrapposizione // debug + //BIPNTVECTOR vPntStep( nStepCnt) ; + //vector> vDirStep( nStepCnt) ; - vector ptLs( nStepCnt) ; - vector ptLe( nStepCnt) ; - vector vtLs( nStepCnt) ; - vector vtLe( nStepCnt) ; + vector ptLs( nStepCnt + 1) ; + vector ptLe( nStepCnt + 1) ; + vector vtLs( nStepCnt + 1) ; + vector vtLe( nStepCnt + 1) ; for ( int i = 0 ; i <= nStepCnt && bOk ; ++ i) { //// replico il tutto ma tenendo degli step più ampi e usando i veri vettori di start e end del tratto @@ -2083,18 +2164,16 @@ VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, co if ( i == nStepCnt) nPhase = VolZmap::MillingPhase::COUNT_END_VOL ; - Point3d ptLs[N_MAPS] ; - - InitializePointsAndVectors( ptSti, ptEni, vtDSi, vtDEi, &ptLs[i], ptLe[i], vtLs[i], vtLe[i]) ; + InitializePointsAndVectors( ptSti, ptEni, vtDSi, vtDEi, ptLs[i], ptLe[i], vtLs[i], vtLe[i]) ; } ///// decommentare solo per debug for( int j = 0 ; j < N_MAPS; ++j) { - PNTVECTOR ptLs_j( nStepCnt) ; - PNTVECTOR ptLe_j( nStepCnt) ; - VCT3DVECTOR vtLs_j( nStepCnt) ; - VCT3DVECTOR vtLe_j( nStepCnt) ; - for ( int z = 0 ; z < nStepCnt ; ++z) { + PNTVECTOR ptLs_j( nStepCnt + 1) ; + PNTVECTOR ptLe_j( nStepCnt + 1) ; + VCT3DVECTOR vtLs_j( nStepCnt + 1) ; + VCT3DVECTOR vtLe_j( nStepCnt + 1) ; + for ( int z = 0 ; z <= nStepCnt ; ++z) { ptLs_j[z] = ptLs[z][j] ; ptLe_j[z] = ptLe[z][j] ; vtLs_j[z] = vtLs[z][j] ;