From 3bbdfc4a7483b79a09b6884140c06c753622b8bb Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 13 Jun 2016 07:10:18 +0000 Subject: [PATCH] EgtGeomKernel 1.6r9 : - inseriti sviluppi Zmap. --- EgtGeomKernel.rc | Bin 11718 -> 11718 bytes GdbExecutor.cpp | 57 +- GdbExecutor.h | 1 + VolZmap.cpp | 3642 +++++++++++++++++++++++++++++++++++++++++++++- VolZmap.h | 63 +- 5 files changed, 3703 insertions(+), 60 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index d1fc48936524299ad573fe7fd14ba62288033e73..46750777cb65a1aa3caefde8347f45f7e61947f6 100644 GIT binary patch delta 110 zcmX>WeJpyzA2vqI&G-4vGfl1&(wY2&Q;pGbvZAo=W*@FeEMOU1X1ItOWeJpyzA2vpd&G-4vGfl1&(wY2&Q;pGLvZAo=W*@FeEMOU1X1ItOGetGeoObj( nCrvId)) ; if ( pToolOutline == nullptr) return false ; - // recupero tipo utensile - int nToolType ; - if ( ! FromString( vsParams[2], nToolType)) + // recupero la stringa nome dell'utensile + string sToolName ; + sToolName = vsParams[2] ; + // assegno utensile + return pZmap->SetTool( sToolName, pToolOutline) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::VolZmapSetStdTool( const STRVECTOR& vsParams) +{ + // parametri : ZmapId, sToolName, nToolType, dH, dTH, dR, dTR, dRc + if ( vsParams.size() != 8) + return false ; + // recupero lo Zmap + int nZmapId = GetIdParam( vsParams[0]) ; + VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ; + if ( pZmap == nullptr) return false ; // recupero la stringa nome dell'utensile string sToolName ; - sToolName = vsParams[3] ; + sToolName = vsParams[1] ; + // recupero il tipo di utensile + int nToolType ; + if ( ! FromString( vsParams[2], nToolType)) + return false ; + if (nToolType < 0 || nToolType > 4) + return false ; + // recupero altezza utensile + double dH ; + if ( ! FromString( vsParams[3], dH)) + return false ; + // recupero raggio utensile + double dTH ; + if ( ! FromString( vsParams[4], dTH)) + return false ; + // recupero raggio corner + double dR ; + if ( ! FromString( vsParams[5], dR)) + return false ; + double dTR ; + if ( ! FromString( vsParams[6], dTR)) + return false ; + double dRc ; + if ( ! FromString( vsParams[7], dRc)) + return false ; + // assegno utensile - return pZmap->SetTool( sToolName, nToolType, pToolOutline) ; + return pZmap->SetStdTool( sToolName, nToolType, dH, dTH, dR, dTR, dRc) ; } //---------------------------------------------------------------------------- diff --git a/GdbExecutor.h b/GdbExecutor.h index 59345b6..953e4cd 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -119,6 +119,7 @@ class GdbExecutor : public IGdbExecutor bool VolZmapIntervalsAddiction( const STRVECTOR& vsParams) ; bool VolZmapMilling( const STRVECTOR& vsParams) ; bool VolZmapSetTool( const STRVECTOR& vsParams) ; + bool VolZmapSetStdTool( const STRVECTOR& vsParams) ; bool ExecuteText( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool TextSimple( const STRVECTOR& vsParams) ; bool TextComplete( const STRVECTOR& vsParams) ; diff --git a/VolZmap.cpp b/VolZmap.cpp index 08c3b3f..02fc1c3 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -378,6 +378,9 @@ VolZmap::CreateMap( const Point3d& ptO, double dPrec, double dLengthX, double dL m_ZValues[i][1] = dLengthZ ; } + m_dMinZ = 0 ; + m_dMaxZ = dLengthZ ; + m_nStatus = OK ; return true ; } @@ -402,7 +405,7 @@ VolZmap::SubtractIntervals( unsigned int nI, unsigned int nJ, double dMin, doubl double dTemp = dMax ; dMax = dMin ; - dMin = dMax ; + dMin = dTemp ; // cambiato il 3/2 } // Calcolo nPos @@ -488,13 +491,13 @@ VolZmap::SubtractIntervals( const Point3d& ptP, double dMin, double dMax) // ptP double integerPartX = floor( dX / m_dStep) ; double integerPartY = floor( dY / m_dStep) ; - unsigned int i = static_cast (integerPartX) ; // Indici del punto di griglia più vicino. + unsigned int i = static_cast (integerPartX) ; // Indici del punto di griglia più vicino. unsigned int j = static_cast (integerPartY) ; // i = 0, 1, ..., m_Nx - 1 ; j = 0, 1, ..., m_Ny - 1 // Controllo se le coordinate x e y del punto dato siano all'interno della griglia: // se sono dentro la griglia chiamo l'altra subtract if ( dX < m_dStep*m_nNx && dY < m_dStep*m_nNy - && dX >= 0 && dY >= 0) { // Mettendo > - qlc può sempre capitare un punto compreso fra - qlc e 0 e si esce dai limiti dell vector + && dX >= 0 && dY >= 0) { // Mettendo > - qlc può sempre capitare un punto compreso fra - qlc e 0 e si esce dai limiti dell vector e vi è errore runtime return SubtractIntervals( i, j, dhMin, dhMax) ; } @@ -526,7 +529,7 @@ VolZmap::AddIntervals( unsigned int nI, unsigned int nJ, double dMin, double dMa double dTemp = dMax ; dMax = dMin ; - dMin = dMax ; + dMin = dTemp ; // cambiato il 3/2 } // Calcolo nPos @@ -636,13 +639,13 @@ VolZmap::AddIntervals( const Point3d& ptP, double dMin, double dMax) // ptP double integerPartX = floor( dX / m_dStep) ; double integerPartY = floor( dY / m_dStep) ; - unsigned int i = static_cast (integerPartX) ; // Indici del punto di griglia più vicino. + unsigned int i = static_cast (integerPartX) ; // Indici del punto di griglia più vicino. unsigned int j = static_cast (integerPartY) ; // i = 0, 1, ..., m_Nx - 1 ; j = 0, 1, ..., m_Ny - 1 // Controllo se le coordinate x e y del punto dato siano all'interno della griglia: // se sono dentro la griglia chiamo l'altra subtract if ( dX < m_dStep*m_nNx && dY < m_dStep*m_nNy - && dX >= 0 && dY >= 0) { // Mettendo > - qlc può sempre capitare un punto compreso fra - qlc e 0 e si esce dai limiti dell vector + && dX >= 0 && dY >= 0) { // Mettendo > - qlc può sempre capitare un punto compreso fra - qlc e 0 e si esce dai limiti dell vector e vi è errore runtime return AddIntervals( i, j, dhMin, dhMax) ; } @@ -878,28 +881,104 @@ VolZmap::AddDexelSideFace( int nPos, int nPosAdj, const Point3d& ptP, const Poin //---------------------------------------------------------------------------- bool -VolZmap::SetTool( const string& pToolName, unsigned int nToolType, const CurveComposite* pToolOutline) +VolZmap::SetTool( const string& pToolName, const CurveComposite* pToolOutline) { m_sToolName = pToolName ; - m_nToolType = nToolType ; + m_nToolType = GenericTool ; m_ToolOutline.CopyFrom( pToolOutline) ; + // Dimensioni dell'utensile + BBox3d Bounding ; + m_ToolOutline.GetLocalBBox( Bounding) ; + double m_dHeight = Bounding.GetMax().y - Bounding.GetMin().y ; + double m_dRadius = Bounding.GetMax().x - Bounding.GetMin().x ; + return true ; } //---------------------------------------------------------------------------- bool -VolZmap::MillingStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtDe) +VolZmap::SetStdTool( const string& pToolName, unsigned int nToolType, double dH, double dTH, double dR, double dTR, double dRc) { - // Dimensioni dell'utensile - BBox3d Bounding ; - m_ToolOutline.GetLocalBBox( Bounding) ; - double dHeight = Bounding.GetMax().y - Bounding.GetMin().y ; - double dRadius = Bounding.GetMax().x - Bounding.GetMin().x ; + // Controllo sull'ammissibilità del tipo di utensile + if ( nToolType == GenericTool || nToolType > 4) - // Porto i dati del movimento nel riferimento intrinseco + return false ; + else { + // Controllo sull'ammissibilità dei parametri geometrici dell'utensile + if ( dH < EPS_SMALL || dR < EPS_SMALL) + + return false ; + + m_sToolName = pToolName ; + m_nToolType = nToolType ; + + m_dRadius = dR ; + m_dHeight = dH ; + + if ( nToolType == CylindricalMill) { + + m_dTipHeight = 0 ; + m_dTipRadius = m_dRadius ; + } + else if ( nToolType == BallEndMill) { + + m_dTipHeight = m_dRadius ; + m_dTipRadius = 0 ; + } + else if ( nToolType == BullNoseMill) { + + if ( dR < dRc) + + return false ; + + m_dRCorner = dRc ; + m_dTipHeight = dRc ; + m_dTipRadius = dR - dRc ; + + if ( dRc < EPS_SMALL) { + + m_dRCorner = 0 ; + m_nToolType = CylindricalMill ; + } + + if ( dRc > dR - EPS_SMALL) { + + m_dRCorner = m_dRadius ; + m_nToolType = BallEndMill ; + } + } + else if ( nToolType == ConusMill) { + + if ( dTH < 0 || dTR < 0) + + return false ; + + if ( abs( dR - dTR) < EPS_SMALL) { + + m_nToolType = CylindricalMill ; + + m_dTipHeight = 0 ; + m_dTipRadius = m_dRadius ; + } + else { + + m_dTipHeight = dTH ; + m_dTipRadius = dTR ; + } + } + return true ; + } +} + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingStep( const Point3d& ptPs, const Point3d& ptPe, Vector3d& vtDs, Vector3d& vtDe) +{ + + // Porto i dati del movimento nel riferimento intrinseco Point3d ptLs = ptPs ; ptLs.ToLoc( m_LocalFrame) ; Point3d ptLe = ptPe ; @@ -909,32 +988,85 @@ VolZmap::MillingStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& Vector3d vtLe = vtDe ; vtLe.ToLoc( m_LocalFrame) ; - // Direzione utensile costante e come asse Z dello Zmap - if ( AreSameVectorApprox( vtLs, vtLe) && vtLs.IsZplus()) { - // Movimento diretto come direzione utensile - if ( AreSamePointXYApprox( ptLs, ptLe)) - return MillingDrill(ptLs, ptLe, dHeight, dRadius) ; - // Movimento perpendicolare a direzione utensile - else if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) - return MillingPerp(ptLs, ptLe, dHeight, dRadius) ; - // Movimento generico (per ora non gestito) - else - return false ; + if ( AreSamePointApprox( ptLs, ptLe) && AreSameVectorApprox( vtLs, vtLe)) + return true ; + + // Normalizzo i vettori + vtLs.Normalize() ; + vtLe.Normalize() ; + + // Direzione utensile costante + if ( AreSameVectorApprox( vtLs, vtLe)) { + // Versori della direzione utensile paralleli/ antiparalleli a Z + if ( vtLs.IsZplus() || vtLs.IsZminus()) { + // Movimento diretto come direzione utensile + if ( AreSamePointXYApprox( ptLs, ptLe)) + return MillingDrillZ( ptLs, ptLe, vtLs) ; + // Movimento perpendicolare a direzione utensile + else if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) + return MillingPerpZ( ptLs, ptLe, vtLs) ; + // Movimento generico + else + return MillingZ( ptLs, ptLe, vtLs) ; + } + // Versori della direzione utensile perpendicolari all'asse Z + else if ( abs(vtLs * Z_AX) < EPS_SMALL) { + // Movimento con Z costante (con vettore movimento parallelo od ortogonale al versore dell'utensile) + if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) { + // Movimento parallelo alla direzione dell'utensile (foratura) + Vector3d vtTest = ptLe - ptLs ; vtTest.Normalize() ; + if ( abs( ( vtTest * vtLs) - 1) < EPS_SMALL) + return MillingDrillXY( ptLs, ptLe, vtLs) ; + // Movimento perpendicolare alla direzione dell'utensile + else if ( abs( (ptLe - ptLs) * vtLs) < EPS_SMALL) + return MillingPerpXY( ptLs, ptLe, vtLs) ; + // Movimento nel piano generico + else + return MillingXYPlaneGen( ptLs, ptLe, vtLs) ; + } + // Movimento con Z non costante + else { + // Grandezze geometriche per selezione + Vector3d vtMove = ptLe - ptLs ; + Vector3d vtTest = vtMove - ( vtMove * vtLs) * vtLs ; + + if ( abs( vtTest * X_AX) < EPS_SMALL && abs( vtTest * Y_AX) < EPS_SMALL) + return MillingXYLongVert( ptLs, ptLe, vtLs) ; + else { + if ( abs( vtMove * vtLs) < EPS_SMALL) { + if ( m_nToolType == 1) + return MillingXYCyl( ptLs, ptLe, vtLs) ; + else if ( m_nToolType == 2) + return MillingXYBall( ptLs, ptLe, vtLs) ; + } + else { + if ( m_nToolType ==1) + return MillingXYPlusCyl( ptLs, ptLe, vtLs) ; + else if ( m_nToolType == 2) + return MillingXYPlusBall( ptLs, ptLe, vtLs) ; + } + } + } + } } // Altri casi, non gestiti - else - return false ; + return false ; } +// Frese: cylindrical, ball-end e bull-nose ////////////////////////////////// +// Versore utensile parallelo all'asse Z //---------------------------------------------------------------------------- bool -VolZmap::MillingDrill( const Point3d& ptLs, const Point3d& ptLe, double dHeight, double dRadius) +VolZmap::MillingDrillZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + if ( m_nToolType == 4) + return ConusDrillingZ( ptLs, ptLe, vtToolDir) ; + // Bounding box - double dMinX = min( ptLs.x, ptLe.x) - dRadius ; - double dMinY = min( ptLs.y, ptLe.y) - dRadius ; - double dMaxX = max( ptLs.x, ptLe.x) + dRadius ; - double dMaxY = max( ptLs.y, ptLe.y) + dRadius ; + double dMinX = min( ptLs.x, ptLe.x) - m_dRadius ; + double dMinY = min( ptLs.y, ptLe.y) - m_dRadius ; + double dMaxX = max( ptLs.x, ptLe.x) + m_dRadius ; + double dMaxY = max( ptLs.y, ptLe.y) + m_dRadius ; // Verifico interferisca con lo Zmap if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) @@ -949,11 +1081,13 @@ VolZmap::MillingDrill( const Point3d& ptLs, const Point3d& ptLe, double dHeight, unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; // Determino quote estreme del tagliente - double dMax = ptLs.z - dHeight ; - double dMin = ptLe.z - dHeight ; + double dMax = ptLs.z - m_dHeight ; // Volendo si può effettuare un controllo su quota punto finale e iniziale, + double dMin = ptLe.z - m_dHeight ; // ma non è necessaria dal momento che Subtract intervals scambia min con max se max < min + double dZCutBase = ptLs.z ; // Quota della base del tagliente nella posizione iniziale + double dDeltaZ = ptLe.z - ptLs.z ; // Differenza delle quote fra le posizioni finale e iniziale della base del tagliente // Limite sul quadrato del raggio - double dSqRad = ( dRadius + EPS_SMALL) * ( dRadius + EPS_SMALL) ; + double dSqRad = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ; // Ciclo sui punti nei limiti for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { @@ -966,7 +1100,7 @@ VolZmap::MillingDrill( const Point3d& ptLs, const Point3d& ptLe, double dHeight, double dSqDist = SqDistXY( ptQ, ptLe) ; // se distanza nei limiti, taglio if ( dSqDist < dSqRad) - SubtractIntervals( i, j, dMin, dMax) ; + GetMinMaxZ( i, j, dZCutBase, dDeltaZ, dSqDist, vtToolDir) ; } } @@ -975,13 +1109,16 @@ VolZmap::MillingDrill( const Point3d& ptLs, const Point3d& ptLe, double dHeight, //---------------------------------------------------------------------------- bool -VolZmap::MillingPerp( Point3d& ptLs, Point3d& ptLe, double dHeight, double dRadius) +VolZmap::MillingPerpZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + if ( m_nToolType == 4) + return ConusPerpZ( ptLs, ptLe, vtToolDir) ; + // Bounding box - double dMinX = min( ptLs.x, ptLe.x) - dRadius ; - double dMinY = min( ptLs.y, ptLe.y) - dRadius ; - double dMaxX = max( ptLs.x, ptLe.x) + dRadius ; - double dMaxY = max( ptLs.y, ptLe.y) + dRadius ; + double dMinX = min( ptLs.x, ptLe.x) - m_dRadius ; + double dMinY = min( ptLs.y, ptLe.y) - m_dRadius ; + double dMaxX = max( ptLs.x, ptLe.x) + m_dRadius ; + double dMaxY = max( ptLs.y, ptLe.y) + m_dRadius ; // Verifico interferisca con lo Zmap if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) @@ -996,11 +1133,11 @@ VolZmap::MillingPerp( Point3d& ptLs, Point3d& ptLe, double dHeight, double dRadi unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; // Determino quote estreme del tagliente - double dMax = ptLs.z ; - double dMin = ptLs.z - dHeight ; // Questa andrà eliminata in futuro oppure la teniamo e la usiamo al bisogno + double dZCutBase = ptLs.z ; // Quota della base del tagliente nella posizione iniziale + double dDeltaZ = ptLe.z - ptLs.z ; // Differenza delle quote fra le posizioni finale e iniziale della base del tagliente // Limite sul quadrato del raggio - double dSqRad = ( dRadius + EPS_SMALL) * ( dRadius + EPS_SMALL) ; + double dSqRad = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ; // Segmento di movimento (nel piano griglia) Point3d ptStart( ptLs.x, ptLs.y, 0) ; @@ -1026,9 +1163,3422 @@ VolZmap::MillingPerp( Point3d& ptLs, Point3d& ptLe, double dHeight, double dRadi double dSqDist = SqDistXY( ptQ, ptMinDist) ; // se distanza nei limiti, taglio if ( dSqDist < dSqRad) - SubtractIntervals( i, j, dMin, dMax) ; + GetMinMaxZ( i, j, dZCutBase, dDeltaZ, dSqDist, vtToolDir) ; } } return true ; } + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + if ( m_nToolType == 4) + if ( m_dRadius > m_dTipRadius) + return ConusMillingZDr( ptLs, ptLe, vtToolDir) ; + else + return ConusMillingZSw( ptLs, ptLe, vtToolDir) ; + + // Setto il fattore per l'orientazione in z + double dFactor = ( vtToolDir.z < 0 ? 1 : - 1) ; + + // Bounding box + double dMinX = min( ptLs.x, ptLe.x) - m_dRadius ; + double dMaxX = max( ptLs.x, ptLe.x) + m_dRadius ; + double dMinY = min( ptLs.y, ptLe.y) - m_dRadius ; + double dMaxY = max( ptLs.y, ptLe.y) + m_dRadius ; + double dMinZ = min( min( ptLs.z, ptLs.z + dFactor * m_dHeight), min( ptLe.z, ptLe.z + dFactor * m_dHeight)) ; + double dMaxZ = max( max( ptLs.z, ptLs.z + dFactor * m_dHeight), max( ptLe.z, ptLe.z + dFactor * m_dHeight)) ; + + // Verifico interferisca con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + // Determino i limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + // + double dZCutBase = ptLs.z ; // Quota della base del tagliente nella posizione iniziale + double dDeltaZ = ptLe.z - ptLs.z ; // Differenza delle quote fra le posizioni finale e iniziale della base del tagliente + + // Limite sul quadrato del raggio + double dSqRad = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ; + + // Segmento di movimento (nel piano griglia) + Point3d ptStart( ptLs.x, ptLs.y, 0) ; + Point3d ptEnd( ptLe.x, ptLe.y, 0) ; + double dLen ; + Vector3d vtDir ; + DirDist( ptStart, ptEnd, vtDir, dLen) ; + + // Ciclo sui punti nei limiti + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { + double dX = ( i + 0.5) * m_dStep ; + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + double dY = ( j + 0.5) * m_dStep ; + // punto + Point3d ptQ( dX, dY, 0) ; + // determino il quadrato della distanza del punto dal segmento + double dProj = vtDir * ( ptQ - ptStart) ; + double dProiez ; + + if ( dProj < 0) + dProiez = 0 ; + else if ( dProj < dLen) + dProiez = dProj ; + else + dProiez = dLen ; + + Point3d ptMinDist = ptStart + vtDir * dProiez ; + double dSqDist = SqDistXY( ptQ, ptMinDist) ; + + // se distanza nei limiti, taglio + if ( dSqDist < dSqRad) + GetMinMaxZGen( i, j, dProj, dSqDist, dLen, dZCutBase, dDeltaZ, vtToolDir) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMinMaxZ( unsigned int nI, unsigned int nJ, double dZCutBase, double dDeltaZ, double dSqDist, const Vector3d& vtToolDir) { + + // Definisco variabili + double dSqRad = m_dRadius * m_dRadius ; + double dFactor = ( vtToolDir.z < 0 ? - 1 : 1) ; + double dZtip = ( vtToolDir.z < 0 ? dZCutBase + m_dHeight : dZCutBase - m_dHeight) ; + + double dMin ; double dMax ; + + // Caso utensile generico al momento non gestito + if ( m_nToolType == 0) + + return false; + // Caso Cylindrical Mill + else if ( m_nToolType == 1) { + + if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) { // Non è meglio fare if (vt * delta < - Eps_small ) else if ( vt * delta < Eps) else ? + dMin = min(dZCutBase, dZtip) ; + dMax = max(dZCutBase, dZtip) ; + } + else if ( vtToolDir.z * dDeltaZ < 0) { + dMin = min(dZtip, dZtip + dDeltaZ) ; + dMax = max(dZtip, dZtip + dDeltaZ) ; + } + else { + dMin = min(dZCutBase, dZCutBase + dDeltaZ) ; + dMax = max(dZCutBase, dZCutBase + dDeltaZ) ; + } + return SubtractIntervals( nI, nJ, dMin, dMax) ; + } + // Caso Ball-End Mill + else if ( m_nToolType == 2) { + + if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) { + dMin = min(dZCutBase, dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist))) ; + dMax = max(dZCutBase, dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist))) ; + } + else if ( vtToolDir.z * dDeltaZ < 0) { + dMin = min(dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)), dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)) + dDeltaZ) ;// ocio + dMax = max(dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)), dZtip + dFactor*(m_dRadius - sqrt(dSqRad - dSqDist)) + dDeltaZ) ;// ocio + } + else { + dMin = min(dZCutBase, dZCutBase + dDeltaZ) ; + dMax = max(dZCutBase, dZCutBase + dDeltaZ) ; + } + return SubtractIntervals( nI, nJ, dMin, dMax) ; + } + // Caso Bull-Nose Mill + else if ( m_nToolType == 3) { + + double dDeltaR = m_dRadius - m_dRCorner ; + + if ( dSqDist < dDeltaR*dDeltaR) { + + if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) { + dMin = min(dZCutBase, dZtip) ; + dMax = max(dZCutBase, dZtip) ; + } + else if ( vtToolDir.z * dDeltaZ < 0) { + dMin = min(dZtip, dZtip + dDeltaZ) ; + dMax = max(dZtip, dZtip + dDeltaZ) ; + } + else { + dMin = min(dZCutBase, dZCutBase + dDeltaZ) ; + dMax = max(dZCutBase, dZCutBase + dDeltaZ) ; + } + return SubtractIntervals( nI, nJ, dMin, dMax) ; + } + else { + + double dSqRadC = m_dRCorner*m_dRCorner ; + double dSqd = dSqDist + dDeltaR*dDeltaR - 2*sqrt(dSqDist)*dDeltaR ; + + if ( abs(vtToolDir.z * dDeltaZ) < EPS_SMALL) { + dMin = min(dZCutBase, dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd))) ; + dMax = max(dZCutBase, dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd))) ; + } + else if ( vtToolDir.z * dDeltaZ < 0) { + dMin = min(dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)), dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)) + dDeltaZ) ; + dMax = max(dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)), dZtip + dFactor*(m_dRCorner - sqrt(dSqRadC - dSqd)) + dDeltaZ) ; + } + else { + dMin = min(dZCutBase, dZCutBase + dDeltaZ) ; + dMax = max(dZCutBase, dZCutBase + dDeltaZ) ; + } + return SubtractIntervals( nI, nJ, dMin, dMax) ; + } + } + // Caso di utensile inesistente ( m_nToolType fuori dai valori concessi) + else + return false ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMinMaxZGen( unsigned int nI, unsigned int nJ, double dProj, double dSqd, double dLenPath, double dZheight, double dDelta, const Vector3d& vtToolDir) { + + // Controllo sul tipo di utensile: se 0 utensile generico (al momento non gestito) se maggiore di 3 utensile fuori dai tipi consentiti + if ( m_nToolType == 0 || m_nToolType > 3) + return false ; + + // Definisco variabili quota della punta, minimo e massimo dell'intervallo da sottrarre + double dZTip = ( vtToolDir.z < 0 ? dZheight + m_dHeight : dZheight - m_dHeight) ; + double dMin, dMax ; double dStart ; // dStart è un parametro che esprime l'ascissa in cui la retta congiungente le due posizioni iniziale e finale + double dRSqDist1, dRSqDist2 ; // di un punto del tagliente (nel sistema dell'asse dell'utensile nella posizione iniziale) assume la quota dZheight + + // Nei conti è comodo che dSqd assuma sempre il significato di distanza del punto dall'asse del movimento al quadrato + if ( dProj < 0) + dSqd = dSqd - dProj * dProj ; + else if ( dProj > dLenPath) + dSqd = dSqd - ( dProj - dLenPath) * ( dProj - dLenPath) ; + + // Caso di cylindrical mill + if ( m_nToolType == 1) { + + double dZ1, dZ2 ; + // Se lavora la punta + if ( vtToolDir.z * dDelta < 0) { + dZ1 = dZTip ; + dZ2 = dZheight ; + } + // Se lavora il fondo + else { + dZ1 = dZheight ; + dZ2 = dZTip ; + } + + dStart = sqrt( m_dRadius * m_dRadius - dSqd) ; + dRSqDist1 = dProj * dProj + dSqd ; + dRSqDist2 = ( dLenPath - dProj) * ( dLenPath - dProj) + dSqd ; + + if ( dRSqDist1 < (m_dRadius + EPS_SMALL) * (m_dRadius + EPS_SMALL)) { + + dMin = min( max( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ1 + dDelta), dZ2) ; + dMax = max( min( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ1 + dDelta), dZ2) ; + } + else if ( dRSqDist2 < (m_dRadius + EPS_SMALL) * (m_dRadius + EPS_SMALL)) { + + dMin = min( min(dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath, dZ2 + dDelta), dZ1 + dDelta) ; + dMax = max( max(dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath, dZ2 + dDelta), dZ1 + dDelta) ; + } + else { + + dMin = min( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath) ; + dMax = max( dZ1 + ( dDelta * ( dProj + dStart)) / dLenPath, dZ2 + ( dDelta * ( dProj - dStart)) / dLenPath) ; + } + } + // Caso di ball-end mill + else if ( m_nToolType == 2) { + + if ( dDelta < 0) { + + dDelta = - dDelta ; + dProj = dLenPath - dProj ; + dZheight = dZheight - dDelta ; + dZTip = dZTip - dDelta ; + } + + dStart = sqrt( m_dRadius * m_dRadius - dSqd) ; + dRSqDist1 = dProj * dProj + dSqd ; + dRSqDist2 = ( dLenPath - dProj) * ( dLenPath - dProj) + dSqd ; + + if ( vtToolDir.z > 0) { + + // Semi-asse ellisse + double dSemiAxMin = m_dRadius * sqrt( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ; + double dSqrSemiAxMin = m_dRadius * m_dRadius * ( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ; + double dXD2 = ( dProj - dLenPath) * ( dProj - dLenPath) ; + + if ( dRSqDist2 < m_dRadius * m_dRadius) { + + dMax = dZheight + dDelta ; + + double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ; + + if ( dProj - dLenPath > dSemiAxMin * dTest) { + + double dSqrRad = ( dProj - dLenPath) * ( dProj - dLenPath) + dSqd ; + double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ; + dMin = dZTip + m_dRadius + dDelta - dH ; + } + else if ( dProj > dSemiAxMin * dTest) { + // Determino l'altezza del punto sull'ellisse da cui passa la retta + double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dLenPath + dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : dLenPath) ; + double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ; + double dZ0 = ( ( dPr0 - dLenPath) * dPar) / dSemiAxMin ; + + dMin = dZTip + dDelta + m_dRadius - dZ0 + ( dDelta / dLenPath) * ( dProj - dPr0) ; + } + else { + + double dSqrRad = dProj * dProj + dSqd ; + double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ; + dMin = dZTip + m_dRadius - dH ; + } + } + else { + + dMax = dZheight + ( dDelta * ( dProj + dStart)) / dLenPath ; + + double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ; + + if ( dProj > dSemiAxMin * dTest) { + // Determino l'altezza del punto sull'ellisse da cui passa la retta + double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dLenPath + dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : dLenPath) ; + double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ; + double dZ0 = ( ( dPr0 - dLenPath) * dPar) / dSemiAxMin ; + + dMin = dZTip + dDelta + m_dRadius - dZ0 + ( dDelta / dLenPath) * ( dProj - dPr0) ; + } + else { + + double dSqrRad = dProj * dProj + dSqd ; + double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ; + + dMin = dZTip + m_dRadius - dH ; + } + } + } + else { + + // Semi-asse ellisse + double dSemiAxMin = m_dRadius * sqrt( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ; + double dSqrSemiAxMin = m_dRadius * m_dRadius * ( 1 - dLenPath * dLenPath / ( dLenPath * dLenPath + dDelta * dDelta)) ; + double dXD2 = ( dProj - dLenPath) * ( dProj - dLenPath) ; + + if ( dRSqDist1 < m_dRadius * m_dRadius) { + + dMin = dZheight ; + + double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ; + + if ( dProj < - dSemiAxMin * dTest) { + + double dSqrRad = dProj * dProj + dSqd ; + double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ; + + dMax = dZTip - m_dRadius + dH ; + } + else if ( dProj - dLenPath < - dSemiAxMin * dTest) { + // Determino l'altezza del punto sull'ellisse da cui passa la retta + double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : 0) ; + double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ; + double dZ0 = ( dPr0 * dPar) / dSemiAxMin ; + + dMax = dZTip - m_dRadius + dZ0 + ( dDelta / dLenPath) * ( dProj + dPr0) ; + } + else { + + double dSqrRad = dProj * dProj + dSqd ; + double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ; + dMax = dZTip - m_dRadius + dDelta + dH ; + } + } + else { + + dMin = dZheight + ( dDelta * ( dProj - dStart)) / dLenPath ; + + double dTest = ( 1 - dSqd / ( m_dRadius * m_dRadius) > 0 ? sqrt( 1 - dSqd / ( m_dRadius * m_dRadius)) : 0) ; + + if ( dProj - dLenPath < - dSemiAxMin * dTest) { + // Determino l'altezza del punto sull'ellisse da cui passa la retta + double dPr0 = ( ( 1 - dSqd / ( m_dRadius * m_dRadius)) > 0 ? dSemiAxMin * sqrt( ( 1 - dSqd / (m_dRadius * m_dRadius))) : 0) ; + double dPar = ( m_dRadius * m_dRadius - dSqrSemiAxMin > 0 ? sqrt( m_dRadius * m_dRadius - dSqrSemiAxMin) : 0) ; + double dZ0 = ( dPr0 * dPar) / dSemiAxMin ; + + dMax = dZTip - m_dRadius + dZ0 + ( dDelta / dLenPath) * ( dProj + dPr0) ; + } + else { + + double dSqrRad = ( dProj - dLenPath) * ( dProj - dLenPath) + dSqd ; + double dH = ( m_dRadius * m_dRadius - dSqrRad > 0 ? sqrt( m_dRadius * m_dRadius - dSqrRad) : 0) ; + dMax = dZTip + dDelta - m_dRadius + dH ; + } + } + } + } + // Caso di bull-nose mill + else + return true ; + + return SubtractIntervals( nI, nJ, dMin, dMax) ; +} + +// Versore utensile nel piano XY +//---------------------------------------------------------------------------- +bool +VolZmap::MillingDrillXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + // Punti per la determinazione del materiale asportato + Vector3d vtMove = ptLe - ptLs ; + // Punti di riferimento dell'asportazione + Point3d ptLNs ; + Point3d ptLNe ; + // Parametro relativo all'utensile altezza della parte non cilindrica e fattore determinante + // la lunghezza della parte lavorata a seconda che lavori la punta o il fondo + double dCylH ; double dFactor ; + + // Caso utensile generico (al momento non gestito) + if ( m_nToolType == 0) + return false ; + // Caso Cylindrical Mill + else if ( m_nToolType == 1) + dCylH = m_dHeight ; + // Caso Ball-end Mill + else if ( m_nToolType == 2) + dCylH = m_dHeight - m_dRadius ; + // Caso Bull-nose Mill + else if ( m_nToolType == 3) + dCylH = m_dHeight - m_dRCorner ; + + // Normalizzo tale vettore e ne determino la lunghezza: + double dLenPath = vtMove.Len() ; vtMove.Normalize() ; + + // Prodotto scalare fra versore direzione utensile e direzione movimento + double dScProd = vtMove * vtToolDir ; + // Se lavora la punta + if ( dScProd < 0) { + // Trovo i punti di riferimento per la lavorazione + ptLNs = ptLs + ( vtMove * dCylH) ; + ptLNe = ptLe + ( vtMove * dCylH) ; + dFactor = 1 ; + } + // Se lavora il fondo + else { + ptLNs = ptLs ; + ptLNe = ptLe ; + dFactor = 0 ; + } + + // Quota z dei punti iniziale e finale + double dHz = ptLNs.z ; + + // Bounding box + double dMinX = min( ptLNs.x, ptLNe.x) - m_dRadius ; + double dMaxX = max( ptLNs.x, ptLNe.x) + m_dRadius ; + double dMinY = min( ptLNs.y, ptLNe.y) - m_dRadius ; + double dMaxY = max( ptLNs.y, ptLNe.y) + m_dRadius ; + double dMinZ = dHz - m_dRadius ; + double dMaxZ = dHz + m_dRadius ; + + // Verifico se il movimento intersca lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + // Determino i limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + //Proietto ptLNs sul piano XY: + Point3d ptStart( ptLNs.x, ptLNs.y, 0) ; + + //Ciclo sui punti + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + // Punto da valutare + Point3d ptC( (i + 0.5)*m_dStep, (j + 0.5)*m_dStep, 0) ; + // Vettore spostamento da ptLe a ptC + Vector3d vtC = ( ptC - ptStart) ; + // Componenti parallela e perpendicolare a vtMove + // Vettore ortogonale a vtMove + Vector3d vtOrt = vtMove ; + // Ruoto vtOrt affinché sia ortogonale + vtOrt.Rotate( Z_AX, -90) ; + + double dProj = vtC * vtOrt ; + Vector3d vtPara = vtOrt * dProj ; // Parallelo alla perpendicolare al movimento + Vector3d vtPerp = vtC - vtPara ; // Perpendicolare alla perpendicolare al movimento ( serve per unire le getminmax di drill e perp) + // Distanza di ptC dall'asse dell'untensile + double dSqDist = vtPerp.SqLen() ; + double dLimitMill = dLenPath + dFactor * ( m_dHeight - dCylH) ; + // Se dTestProj è positivo è vtC è dalla parte giusta + double dTestProj = vtC * vtMove ; + + if ( dTestProj > 0 && dSqDist < dLimitMill * dLimitMill) + if ( dProj > - m_dRadius && dProj < m_dRadius) + GetMinMaxXY( i, j, dProj, dHz, dSqDist, 0, dLenPath, dScProd) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingPerpXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + // Determinazione delle posizioni iniziali e finali della punta dell'utensile + Point3d ptTLs = ptLs - vtToolDir * m_dHeight ; + Point3d ptTLe = ptLe - vtToolDir * m_dHeight ; + + // Quota Z + double dZH = ptLs.z ; + + // Estremi Bounding box + double dMinX = min( min( ptLs.x, ptLe.x), min( ptTLs.x, ptTLe.x)) - m_dRadius ; + double dMaxX = max( max( ptLs.x, ptLe.x), max( ptTLs.x, ptTLe.x)) + m_dRadius ; + double dMinY = min( min( ptLs.y, ptLe.y), min( ptTLs.y, ptTLe.y)) - m_dRadius ; + double dMaxY = max( max( ptLs.y, ptLe.y), max( ptTLs.y, ptTLe.y)) + m_dRadius ; + double dMinZ = dZH - m_dRadius ; + double dMaxZ = dZH + m_dRadius ; + + // Verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Proiezione sul piano XY delle grandezze di interesse + Point3d ptStart( ptLs.x, ptLs.y, 0) ; + Point3d ptEnd( ptLe.x, ptLe.y, 0) ; + Vector3d vtMove = ptEnd - ptStart ; + double dLenPath = vtMove.Len() ; + // Normalizzo il vettore vtMove congiungente le posizioni iniziale e finale della base dell'utensile + vtMove.Normalize() ; + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + // Punto su cui ciclare e vettore congiungente posizione iniziale della base a tale punto + Point3d ptC( (i + 0.5) * m_dStep, (j + 0.5) * m_dStep, 0) ; + Vector3d vtC = ptC - ptStart ; + // Proiezione di vtC sulla direzione del movimento + double dProj = vtC * vtMove ; + // Componente di vtC ortogonale al movimento + Vector3d vtPerp = vtC - vtMove * dProj ; + // Lunghezza quadrata del precedente vettore + double dSqDist = vtPerp.SqLen() ; + + if ( dProj > - m_dRadius && dProj < dLenPath + m_dRadius && vtPerp * vtToolDir < 0 && dSqDist < m_dHeight * m_dHeight) + GetMinMaxXY( i, j, dProj, dZH, dSqDist, dLenPath, 0, 0) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYPlaneGen( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ; + double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + Point3d ptI = ptLs ; Point3d ptF = ptLe ; + + // Quote dei punti ptI e ptF + double dZ = ptI.z ; + + Point3d ptIT = ptI - vtToolDir * m_dHeight ; + Point3d ptFT = ptF - vtToolDir * m_dHeight ; + + // Bounding box + double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ; + double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ; + double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ; + double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + Vector3d vtMove = ptF - ptI ; + + if ( vtMove * vtToolDir > 0) { + Point3d ptTemp = ptI ; + ptI = ptF ; + ptF = ptTemp ; + vtMove = - vtMove ; + } + + Vector3d vtMoveOrt = vtMove - ( vtMove * vtToolDir) * vtToolDir ; double dLen2 = vtMoveOrt.Len() ; + Vector3d vtMoveLong = ( vtMove * vtToolDir) * vtToolDir ; double dLen1 = vtMoveLong.Len() ; + + // Determino sistema di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento + Vector3d vtV1 = vtToolDir ; + Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ; + + // Punti iniziale e finale proiettati sul piano + Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + if ( m_nToolType == 1) { + + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + + Vector3d vtC = ptC - ptIxy ; + + double dProj1 = vtC * vtV1 ; + double dProj2 = vtC * vtV2 ; + + GetMMPlaneGenCyl( i, j, dZ, dLen1, dLen2, dProj1, dProj2) ; + } + else if ( m_nToolType == 2) + + GetMMPlaneGenBall( i, j, dZ, dLen1, dLen2, ptIxy, vtMove, vtV1, vtV2) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMMPlaneGenCyl( unsigned int i, unsigned int j, double dZ, double dLen1, double dLen2, double dProj1, double dProj2) { + + double dMin, dMax ; + + if ( dProj2 > - m_dRadius && dProj2 < 0) { + + if ( dProj1 < 0 && dProj1 > - m_dHeight) { + + double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj1 <= - m_dHeight) { + + if ( ( dProj2 < dLen2 - m_dRadius && dProj1 > - m_dHeight - ( dLen1 / dLen2) * ( dProj2 + m_dRadius)) + || ( dProj2 >= dLen2 - m_dRadius && dProj1 > - m_dHeight - dLen1)) { // In questo costrutto if-else non c'è bisogno di specificare nient'altro perché già siamo nella regione - m_dRadius < dProj2 < 0 + + double dPar = m_dHeight + ( dLen1 / dLen2) * ( dProj2 + m_dRadius) + dProj1 ; + double dL = m_dRadius - ( dLen2 / dLen1) * dPar ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + else if ( dProj2 >= 0 && dProj2 < m_dRadius) { + + if ( dProj1 < 0 && ( ( dProj2 < dLen2 && dProj1 > - ( dLen1 / dLen2) * dProj2) || ( dProj2 >= dLen2 && dProj1 > - dLen1))) { + + double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ; + /* Oppure + double dPar1 = ( dLen1 / dLen2) * dProj2 + dProj1 ; + double dPar2 = ( dLen2 / dLen1) * dPar1 ; */ + double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj2 < dLen2 && dProj1 <= - ( dLen1 / dLen2) * dProj2) { + + if ( dProj1 > - ( dLen1 / dLen2) * dProj2 - m_dHeight) { + + dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj1 <= - ( dLen1 / dLen2) * dProj2 - m_dHeight) { + + if ( ( dProj2 < dLen2 - m_dRadius && dProj1 > - ( dLen1 / dLen2) * ( dProj2 + m_dRadius) - m_dHeight) + || ( dProj2 >= dLen2 - m_dRadius && dProj1 > - m_dHeight - dLen1)) { // modificato qui + + double dPar = m_dHeight + ( dLen1 / dLen2) * ( dProj2 + m_dRadius) + dProj1 ; + double dL = m_dRadius - ( dLen2 / dLen1) * dPar ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + else if ( dProj2 >= dLen2 && dProj1 < - dLen1) { + + if ( dProj1 > - m_dHeight - dLen1) { + + double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dLen2) * ( dProj2 - dLen2)) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + else if ( dProj2 >= m_dRadius && dProj2 < dLen2) { + + if ( dProj1 < - ( dLen1 / dLen2) * ( dProj2 - m_dRadius) && dProj1 > - ( dLen1 / dLen2) * dProj2) { + + double dL = ( dLen2 / dLen1) * ( ( dLen1 / dLen2) * dProj2 + dProj1) ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj1 <= - ( dLen1 / dLen2) * dProj2 && dProj1 > - ( dLen1 / dLen2) * dProj2 - m_dHeight) { + + dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ; + + SubtractIntervals( i, j, dMin , dMax) ; + } + else if ( dProj1 <= - ( dLen1 / dLen2) * dProj2 - m_dHeight) { + + if ( ( dProj2 < dLen2 - m_dRadius && dProj1 > - ( dLen1 / dLen2) * ( dProj2 + m_dRadius) - m_dHeight) + || ( dProj2 >= dLen2 - m_dRadius && dProj1 > - m_dHeight - dLen1)) { + + double dPar = m_dHeight + ( dLen1 / dLen2) * ( dProj2 + m_dRadius) + dProj1 ; + double dL = m_dRadius - ( dLen2 / dLen1) * dPar ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + else if ( dProj2 >= dLen2 && dProj2 < dLen2 + m_dRadius) { + + if ( dProj1 < - ( dLen1 / dLen2) * ( dProj2 - m_dRadius) && dProj1 >= - dLen1) { + + double dL = ( dLen2 / dLen1) * ( ( dLen1 / dLen2) * dProj2 + dProj1) ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj1 < - dLen1 && dProj1 > - dLen1 - m_dHeight) { + + double dL = dProj2 - dLen2 ; + double dH = sqrt( m_dRadius * m_dRadius - dL * dL) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMMPlaneGenBall( unsigned int i, unsigned int j, double dZ, double dLen1, double dLen2, Point3d ptIxy, Vector3d vtMove, Vector3d vtV1, Vector3d vtV2) { + + double dMin, dMax ; + + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + + Vector3d vtC = ptC - ptIxy ; + + double dProj1 = vtC * vtV1 ; // vtV1, vtV2 sono paralleli al piano + double dProj2 = vtC * vtV2 ; + + double dCH = m_dHeight - m_dRadius ; + double dLMove = vtMove.LenXY() ; + + Point3d ptCS = ptIxy - dCH * vtV1 ; Point3d ptCE = ptCS + vtMove ; // vtMove è orizzontale + + Vector3d vtCS = ptC - ptCS ; Vector3d vtCE = ptC - ptCE ; + + double dProjMove = ( vtCS * vtMove) / dLMove ; + + Vector3d vtCSP = vtCS - ( ( vtCS * vtMove) / ( dLMove * dLMove)) * vtMove ; + + double dSQDist = vtCSP.SqLenXY() ; + double dSQDistS = vtCS.SqLenXY() ; + double dSQDistE = vtCE.SqLenXY() ; + + // parte cilindrica + + if ( dProj2 > - m_dRadius && dProj2 < 0) { + + if ( dProj1 > - dCH && dProj1 < 0) { + + double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + else if ( dProj2 >= 0 && dProj2 < m_dRadius) { + + if ( dProj1 < 0 && ( ( dProj2 < dLen2 && dProj1 > - ( dLen1 / dLen2) * dProj2) || ( dProj2 >= dLen2 && dProj1 > - dLen1))) { + + double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ; + /* Oppure + double dPar1 = ( dLen1 / dLen2) * dProj2 + dProj1 ; + double dPar2 = ( dLen2 / dLen1) * dPar1 ; */ + double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj2 < dLen2 && dProj1 <= - ( dLen1 / dLen2) * dProj2 && dProj1 > - ( dLen1 / dLen2) * dProj2 - dCH) { + + dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj2 >= dLen2 && dProj1 <= - dLen1 && dProj1 > - dLen1 - dCH) { + + double dL = dProj2 - dLen2 ; + double dH = sqrt( m_dRadius * m_dRadius - dL * dL) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + else if ( dProj2 >= m_dRadius && dProj1 < - ( dLen1 / dLen2) * ( dProj2 - m_dRadius)) { + + if ( dProj2 < dLen2 && dProj1 > - ( dLen1 / dLen2) * dProj2) { + + double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ; + double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj2 < dLen2 && dProj1 <= - ( dLen1 / dLen2) * dProj2 && dProj1 > - ( dLen1 / dLen2) * dProj2 - dCH) { + + dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj2 >= dLen2 && dProj2 < dLen2 + m_dRadius) { + + if ( dProj1 > - dLen1) { + + double dPar = dProj2 + ( dLen2 / dLen1) * dProj1 ; + double dH = ( m_dRadius * m_dRadius - dPar * dPar > 0 ? sqrt( m_dRadius * m_dRadius - dPar * dPar) : 0) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj1 <= - dLen1 && dProj1 > - dLen1 - dCH) { + + double dL = dProj2 - dLen2 ; + double dH = sqrt( m_dRadius * m_dRadius - dL * dL) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + // parte non cilindrica + + + if ( dProjMove > - m_dRadius && dProjMove < 0) { + + if ( dSQDistS < m_dRadius * m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - dSQDistS) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + else if ( dProjMove >= 0 && dProjMove < dLMove) { + + if ( dSQDist < m_dRadius * m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - dSQDist) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + else { + + if ( dSQDistE < m_dRadius * m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - dSQDistE) ; + + dMin = dZ - dH ; dMax = dZ + dH ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYLongVert( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + // Determino posizioni punte + Point3d ptTLs = ptLs - vtToolDir * m_dHeight ; + Point3d ptTLe = ptLe - vtToolDir * m_dHeight ; + + // Variabili utili + double dDelta = ptLe.z - ptLs.z ; double dMin, dMax ; + + // Bounding box + double dMinX = min( min( ptLs.x, ptLe.x), min( ptTLs.x, ptTLe.x)) - m_dRadius ; + double dMaxX = max( max( ptLs.x, ptLe.x), max( ptTLs.x, ptTLe.x)) + m_dRadius ; + double dMinY = min( min( ptLs.y, ptLe.y), min( ptTLs.y, ptTLe.y)) - m_dRadius ; + double dMaxY = max( max( ptLs.y, ptLe.y), max( ptTLs.y, ptTLe.y)) + m_dRadius ; + double dMinZ = min( ptLs.z, ptLs.z + dDelta) - m_dRadius ; + double dMaxZ = max( ptLs.z, ptLs.z + dDelta) + m_dRadius ; + + // Controllo su interferenza utensile-Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Definizione delle grandezze geometriche essenziali + Vector3d vtMove = ptLe - ptLs ; + Vector3d vtPlaneMove = ( vtMove * vtToolDir) * vtToolDir ; //( vtMove * vtToolDir < 0 ? ( - vtMove * vtToolDir) * vtToolDir : ( vtMove * vtToolDir) * vtToolDir) ; + Vector3d vtZMove = vtMove - vtPlaneMove ; + + double dLenPlanePath = sqrt( vtPlaneMove * vtPlaneMove) ; + + if ( m_nToolType == 1) { + + if ( abs ( ( vtMove * vtToolDir) * dDelta) < EPS_SMALL) { + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + Point3d ptStart( ptLs.x, ptLs.y, 0) ; + Vector3d vtC = ptC - ptStart ; + double dProj = vtC * vtToolDir ; + Vector3d vtP = vtC - dProj * vtToolDir ; + double dSqD = vtP * vtP ; + double dZH = ptLs.z ; + + if ( dSqD < m_dRadius * m_dRadius && dProj < 0 && dProj > - m_dHeight) { + + double dFactor = ( dDelta > 0 ? 1 : - 1) ; + dMin = min( dZH, dZH + dDelta + dFactor * sqrt( m_dRadius * m_dRadius - dSqD)) ; + dMax = max( dZH, dZH + dDelta + dFactor * sqrt( m_dRadius * m_dRadius - dSqD)) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + else { + + Point3d ptSt ; + + if ( vtMove * vtToolDir < 0 && dDelta > 0) + ptSt = ptLs ; + else if ( vtMove * vtToolDir < 0 && dDelta < 0) { + ptSt = ptTLe ; vtPlaneMove = - vtPlaneMove ; dDelta = - dDelta ; + } + else if ( vtMove * vtToolDir > 0 && dDelta < 0) { + ptSt = ptLe ; vtPlaneMove = - vtPlaneMove ; dDelta = - dDelta ; + } + else { + ptSt = ptTLs ;// vtPlaneMove = - vtPlaneMove ; + } + + double dZH = ptSt.z ; + Point3d ptStart ( ptSt.x, ptSt.y, 0) ; + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + vtPlaneMove.Normalize() ; + + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + Vector3d vtC = ptC - ptStart ; + + double dProj = vtPlaneMove * vtC ; + + Vector3d vtP = vtC - dProj * vtPlaneMove ; + + double dSqD = vtP * vtP ; + + if ( dSqD < m_dRadius * m_dRadius) { + + if ( dProj > 0 && dProj < m_dHeight) { + + dMin = dZH - sqrt( m_dRadius * m_dRadius - dSqD) ; + + if ( dProj < dLenPlanePath) + dMax = dZH + sqrt( m_dRadius * m_dRadius - dSqD) + ( dDelta/dLenPlanePath) * dProj ; + else + dMax = dZH + dDelta + sqrt( m_dRadius * m_dRadius - dSqD) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dProj >= m_dHeight && dProj < m_dHeight + dLenPlanePath) { + + dMin = dZH - sqrt( m_dRadius * m_dRadius - dSqD) + ( dDelta/dLenPlanePath) * ( dProj - m_dHeight) ; + + if ( dProj < dLenPlanePath) + dMax = dZH + sqrt( m_dRadius * m_dRadius - dSqD) + ( dDelta/dLenPlanePath) * dProj ; + else + dMax = dZH + dDelta + sqrt( m_dRadius * m_dRadius - dSqD) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + } + return true ; + } + else if ( m_nToolType == 2) { + + if ( abs ( ( vtMove * vtToolDir) * dDelta) < EPS_SMALL) { + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + Point3d ptStart( ptLs.x, ptLs.y, 0) ; + Vector3d vtC = ptC - ptStart ; + double dProj = vtC * vtToolDir ; + Vector3d vtP = vtC - dProj * vtToolDir ; + double dSqD = vtP * vtP ; + double dZH = ptLs.z ; + + + if ( dProj < 0 && dProj > - m_dHeight + m_dRadius) { + + if ( dSqD < m_dRadius * m_dRadius) { + + dMin = min( dZH - sqrt( m_dRadius * m_dRadius - dSqD), dZH + dDelta - sqrt( m_dRadius * m_dRadius - dSqD)) ; + dMax = max( dZH + sqrt( m_dRadius * m_dRadius - dSqD), dZH + dDelta + sqrt( m_dRadius * m_dRadius - dSqD)) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Chiedere per = + else if ( dProj <= - m_dHeight + m_dRadius && dProj > - m_dHeight) { + + double dCylH = m_dHeight - m_dRadius ; + double dL = abs( - dProj - dCylH) ; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + + if ( dSqD < dR * dR) { + + double dH = ( dR * dR - dSqD > 0 ? sqrt ( dR * dR - dSqD) : 0) ; + + dMin = min( dZH - dH, dZH - dH + dDelta) ; + dMax = max( dZH + dH, dZH + dH + dDelta) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + } + else { // Movimento obliquo + + Point3d ptStart = ptLs ; + + double dA = m_dRadius / sqrt( 1 + ( dDelta * dDelta) / (dLenPlanePath * dLenPlanePath)) ; + double dSemiAxMin = ( abs( dDelta) * dA) / dLenPlanePath ; + + if ( ( vtToolDir * vtMove) * dDelta < 0) { + + if ( dDelta < 0) { + vtPlaneMove = - vtPlaneMove ; + dDelta = - dDelta ; + ptStart = ptLe ; + } + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + Point3d ptS( ptStart.x, ptStart.y, 0) ; + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + Vector3d vtC = ptC - ptS ; + double dProj = vtC * vtToolDir ; + Vector3d vtP = vtC - ( vtC * vtToolDir) * vtToolDir ; + double dSqD = vtP * vtP ; + double dCylH = m_dHeight - m_dRadius ; + double dZH = ptStart.z ; + + if ( dSqD < m_dRadius * m_dRadius) { + + if ( dProj < 0 && dProj > - m_dHeight - dLenPlanePath) { + + if ( dProj > -dCylH) { + // parte cilindrica orizzontale inferiore + double dH = ( m_dRadius * m_dRadius - dSqD > 0 ? sqrt( m_dRadius * m_dRadius - dSqD) : 0) ; + dMin = dZH - dH ; + } + else if ( dProj > - dCylH - dSemiAxMin * sqrt( 1 - dSqD / ( m_dRadius * m_dRadius))) { + // parte sferica inferiore + double dL = - dProj - dCylH ; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ; + + dMin = dZH - dH ; + } + else if ( dProj > - dCylH - dLenPlanePath - dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius))) { + // parte cilindrica obliqua inferiore + double dl = dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) ; + + dMin = dZH - dA * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) - ( dDelta / dLenPlanePath) * ( dProj + dCylH + dl) ; + } + else if ( dProj > - m_dHeight - dLenPlanePath) { + // seconda parte sferica inferiore + double dL = - dProj - dCylH - dLenPlanePath; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ; + + dMin = dZH + dDelta - dH ; + } + + if ( dProj > - dLenPlanePath) { + // parte cilindrica obliqua superiore + double dH = sqrt( m_dRadius * m_dRadius - dSqD) ; + + dMax = dZH + dH - ( dDelta / dLenPlanePath) * dProj ; + } + else if ( dProj > - dLenPlanePath - dCylH) { + // parte cilindrica orizzontale superiore + double dH = sqrt( m_dRadius * m_dRadius - dSqD) ; + + dMax = dZH + dDelta + dH ; + } + else if ( dProj > - dLenPlanePath - m_dHeight) { + // parte sferica superiore + double dL = - dProj - dCylH - dLenPlanePath; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ; + + dMax = dZH + dDelta + dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + return true ; + } + else { + + if ( dDelta > 0) { + vtPlaneMove = - vtPlaneMove ; + dDelta = - dDelta ; + ptStart = ptLe ; + } + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + Point3d ptS( ptStart.x, ptStart.y, 0) ; + Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; + Vector3d vtC = ptC - ptS ; + double dProj = vtC * vtToolDir ; + Vector3d vtP = vtC - ( vtC * vtToolDir) * vtToolDir ; + double dSqD = vtP * vtP ; + double dCylH = m_dHeight - m_dRadius ; + double dZH = ptStart.z ; + + if ( dSqD < m_dRadius * m_dRadius) { + + if ( dProj < 0 && dProj > - m_dHeight - dLenPlanePath) { + + if ( dProj > - dLenPlanePath) { + + double dH = sqrt( m_dRadius * m_dRadius - dSqD) ; + + dMin = dZH - dH - ( dDelta / dLenPlanePath) * dProj ; + } + else if ( dProj > - dLenPlanePath - dCylH) { + + double dH = sqrt( m_dRadius * m_dRadius - dSqD) ; + + dMin = dZH + dDelta - dH ; + } + else if ( dProj > - dLenPlanePath - m_dHeight) { + + double dL = - dProj - dCylH - dLenPlanePath; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ; + + dMin = dZH + dDelta - dH ; + } + + if ( dProj > - dCylH) { + + double dH = ( m_dRadius * m_dRadius - dSqD > 0 ? sqrt( m_dRadius * m_dRadius - dSqD) : 0) ; + dMax = dZH + dH ; + } + else if ( dProj > - dCylH - dSemiAxMin * sqrt( 1 - dSqD / ( m_dRadius * m_dRadius))) { + + double dL = - dProj - dCylH ; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ; + + dMax = dZH + dH ; + } + else if ( dProj > - dCylH - dLenPlanePath - dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius))) { + + double dl = dSemiAxMin * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) ; + + dMax = dZH + dA * sqrt( 1 - dSqD / (m_dRadius * m_dRadius)) - ( dDelta / dLenPlanePath) * ( dProj + dCylH + dl) ; + } + else if ( dProj > - m_dHeight - dLenPlanePath) { + + double dL = - dProj - dCylH - dLenPlanePath; + double dR = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dH = ( dR * dR - dSqD > 0 ? sqrt( dR * dR - dSqD) : 0) ; + + dMax = dZH + dDelta + dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } + return true ; + } + } + + return true ; + } + else if ( m_nToolType == 3) + return true ; + else + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + + double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ; + double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + Point3d ptI, ptF ; + + if ( ptLs.z < ptLe.z) { + ptI = ptLs ; + ptF = ptLe ; + } + else { + ptI = ptLe ; + ptF = ptLs ; + } + + // Quote dei punti ptI e ptF + double dZI = ptI.z ; double dZF = ptF.z ; + + Point3d ptIT = ptI - vtToolDir * m_dHeight ; + Point3d ptFT = ptF - vtToolDir * m_dHeight ; + + // Bounding box + double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ; + double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ; + double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ; + double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + Vector3d vtMove = ptF - ptI ; //double dLenPath = vtMove.Len() ; + + // Determino sistema di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento + Vector3d vtV1 = vtToolDir ; + Vector3d vtV2 = vtMove ; vtV2.Normalize() ; + Vector3d vtV3 = vtV1 ^ vtV2 ; + + // Determinazione punti notevoli del volume spazzato dall'utensile + Point3d ptPlaneSup, ptPlaneInf ; + + if ( vtV3.z > 0) { + ptPlaneInf = ptI - m_dRadius * vtV3 ; + ptPlaneSup = ptI + m_dRadius * vtV3 ; + } + else { + ptPlaneInf = ptI + m_dRadius * vtV3 ; + ptPlaneSup = ptI - m_dRadius * vtV3 ; + } + + // Prodotti scalari per costruire i piani passanti per i punti notevoli + Vector3d vtR0Inf = ptPlaneInf - ORIG ; + Vector3d vtR0Sup = ptPlaneSup - ORIG ; + + double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ; + + // Determinazione delle proiezioni sul piano delle entità geometriche fondamentali + Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPlanePath = vtPlaneMove.Len() ; vtPlaneMove.Normalize() ; + Vector3d vtPlaneLim( m_dRadius * vtV3.x, m_dRadius * vtV3.y, 0) ; double dPlaneLim = vtPlaneLim.Len() ; + Point3d ptIxy( ptI.x, ptI.y, 0) ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + double dZInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y + double dZSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y + + Point3d ptC( dX, dY, 0) ; + Vector3d vtC = ptC - ptIxy ; + + double dProj1 = vtC * vtV1 ; // vtV1 è vtToolDir che per il momento giace nel piano + double dProj2 = vtC * vtPlaneMove ; // vtPlaneMove è stato normalizzato dopo averne calcolato la lunghezza + + if ( dProj1 < 0 && dProj1 > - m_dHeight && dProj2 > - m_dRadius && dProj2 < dPlanePath + m_dRadius) { + + + // Minimi + if ( dProj2 > - m_dRadius && dProj2 < dPlaneLim) { + + double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; + + dMin = dZI - dH ; + } + else if ( dProj2 >= dPlaneLim && dProj2 < dPlanePath + dPlaneLim) { + + dMin = dZInf ; + } + else if ( dProj2 >= dPlanePath + dPlaneLim && dProj2 < dPlanePath + m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ; + + dMin = dZF - dH ; + } + // Massimi + if ( dProj2 > - m_dRadius && dProj2 < - dPlaneLim) { + + double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; + + dMax = dZI + dH ; + } + else if ( dProj2 >= - dPlaneLim && dProj2 < dPlanePath - dPlaneLim) { + + dMax = dZSup ; + } + else if ( dProj2 >= dPlanePath - dPlaneLim && dProj2 < dPlanePath + m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ; + + dMax = dZF + dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ; + double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + Point3d ptI, ptF ; + + if ( ptLs.z < ptLe.z) { + ptI = ptLs ; + ptF = ptLe ; + } + else { + ptI = ptLe ; + ptF = ptLs ; + } + + // Quote dei punti ptI e ptF e DeltaZ + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; + + Point3d ptIT = ptI - vtToolDir * m_dHeight ; + Point3d ptFT = ptF - vtToolDir * m_dHeight ; + + // Bounding box + double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ; + double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ; + double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ; + double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + Vector3d vtMove = ptF - ptI ; + + // Determino sistema di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento + Vector3d vtV1 = vtToolDir ; + Vector3d vtV2 = vtMove ; vtV2.Normalize() ; + Vector3d vtV3 = vtV1 ^ vtV2 ; + + // Determinazione punti notevoli del volume spazzato dall'utensile + Point3d ptPlaneSup, ptPlaneInf ; + + if ( vtV3.z > 0) { + ptPlaneInf = ptI - m_dRadius * vtV3 ; + ptPlaneSup = ptI + m_dRadius * vtV3 ; + } + else { + ptPlaneInf = ptI + m_dRadius * vtV3 ; + ptPlaneSup = ptI - m_dRadius * vtV3 ; + } + + // Prodotti scalari per costruire i piani passanti per i punti notevoli + Vector3d vtR0Inf = ptPlaneInf - ORIG ; + Vector3d vtR0Sup = ptPlaneSup - ORIG ; + + double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ; + + // Determinazione delle proiezioni sul piano delle entità geometriche fondamentali + Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPlanePath = vtPlaneMove.Len() ; vtPlaneMove.Normalize() ; + Vector3d vtPlaneLim( m_dRadius * vtV3.x, m_dRadius * vtV3.y, 0) ; double dPlaneLim = vtPlaneLim.Len() ; + Point3d ptIxy( ptI.x, ptI.y, 0) ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + double dCylH = m_dHeight - m_dRadius ; + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + double dZInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y + double dZSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y + + Point3d ptC( dX, dY, 0) ; + Vector3d vtC = ptC - ptIxy ; + + double dProj1 = vtC * vtV1 ; // vtV1 è vtToolDir che per il momento giace nel piano + double dProj2 = vtC * vtPlaneMove ; // vtPlaneMove è stato normalizzato dopo averne calcolato la lunghezza + + // Parte cilindrica + if ( dProj1 < 0 && dProj1 > - dCylH && dProj2 > - m_dRadius && dProj2 < dPlanePath + m_dRadius) { + + // Minimi + if ( dProj2 > - m_dRadius && dProj2 < dPlaneLim) { + + double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; + + dMin = dZI - dH ; + } + else if ( dProj2 >= dPlaneLim && dProj2 < dPlanePath + dPlaneLim) { + + dMin = dZInf ; + } + else if ( dProj2 >= dPlanePath + dPlaneLim && dProj2 < dPlanePath + m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ; + + dMin = dZF - dH ; + } + // Massimi + if ( dProj2 > - m_dRadius && dProj2 < - dPlaneLim) { + + double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; + + dMax = dZI + dH ; + } + else if ( dProj2 >= - dPlaneLim && dProj2 < dPlanePath - dPlaneLim) { + + dMax = dZSup ; + } + else if ( dProj2 >= dPlanePath - dPlaneLim && dProj2 < dPlanePath + m_dRadius) { + + double dH = sqrt( m_dRadius * m_dRadius - ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath)) ; + + dMax = dZF + dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + // Parte sferica + else if ( ( dProj2 > - m_dRadius && dProj2 < 0 && dProj2 * dProj2 + (- dProj1 - dCylH) * (- dProj1 - dCylH) < m_dRadius * m_dRadius) || + ( dProj2 >= 0 && dProj2 < dPlanePath && dProj1 > - m_dHeight && dProj1 <= - dCylH) || + ( dProj2 >= dPlanePath && dProj2 < dPlanePath + m_dRadius && ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath) + (- dProj1 - dCylH) * (- dProj1 - dCylH) < m_dRadius * m_dRadius)) { + + + double dSemiMin = dPlaneLim ; double dSemiMax = m_dRadius ; // Semi-assi dell'ellisse + double dl = - dProj1 - dCylH ; + + // Massimi + if ( dProj2 < - dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) { + + double dr = sqrt( dProj2 * dProj2 + dl * dl) ; + double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ; + + dMax = dZI + dH ; + } + else if ( dProj2 < dPlanePath - dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) { + + double dCos = abs( vtV3 * Z_AX) ; + + dMax = dZI + sqrt( m_dRadius * m_dRadius - dl * dl) * dCos + ( dDeltaZ / dPlanePath) * ( dProj2 + dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) ; + } + else { + + double dL = dProj2 - dPlanePath ; + double dr = sqrt( dL * dL + dl * dl) ; + + double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ; + + dMax = dZF + dH ; + } + + // Minimi + if ( dProj2 < dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) { + + double dr = sqrt( dProj2 * dProj2 + dl * dl) ; + double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ; + + dMin = dZI - dH ; + } + else if ( dProj2 < dPlanePath + dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) { + + double dCos = abs( vtV3 * Z_AX) ; + + dMin = dZI - sqrt( m_dRadius * m_dRadius - dl * dl) * dCos + ( dDeltaZ / dPlanePath) * ( dProj2 - dSemiMin * sqrt( 1 - ( dl * dl) / ( dSemiMax * dSemiMax))) ; + } + else { + + double dr = sqrt( ( dProj2 - dPlanePath) * ( dProj2 - dPlanePath) + dl * dl) ; + double dH = sqrt( m_dRadius * m_dRadius - dr * dr) ; + + dMin = dZF - dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + return true ; +} +/* +// DA TENERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYPlusCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ; + double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + Point3d ptI, ptF ; + + if ( ptLs.z <= ptLe.z) { + ptI = ptLs ; + ptF = ptLe ; + } + else { + ptI = ptLe ; + ptF = ptLs ; + } + + // Quote dei punti ptI e ptF e DeltaZ + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; + + Point3d ptIT = ptI - vtToolDir * m_dHeight ; + Point3d ptFT = ptF - vtToolDir * m_dHeight ; + + // Bounding box + double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ; + double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ; + double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ; + double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + // Vettori di riferimento nello spazio e controllo per simmetria + Vector3d vtMove = ptF - ptI ; + Vector3d vtTool = vtToolDir ; + + if ( vtToolDir * vtMove > 0) { + + Point3d ptTemp = ptI ; + ptI = ptIT ; ptIT = ptTemp ; + ptTemp = ptF ; + ptF = ptFT ; + ptFT = ptTemp ; + vtTool = - vtTool ; + } + + Vector3d vtMoveOrt = vtMove - ( vtMove * vtTool) * vtTool ; double dLen2 = vtMoveOrt.Len() ; + Vector3d vtMoveLong = ( vtMove * vtTool) * vtTool ; double dLen1 = vtMoveLong.Len() ; + + // Vettori di riferimento nel piano + Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPLen = vtPlaneMove.LenXY() ; + Vector3d vtPlaneMoveLong( vtMoveLong.x, vtMoveLong.y, 0) ; double dPLen1 = vtPlaneMoveLong.LenXY() ; + Vector3d vtPlaneMoveOrt( vtMoveOrt.x, vtMoveOrt.y, 0) ; double dPLen2 = vtPlaneMoveOrt.LenXY() ; vtPlaneMoveOrt.Normalize() ; + + // Punti iniziale e finale proiettati sul piano + Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; + + // Determino i sistemi di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento + Vector3d vtV1 = vtTool ; + Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ; + Vector3d vtV3 = vtV1 ^ vtV2 ; + + // Determinazione punti notevoli del volume spazzato dall'utensile + Point3d ptPlaneSup, ptPlaneInf ; + + if ( vtV3.z > 0) { + ptPlaneInf = ptI - m_dRadius * vtV3 ; + ptPlaneSup = ptI + m_dRadius * vtV3 ; + } + else { + ptPlaneInf = ptI + m_dRadius * vtV3 ; + ptPlaneSup = ptI - m_dRadius * vtV3 ; + } + + Point3d ptPlaneSupxy( ptPlaneSup.x, ptPlaneSup.y, 0) ; + Point3d ptPlaneInfxy( ptPlaneInf.x, ptPlaneInf.y, 0) ; + + double dr = sqrt( ( ptPlaneSupxy - ptIxy) * ( ptPlaneSupxy - ptIxy)) ; + + // Determinazione degli analoghi punti sulla punta dell'utensile e delle loro proiezioni sul piano XY + Point3d ptPlTInf = ptPlaneInf - m_dHeight * vtTool ; Point3d ptPlTInfxy( ptPlTInf.x, ptPlTInf.y, 0) ; + Point3d ptPlTSup = ptPlaneSup - m_dHeight * vtTool ; Point3d ptPlTSupxy( ptPlTSup.x, ptPlTSup.y, 0) ; + + // Prodotti scalari per costruire i piani passanti per i punti notevoli + Vector3d vtR0Inf = ptPlaneInf - ORIG ; + Vector3d vtR0Sup = ptPlaneSup - ORIG ; + Vector3d vtR0 = ptI - ORIG ; + double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ; double dP = vtR0 * vtV3 ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + double dZPInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y + double dZPSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano superiore come funzione di x e y + + // Punto e vettori del ciclo + Point3d ptC( dX, dY, 0) ; Vector3d vtCi = ptC - ptIxy ; + // Proiezione fondamentale + double dPro1 = vtCi * vtV1 ; double dPro2 = vtCi * vtPlaneMoveOrt ; + + + // Se il punto cade nella proiezione sul piano XY del volume spazzato si taglia + if ( ((dPro2 > - m_dRadius && dPro2 < m_dRadius) && (((dPro2 < dPLen2 - m_dRadius && (dPro1 > - m_dHeight - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) && dPro1 < 0))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < 0)))) + || ((dPro2 >= m_dRadius && dPro2 < dPLen2 + m_dRadius) && ((dPro2 < dPLen2 - m_dRadius && (dPro1 > - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) - m_dHeight && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius)))))) { + + // Massimi ////////////////////////////////////////////////////////////////////////// + // Prima zona cilindrica superiore + if ( ( dPro2 > - m_dRadius && dPro2 < - dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ; + + dMax = dZI + dH ; + } + + // Vettore per seconda zona cilindrica superiore + Vector3d vtCf = ptC - ptFxy ; + // Proiezione per seconda zona cilindrica sueriore + double dPr1 = vtCf * vtV1 ; double dPr2 = vtCf * vtPlaneMoveOrt ; + + // Seconda zona cilindrica superiore + if ( ( dPr2 >= - dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ; + + dMax = dZF + dH ; + } + + // Vettore per Piano superiore e zona di fondo superiore + Vector3d vtCS = ptC - ptPlaneSupxy ; + // Proiezioni + double dPrS1 = vtCS * vtV1 ; double dPrS2 = vtCS * vtPlaneMoveOrt ; + + // Piano superiore + if ( dPrS2 >= 0 && dPrS2 < dPLen2 && dPrS1 > - m_dHeight - ( dPLen1/dPLen2) * dPrS2 && dPrS1 <= - ( dPLen1/dPLen2) * dPrS2) + + dMax = dZPSup ; + + // Vettore per zona di punta superiore + Vector3d vtCTS = ptC - ptPlTSupxy ; + // Proiezioni + double dPrTS1 = vtCTS * vtV1 ; double dPrTS2 = vtCTS * vtPlaneMoveOrt ; + + // Zona di punta superiore + if ( dPrTS1 <= 0 && dPrTS1 > - dPLen1) + if ( dPrTS2 <= - ( dPLen2 / dPLen1) * dPrTS1 && dPrTS2 > - ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrTS1) { + + double dDist = - ( dPLen2 / dPLen1) * dPrTS1 - dPrTS2 ; + double dL = dDist + dr ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrTS1 * dPrTS1 + ( ( dPLen2 / dPLen1) * dPrTS1) * ( ( dPLen2 / dPLen1) * dPrTS1)) ; + + dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ; + } + + // Zona di fondo superiore + if ( dPrS1 < 0 && dPrS1 > - dPLen1) + if ( dPrS2 > - ( dPLen2 / dPLen1) * dPrS1 && dPrS2 < dr - ( dPLen2 / dPLen1) * dPrS1) { + + double dL = dr - ( dPLen2 / dPLen1) * dPrS1 - dPrS2 ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrS1 * dPrS1 + ( ( dPLen2 / dPLen1) * dPrS1) * ( ( dPLen2 / dPLen1) * dPrS1)) ; + + dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ; + } + else if ( dPrS2 >= dr - ( dPLen2 / dPLen1) * dPrS1 && dPrS2 < dr + m_dRadius - ( dPLen2 / dPLen1) * dPrS1) { + + double dL = dPrS2 - ( dr - ( dPLen2 / dPLen1) * dPrS1) ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrS1 * dPrS1 + ( ( dPLen2 / dPLen1) * dPrS1) * ( ( dPLen2 / dPLen1) * dPrS1)) ; + + dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ; + } + + // Minimi ////////////////////////////////////////////////////////////////////////// + // Prima zona cilindrica inferiore + if ( ( dPro2 > - m_dRadius && dPro2 < dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ; + + dMin = dZI - dH ; + } + + // Seconda zona cilindrica inferiore + if ( ( dPr2 >= dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ; + + dMin = dZF - dH ; + } + + // Vettore per piano inferiore e zona di fondo inferiore + Vector3d vtCI = ptC - ptPlaneInfxy ; + // Proiezioni + double dPrI1 = vtCI * vtV1 ; double dPrI2 = vtCI * vtPlaneMoveOrt ; + + // Piano inferiore + if ( dPrI2 >= 0 && dPrI2 < dPLen2 && dPrI1 > - m_dHeight - ( dPLen1/dPLen2) * dPrI2 && dPrI1 <= - ( dPLen1/dPLen2) * dPrI2) + + dMin = dZPInf ; + + // Zona di fondo inferiore + if ( dPrI1 <= 0 && dPrI1 > - dPLen1) + if ( dPrI2 > - ( dPLen2 / dPLen1) * dPrI1 && dPrI2 < ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrI1) { + + double dDist = dPrI2 + ( dPLen2 / dPLen1) * dPrI1 ; + double dL = dDist + dr ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrI1 * dPrI1 + ( ( dPLen2 / dPLen1) * dPrI1) * ( ( dPLen2 / dPLen1) * dPrI1)) ; + + dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ; + } + + // Vettore per zona di punta inferiore + Vector3d vtCTI = ptC - ptPlTInfxy ; + // Proiezioni + double dPrTI1 = vtCTI * vtV1 ; double dPrTI2 = vtCTI * vtPlaneMoveOrt ; + + // zona di punta inferiore + if ( dPrTI1 <= 0 && dPrTI1 > - dPLen1) + if ( dPrTI2 > - m_dRadius - dr - ( dPLen2 / dPLen1) * dPrTI1 && dPrTI2 <= - dr - ( dPLen2 / dPLen1) * dPrTI1) { + + double dL = - dr - ( dPLen2 / dPLen1) * dPrTI1 - dPrTI2 ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrTI1 * dPrTI1 + ( ( dPLen2 / dPLen1) * dPrTI1) * ( ( dPLen2 / dPLen1) * dPrTI1)) ; + + dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ; + } + else if ( dPrTI2 > - dr - ( dPLen2 / dPLen1) * dPrTI1 && dPrTI2 < - ( dPLen2 / dPLen1) * dPrTI1) { + + double dL = dPrTI2 - ( - dr - ( dPLen2 / dPLen1) * dPrTI1 ) ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrTI1 * dPrTI1 + ( ( dPLen2 / dPLen1) * dPrTI1) * ( ( dPLen2 / dPLen1) * dPrTI1)) ; + + dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ; + } + + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + return true ; +}*/ + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYPlusCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + double dMinZ = min( ptLs.z, ptLe.z) - m_dRadius ; + double dMaxZ = max( ptLs.z, ptLe.z) + m_dRadius ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + Point3d ptI, ptF ; + + if ( ptLs.z <= ptLe.z) { + ptI = ptLs ; + ptF = ptLe ; + } + else { + ptI = ptLe ; + ptF = ptLs ; + } + + // Quote dei punti ptI e ptF e DeltaZ + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; + + Point3d ptIT = ptI - vtToolDir * m_dHeight ; + Point3d ptFT = ptF - vtToolDir * m_dHeight ; + + // Bounding box + double dMinX = min( min( ptI.x, ptIT.x), min( ptF.x, ptFT.x)) - m_dRadius ; + double dMaxX = max( max( ptI.x, ptIT.x), max( ptF.x, ptFT.x)) + m_dRadius ; + double dMinY = min( min( ptI.y, ptIT.y), min( ptF.y, ptFT.y)) - m_dRadius ; + double dMaxY = max( max( ptI.y, ptIT.y), max( ptF.y, ptFT.y)) + m_dRadius ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + // Vettori di riferimento nello spazio e controllo per simmetria + Vector3d vtMove = ptF - ptI ; + Vector3d vtTool = vtToolDir ; + + if ( vtToolDir * vtMove > 0) { + + Point3d ptTemp = ptI ; + ptI = ptIT ; ptIT = ptTemp ; + ptTemp = ptF ; + ptF = ptFT ; + ptFT = ptTemp ; + vtTool = - vtTool ; + } + + Vector3d vtMoveLong = ( vtMove * vtTool) * vtTool ; double dLen1 = vtMoveLong.Len() ; + Vector3d vtMoveOrt = vtMove - vtMoveLong ; double dLen2 = vtMoveOrt.Len() ; + + // Vettori di riferimento nel piano + Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPLen = vtPlaneMove.LenXY() ; + Vector3d vtPlaneMoveLong( vtMoveLong.x, vtMoveLong.y, 0) ; double dPLen1 = vtPlaneMoveLong.LenXY() ; + Vector3d vtPlaneMoveOrt( vtMoveOrt.x, vtMoveOrt.y, 0) ; double dPLen2 = vtPlaneMoveOrt.LenXY() ; vtPlaneMoveOrt.Normalize() ; + + // Punti iniziale e finale proiettati sul piano + Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; + + // Determino i sistemi di riferimento del movimento: costruisco un sistrema di vettori ortonormali e destrorsi spiccati dal punto iniziale del movimento + Vector3d vtV1 = vtTool ; + Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ; + Vector3d vtV3 = vtV1 ^ vtV2 ; + + // Determinazione punti notevoli del volume spazzato dall'utensile + Point3d ptPlaneSup, ptPlaneInf ; + + if ( vtV3.z > 0) { + ptPlaneInf = ptI - m_dRadius * vtV3 ; + ptPlaneSup = ptI + m_dRadius * vtV3 ; + } + else { + ptPlaneInf = ptI + m_dRadius * vtV3 ; + ptPlaneSup = ptI - m_dRadius * vtV3 ; + } + + Point3d ptPlaneSupxy( ptPlaneSup.x, ptPlaneSup.y, 0) ; + Point3d ptPlaneInfxy( ptPlaneInf.x, ptPlaneInf.y, 0) ; + + double dr = sqrt( ( ptPlaneSupxy - ptIxy) * ( ptPlaneSupxy - ptIxy)) ; + + // Determinazione degli analoghi punti sulla punta dell'utensile e delle loro proiezioni sul piano XY + Point3d ptPlTInf = ptPlaneInf - m_dHeight * vtTool ; Point3d ptPlTInfxy( ptPlTInf.x, ptPlTInf.y, 0) ; + Point3d ptPlTSup = ptPlaneSup - m_dHeight * vtTool ; Point3d ptPlTSupxy( ptPlTSup.x, ptPlTSup.y, 0) ; + + // Prodotti scalari per costruire i piani passanti per i punti notevoli + Vector3d vtR0Inf = ptPlaneInf - ORIG ; + Vector3d vtR0Sup = ptPlaneSup - ORIG ; + Vector3d vtR0 = ptI - ORIG ; + double dPInf = vtR0Inf * vtV3 ; double dPSup = vtR0Sup * vtV3 ; double dP = vtR0 * vtV3 ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + double dZPInf = ( dPInf - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano inferiore come funzione di x e y + double dZPSup = ( dPSup - vtV3.x * dX - vtV3.y * dY) / vtV3.z ; // Quota Z Piano superiore come funzione di x e y + + // Punto e vettori del ciclo + Point3d ptC( dX, dY, 0) ; Vector3d vtCi = ptC - ptIxy ; + // Proiezione fondamentale + double dPro1 = vtCi * vtV1 ; double dPro2 = vtCi * vtPlaneMoveOrt ; + + + // Se il punto cade nella proiezione sul piano XY del volume spazzato si taglia + if ( ((dPro2 > - m_dRadius && dPro2 < m_dRadius) && (((dPro2 < dPLen2 - m_dRadius && (dPro1 > - m_dHeight - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) && dPro1 < 0))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < 0)))) + || ((dPro2 >= m_dRadius && dPro2 < dPLen2 + m_dRadius) && ((dPro2 < dPLen2 - m_dRadius && (dPro1 > - (dPLen1 / dPLen2) * (dPro2 + m_dRadius) - m_dHeight && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius))) || (dPro2 >= dPLen2 - m_dRadius && (dPro1 > - m_dHeight - dPLen1 && dPro1 < - (dPLen1 / dPLen2) * (dPro2 - m_dRadius)))))) { + + // Massimi ////////////////////////////////////////////////////////////////////////// + // Prima zona cilindrica superiore + if ( ( dPro2 > - m_dRadius && dPro2 < - dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ; + + dMax = dZI + dH ; + } + + // Vettore per seconda zona cilindrica superiore + Vector3d vtCf = ptC - ptFxy ; + // Proiezione per seconda zona cilindrica sueriore + double dPr1 = vtCf * vtV1 ; double dPr2 = vtCf * vtPlaneMoveOrt ; + + // Seconda zona cilindrica superiore + if ( ( dPr2 >= - dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ; + + dMax = dZF + dH ; + } + + // Vettore per Piano superiore e zona di fondo superiore + Vector3d vtCS = ptC - ptPlaneSupxy ; + // Proiezioni + double dPrS1 = vtCS * vtV1 ; double dPrS2 = vtCS * vtPlaneMoveOrt ; + + // Piano superiore + if ( dPrS2 >= 0 && dPrS2 < dPLen2 && dPrS1 > - m_dHeight - ( dPLen1/dPLen2) * dPrS2 && dPrS1 <= - ( dPLen1/dPLen2) * dPrS2) + + dMax = dZPSup ; + + // Vettore per zona di punta superiore + Vector3d vtCTS = ptC - ptPlTSupxy ; + // Proiezioni + double dPrTS1 = vtCTS * vtV1 ; double dPrTS2 = vtCTS * vtPlaneMoveOrt ; + + // Zona di punta superiore + if ( dPrTS1 <= 0 && dPrTS1 > - dPLen1) + if ( dPrTS2 <= - ( dPLen2 / dPLen1) * dPrTS1 && dPrTS2 > - ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrTS1) { + + double dDist = - ( dPLen2 / dPLen1) * dPrTS1 - dPrTS2 ; + double dL = dDist + dr ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrTS1 * dPrTS1 + ( ( dPLen2 / dPLen1) * dPrTS1) * ( ( dPLen2 / dPLen1) * dPrTS1)) ; + + dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ; + } + + // Zona di fondo superiore + if ( dPrS1 < 0 && dPrS1 > - dPLen1) + if ( dPrS2 > - ( dPLen2 / dPLen1) * dPrS1 && dPrS2 < m_dRadius + dr - ( dPLen2 / dPLen1) * dPrS1) { + + double dL = abs( dr - ( dPLen2 / dPLen1) * dPrS1 - dPrS2) ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrS1 * dPrS1 + ( ( dPLen2 / dPLen1) * dPrS1) * ( ( dPLen2 / dPLen1) * dPrS1)) ; + + dMax = dZI + ( dDeltaZ / dPLen) * dl + dH ; + } + + // Minimi ////////////////////////////////////////////////////////////////////////// + // Prima zona cilindrica inferiore + if ( ( dPro2 > - m_dRadius && dPro2 < dr) && ( dPro1 > - m_dHeight && dPro1 < 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPro2 * dPro2) ; + + dMin = dZI - dH ; + } + + // Seconda zona cilindrica inferiore + if ( ( dPr2 >= dr && dPr2 < m_dRadius) && ( dPr1 > - m_dHeight && dPr1 <= 0)) { + + double dH = sqrt( m_dRadius * m_dRadius - dPr2 * dPr2) ; + + dMin = dZF - dH ; + } + + // Vettore per piano inferiore e zona di fondo inferiore + Vector3d vtCI = ptC - ptPlaneInfxy ; + // Proiezioni + double dPrI1 = vtCI * vtV1 ; double dPrI2 = vtCI * vtPlaneMoveOrt ; + + // Piano inferiore + if ( dPrI2 >= 0 && dPrI2 < dPLen2 && dPrI1 > - m_dHeight - ( dPLen1/dPLen2) * dPrI2 && dPrI1 <= - ( dPLen1/dPLen2) * dPrI2) + + dMin = dZPInf ; + + // Zona di fondo inferiore + if ( dPrI1 <= 0 && dPrI1 > - dPLen1) + if ( dPrI2 > - ( dPLen2 / dPLen1) * dPrI1 && dPrI2 < ( m_dRadius - dr) - ( dPLen2 / dPLen1) * dPrI1) { + + double dDist = dPrI2 + ( dPLen2 / dPLen1) * dPrI1 ; + double dL = dDist + dr ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrI1 * dPrI1 + ( ( dPLen2 / dPLen1) * dPrI1) * ( ( dPLen2 / dPLen1) * dPrI1)) ; + + dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ; + } + + // Vettore per zona di punta inferiore + Vector3d vtCTI = ptC - ptPlTInfxy ; + // Proiezioni + double dPrTI1 = vtCTI * vtV1 ; double dPrTI2 = vtCTI * vtPlaneMoveOrt ; + + // zona di punta inferiore + if ( dPrTI1 <= 0 && dPrTI1 > - dPLen1) + if ( dPrTI2 > - m_dRadius - dr - ( dPLen2 / dPLen1) * dPrTI1 && dPrTI2 < - ( dPLen2 / dPLen1) * dPrTI1) { + + double dL = abs( - dr - ( dPLen2 / dPLen1) * dPrTI1 - dPrTI2) ; + double dH = ( m_dRadius * m_dRadius - dL * dL > 0 ? sqrt( m_dRadius * m_dRadius - dL * dL) : 0) ; + double dl = sqrt( dPrTI1 * dPrTI1 + ( ( dPLen2 / dPLen1) * dPrTI1) * ( ( dPLen2 / dPLen1) * dPrTI1)) ; + + dMin = dZI + ( dDeltaZ / dPLen) * dl - dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + return true ; +} + +/* +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYPlusBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + // Parte cilindrica + + m_dHeight = m_dHeight - m_dRadius ; + + MillingXYPlusCyl( ptLs, ptLe, vtToolDir) ; + + m_dHeight = m_dHeight + m_dRadius ; + //////////////////////////////////////// + Point3d ptI, ptF ; + + if ( ptLs.z < ptLe.z) { + + ptI = ptLs ; + ptF = ptLe ; + } + else { + + ptI = ptLe ; + ptF = ptLs ; + } + + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; + + double dCylH = m_dHeight - m_dRadius ; + + Point3d ptCI = ptI - dCylH * vtToolDir ; + Point3d ptCF = ptF - dCylH * vtToolDir ; + + Point3d ptCIxy( ptCI.x, ptCI.y, 0) ; + + // Bounding box + double dMinX = min( ptCI.x, ptCF.x) - m_dRadius ; + double dMaxX = max( ptCI.x, ptCF.x) + m_dRadius ; + double dMinY = min( ptCI.y, ptCF.y) - m_dRadius ; + double dMaxY = max( ptCI.y, ptCF.y) + m_dRadius ; + + Vector3d vtMove = ptF - ptI ; + + // Sistema di riferimento + Vector3d vtV2 = vtMove ; vtV2.Normalize() ; + Vector3d vtV1 ; + + if ( abs( vtV2.y) < EPS_SMALL) + + vtV1 = Y_AX ; + else + vtV1 = X_AX - ( vtV2.x / vtV2.y) * Y_AX ; + + if ( vtV1 * vtToolDir < 0) + + vtV1 = - vtV1 ; + + vtV1.Normalize() ; + + Vector3d vtV3 = vtV1 ^ vtV2 ; + + // Determino il semi-asse minore + Vector3d vtSemiMin( vtV3.x, vtV3.y, 0) ; + double dSemiAxMin = m_dRadius * vtSemiMin.LenXY() ; + + Vector3d vtMovexy( vtMove.x, vtMove.y, 0) ; double dPlaneLen = vtMovexy.LenXY() ; + Vector3d vtU1 = vtV1 ; + Vector3d vtU2 ; + + if ( abs( vtV2.y) < EPS_SMALL) { + + if ( vtV2.x > 0) + + vtU2 = X_AX ; + else + vtU2 = - X_AX ; + } + else { + + vtU2 = vtMovexy ; vtU2.Normalize() ; + } + + + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; + + Vector3d vtC = ptC - ptCIxy ; + + double dProj1 = vtC * vtU1 ; double dProj2 = vtC * vtU2 ; + + double dSqRadDistI = dProj1 * dProj1 + dProj2 * dProj2 ; + double dSqRadDistF = dProj1 * dProj1 + ( dProj2 - dPlaneLen) * ( dProj2 - dPlaneLen) ; + double dSqAxDist = dProj1 * dProj1 ; + + if ( ( dProj2 < 0 && dSqRadDistI < m_dRadius * m_dRadius) || + ( dProj2 >= 0 && dProj2 < dPlaneLen && dSqAxDist < m_dRadius * m_dRadius) || + ( dProj2 >= dPlaneLen && dSqRadDistF < m_dRadius * m_dRadius)) { + + // Massimi + if ( dProj2 < - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ; + + dMax = dZI + dH ; + } + else if ( dProj2 >= - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) && + dProj2 < dPlaneLen - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) { + + double dProj0 = - dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) ; + double dZ0 = dZI + ( dPlaneLen / dDeltaZ) * ( - dProj0) ; + + dMax = dZ0 + ( dDeltaZ / dPlaneLen) * ( dProj2 - dProj0) ; + } + else { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ; + + dMax = dZF + dH ; + } + + // Minimi + if ( dProj2 < dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ; + + dMin = dZI - dH ; + } + else if ( dProj2 >= dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) && + dProj2 < dPlaneLen + dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius))) { + + double dProj0 = dSemiAxMin * sqrt( 1 - ( dProj1 * dProj1) / ( m_dRadius * m_dRadius)) ; + double dZ0 = dZI + ( dPlaneLen / dDeltaZ) * ( - dProj0) ; + + dMin = dZ0 + ( dDeltaZ / dPlaneLen) * ( dProj2 - dProj0) ; + } + else { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ; + + dMin = dZF - dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + + return true ; +} +*/ + +//---------------------------------------------------------------------------- +bool +VolZmap::MillingXYPlusBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { + + // Parte cilindrica + + double dCylH = m_dHeight - m_dRadius ; + + m_dHeight = dCylH ; + + MillingXYPlusCyl( ptLs, ptLe, vtToolDir) ; + + m_dHeight = m_dHeight + m_dRadius ; + //////////////////////////////////////// + Point3d ptI, ptF ; + + if ( ptLs.z < ptLe.z) { + + ptI = ptLs ; + ptF = ptLe ; + } + else { + + ptI = ptLe ; + ptF = ptLs ; + } + + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; + + Point3d ptCI = ptI - dCylH * vtToolDir ; + Point3d ptCF = ptF - dCylH * vtToolDir ; + + Point3d ptCIxy( ptCI.x, ptCI.y, 0) ; + + // Bounding box + double dMinX = min( ptCI.x, ptCF.x) - m_dRadius ; + double dMaxX = max( ptCI.x, ptCF.x) + m_dRadius ; + double dMinY = min( ptCI.y, ptCF.y) - m_dRadius ; + double dMaxY = max( ptCI.y, ptCF.y) + m_dRadius ; + + Vector3d vtMove = ptF - ptI ; + Vector3d vtPlaneMove( vtMove.x, vtMove.y, 0) ; double dPLen = vtPlaneMove.LenXY() ; vtMove.Normalize() ; + + // Sistema di riferimento nel piano + Vector3d vtV2 = vtPlaneMove ; vtV2.Normalize() ; double dComp1 = vtV2 * X_AX ; double dComp2 = vtV2 * Y_AX ; + Vector3d vtV1 = dComp2 * X_AX - dComp1 * Y_AX ; + + // Determino il semi-asse minore + double dOriz = vtMove * Z_AX ; double dVert = vtMove * vtV2 ; + + double dSemiAxMin = m_dRadius * dOriz ; + + // Determinazione limiti sugli indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + // Ciclo + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; + + Vector3d vtC = ptC - ptCIxy ; + + double dProj1 = vtC * vtV1 ; double dProj2 = vtC * vtV2 ; + + double dSqRadDistI = dProj1 * dProj1 + dProj2 * dProj2 ; + double dSqRadDistF = dProj1 * dProj1 + ( dProj2 - dPLen) * ( dProj2 - dPLen) ; + double dSqAxDist = dProj1 * dProj1 ; + + if ( ( dProj2 < 0 && dSqRadDistI < m_dRadius * m_dRadius) || + ( dProj2 >= 0 && dProj2 < dPLen && dSqAxDist < m_dRadius * m_dRadius) || + ( dProj2 >= dPLen && dSqRadDistF < m_dRadius * m_dRadius)) { + + // Massimi + if ( dProj2 < - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ; + + dMax = dZI + dH ; + } + else if ( dProj2 >= - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) && + dProj2 < dPLen - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) { + + double dProj0 = - dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) ; + double dZ0 = dZI + dVert * sqrt( m_dRadius * m_dRadius - dSqAxDist) ; + + dMax = dZ0 + ( dDeltaZ / dPLen) * ( dProj2 - dProj0) ; + } + else { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ; + + dMax = dZF + dH ; + } + + // Minimi + if ( dProj2 < dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistI) ; + + dMin = dZI - dH ; + } + else if ( dProj2 >= dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) && + dProj2 < dPLen + dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius))) { + + double dProj0 = dSemiAxMin * sqrt( 1 - ( dSqAxDist) / ( m_dRadius * m_dRadius)) ; + double dZ0 = dZI - dVert * sqrt( m_dRadius * m_dRadius - dSqAxDist) ; + + dMin = dZ0 + ( dDeltaZ / dPLen) * ( dProj2 - dProj0) ; + } + else { + + double dH = sqrt( m_dRadius * m_dRadius - dSqRadDistF) ; + + dMin = dZF - dH ; + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMinMaxXY( unsigned int nI, unsigned int nJ, double dProj, double dZheight, double dSqD, double dPathPerp, double dPathPar, double dScProd) { + + // Definisco la variabile altezza della parte cilindrica dell'utensile + double dCylH ; + // Definisco variabili per determinazione intervallo da sottrarre + double dL, dR, dH ; + + // Caso di utensile generico ( per ora non gestito) + if ( m_nToolType == 0) + return false ; + // Se utensile standard setto altezza della parte cilindrica + else if ( m_nToolType == 1) + dCylH = m_dHeight ; + else if ( m_nToolType == 2) + dCylH = m_dHeight - m_dRadius ; + else if ( m_nToolType == 3) + dCylH = m_dHeight - m_dRCorner ; + // Caso di utensile non definito + else + return false ; + + // Parametri per isolare la lavorazione della parte cilindrica comune a tutti gli utensili standard + // Limite nella direziona parallela all'asse dell'utensile e parametro perpendicolare + double dLimPar, dParPerp ; + + // Tagli perpendicolari all'asse dell'utensile + if ( abs( dScProd) < EPS_SMALL) { + dLimPar = dCylH ; + dParPerp = dPathPerp ; + } + // Tagli paralleli all'asse dell'utensile + else { + dLimPar = dPathPar ; + dParPerp = 0 ; + } + + // Parte cilindrica della lavorazione + if ( dSqD < dLimPar * dLimPar) { + // Qui il raggio del semicerchio è m_dRadius + if ( dProj < 0) + // dH = sqrt( m_dRadius^2 - dProj^2) + dH = sqrt( m_dRadius * m_dRadius - ( dProj * dProj)) ; + // Qui l'altezza è costante + else if ( dProj < dParPerp) + // dH = m_dRadius + dH = m_dRadius ; + // Qui il raggio del semicerchio è m_dRadius + else if ( dProj < dParPerp + m_dRadius) + // dH = sqrt( m_dRadius^2 - ( dProj - dParPerp)^2) + dH = sqrt( m_dRadius * m_dRadius - ( dProj - dParPerp) * ( dProj - dParPerp)) ; + // Eseguo il taglio + return SubtractIntervals( nI, nJ, dZheight - dH, dZheight + dH) ; + } + // Parte non cilindrica, questa parte esiste solo nei tagli (dScProd = 0) e nel foro con la punta quindi (dScProd < 0) + // e solo con frese non cilindriche + else { + if ( dScProd < EPS_SMALL) { + // Definisco variabili + // Caso fresa ball-end + if ( m_nToolType == 2) { + // Il raggio è sqrt( m_dRadius^2 - ( sqrt( dSqD) - dLimPar)^2) + if ( dProj < 0) { + dL = sqrt( dSqD) - dLimPar ; + dR = sqrt( m_dRadius * m_dRadius - dL * dL) ; + dH = sqrt( dR * dR - (dProj * dProj)) ; + } + // Qui dH non dipende da dProj + else if ( dProj < dParPerp) { + dL = sqrt( dSqD) - dLimPar ; + dH = sqrt( m_dRadius * m_dRadius - dL * dL) ; + } + // E' analogo al primo caso con la sostituzione di dProj con dProj - dParPerp + else if ( dProj < dParPerp + m_dRadius) { // In questo caso è equivalente a else + dL = sqrt( dSqD) - dLimPar ; + dR = sqrt( m_dRadius * m_dRadius - dL * dL) ; + dH = sqrt( dR * dR - ((dProj - dParPerp) * (dProj - dParPerp))) ; + } + } + // Caso di fresa bull-nose + else if ( m_nToolType == 3) { + // Raggio semicerchio m_dRadius - m_dRCorner + sqrt( m_dRCorner^2 - ( sqrt( dSqD) - dLimPar)^2) + if ( dProj < 0) { + dL = sqrt( dSqD) - dLimPar ; + dR = m_dRadius - m_dRCorner + sqrt( m_dRCorner * m_dRCorner - dL * dL) ; + dH = sqrt( dR * dR - ( dProj * dProj)) ; + } + // Qui dH non dipende da dProj + else if ( dProj < dParPerp) { + dL = sqrt( dSqD) - dLimPar ; + dH = m_dRadius - m_dRCorner + sqrt( m_dRCorner * m_dRCorner - dL * dL) ; + } + // E' analogo al primo caso con la sostituzione di di dProj con dProj - dParPerp + else if ( dProj < dParPerp + m_dRadius) { // In questo caso equivalente a else + dL = sqrt( dSqD) - dLimPar ; + dR = m_dRadius - m_dRCorner + sqrt( m_dRCorner * m_dRCorner - dL * dL) ; + dH = sqrt( dR * dR - ( ( dProj - dParPerp) * ( dProj - dParPerp))) ; + } + } + return SubtractIntervals( nI, nJ, dZheight - dH, dZheight + dH) ; + } + } + return true ; +} + +// Frese conus +//---------------------------------------------------------------------------- +bool +VolZmap::ConusDrillingZ( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) { + + double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + double dMaxRad = max( m_dRadius, m_dTipRadius) ; + double dMinRad = min( m_dRadius, m_dTipRadius) ; + + // Bounding box + double dMinX = ptLs.x - dMaxRad ; + double dMaxX = ptLs.x + dMaxRad ; + double dMinY = ptLs.y - dMaxRad ; + double dMaxY = ptLs.y + dMaxRad ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + double dDeltaZ = abs( ptLe.z - ptLs.z) ; + + Point3d ptO( ptLs.x, ptLs.y, 0) ; + + // Limiti su indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + + if ( m_dRadius < m_dTipRadius) + + return GetMinMaxZSw( ptO, nStartI, nEndI, nStartJ, nEndJ, dMinZ, dMaxZ, dMinRad, dMaxRad, vtToolDir.z, dDeltaZ) ; + + else + + return GetMinMaxZDr( ptO, nStartI, nEndI, nStartJ, nEndJ, dMinZ, dMaxZ, dMinRad, dMaxRad, vtToolDir.z, dDeltaZ) ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMinMaxZSw( const Point3d ptO, unsigned int nStartI, unsigned int nEndI, unsigned int nStartJ, unsigned int nEndJ, double dMinZ, double dMaxZ, double dMinRad, double dMaxRad, double dDir, double dDeltaZ) { + + double dMin, dMax ; + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; + + double dSqDist = vtC * vtC ; + + if ( dSqDist < dMaxRad * dMaxRad) { + + if ( dSqDist < dMinRad * dMinRad) { + + dMin = dMinZ ; + dMax = dMaxZ ; + } + else { + + if ( dDir > 0) { + + dMin = dMinZ ; + dMax = dMinZ + dDeltaZ + ( m_dTipHeight * ( dMaxRad - sqrt( dSqDist))) / ( dMaxRad - dMinRad) ; + } + else { + + dMin = dMaxZ - dDeltaZ + ( m_dTipHeight * ( sqrt( dSqDist) - dMaxRad)) / ( dMaxRad - dMinRad) ; + dMax = dMaxZ ; + } + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMinMaxZDr( const Point3d ptO, unsigned int nStartI, unsigned int nEndI, unsigned int nStartJ, unsigned int nEndJ, double dMinZ, double dMaxZ, double dMinRad, double dMaxRad, double dDir, double dDeltaZ) { + + double dMin, dMax ; + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; + + double dSqDist = vtC * vtC ; + + if ( dSqDist < dMaxRad * dMaxRad) { + + if ( dSqDist < dMinRad * dMinRad) { + + dMin = dMinZ ; + dMax = dMaxZ ; + } + else { + + if ( dDir > 0) { + + dMin = dMinZ + ( m_dTipHeight * ( sqrt( dSqDist) - dMinRad)) / ( dMaxRad - dMinRad) ; + dMax = dMaxZ ; + } + else { + + dMin = dMinZ ; + dMax = dMaxZ + ( m_dTipHeight * ( sqrt( dSqDist) - dMinRad)) / ( dMinRad - dMaxRad) ; + } + } + + SubtractIntervals( i, j, dMin, dMax) ; + } + } // Fine ciclo + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::ConusPerpZ( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) { + + double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + double dMaxRad = max( m_dRadius, m_dTipRadius) ; + double dMinRad = min( m_dRadius, m_dTipRadius) ; + + // Bounding box + double dMinX = min( ptLs.x, ptLe.x) - dMaxRad ; + double dMaxX = max( ptLs.x, ptLe.x) + dMaxRad ; + double dMinY = min( ptLs.y, ptLe.y) - dMaxRad ; + double dMaxY = max( ptLs.y, ptLe.y) + dMaxRad ; // Ricordati del caso balordo da mettere nella documentazione + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + Point3d ptO( ptLs.x, ptLs.y, 0) ; + Vector3d vtMove = ptLe - ptLs ; double dLen = vtMove.LenXY() ; + Vector3d vtV1 = vtMove ; vtV1.Normalize() ; + + double dZBase = ptLs.z ; + double dZStem = ptLs.z - ( m_dHeight - m_dTipHeight) * vtToolDir.z ; + double dZTip = ptLs.z - m_dHeight * vtToolDir.z ; + + // Limiti su indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + for( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; + + double dProj1 = vtC * vtV1 ; + Vector3d vtOrt = vtC - dProj1 * vtV1 ; + + if ( dProj1 < 0) { + + double dSqDist = vtC * vtC ; + + if ( dSqDist < dMinRad * dMinRad) { + + dMin = min( dZBase, dZTip) ; + dMax = max( dZBase, dZTip) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dSqDist >= dMinRad * dMinRad && dSqDist < dMaxRad * dMaxRad) { + + if ( m_dRadius < m_dTipRadius) { + + dMin = min( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; + dMax = max( dZTip, dZStem+ ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; + } + else { + + dMin = min( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; + dMax = max( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; + } + SubtractIntervals( i, j, dMin, dMax) ; + } + } + else if ( dProj1 >= 0 && dProj1 < dLen) { + + double dSqDist = vtOrt * vtOrt ; + + if ( dSqDist < dMinRad * dMinRad) { + + dMin = min( dZBase, dZTip) ; + dMax = max( dZBase, dZTip) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dSqDist >= dMinRad * dMinRad && dSqDist < dMaxRad * dMaxRad) { + + if ( m_dRadius < m_dTipRadius) { + + dMin = min( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; + dMax = max( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; + } + else { + + dMin = min( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; + dMax = max( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; + } + SubtractIntervals( i, j, dMin, dMax) ; + } + } + else if ( dProj1 >= dLen) { + + Vector3d vtCn = vtC - vtMove ; + + double dSqDist = vtCn * vtCn ; + + if ( dSqDist < dMinRad * dMinRad) { + + dMin = min( dZBase, dZTip) ; + dMax = max( dZBase, dZTip) ; + + SubtractIntervals( i, j, dMin, dMax) ; + } + else if ( dSqDist >= dMinRad * dMinRad && dSqDist < dMaxRad * dMaxRad) { + + if ( m_dRadius < m_dTipRadius) { + + dMin = min( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; + dMax = max( dZTip, dZStem + ( sqrt( dSqDist) - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; + } + else { + + dMin = min( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; + dMax = max( dZBase, dZTip + ( sqrt( dSqDist) - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; + } + SubtractIntervals( i, j, dMin, dMax) ; + } + } + } // Fine ciclo + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::ConusMillingZDr( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) { + + double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + double dMaxRad = max( m_dRadius, m_dTipRadius) ; + double dMinRad = min( m_dRadius, m_dTipRadius) ; + + // Bounding box + double dMinX = min( ptLs.x, ptLe.x) - dMaxRad ; + double dMaxX = max( ptLs.x, ptLe.x) + dMaxRad ; + double dMinY = min( ptLs.y, ptLe.y) - dMaxRad ; + double dMaxY = max( ptLs.y, ptLe.y) + dMaxRad ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + // Punti iniziale e finale e proiezione sul piano del punto iniziale + Point3d ptI, ptF, ptO ; + + if( vtToolDir.z > 0) { + + ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ; + ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; + } + else { + + ptI = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ; + ptF = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; + } + + + // Quote iniziale e finale della base dell'utensile e DeltaZ + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; + + // Vettori di movimento + Vector3d vtMove = ptF - ptI ; + Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMoveXY.LenXY() ; + + // Sistema di riferimento sul cono e vertice del cono + Vector3d vtV1 = vtToolDir ; + Vector3d vtV2 = vtMoveXY ; vtV2.Normalize() ; + Vector3d vtV3 = vtV1 ^ vtV2 ; + Point3d ptV = ptI - ( m_dHeight + m_dTipHeight * dMinRad / ( dMaxRad - dMinRad)) * vtV1 ; + + // Apertura del cono e parametri per determinare i piani + double dTanAlpha = ( dMaxRad - dMinRad) / m_dTipHeight ; + double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ; + double dCos = dTanAlpha * dRatio ; + + // Versori normali e prodotti scalari per per determinare i piani + Vector3d vtNs = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 + ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ; + Vector3d vtNd = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 - ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ; + Vector3d vtR0 = ptV - ORIG ; + double dDots = vtR0 * vtNs ; + double dDotd = vtR0 * vtNd ; + + // Limiti su indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { + + double dMin, dMax ; + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; Vector3d vtCf = vtC - vtMoveXY ; + + Vector3d vtUC = vtC ; Vector3d vtUCf = vtCf ; vtUC.Normalize() ; vtUCf.Normalize() ; + + double dCCos = vtUC * vtV2 ; double dCCosf = vtUCf * vtV2 ; + + double dProj = vtC * vtV2 ; + Vector3d vtOrt = vtC - dProj * vtV2 ; + + double dSqDistI = vtC * vtC ; double dSqDistM = vtOrt * vtOrt ; double dSqDistF = vtCf * vtCf ; + + if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad) + ||( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad) + ||( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) { + + if ( vtToolDir.z > 0) { + // Massimi + double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ; + + if ( dProj < dLen - dPMaxI) + + dMax = dZI + ( dDeltaZ / dLen) * ( dProj + dPMaxI) ; + else + dMax = dZF ; + + // Minimi + if ( dSqDistI < dMinRad * dMinRad) + + dMin = dZI - m_dHeight ; + + else { + + if ( ( vtMove * vtV1) / ( vtMove * vtV2) <= 1 / dTanAlpha) { + + if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos) + + dMin = dZI - m_dHeight + ( ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ; + + else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) { + + double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ; + double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ; + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistM <= dMinSql) + + dMin = dZI - m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ; + + else if ( dSqDistM < dMaxSql) { + + if ( vtC * vtV3 > 0) + + dMin = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; + else + dMin = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ; + } + } + else if ( dCCosf >= dCos) { + + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistF < dMinRad * dMinRad) + + dMin = dZI - m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ; + else + dMin = dZF - m_dHeight + ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ; + } + else + + dMin = dZI - m_dHeight + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + } + else { + + if ( dSqDistI < dMaxRad * dMaxRad) + + dMin = dZI - m_dHeight + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ; + + else if ( dProj >= dPMaxI && dProj < dPMaxI + dLen) + + dMin = dZI - m_dHeight + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + } + } + } + else { + // Massimi + double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ; + + if ( dSqDistI < dMinRad * dMinRad) + + dMax = dZI + m_dHeight ; + + else { + + if ( - ( vtMove * vtV1) / ( vtMove * vtV2) <= 1 / dTanAlpha) { + + if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos) + + dMax = dZI + m_dHeight - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ; + + else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) { + + double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ; + double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ; + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistM <= dMinSql) + + dMax = dZI + m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ; + + else if ( dSqDistM < dMaxSql) { + + if ( vtC * vtV3 > 0) + + dMax = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; + else + dMax = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ; + } + } + else if ( dCCosf >= dCos) { + + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistF < dMinRad * dMinRad) + + dMax = dZI + m_dHeight + ( dProj - dPMinI) * dDeltaZ / dLen ; + else + dMax = dZF + m_dHeight - ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ; + } + else + + dMax = dZI + m_dHeight - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + + } + else { + + if ( dSqDistI < dMaxRad * dMaxRad) + + dMax = dZI + m_dHeight - ( ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ; + + else if ( dProj >= dPMaxI && dProj < dPMaxI + dLen) + + dMax = dZI + m_dHeight - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + + } + } + // Minimi + double dPMaxCirc = sqrt( dMaxRad * dMaxRad - dSqDistM) ; + + if ( dProj > dLen - dPMaxCirc) + + dMin = dZF ; + else + dMin = dZI + ( dDeltaZ / dLen) * ( dProj + dPMaxCirc) ; + } + SubtractIntervals( i, j, dMin, dMax) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::ConusMillingZSw( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) { + + double dMinZ = min( min( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), min( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + double dMaxZ = max( max( ptLs.z, ptLs.z - vtToolDir.z * m_dHeight), max( ptLe.z, ptLe.z - vtToolDir.z * m_dHeight)) ; + + // Prima verifica sull'interferenza dell'utensile con lo Zmap + if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) + return true ; + + double dMaxRad = max( m_dRadius, m_dTipRadius) ; + double dMinRad = min( m_dRadius, m_dTipRadius) ; + + // Bounding box + double dMinX = min( ptLs.x, ptLe.x) - dMaxRad ; + double dMaxX = max( ptLs.x, ptLe.x) + dMaxRad ; + double dMinY = min( ptLs.y, ptLe.y) - dMaxRad ; + double dMaxY = max( ptLs.y, ptLe.y) + dMaxRad ; + + // Seconda verifica dell'interferenza dell'utensile con lo Zmap + if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) + return true ; + if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) + return true ; + + // Punti iniziale e finale e proiezione sul piano del punto iniziale + Point3d ptI, ptF, ptO ; + + if( vtToolDir.z > 0) { + + ptI = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ; + ptF = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; + } + else { + + ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; ptO.x = ptI.x ; ptO.y = ptI.y ; ptO.z = 0 ; + ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; + } + + Point3d ptICyl = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; + + double dDeltaH = m_dHeight - m_dTipHeight ; + double dMinZCyl = min( ptICyl.z, ptICyl.z - vtToolDir.z * dDeltaH) ; + + + // Punti contatto cono cilindro + Point3d ptIS = ptI - ( m_dHeight - m_dTipHeight) * vtToolDir ; + Point3d ptFS = ptF - ( m_dHeight - m_dTipHeight) * vtToolDir ; + + // Quote iniziali e finali e DeltaZ + double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = dZF - dZI ; double dADeltaZ = abs( dDeltaZ) ; + double dZIS = ptIS.z ; double dZFS = ptFS.z ; + + // Vettori di movimento + Vector3d vtMove = ptF - ptI ; + Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMoveXY.LenXY() ; + + // Sistema di riferimento sul cono e vertice del cono + Vector3d vtV1 = - vtToolDir ; + Vector3d vtV2 = vtMoveXY ; vtV2.Normalize() ; + Vector3d vtV3 = vtV1 ^ vtV2 ; + Point3d ptV = ptI + ( m_dHeight - m_dTipHeight * ( 1 + dMinRad / ( dMaxRad - dMinRad))) * vtV1 ; + + // Apertura del cono e parametri per determinare i piani + double dTanAlpha = ( dMaxRad - dMinRad) / m_dTipHeight ; + double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ; + double dCos = dTanAlpha * dRatio ; + + // Versori normali e prodotti scalari per per determinare i piani + Vector3d vtNp = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 + ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ; + Vector3d vtNm = - ( dTanAlpha / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV1 + ( dCos / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV2 - ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTanAlpha * dTanAlpha)) * vtV3 ; + Vector3d vtR0 = ptV - ORIG ; + double dDotp = vtR0 * vtNp ; + double dDotm = vtR0 * vtNm ; + + // Limiti su indici + unsigned int nStartI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; + unsigned int nEndI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; + unsigned int nStartJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; + unsigned int nEndJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; + + for ( unsigned int i = nStartI ; i <= nEndI ; ++i) + for ( unsigned int j = nStartJ ; j <= nEndJ ; ++j) { + + double dMin, dMax ; + double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; + + Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptO ; Vector3d vtCf = vtC - vtMoveXY ; + + Vector3d vtUC = vtC ; Vector3d vtUCf = vtCf ; vtUC.Normalize() ; vtUCf.Normalize() ; + + double dCCos = vtUC * vtV2 ; double dCCosf = vtUCf * vtV2 ; + + double dProj = vtC * vtV2 ; + Vector3d vtOrt = vtC - dProj * vtV2 ; + + double dSqDistI = vtC * vtC ; double dSqDistM = vtOrt * vtOrt ; double dSqDistF = vtCf * vtCf ; + + if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad) + ||( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad) + ||( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) { + + if ( vtV1.z < 0) { + + double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ; + + // Massimi + if ( dRatio <= 1 / dTanAlpha) { + + if ( dSqDistI < dMinRad * dMinRad) + + dMax = dZIS ; + + else { + + if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos) + + dMax = dZIS - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ; + + else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) { + + double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ; + double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ; + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistM <= dMinSql) + + dMax = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ; + + else if ( dSqDistM < dMaxSql) { + + if ( vtC * vtV3 > 0) + + dMax = ( dDotp - dX * vtNp.x - dY * vtNp.y) / vtNp.z ; + else + dMax = ( dDotm - dX * vtNm.x - dY * vtNm.y) / vtNm.z ; + } + } + else if ( dCCosf >= dCos) { + + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistF < dMinRad * dMinRad) + + dMax = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ; + else + dMax = dZFS - ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ; + } + else + dMax = dZIS - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + } + } + else { + + if ( dSqDistI < dMinRad * dMinRad) + + dMax = dZIS ; + + else if ( dSqDistI < dMaxRad * dMaxRad) + + dMax = dZIS - ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ; + + else { + + if ( dProj >= dPMaxI) + + dMax = dZIS - m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + } + } + // Minimi + + if ( dSqDistF < dMaxRad * dMaxRad) + + dMin = dZFS - m_dTipHeight ; + + else if ( dProj <= dLen - dPMaxI) + + dMin = dZIS - m_dTipHeight + ( dProj + dPMaxI) * dDeltaZ / dLen ; + + } // Fine vtV1 < 0 + else { + + double dPMaxI = ( dMaxRad * dMaxRad - dSqDistM > 0 ? sqrt( dMaxRad * dMaxRad - dSqDistM) : 0) ; + + // Massimi + if ( dSqDistF < dMaxRad * dMaxRad) + + dMax = dZFS + m_dTipHeight ; + + else if ( dProj <= dLen - dPMaxI) + + dMax = dZIS + m_dTipHeight + ( dProj + dPMaxI) * dDeltaZ / dLen ; + + // Minimi + if ( dRatio <= 1 / dTanAlpha) { + + if ( dSqDistI < dMinRad * dMinRad) + + dMin = dZIS ; + + else { + + if ( dSqDistI < dMaxRad * dMaxRad && dCCos < dCos) + + dMin = dZIS + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ; + + else if ( dCCos >= dCos && dCCosf < dCos && dSqDistM < dMaxRad * dMaxRad * ( 1 - dCos * dCos)) { + + double dMinSql = dMinRad * dMinRad * ( 1 - dCos * dCos) ; + double dMaxSql = dMaxRad * dMaxRad * ( 1 - dCos * dCos) ; + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistM <= dMinSql) + + dMin = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ; + + else if ( dSqDistM < dMaxSql) { + + if ( vtC * vtV3 > 0) + + dMin = ( dDotp - dX * vtNp.x - dY * vtNp.y) / vtNp.z ; + else + dMin = ( dDotm - dX * vtNm.x - dY * vtNm.y) / vtNm.z ; + } + } + else if ( dCCosf >= dCos) { + + double dPMinI = ( dMinRad * dMinRad - dSqDistM > 0 ? sqrt( dMinRad * dMinRad - dSqDistM) : 0) ; + + if ( dSqDistF < dMinRad * dMinRad) + + dMin = dZIS + ( dProj - dPMinI) * dDeltaZ / dLen ; + else + dMin = dZFS + ( ( sqrt( dSqDistF) - dMinRad) * m_dTipHeight) / ( dMaxRad - dMinRad) ; + } + else + dMin = dZIS + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + } + } + else { + + if ( dSqDistI < dMinRad * dMinRad) + + dMin = dZIS ; + + else if ( dSqDistI < dMaxRad * dMaxRad) + + dMin = dZIS + ( sqrt( dSqDistI) - dMinRad) * m_dTipHeight / ( dMaxRad - dMinRad) ; + + else + + dMin = dZIS + m_dTipHeight + ( dProj - dPMaxI) * dDeltaZ / dLen ; + + } + } + SubtractIntervals( i, j, dMin, dMax) ; + } + + // Parte cilindrica + Vector3d vtCyl = ( vtV1.z < 0 ? vtCf : vtC) ; + Vector3d vtCylf = ( vtV1.z < 0 ? vtC : vtCf) ; + Vector3d vtMot = ( vtV1.z < 0 ? - vtV2 : vtV2) ; + + double dCylProj = vtCyl * vtMot ; + double dCylSqDistI = vtCyl * vtCyl ; + double dCylSqDistF = vtCylf * vtCylf ; + double dCylSqDistM = ( vtCyl - dCylProj * vtMot) * ( vtCyl - dCylProj * vtMot) ; + + + if ( dCylSqDistI < dMinRad * dMinRad + || dCylSqDistF < dMinRad * dMinRad + || ( dCylProj > 0 && dCylProj < dLen && dCylSqDistM < dMinRad * dMinRad)) { + + double dSt = sqrt( dMinRad * dMinRad - dCylSqDistM) ; + + // Minimi + if ( dCylSqDistI < dMinRad * dMinRad ) + + dMin = dMinZCyl ; + + else if ( dCylProj >= dSt) + + dMin = dMinZCyl + ( dCylProj - dSt) * dADeltaZ / dLen ; + + // Massimi + if ( dCylSqDistF < dMinRad * dMinRad) + + dMax = dMinZCyl + dDeltaH + dADeltaZ ; + + else if ( dCylProj <= dLen - dSt) + + dMax = dMinZCyl + dDeltaH + ( dCylProj + dSt) * dADeltaZ / dLen ; + + SubtractIntervals( i, j, dMin, dMax) ; + + } + } + return true ; +} + + + +// Utensile generico +//---------------------------------------------------------------------------- +inline bool +VolZmap::GetMinMaxZGenTool( unsigned int nI, unsigned int nJ, double dZCutBase, double dDeltaZ, double dSqDist, const Vector3d& vtToolDir) { + + // Estremi dell'intervallo da asportare + double dMin, dMax ; + + unsigned int CurveNum = m_ToolOutline.GetCurveCount() ; // Non dovrebbe servire + // Puntatore a un oggetto costante di tipo ICurve + const ICurve* pCurve ; + // L'inizio del ciclo dipende dal fatto che lavori la punta o il fondo dell'utensile + if ( vtToolDir.z * dDeltaZ < 0) + pCurve = m_ToolOutline.GetLastCurve() ; + else + pCurve = m_ToolOutline.GetFirstCurve() ; + + // Ciclo + while ( pCurve != nullptr) { + + int nCrvType = pCurve -> GetType() ; + + const ICurve* pTest = pCurve ; + + if ( vtToolDir.z * dDeltaZ < 0) + pTest = m_ToolOutline.GetNextCurve() ; + else + pTest = m_ToolOutline.GetPrevCurve() ; + + // Caso di segmento + if ( nCrvType == CRV_LINE) { + + Point3d ptStart, ptEnd ; + pCurve->GetStartPoint( ptStart) ; + pCurve->GetEndPoint( ptEnd) ; + double dZStart, dMDPrev, angC, angCPrev ; + + if ( abs( ptEnd.x - ptStart.x) > EPS_SMALL) { + + if ( pTest == nullptr) { + + if ( vtToolDir.z * dDeltaZ < 0) { + dZStart = ptEnd.y ; + angC = ( ptStart.y - ptEnd.y) / ( ptStart.x - ptEnd.x) ; + angCPrev = angC ; + } + else { + dZStart = ptStart.y ; + angC = ( ptEnd.y - ptStart.y) / ( ptEnd.x - ptStart.x) ; + angCPrev = angC ; + } + + dMin = min( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ; + dMax = max( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ; + dMDPrev = max( ptStart.x, ptEnd.x) ; + // Eseguo l'asportazione + SubtractIntervals( nI, nJ, dMin, dMax) ; + } + else { + + double dMD ; + + if ( vtToolDir.z * dDeltaZ < 0) { + + dZStart = ptEnd.y ; + angC = ( ptStart.y - ptEnd.y) / ( ptStart.x - ptEnd.x) ; + dMD = max( ptStart.x, ptEnd.x) ; + + if ( angCPrev < 0 && dMDPrev > dMD) { + dMin = min( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ; + dMax = max( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ; + dMDPrev = max( ptStart.x, ptEnd.x) ; + } + + angCPrev = angC ; + dMDPrev = dMD ; + } + else { + + dZStart = ptStart.y ; + angC = ( ptEnd.y - ptStart.y) / ( ptEnd.x - ptStart.x) ; + dMD = max( ptStart.x, ptEnd.x) ; + + if ( angCPrev < 0 && dMDPrev > max( ptStart.x, ptEnd.x)) { + dMin = min( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ; + dMax = max( dZStart + angC * dSqDist, dZStart + angC * dSqDist + dDeltaZ) ; + dMDPrev = max( ptStart.x, ptEnd.x) ; + } + + angCPrev = angC ; + dMDPrev = dMD ; + } + } + } + } + // Caso di arco + else if ( nCrvType == CRV_ARC) { + return true ; + } + else + // Caso di Bézier et al.. + return true ; + + } + // Decremento/incremento il puntatore + if ( vtToolDir.z * dDeltaZ < 0) + pCurve = m_ToolOutline.GetPrevCurve() ; + else + pCurve = m_ToolOutline.GetNextCurve() ; + + // Ricorda di guardare che tutti i casi abbiano il relatrivo enunciato di return +} + + + + + + + + + + + + + + + + + + + diff --git a/VolZmap.h b/VolZmap.h index 5614f88..dd2ce81 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -25,6 +25,9 @@ #include +// Tipi utensile +enum ToolType { GenericTool = 0, CylindricalMill = 1, BallEndMill = 2, BullNoseMill = 3, ConusMill = 4} ; + //---------------------------------------------------------------------------- class VolZmap : public IVolZmap, public IGeoObjRW { @@ -69,8 +72,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool SubtractIntervals( const Point3d& ptP, double dMin, double dMax) ; bool AddIntervals( unsigned int nI, unsigned int nJ, double dMin, double dMax) ; bool AddIntervals( const Point3d& ptP, double dMin, double dMax) ; - bool SetTool( const std::string& pToolName, unsigned int nToolType, const CurveComposite* pToolOutline) ; - bool MillingStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtDe) ; + bool SetTool( const std::string& pToolName, const CurveComposite* pToolOutline) ; + bool SetStdTool( const std::string& pToolName, unsigned int nToolType, double dH, double dTH, double dR, double dTR, double dRc = 0) ; + bool MillingStep( const Point3d& ptPs, const Point3d& ptPe, Vector3d& vtDs, Vector3d& vtDe) ; public : // IGeoObjRW virtual int GetNgeId( void) const ; @@ -94,8 +98,44 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool CalcDexelPrisms( int nPos1, int nPos2, TRIA3DLIST& lstTria) const ; bool AddDexelSideFace( int nPos, int nPosAdj, const Point3d& ptP, const Point3d& ptQ, const Vector3d& vtZ, const Vector3d& vtNorm, TRIA3DLIST& lstTria) const ; - bool MillingDrill( const Point3d& ptLs, const Point3d& ptLe, double dHeight, double dRadius) ; - bool MillingPerp( Point3d& ptPs, Point3d& ptPe, double dHeight, double dRadius) ; + + // frese: cylindrical, ball-end e bull-nose + // Versore utensile parallelo all'asse Z + bool MillingDrillZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingPerpZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + inline bool GetMinMaxZ( unsigned int nI, unsigned int nJ, double dZCutBase, double dDeltaZ, double dSqDist, const Vector3d& vtToolDir) ; + inline bool GetMinMaxZGen( unsigned int nI, unsigned int nJ, double dProj, double dSqd, double dLenPath, double dZheight, double dDelta, const Vector3d& vtToolDir) ; + // Versore utensile nel piano XY + bool MillingDrillXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingPerpXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingXYPlaneGen( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingXYCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingXYBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingXYPlusCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingXYPlusBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + bool MillingXYLongVert( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) ; + inline bool GetMinMaxXY( unsigned int nI, unsigned int nJ, double dProj, double dZheight, double dSqD, double dPathPerp, double dPathPar, double dScProd) ; + inline bool GetMMPlaneGenCyl( unsigned int i, unsigned int j, double dZ, double dLen1, double dLen2, double dProj1, double dProj2) ; + inline bool GetMMPlaneGenBall( unsigned int i, unsigned int j, double dZ, double dLen1, double dLen2, Point3d ptIxy, Vector3d vtMove, Vector3d vtV1, Vector3d vtV2) ; + + // frese: conus + // Versore utensile parallelo all'asse Z + bool ConusDrillingZ( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + bool ConusPerpZ( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + //bool ConusMillingZDr( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + //bool ConusMillingZDrP( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + //bool ConusMillingZDrPnew( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + //bool ConusMillingZDrPnew2( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + bool ConusMillingZDr( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + bool ConusMillingZSw( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) ; + inline bool GetMinMaxZSw( const Point3d ptO, unsigned int nStartI, unsigned int nEndI, unsigned int nStartJ, unsigned int nEndJ, double dMinZ, double dMaxZ, double dMinRad, double dMaxRad, double dDir, double dDeltaZ) ; + inline bool GetMinMaxZDr( const Point3d ptO, unsigned int nStartI, unsigned int nEndI, unsigned int nStartJ, unsigned int nEndJ, double dMinZ, double dMaxZ, double dMinRad, double dMaxRad, double dDir, double dDeltaZ) ; + + // utensile generico + inline bool GetMinMaxZGenTool( unsigned int nI, unsigned int nJ, double dZCutBase, double dDeltaZ, double dSqDist, const Vector3d& vtToolDir) ; + + private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; @@ -110,11 +150,18 @@ class VolZmap : public IVolZmap, public IGeoObjRW unsigned int m_nNx ; // i = 0, 1, ..., m_nNx - 1 unsigned int m_nNy ; // j = 0, 1, ..., m_nNy - 1 unsigned int m_nDim ; - std::vector > m_ZValues ; + double m_dMinZ ; + double m_dMaxZ ; + std::vector > m_ZValues ; - CurveComposite m_ToolOutline ; std::string m_sToolName ; - unsigned int m_nToolType ; // 0, 1, 2 per cylindrical mill, fresa ball-end, bull nose + unsigned int m_nToolType ; + CurveComposite m_ToolOutline ; + double m_dHeight ; + double m_dTipHeight ; + double m_dRadius ; + double m_dRCorner ; + double m_dTipRadius ; } ; //----------------------------------------------------------------------------- @@ -132,3 +179,5 @@ inline VolZmap* GetBasicVolZmap( IGeoObj* pGObj) { if ( pGObj == nullptr || pGObj->GetType() != VOL_ZMAP) return nullptr ; return (static_cast(pGObj)) ; } + +