//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 // Contenuto : Implementazione della classe Volume Zmap (singola griglia) // // // // Modifiche : 22.01.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "VolZmap.h" #include "GeoConst.h" using namespace std ; //---------- Sottrazione intervalli ------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::SubtractIntervals( unsigned int nI, unsigned int nJ, double dMin, double dMax) { // Controllo che dMin e dMax non siano quasi coincidenti if ( abs( dMax - dMin) < EPS_SMALL) return true ; // Controllo che dMin < dMax if ( dMax < dMin ) swap( dMax, dMin) ; // Calcolo nPos dello spillone unsigned int nPos = nJ * m_nNx + nI ; // Ciclo sugli intervalli dello spillone bool bModified = false ; unsigned int i = 0 ; while ( i + 1 < m_ZValues[nPos].size()) { // Intervallo da sottrarre è tutto a sinistra di quello corrente, non vi è intersezione if ( m_ZValues[nPos][i] > dMax - EPS_SMALL) { ; } // Intersezione else if ( m_ZValues[nPos][i + 1] > dMax + EPS_SMALL) { // L'intervallo corrente corrente viene limitato a sinistra if ( m_ZValues[nPos][i] > dMin - EPS_SMALL) { bModified = true ; m_ZValues[nPos][i] = dMax ; } // L'intervallo si divide in due intervalli else { bModified = true ; m_ZValues[nPos].resize( m_ZValues[nPos].size() + 2) ; for ( size_t j = m_ZValues[nPos].size() - 1 ; j >= i + 3 ; -- j) m_ZValues[nPos][j] = m_ZValues[nPos][j - 2] ; m_ZValues[nPos][i + 1] = dMin ; m_ZValues[nPos][i + 2] = dMax ; i = i + 2 ; } } else { // L'intervallo corrente viene eliminato if ( m_ZValues[nPos][i] > dMin - EPS_SMALL) { bModified = true ; for ( unsigned int j = i ; j < m_ZValues[nPos].size() - 2 ; ++ j) m_ZValues[nPos][j] = m_ZValues[nPos][j + 2] ; m_ZValues[nPos].resize( m_ZValues[nPos].size() - 2) ; i = i - 2 ; } // L'intervallo corrente viene limitato a destra else if ( m_ZValues[nPos][i + 1] > dMin + EPS_SMALL) { bModified = true ; m_ZValues[nPos][i + 1] = dMin ; } // L'intervallo da sottrarre è tutto a destra di quello corrente, non vi è intersezione else { ; } } i = i + 2 ; } // Se eseguita modifica, imposto ricalcolo della grafica if ( bModified) m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::SubtractIntervals( const Point3d& ptP, double dMin, double dMax) { // ptP è espresso nel sistema locale e viene convertito in quello intrinseco (localFrame) Point3d ptPL = ptP ; ptPL.ToLoc( m_LocalFrame) ; double dX, dY, dZ ; // Coordinate di ptPL nel sistema intrinseco double dhMin, dhMax ; // Altezze dMin e dMax RIESPRESSE nel sistema intrinseco (dMin e dMax sono altezze rispetto a ptP) dX = ptPL.x ; dY = ptPL.y ; dZ = ptPL.z ; dhMin = dZ + dMin ; dhMax = dZ + dMax ; // Cerco il punto della griglia più vicino (indice è l'intero appena più basso) 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 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 e vi è errore runtime return SubtractIntervals( i, j, dhMin, dhMax) ; } // altrimenti non succede niente return true ; } //---------- Addizione intervalli -------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::AddIntervals( unsigned int nI, unsigned int nJ, double dMin, double dMax) { // Controllo che dMin e dMax non siano quasi coincidenti if ( abs( dMax - dMin) < EPS_SMALL) return true ; // Controllo che dMin < dMax if ( dMax < dMin) swap( dMax, dMin) ; // Calcolo nPos unsigned int nPos = nJ * m_nNx + nI ; // Se spillone vuoto if ( m_ZValues[nPos].size() == 0) { m_ZValues[nPos].resize( 2) ; m_ZValues[nPos][0] = dMin ; m_ZValues[nPos][1] = dMax ; m_OGrMgr.Reset() ; return true ; } // Ciclo sugli intervalli dello spillone bool bModified = false ; unsigned int i = 0 ; while ( i + 1 < m_ZValues[nPos].size()) { // Eventuale aggiustamento di intervalli sovrapposti if ( i > 0) { if ( m_ZValues[nPos][i] < m_ZValues[nPos][i - 1] + EPS_SMALL) { // Se l'intervallo corrente non è contenuto totalmente si esegue l'istruzione successiva if ( m_ZValues[nPos][i - 1] < m_ZValues[nPos][i + 1] + EPS_SMALL) m_ZValues[nPos][i - 1] = m_ZValues[nPos][i + 1] ; for ( unsigned int j = i ; j < m_ZValues[nPos].size() - 2 ; ++ j) m_ZValues[nPos][j] = m_ZValues[nPos][j + 2] ; m_ZValues[nPos].resize( m_ZValues[nPos].size() - 2) ; i = i - 2 ; } } // Caso in cui devo aggiungere un intervallo a sinistra dell'intervallo corrente if ( m_ZValues[nPos][i] > dMax + EPS_SMALL) { bModified = true ; m_ZValues[nPos].resize( m_ZValues[nPos].size() + 2) ; for ( size_t j = m_ZValues[nPos].size() - 1 ; j >= i + 2 ; -- j) m_ZValues[nPos][j] = m_ZValues[nPos][j - 2] ; m_ZValues[nPos][i] = dMin ; m_ZValues[nPos][i + 1] = dMax ; i = i + 2 ; } // Casi d'intersezione: else if ( m_ZValues[nPos][i + 1] > dMax - EPS_SMALL) { // Se l'intervallo da aggiungere sconfina a sinistra modifico il minimo dell'intervalo corrente if ( m_ZValues[nPos][i] > dMin - EPS_SMALL) { bModified = true ; m_ZValues[nPos][i] = dMin ; } } else { // Se l'intervallo corrente è tutto contenuto nell'intervallo da aggungere modifico gli estremi if ( m_ZValues[nPos][i] > dMin + EPS_SMALL) { bModified = true ; m_ZValues[nPos][i] = dMin ; m_ZValues[nPos][i + 1] = dMax ; } // Se l'intervallo da aggiungere sconfina a destra modifico il massimo dell'intervallo corrente else if ( m_ZValues[nPos][i + 1] > dMin - EPS_SMALL) { bModified = true ; m_ZValues[nPos][i + 1] = dMax ; } else { // Aggiungo intervallo a destra dell'ultimo intervallo if ( i == m_ZValues[nPos].size() - 2) { bModified = true ; m_ZValues[nPos].resize( m_ZValues[nPos].size() + 2) ; m_ZValues[nPos][i + 2] = dMin ; m_ZValues[nPos][i + 3] = dMax ; i = i + 2 ; } } } i = i + 2 ; } // se eseguita modifica, imposto ricalcolo della grafica if ( bModified) m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::AddIntervals( const Point3d& ptP, double dMin, double dMax) { // ptP è espresso nel sistema locale e viene convertito in quello intrinseco (localFrame) Point3d ptPL = ptP ; ptPL.ToLoc( m_LocalFrame) ; double dX, dY, dZ ; // Coordinate di ptPL nel sistema intrinseco double dhMin, dhMax ; // Altezze dMin e dMax RIESPRESSE nel sistema intrinseco (dMin e dMax sono altezze rispetto a ptP) dX = ptPL.x ; dY = ptPL.y ; dZ = ptPL.z ; dhMin = dZ + dMin ; dhMax = dZ + dMax ; // Cerco il punto della griglia più vicino 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 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 e vi è errore runtime return AddIntervals( i, j, dhMin, dhMax) ; } // altrimenti non succede niente return false ; } //---------- Volumi ---------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Point3d& ptPe, const Vector3d& vtDe) { // Controllo sull'effettiva esistenza del movimento if ( AreSamePointApprox( ptPs, ptPe) && AreSameVectorApprox( vtDs, vtDe)) return true ; // Porto i dati del movimento nel riferimento intrinseco; quest'operazione è necessaria perché // viene chiamata la funzione di sottrazione che accetta come parametri gli indici, // non quella che chiede il punto, nella quale viene eseguita la trasformazione di coordinate. Point3d ptLs = ptPs ; ptLs.ToLoc( m_LocalFrame) ; Point3d ptLe = ptPe ; ptLe.ToLoc( m_LocalFrame) ; Vector3d vtLs = vtDs ; vtLs.ToLoc( m_LocalFrame) ; Vector3d vtLe = vtDe ; vtLe.ToLoc( m_LocalFrame) ; // Normalizzo i vettori if ( ! vtLs.Normalize() || ! vtLe.Normalize()) return false ; // Direzione utensile costante if ( AreSameVectorApprox( vtLs, vtLe)) { // Versori della direzione utensile diretti come Z if ( vtLs.LenXY() < EPS_SMALL) { // Movimento diretto come direzione utensile if ( AreSamePointXYApprox( ptLs, ptLe)) { if ( m_nToolType == GenericTool) return DrillZ( ptLs, ptLe, vtLs) ; else return DrillingZ( ptLs, ptLe, vtLs) ; } // Movimento perpendicolare a direzione utensile if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) { if ( m_nToolType == 0) return MillZ( ptLs, ptLe, vtLs) ; else return MillingPerpZ( ptLs, ptLe, vtLs) ; } // Movimento generico if ( m_nToolType == 0) return MillZ( ptLs, ptLe, vtLs) ; else return MillingZ( ptLs, ptLe, vtLs) ; } // Versori della direzione utensile nel piano XY else if ( abs( vtLs.z) < EPS_SMALL) { Vector3d vtDir( vtLs.x, vtLs.y, 0) ; vtDir.Normalize() ; // Movimento con Z costante (con vettore movimento parallelo od ortogonale al versore dell'utensile) if ( abs( ptLe.z - ptLs.z) < EPS_SMALL) { Vector3d vtTest( ptLe.x - ptLs.x, ptLe.y - ptLs.y, 0) ; Vector3d vtTLong = ( vtTest * vtDir) * vtDir ; Vector3d vtTOrt = vtTest - vtTLong ; // Movimento parallelo alla direzione dell'utensile (foratura) if ( vtTOrt.IsSmall()) { if ( m_nToolType == 0) return DrillingGT( ptLs, ptLe, vtDir) ; else return DrillingXY( ptLs, ptLe, vtDir) ; } // Movimento perpendicolare alla direzione dell'utensile if ( vtTLong.IsSmall()) { if ( m_nToolType == GenericTool) return MillingGT( ptLs, ptLe, vtDir) ; else return MillingPerpXY( ptLs, ptLe, vtDir) ; } // Movimento nel piano generico if ( m_nToolType == GenericTool) return MillingGT( ptLs, ptLe, vtDir) ; else return MillingXYPlaneGen( ptLs, ptLe, vtDir) ; } // Movimento con Z non costante else { if ( m_nToolType == GenericTool) return MillingGT( ptLs, ptLe, vtDir) ; // Movimento verticale if ( AreSamePointXYApprox( ptLs, ptLe)) return MillingXYVert( ptLs, ptLe, vtDir) ; // Grandezze geometriche per selezione Vector3d vtMove = ptLe - ptLs ; Vector3d vtTLong = ( vtMove * vtDir) * vtDir ; Vector3d vtTOrt = vtMove - ( vtMove * vtDir) * vtDir ; // Movimento LongVert if ( vtTOrt.IsSmallXY()) return MillingXYLongVert( ptLs, ptLe, vtDir) ; // Movimento perpendicolare alla direzione dell'utensile if ( vtTLong.IsSmallXY()) return MillingXY( ptLs, ptLe, vtDir) ; // Movimento generico con versore direzione nel piano return Milling( ptLs, ptLe, vtDir) ; } } // Caso generico else { Vector3d vtMove = ptLe - ptLs ; Vector3d vtOrt = vtMove - ( vtMove * vtLs) * vtLs ; // Drilling if ( vtOrt.IsSmall()) { if ( m_nToolType == GenericTool) return DrillingGT( ptLs, ptLe, vtLs) ; else return Drilling( ptLs, ptLe, vtLs) ; } // Milling else { if ( m_nToolType == GenericTool) return MillingGT( ptLs, ptLe, vtLs) ; else return Milling( ptLs, ptLe, vtLs) ; } } } // Altri casi, non gestiti return false ; } // Versore utensile parallelo all'asse Z //---------------------------------------------------------------------------- bool VolZmap::DrillingZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Cilindro sfera toro if ( m_nToolType == CylindricalMill || m_nToolType == BallEndMill || m_nToolType == BullNoseMill) return CBTDrillZ( ptLs, ptLe, vtToolDir) ; // Coni else if ( m_nToolType == ConusMill) return ConusDrillingZ( ptLs, ptLe, vtToolDir) ; else return false ; } //---------------------------------------------------------------------------- bool VolZmap::CBTDrillZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Bounding box 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) return true ; if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - 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)) ; // Determino quote estreme del tagliente 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 = ( m_dRadius + EPS_SMALL) * ( m_dRadius + EPS_SMALL) ; // 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 double dSqDist = SqDistXY( ptQ, ptLe) ; // se distanza nei limiti, taglio if ( dSqDist < dSqRad) GetMinMaxZ( i, j, dZCutBase, dDeltaZ, dSqDist, vtToolDir) ; } } return true ; } //---------------------------------------------------------------------------- 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) // Coda di rondine return GetMinMaxZSw( ptO, nStartI, nEndI, nStartJ, nEndJ, dMinZ, dMaxZ, dMinRad, dMaxRad, vtToolDir.z, dDeltaZ) ; // Punta di trapano 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) { for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { // Determinazione della posizione xy del dexel rispetto // all'asse di simmetria dell'utensile 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 ; // Se il dexel cade nel cerchio di interesse taglio if ( dSqDist < dMaxRad * dMaxRad) { double dMin, dMax ; if ( dSqDist < dMinRad * dMinRad) { dMin = dMinZ ; dMax = dMaxZ ; } else { double dR = sqrt( dSqDist) ; if ( dDir > 0) { dMin = dMinZ ; dMax = dMinZ + dDeltaZ + ( m_dTipHeight * ( dMaxRad - dR)) / ( dMaxRad - dMinRad) ; } else { dMin = dMaxZ - dDeltaZ + ( m_dTipHeight * ( dR - dMaxRad)) / ( dMaxRad - dMinRad) ; dMax = dMaxZ ; } } SubtractIntervals( i, j, dMin, dMax) ; } } } 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) { 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 ; // Se il dexel cade nel cerchio di interesse taglio if ( dSqDist < dMaxRad * dMaxRad) { double dMin, dMax ; if ( dSqDist < dMinRad * dMinRad) { dMin = dMinZ ; dMax = dMaxZ ; } else { double dR = sqrt( dSqDist) ; if ( dDir > 0) { dMin = dMinZ + ( m_dTipHeight * ( dR - dMinRad)) / ( dMaxRad - dMinRad) ; dMax = dMaxZ ; } else { dMin = dMinZ ; dMax = dMaxZ + ( m_dTipHeight * ( dR - dMinRad)) / ( dMinRad - dMaxRad) ; } } SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingPerpZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Cilindro sfera toro if ( m_nToolType == CylindricalMill || m_nToolType == BallEndMill || m_nToolType == BullNoseMill) return CBTMillingPerpZ( ptLs, ptLe, vtToolDir) ; // Coni else if ( m_nToolType == ConusMill) return ConusPerpZ( ptLs, ptLe, vtToolDir) ; else return false ; } //---------------------------------------------------------------------------- bool VolZmap::CBTMillingPerpZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Bounding box 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) return true ; if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - 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)) ; // Determino quote estreme del tagliente 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 dProiez = vtDir * ( ptQ - ptStart) ; if ( dProiez < 0) dProiez = 0 ; else if ( dProiez > dLen) dProiez = dLen ; Point3d ptMinDist = ptStart + vtDir * dProiez ; double dSqDist = SqDistXY( ptQ, ptMinDist) ; // se distanza nei limiti, taglio if ( dSqDist < dSqRad) GetMinMaxZ( i, j, dZCutBase, dDeltaZ, dSqDist, vtToolDir) ; } } 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) { double dr = sqrt( dSqDist) ; if ( m_dRadius < m_dTipRadius) { dMin = min( dZTip, dZStem + ( dr - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; dMax = max( dZTip, dZStem + ( dr - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; } else { dMin = min( dZBase, dZTip + ( dr - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; dMax = max( dZBase, dZTip + ( dr - 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) { double dr = sqrt( dSqDist) ; if ( m_dRadius < m_dTipRadius) { dMin = min( dZTip, dZStem + ( dr - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; dMax = max( dZTip, dZStem + ( dr - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; } else { dMin = min( dZBase, dZTip + ( dr - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; dMax = max( dZBase, dZTip + ( dr - 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) { double dr = sqrt( dSqDist) ; if ( m_dRadius < m_dTipRadius) { dMin = min( dZTip, dZStem + ( dr - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; dMax = max( dZTip, dZStem + ( dr - dMinRad) * ( dZTip - dZStem) / ( dMaxRad - dMinRad)) ; } else { dMin = min( dZBase, dZTip + ( dr - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; dMax = max( dZBase, dZTip + ( dr - dMinRad) * ( dZStem - dZTip) / ( dMaxRad - dMinRad)) ; } SubtractIntervals( i, j, dMin, dMax) ; } } } } 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) ; // Caso utensile generico al momento non gestito if ( m_nToolType == 0) return false ; // Caso Cylindrical Mill else if ( m_nToolType == 1) { double dMin, dMax ; 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) { double dMin, dMax ; double dH = sqrt( dSqRad - dSqDist) ; if ( abs( vtToolDir.z * dDeltaZ) < EPS_SMALL) { dMin = min( dZCutBase, dZtip + dFactor*( m_dRadius - dH)) ; dMax = max( dZCutBase, dZtip + dFactor*( m_dRadius - dH)) ; } else if ( vtToolDir.z * dDeltaZ < 0) { dMin = min( dZtip + dFactor*( m_dRadius - dH), dZtip + dFactor*( m_dRadius - dH) + dDeltaZ) ;// ocio dMax = max( dZtip + dFactor*( m_dRadius - dH), dZtip + dFactor*( m_dRadius - dH) + 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) { double dMin, dMax ; 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 ; double dSqrt = sqrt(dSqRadC - dSqd) ; double dMin, dMax ; if ( abs( vtToolDir.z * dDeltaZ) < EPS_SMALL) { dMin = min( dZCutBase, dZtip + dFactor*( m_dRCorner - dSqrt)) ; dMax = max( dZCutBase, dZtip + dFactor*( m_dRCorner - dSqrt)) ; } else if ( vtToolDir.z * dDeltaZ < 0) { dMin = min( dZtip + dFactor *( m_dRCorner - dSqrt), dZtip + dFactor *( m_dRCorner - dSqrt) + dDeltaZ) ; dMax = max( dZtip + dFactor *( m_dRCorner - dSqrt), dZtip + dFactor *( m_dRCorner - dSqrt) + 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 ; } //---------------------------------------------------------------------------- bool VolZmap::MillingZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == 1 || m_nToolType == 2) return CBMillingZ( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == 3) return false ; else if ( m_nToolType == 4) { if ( m_dRadius > m_dTipRadius) return ConusMillingZDr( ptLs, ptLe, vtToolDir) ; else return ConusMillingZSw( ptLs, ptLe, vtToolDir) ; } else return true ; // forse ci va il nuovo } //---------------------------------------------------------------------------- bool VolZmap::CBMillingZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& 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 ; } //---------------------------------------------------------------------------- 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 ; double dSin = ( abs( dCos) < 1 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTanAlpha * dTanAlpha) ; // Versori normali e prodotti scalari per per determinare i piani Vector3d vtNs = - ( dTanAlpha / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNd = - ( dTanAlpha / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * 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) { // Grandezze per determinare la configurazione geometrica dell'utensile 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 ; vtUC.Normalize() ; Vector3d vtUCf = vtCf ; 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 ; // Se dentro la zona interessata dalla lavorazione valuto // la tipologia di tale zona if ( ( dProj < 0 && dSqDistI < dMaxRad * dMaxRad) || ( dProj >= 0 && dProj < dLen && dSqDistM < dMaxRad * dMaxRad) || ( dProj >= dLen && dSqDistF < dMaxRad * dMaxRad)) { // Caso vettore utensile equiverso all'asse Z 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 ; } } } // Caso vettore utensile opposto all'asse Z 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 ; double dSin = ( abs( dCos) < 1 ? sqrt( 1- dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTanAlpha * dTanAlpha) ; // Versori normali e prodotti scalari per per determinare i piani Vector3d vtNp = - ( dTanAlpha / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNm = - ( dTanAlpha / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * 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)) { // Caso vettore utensile equiverso all'asse Z 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 ; } // Caso vettore utensile opposto all'asse Z 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 ; } //---------------------------------------------------------------------------- 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 // DeltaZ = 0 //---------------------------------------------------------------------------- bool VolZmap::DrillingXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill || m_nToolType == BallEndMill || m_nToolType == BullNoseMill) return CBTDrillXY( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == ConusMill) return ConusDrillingXY( ptLs, ptLe, vtToolDir) ; else return false ; } //---------------------------------------------------------------------------- bool VolZmap::CBTDrillXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == ConusMill) return ConusDrillingXY( ptLs, ptLe, 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::ConusDrillingXY( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; double dMin, dMax ; // Determinazione dell'interferenza dell'utensile con lo Zmap, bouding box e limiti su indici BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; // Parametri geometrici dell'utensile double dMinRad = min( m_dRadius, m_dTipRadius) ; double dMaxRad = max( m_dRadius, m_dTipRadius) ; double dCylH = m_dHeight - m_dTipHeight ; Vector3d vtMove = ptLe - ptLs ; double dLen = vtMove.LenXY() ; vtMove.Normalize() ; Point3d ptI = ( vtToolDir * vtMove < 0 ? ptLs : ptLe) ; double dZH = ptI.z ; Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep , dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptI ; double dPL = vtC * vtV1 ; double dPT = vtC * vtV2 ; if ( m_dRadius > m_dTipRadius) { if ( dPL < 0 && dPL > - dCylH - dLen && dPT > - dMaxRad && dPT < dMaxRad) { double dH = sqrt( dMaxRad * dMaxRad - dPT * dPT) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPL <= - dCylH - dLen && dPL > - m_dHeight - dLen && dPT > - dMaxRad + ( - dPL - dCylH - dLen) * ( dMaxRad - dMinRad) / m_dTipHeight && dPT < dMaxRad - ( - dPL - dCylH - dLen) * ( dMaxRad - dMinRad) / m_dTipHeight) { double dr = dMaxRad - ( - dPL - dCylH - dLen) * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - dPT * dPT) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } else { if ( dPL < 0 && dPL > - dCylH && dPT > - dMinRad && dPT < dMinRad) { double dH = sqrt( dMinRad * dMinRad - dPT * dPT) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPL <= - dCylH && dPL > - m_dHeight && dPT > - dMinRad - ( - dPL - dCylH) * ( dMaxRad - dMinRad) / m_dTipHeight && dPT < dMinRad + ( - dPL - dCylH) * ( dMaxRad - dMinRad) / m_dTipHeight) { double dr = dMinRad + ( - dPL - dCylH) * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - dPT * dPT) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPL <= - m_dHeight && dPL > - m_dHeight - dLen && dPT > - dMaxRad && dPT < dMaxRad) { double dH = sqrt( dMaxRad * dMaxRad - dPT * dPT) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingPerpXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill || m_nToolType == BallEndMill || m_nToolType == BullNoseMill) return CBTPerpXY( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == ConusMill) return ConusPerpXY( ptLs, ptLe, vtToolDir) ; else return false ; } //---------------------------------------------------------------------------- bool VolZmap::CBTPerpXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == ConusMill) return ConusPerpXY( ptLs, ptLe, 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::ConusPerpXY( const Point3d ptLs, const Point3d ptLe, const Vector3d vtToolDir) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; double dMin, dMax ; // Determinazione dell'interferenza dell'utensile con lo Zmap, bouding box e limiti su indici bool bControl = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( bControl == false) return true ; // Parametri geometrici dell'utensile double dCylH = m_dHeight - m_dTipHeight ; Vector3d vtMove = ptLe - ptLs ; double dLen = vtMove.LenXY() ; // Sistema di riferimento Vector3d vtV1 = - vtToolDir ; Vector3d vtV2 = vtMove ; vtV2.Normalize() ; Point3d ptIC = ptLs ; double dZ = ptLs.z ; // Ciclo sui punti for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { double dY = ( j + 0.5) * m_dStep ; double dX = ( i + 0.5) * m_dStep ; Point3d ptCC( dX, dY, 0) ; Vector3d vtCC = ptCC - ptIC ; double dPCL = vtCC * vtV1 ; double dPCT = vtCC * vtV2 ; // Parte cilindrica if( dPCL > 0 && dPCL < dCylH) { if ( dPCT > - m_dRadius && dPCT < 0) { double dH = sqrt( m_dRadius * m_dRadius - dPCT * dPCT) ; dMin = dZ - dH ; dMax = dZ + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPCT >= 0 && dPCT < dLen) { dMin = dZ - m_dRadius ; dMax = dZ + m_dRadius ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPCT >= dLen && dPCT < dLen + m_dRadius) { double dH = sqrt( m_dRadius * m_dRadius - ( dPCT - dLen) * ( dPCT - dLen)) ; dMin = dZ - dH ; dMax = dZ + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } // Parte non cilindrica else if ( dPCL >= dCylH && dPCL < m_dHeight) { double dPNCL = dPCL - dCylH ; double dPNCT = dPCT ; if ( dPNCT > - m_dRadius - dPNCL * ( m_dTipRadius - m_dRadius) / m_dTipHeight && dPNCT < 0) { double dr = m_dRadius + dPNCL * ( m_dTipRadius - m_dRadius) / m_dTipHeight ; double dH = sqrt( dr * dr - dPNCT * dPNCT) ; dMin = dZ - dH ; dMax = dZ + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPNCT >= 0 && dPNCT < dLen) { double dH = m_dRadius + dPNCL * ( m_dTipRadius - m_dRadius) / m_dTipHeight ; dMin = dZ - dH ; dMax = dZ + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dPNCT >= dLen && dPNCT < dLen + m_dRadius + dPNCL * ( m_dTipRadius - m_dRadius) / m_dTipHeight) { double dr = m_dRadius + dPNCL * ( m_dTipRadius - m_dRadius) / m_dTipHeight ; double dH = sqrt( dr * dr - ( dPNCT - dLen) * ( dPNCT - dLen)) ; dMin = dZ - dH ; dMax = dZ + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingXYPlaneGen( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill || m_nToolType == BallEndMill) return PlaneGenCylBall( ptLs, ptLe, vtToolDir) ; else return ConusPlaneGen( ptLs, ptLe, vtToolDir) ; } //---------------------------------------------------------------------------- bool VolZmap::PlaneGenCylBall( 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::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 ; } //---------------------------------------------------------------------------- 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::ConusPlaneGen( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( Control == false) return true ; double dMinRad = min( m_dRadius, m_dTipRadius) ; double dMaxRad = max( m_dRadius, m_dTipRadius) ; double dCylH = m_dHeight - m_dTipHeight ; double dZH = ptLs.z ; m_nToolType = CylindricalMill ; m_dHeight = dCylH ; MillingXYPlaneGen( ptLs, ptLe, vtToolDir) ; m_nToolType = ConusMill ; m_dHeight = m_dHeight + m_dTipHeight ; Point3d ptI, ptF ; Vector3d vtV1 ; if ( m_dTipRadius < m_dRadius) { vtV1 = vtToolDir ; ptI = ( vtV1 * ( ptLe - ptLs) > 0 ? ptLs - vtV1 * dCylH : ptLe - vtV1 * dCylH) ; ptF = ( vtV1 * ( ptLe - ptLs) > 0 ? ptLe - vtV1 * dCylH : ptLs - vtV1 * dCylH) ; } else { vtV1 = - vtToolDir ; ptI = ( vtToolDir * ( ptLe - ptLs) > 0 ? ptLe + vtV1 * m_dHeight : ptLs + vtV1 * m_dHeight) ; ptF = ( vtToolDir * ( ptLe - ptLs) > 0 ? ptLs + vtV1 * m_dHeight : ptLe + vtV1 * m_dHeight) ; } Point3d ptIxy( ptI.x, ptI.y, 0) ; Vector3d vtMove = ptF - ptI ; Vector3d vtLong = ( vtMove * vtV1) * vtV1 ; double dLen1 = vtLong.LenXY() ; Vector3d vtOrt = vtMove - vtLong ; double dLen2 = vtOrt.LenXY() ; Vector3d vtTemp = vtV1 ; vtTemp.Rotate( Z_AX, 90) ; vtMove.Normalize() ; Vector3d vtV2 = ( vtMove * vtTemp > 0 ? vtTemp : - vtTemp) ; Vector3d vtV3 = vtV1 ^ vtV2 ; double dTan = ( dMaxRad - dMinRad) / m_dTipHeight ; double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ; double dCos = dTan * dRatio ; double dSin = ( abs( dCos) < 1 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTan * dTan) ; double dDeltaR = dMaxRad - dMinRad ; double dMinLim = dMinRad * dCos ; double dMaxLim = dMaxRad * dCos ; // Versori normali e prodotti scalari per determinare i piani Vector3d vtNInf = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNSup = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * vtV3 ; Point3d ptV = ptI - vtV1 * ( dMaxRad * m_dTipHeight) / ( dMaxRad - dMinRad) ; Vector3d vtR0 = ptV - ORIG ; double dDotInf = vtR0 * vtNInf ; double dDotSup = vtR0 * vtNSup ; 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) ; Vector3d vtC = ptC - ptIxy ; double dProj1 = vtC * vtV1 ; double dProj2 = vtC * vtV2 ; if ( dRatio <= m_dTipHeight / dDeltaR) { if ( dProj1 > - m_dTipHeight && dProj1 < 0 && dProj2 > - dMaxRad - dTan * dProj1 && dProj2 < dMaxLim + dProj1 * ( dMaxLim - dMinLim) / m_dTipHeight) { double dr = dMaxRad + dTan * dProj1 ; double dH = sqrt( dr * dr - dProj2 * dProj2) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j , dMin, dMax) ; } else if ( dProj1 > dLen1 - m_dTipHeight && dProj1 < dLen1 && dProj2 > dLen2 - dMaxRad - dTan * dProj1 && dProj2 < dLen2 + dMaxLim + dProj1 * ( dMaxLim - dMinLim) / m_dTipHeight) { // Se due sistemi di riferimento hanno stessi versori di base e differiscono semplicemente per le origini, // le proiezioni di un vettore sugli assi nei due sistemi differiscono per le componenti del vettore che congiunge le origini. double dr = dMaxRad + dTan * ( dProj1 - dLen1) ; double dH = sqrt( dr * dr - ( dProj2 - dLen2) * ( dProj2 - dLen2)) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dProj1 >= 0 && dProj1 < dLen1 && dProj2 > - dMaxRad + dProj1 * dLen2 / dLen1 && dProj2 < dMaxLim + dProj1 * dLen2 / dLen1) { double dr = abs( dProj2 - dProj1 * dLen2 / dLen1) ; // Proj2 del punto meno Proj2 del centro del cerchio double dH = sqrt( dMaxRad * dMaxRad - dr * dr) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dProj1 > - m_dTipHeight && dProj1 < - m_dTipHeight + dLen1 && // Idem con patate dProj2 > dMinLim + dProj1 * ( dLen2 / dLen1) && dProj2 < dMinRad + dProj1 * ( dLen2 / dLen1)) { double dr = dProj2 - dProj1 * dLen2 / dLen1 ; double dH = sqrt( dMinRad * dMinRad - dr * dr) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j , dMin, dMax) ; } else { // L'unico dominio non normale lo detrerminiamo per sottrazione :) dMin = ( dDotInf - ptC.x * vtNInf.x - ptC.y * vtNInf.y) / vtNInf.z ; dMax = ( dDotSup - ptC.x * vtNSup.x - ptC.y * vtNSup.y) / vtNSup.z ; SubtractIntervals( i, j, dMin, dMax) ; } } else { if ( dProj1 > - m_dTipHeight && dProj1 <= 0 && dProj2 > - dMaxRad - dProj1 * ( dMaxRad - dMinRad) / m_dTipHeight && dProj2 < dMaxRad + dProj1 * ( dMaxRad - dMinRad) / m_dTipHeight) { double dr = dMaxRad + dProj1 * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - dProj2 * dProj2) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dProj1 > 0 && dProj1 < dLen1 && dProj2 > - dMaxRad + dProj1 * ( dLen2 / dLen1) && dProj2 < dMaxRad + dProj1 * ( dLen2 / dLen1)) { double dr = abs( dProj2 - dProj1 * ( dLen2 / dLen1)) ; double dH = sqrt( dMaxRad * dMaxRad - dr * dr) ; dMin = dZH - dH ; dMax = dZH + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } // DeltaZ != 0 //---------------------------------------------------------------------------- bool VolZmap::MillingXYVert( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; double dMin, dMax ; // Determinazione dell'interferenza dell'utensile con lo Zmap, bouding box e limiti su indici bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! Control) return true ; double dCylH = m_dHeight - m_dTipHeight ; double dZDown = min( ptLs.z, ptLe.z) ; double dZUp = max( ptLs.z, ptLe.z) ; // Definizione di un sistema di riferimento Vector3d vtV1 = - vtToolDir ; Vector3d vtV2 = vtV1 ; vtV2.Rotate(Z_AX, 90) ; Point3d ptIC = ptLs ; Point3d ptINC = ptLs + dCylH * vtV1 ; Point3d ptICxy( ptIC.x, ptIC.y, 0) ; Point3d ptINCxy( ptINC.x, ptINC.y, 0) ; for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep , dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtCC = ptC - ptICxy ; Vector3d vtNCC = ptC - ptINCxy ; double dCPL = vtCC * vtV1 ; double dCPT = vtCC * vtV2 ; double dNCPL = vtNCC * vtV1 ; double dNCPT = vtNCC * vtV2 ; // Parte cilindrica if ( dCPL > 0 && dCPL < dCylH && dCPT > - m_dRadius && dCPT < m_dRadius) { double dH = sqrt( m_dRadius * m_dRadius - dCPT * dCPT) ; dMin = dZDown - dH ; dMax = dZUp + dH ; SubtractIntervals( i, j, dMin, dMax) ; } // Parte non cilindrica if ( m_nToolType == BallEndMill) { double dSqLen = vtNCC.SqLenXY() ; if ( dNCPL >= 0 && dSqLen < m_dRadius * m_dRadius) { double dH = sqrt( m_dRadius * m_dRadius - dSqLen) ; dMin = dZDown - dH ; dMax = dZUp + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( m_nToolType == BullNoseMill) { if ( dNCPL >= 0 && dNCPL < m_dTipHeight) { double dR = m_dTipRadius + sqrt( m_dRCorner * m_dRCorner - dNCPL * dNCPL) ; if ( dNCPT > - dR && dNCPT < dR) { double dH = sqrt( dR * dR - dNCPT * dNCPT) ; dMin = dZDown - dH ; dMax = dZUp + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } else if ( m_nToolType == ConusMill) { if ( dNCPL >= 0 && dNCPL < m_dTipHeight && dNCPT > - m_dRadius - dNCPL * ( m_dTipRadius - m_dRadius) / m_dTipHeight && dNCPT < m_dRadius + dNCPL * ( m_dTipRadius - m_dRadius) / m_dTipHeight) { double dr = m_dRadius + dNCPL * ( m_dTipRadius - m_dRadius) / m_dTipHeight ; double dH = sqrt( dr * dr - dNCPT * dNCPT) ; dMin = dZDown - dH ; dMax = dZUp + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingXYLongVert( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill || m_nToolType == BallEndMill) return XYLongVertCylBall( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == ConusMill) return XYLongVertConus( ptLs, ptLe, vtToolDir) ; else // Casi al momento non gestiti return false ; } //---------------------------------------------------------------------------- bool VolZmap::XYLongVertCylBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { unsigned int nStartI, nEndI, nStartJ, nEndJ ; double dMin, dMax ; bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; // Se Control è falso non vi è interferenza fra utensile e Zmap if ( ! Control) return true ; double dDeltaZ = ptLe.z - ptLs.z; double dCylH = m_dHeight - m_dTipHeight ; Point3d ptI, ptF, ptBI, ptBF ; Vector3d vtV1, vtV2 ; Vector3d vtMove = ptLe - ptLs ; // Studio della parte sferica if ( ptLs.z < ptLe.z) { ptBI = ptLs - vtToolDir * dCylH ; ptBF = ptLe - vtToolDir * dCylH ; } else { ptBI = ptLe - vtToolDir * dCylH ; ptBF = ptLs - vtToolDir * dCylH ; } Point3d ptBIxy( ptBI.x, ptBI.y, 0) ; Vector3d vtBMove = ptBF - ptBI ; vtBMove.Normalize() ; Vector3d vtBV1 = ( vtToolDir * vtBMove > 0 ? vtToolDir : - vtToolDir) ; double dDeltaBZ = ptBF.z - ptBI.z ; double dOriz = vtBMove * Z_AX ; double dVert = vtBMove * vtBV1 ; double dSemiAxMin = m_dRadius * dOriz ; // Studio delle simmetrie della parte cilindrica if ( vtToolDir * vtMove < 0 && dDeltaZ < 0) { ptI = ptLe - vtToolDir * dCylH ; ptF = ptLs - vtToolDir * dCylH ; vtMove = - vtMove ; vtV1 = - vtToolDir ; dDeltaZ = - dDeltaZ ; } else if ( vtToolDir * vtMove > 0 && dDeltaZ > 0) { ptI = ptLs - vtToolDir * dCylH ; ptF = ptLe - vtToolDir * dCylH ; vtV1 = - vtToolDir ; } else if ( vtToolDir * vtMove > 0 && dDeltaZ < 0) { ptI = ptLe ; ptF = ptLs ; vtV1 = vtToolDir ; vtMove = - vtMove ; dDeltaZ = - dDeltaZ ; } else { ptI = ptLs ; ptF = ptLe ; vtV1 = vtToolDir ; } Point3d ptIxy( ptI.x, ptI.y, 0) ; double dZI = ptI.z ; vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; double dLen = abs( vtMove * vtV1) ; // Ciclo 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 - ptIxy ; double dProj1 = - vtC * vtV1 ; double dProj2 = vtC * vtV2 ; Vector3d vtBC = ptC - ptBIxy ; double dBpr1 = vtBC * vtBV1 ; double dBpr2 = vtBC * vtV2 ; // Parte cilindrica if ( dProj2 > - m_dRadius && dProj2 < m_dRadius && dProj1 > 0 && dProj1 < dLen + dCylH) { double dH = sqrt( m_dRadius * m_dRadius - dProj2 * dProj2) ; // Massimi if ( dProj1 > 0 && dProj1 < dLen) { double dZ0 = ptI.z + dProj1 * ( dDeltaZ / dLen) ; dMax = dZ0 + dH ; } else if ( dProj1 >= dLen && dProj1 < dLen + dCylH) dMax = ptI.z + dDeltaZ + dH ; // Minimi if ( dProj1 > 0 && dProj1 < dCylH) dMin = ptI.z - dH ; else if ( dProj1 >= dCylH && dProj1 < dLen + dCylH) { double dZ0 = ptI.z + ( dProj1 - dCylH) * ( dDeltaZ / dLen) ; dMin = dZ0 - dH ; } SubtractIntervals( i, j, dMin, dMax) ; } // Parte Non cilindrica if ( m_nToolType == BallEndMill) { double dSqDistO = dBpr2 * dBpr2 ; double dSqDistI = vtBC.SqLenXY() ; double dSqDistF = ( dBpr1 - dLen) * ( dBpr1 - dLen) + dBpr2 * dBpr2 ; if ( ( dBpr1 < 0 && dSqDistI < m_dRadius * m_dRadius) || ( dBpr1 >= 0 && dBpr1 < dLen && dSqDistO < m_dRadius * m_dRadius) || ( dBpr1 >= dLen && dSqDistF < m_dRadius * m_dRadius)) { // Massimi if ( dBpr1 < - dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius))) { double dH = sqrt( m_dRadius * m_dRadius - dSqDistI) ; dMax = ptBI.z + dH ; } else if ( dBpr1 >= - dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius)) && dBpr1 < dLen - dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius))) { double dZ0 = ptBI.z + dVert * sqrt( m_dRadius * m_dRadius - dSqDistO) ; dMax = dZ0 + dDeltaBZ * ( dBpr1 + dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius))) / dLen ; } else { double dH = sqrt( m_dRadius * m_dRadius - dSqDistF) ; dMax = ptBF.z + dH ; } // Minimi if ( dBpr1 < dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius))) { double dH = sqrt( m_dRadius * m_dRadius - dSqDistI) ; dMin = ptBI.z - dH ; } else if ( dBpr1 >= dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius)) && dBpr1 < dLen + dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius))) { double dZ0 = ptBI.z - dVert * sqrt( m_dRadius * m_dRadius - dSqDistO) ; dMin = dZ0 + dDeltaBZ * ( dBpr1 - dSemiAxMin * sqrt( 1 - dSqDistO / ( m_dRadius * m_dRadius))) / dLen ; } else { double dH = sqrt( m_dRadius * m_dRadius - dSqDistF) ; dMin = ptBF.z - dH ; } SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } /* //---------------------------------------------------------------------------- bool VolZmap::XYLongVertConus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { double dMin, dMax ; unsigned int nStartI, nEndI, nStartJ, nEndJ ; bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( Control == false) return true ; // Parte cilindrica m_nToolType = CylindricalMill ; double dSafeHeight = m_dHeight ; double dSafeTipHeight = m_dTipHeight ; double dCylH = m_dHeight - m_dTipHeight ; m_dHeight = dCylH ; m_dTipHeight = 0 ; XYLongVertCylBall( ptLs, ptLe, vtToolDir) ; m_nToolType = ConusMill ; m_dHeight = dSafeHeight ; m_dTipHeight = dSafeTipHeight ; // Parte conica Point3d ptI, ptF ; Vector3d vtV1 ; double dMinRad = min( m_dRadius, m_dTipRadius) ; double dMaxRad = max( m_dRadius, m_dTipRadius) ; double dDeltaR = dMaxRad - dMinRad ; double dStem ; if ( m_dRadius > m_dTipRadius) { vtV1 = vtToolDir ; dStem = - dCylH ; } else { vtV1 = - vtToolDir ; dStem = m_dHeight ; } if ( vtV1 * ( ptLe - ptLs) * ( ptLe.z - ptLs.z) > 0) { ptI = ( ptLe.z - ptLs.z < 0 ? ptLs + vtV1 * dStem : ptLe + vtV1 * dStem) ; ptF = ( ptLe.z - ptLs.z < 0 ? ptLe + vtV1 * dStem : ptLs + vtV1 * dStem) ; } else { ptI = ( ptLe.z - ptLs.z > 0 ? ptLs + vtV1 * dStem : ptLe + vtV1 * dStem) ; ptF = ( ptLe.z - ptLs.z > 0 ? ptLe + vtV1 * dStem : ptLs + vtV1 * dStem) ; } double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; Vector3d vtV2 = vtV1 ; vtV2.Rotate(Z_AX, 90) ; Vector3d vtV3 = vtV1 ^ vtV2 ; Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dPLen = vtMoveXY.LenXY() ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptV = ptI - vtV1 * ( ( dMaxRad * m_dTipHeight) / dDeltaR) ; // Apertura del cono e parametri per determinare i piani double dTan = ( dMaxRad - dMinRad) / m_dTipHeight ; double dRatio = ( vtMove * vtV1) / ( vtMove * vtV3) ; double dCos = dTan * dRatio ; double dSen = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; // Versori normali e prodotti scalari per per determinare i piani Vector3d vtNs = - ( dTan / sqrt( 1 + dTan * dTan)) * vtV1 + ( dCos / sqrt( 1 + dTan * dTan)) * vtV3 - ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTan * dTan)) * vtV2 ; Vector3d vtNd = - ( dTan / sqrt( 1 + dTan * dTan)) * vtV1 + ( dCos / sqrt( 1 + dTan * dTan)) * vtV3 + ( sqrt( 1 - dCos * dCos) / sqrt( 1 + dTan * dTan)) * vtV2 ; Vector3d vtR0 = ptV - ORIG ; double dDots = vtR0 * vtNs ; double dDotd = vtR0 * vtNd ; // Ciclo 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 - ptIxy ; double dProj1 = vtC * vtV1 ; double dProj2 = vtC * vtV2 ; double dOrtLen = abs( dProj2) ; if ( ( dProj1 > 0 && dProj1 < dPLen && dOrtLen < dMaxRad) || ( dProj1 >= dPLen && dProj1 < dPLen + m_dTipHeight && dOrtLen < dMaxRad + ( dProj1 - dPLen) * ( dDeltaR / m_dTipHeight))) { // DeltaZ < 0 if ( dDeltaZ < 0) { if ( dRatio <= 1 / dTan) { if ( dProj1 < m_dTipHeight && dOrtLen < dMaxRad * dSen - dProj1 * dDeltaR * dSen / m_dTipHeight) { // Il limite inferiore d dProj1 è già stato imposto dall' if più esterno double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dMax = dZI + dH ; } else if ( dProj1 > 0 && dProj1 < dPLen && dOrtLen > dMaxRad * dSen && dOrtLen < dMaxRad) { double dH = sqrt( dMaxRad * dMaxRad - dOrtLen * dOrtLen) ; dMax = dZI + dH + dProj1 * dDeltaZ / dPLen ; } else if ( dProj1 > m_dHeight && dProj1 < dPLen + m_dHeight && dOrtLen < dMinRad * dSen) { double dH = sqrt( dMinRad * dMinRad - dOrtLen * dOrtLen) ; dMax = dZI + dH + ( dProj1 - m_dTipHeight) * dDeltaZ / dPLen ; } else if ( dProj1 >= dPLen && dOrtLen > dMaxRad * dSen - ( dProj1 - dPLen) * dDeltaR * dSen / m_dTipHeight) { // I limiti superiori sono già stati imposti dall' if più esterno double dr = dMaxRad - ( dProj1 - dPLen) * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dMax = dZI + dDeltaZ + dH ; } else dMin = ( dOrtLen > 0 ? (dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z : (dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z) ; if ( dProj1 < dPLen) { // Limiti su dOrtLen già imposti dall' if esterno double dH = sqrt( dMaxRad * dMaxRad - dOrtLen* dOrtLen) ; dMin = dZI - dH + ( dProj1 - dPLen) * dDeltaZ / dPLen ; } else if ( dProj1 >= dPLen) { // Limiti su dOrtLen e su dProj1 già imposti dall' if esterno double dr = dMaxRad - ( dProj1 - dPLen) * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dMax = dZI + dDeltaZ - dH ; } SubtractIntervals( i, j, dMax, dMin) ; } else { // dRatio > } } else { // dDeltaZ > 0 if () { // dRatio < } else { // dRatio > } } } } return true ; } */ //---------------------------------------------------------------------------- bool VolZmap::XYLongVertConus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { double dZL1, dZL2 ; unsigned int nStartI, nEndI, nStartJ, nEndJ ; bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! Control) return true ; // Parte cilindrica m_nToolType = CylindricalMill ; double dSafeHeight = m_dHeight ; double dSafeTipHeight = m_dTipHeight ; double dCylH = m_dHeight - m_dTipHeight ; m_dHeight = dCylH ; m_dTipHeight = 0 ; XYLongVertCylBall( ptLs, ptLe, vtToolDir) ; m_nToolType = ConusMill ; m_dHeight = dSafeHeight ; m_dTipHeight = dSafeTipHeight ; // Parte conica Point3d ptI, ptF ; Vector3d vtV1 ; double dMinRad = min( m_dRadius, m_dTipRadius) ; double dMaxRad = max( m_dRadius, m_dTipRadius) ; double dDeltaR = dMaxRad - dMinRad ; double dStem ; if ( m_dRadius > m_dTipRadius) { vtV1 = vtToolDir ; dStem = - dCylH ; } else { vtV1 = - vtToolDir ; dStem = m_dHeight ; } if ( vtV1 * ( ptLe - ptLs) * ( ptLe.z - ptLs.z) > 0) { ptI = ( ptLe.z - ptLs.z < 0 ? ptLs + vtV1 * dStem : ptLe + vtV1 * dStem) ; ptF = ( ptLe.z - ptLs.z < 0 ? ptLe + vtV1 * dStem : ptLs + vtV1 * dStem) ; } else { ptI = ( ptLe.z - ptLs.z > 0 ? ptLs + vtV1 * dStem : ptLe + vtV1 * dStem) ; ptF = ( ptLe.z - ptLs.z > 0 ? ptLe + vtV1 * dStem : ptLs + vtV1 * dStem) ; } double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; double dFactor = ( dDeltaZ > 0 ? - 1 : 1) ; Vector3d vtV2 = vtV1 ; vtV2.Rotate(Z_AX, 90) ; Vector3d vtV3 = vtV1 ^ vtV2 ; Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dPLen = vtMoveXY.LenXY() ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptV = ptI - vtV1 * ( ( dMaxRad * m_dTipHeight) / dDeltaR) ; // Apertura del cono e parametri per determinare i piani double dTan = ( dMaxRad - dMinRad) / m_dTipHeight ; double dRatio = ( dDeltaZ > 0 ? - ( vtMove * vtV1) / ( vtMove * vtV3) : ( vtMove * vtV1) / ( vtMove * vtV3)) ; double dCos = dTan * dRatio ; double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTan * dTan) ; // Versori normali e prodotti scalari per per determinare i piani Vector3d vtNs = - ( dTan / dDen) * vtV1 + dFactor * ( dCos / dDen) * vtV3 - dFactor * ( dSin / dDen) * vtV2 ; Vector3d vtNd = - ( dTan /dDen) * vtV1 + dFactor * ( dCos / dDen) * vtV3 + dFactor * ( dSin / dDen) * vtV2 ; Vector3d vtR0 = ptV - ORIG ; double dDots = vtR0 * vtNs ; double dDotd = vtR0 * vtNd ; // Ciclo 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 - ptIxy ; double dProj1 = - vtC * vtV1 ; double dProj2 = vtC * vtV2 ; double dOrtLen = abs( dProj2) ; if ( ( dProj1 > 0 && dProj1 < dPLen && dOrtLen < dMaxRad) || ( dProj1 >= dPLen && dProj1 < dPLen + m_dTipHeight && dOrtLen < dMaxRad + ( dProj1 - dPLen) * ( dDeltaR / m_dTipHeight))) { if ( dRatio <= 1 / dTan) { if ( dProj1 < m_dTipHeight && dOrtLen < dMaxRad * dSin - dProj1 * dDeltaR * dSin / m_dTipHeight) { // Il limite inferiore d dProj1 è già stato imposto dall' if più esterno double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dZL1 = dZI + dFactor * dH ; } else if ( dProj1 > 0 && dProj1 < dPLen && dOrtLen > dMaxRad * dSin && dOrtLen < dMaxRad) { double dH = sqrt( dMaxRad * dMaxRad - dOrtLen * dOrtLen) ; dZL1 = dZI + dFactor * dH + dProj1 * dDeltaZ / dPLen ; } else if ( dProj1 > m_dTipHeight && dProj1 < dPLen + m_dHeight && dOrtLen < dMinRad * dSin) { double dH = sqrt( dMinRad * dMinRad - dOrtLen * dOrtLen) ; dZL1 = dZI + dFactor * dH + ( dProj1 - m_dTipHeight) * dDeltaZ / dPLen ; } else if ( dProj1 >= dPLen && dOrtLen > dMaxRad * dSin - ( dProj1 - dPLen) * dDeltaR * dSin / m_dTipHeight) { // I limiti superiori sono già stati imposti dall' if più esterno double dr = dMaxRad - ( dProj1 - dPLen) * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dZL1 = dZI + dDeltaZ + dFactor * dH ; } else { if ( dDeltaZ < 0) dZL1 = ( dProj2 > 0 ? (dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z : (dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z) ; else dZL1 = ( dProj2 > 0 ? (dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z : (dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z) ; } if ( dProj1 < dPLen) { // Limiti su dOrtLen già imposti dall' if esterno double dH = sqrt( dMaxRad * dMaxRad - dOrtLen* dOrtLen) ; dZL2 = dZI - dFactor * dH + dProj1 * dDeltaZ / dPLen ; } else if ( dProj1 >= dPLen) { // Limiti su dOrtLen e su dProj1 già imposti dall' if esterno double dr = dMaxRad - ( dProj1 - dPLen) * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dZL2 = dZI + dDeltaZ - dFactor * dH ; } SubtractIntervals( i, j, dZL1, dZL2) ; } else { if ( dProj1 < dPLen && dOrtLen < dMaxRad) { double dH = sqrt( dMaxRad * dMaxRad - dOrtLen * dOrtLen) ; dZL1 = dZI + dH + dProj1 * dDeltaZ / dPLen ; dZL2 = dZI - dH + dProj1 * dDeltaZ / dPLen ; } else if ( dProj1 >= dPLen) { double dr = dMaxRad - ( dProj1 - dPLen) * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dOrtLen * dOrtLen) ; dZL1 = dZI + dDeltaZ + dH ; dZL2 = dZI + dDeltaZ - dH ; } SubtractIntervals( i, j, dZL1, dZL2) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingXY( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill) return MillingXYCyl( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == BallEndMill) return MillingXYBall( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == ConusMill) return MillingXYConus( ptLs, ptLe, vtToolDir) ; else return false ; } //---------------------------------------------------------------------------- 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) ; Vector3d vtTemp = vtV1 ; vtTemp.Rotate( Z_AX, 90) ; Vector3d vtW2 = ( vtTemp * vtV2 > 0 ? vtTemp : - vtTemp) ; // 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 * vtW2 ; // 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) ; } } } 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) ; Vector3d vtTemp = vtToolDir ; vtTemp.Rotate( Z_AX, 90) ; Vector3d vtW2 = ( vtTemp * vtV2 > 0 ? vtTemp : - vtTemp) ; // 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 * vtW2 ; // 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 ( dProj1 <= - dCylH && ( ( dProj2 > - m_dRadius && dProj2 < 0 && dProj2 * dProj2 + (- dProj1 - dCylH) * (- dProj1 - dCylH) < m_dRadius * m_dRadius) || ( dProj2 >= 0 && dProj2 < dPlanePath && dProj1 > - m_dHeight) || ( 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) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingXYConus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! Control) return true ; double dCylH = m_dHeight - m_dTipHeight ; // Parte cilindrica m_nToolType = CylindricalMill ; m_dHeight = dCylH ; MillingXY( ptLs, ptLe, vtToolDir) ; m_nToolType = ConusMill ; m_dHeight = m_dHeight + m_dTipHeight ; Vector3d vtV1, vtV2, vtV3 ; Point3d ptI, ptF ; double dStem ; double dMinRad = min( m_dRadius, m_dTipRadius) ; double dMaxRad = max( m_dRadius, m_dTipRadius) ; double dDeltaR = dMaxRad - dMinRad ; // Studio della parte conica if ( m_dRadius > m_dTipRadius) { vtV1 = vtToolDir ; dStem = - dCylH ; } else { vtV1 = - vtToolDir ; dStem = m_dHeight ; } ptI = ( ptLs.z < ptLe.z ? ptLs + vtV1 * dStem : ptLe + vtV1 * dStem) ; ptF = ( ptLs.z < ptLe.z ? ptLe + vtV1 * dStem : ptLs + vtV1 * dStem) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dPLen = vtMoveXY.LenXY() ; Vector3d vtU2 = vtV1 ; vtU2.Rotate(Z_AX, 90) ; if ( vtMoveXY * vtU2 < 0) vtU2 = - vtU2 ; vtV2 = vtMove ; vtV2.Normalize() ; vtV3 = vtV1 ^ vtV2 ; Point3d ptV = ptI - vtV1 * ( dMaxRad * m_dTipHeight / ( dMaxRad - dMinRad)) ; Vector3d vtV3XY( vtV3.x, vtV3.y, 0) ; double dPrV3 = vtV3XY.LenXY() ; double dRl = dMaxRad * dPrV3 ; double drl = dMinRad * dPrV3 ; double dDl = dDeltaR * dPrV3 ; // 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 ; double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTanAlpha * dTanAlpha) ; // Versori normali e prodotti scalari per per determinare i piani Vector3d vtNs = - ( dTanAlpha / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNd = - ( dTanAlpha / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * vtV3 ; Vector3d vtR0 = ptV - ORIG ; double dDots = vtR0 * vtNs ; double dDotd = vtR0 * vtNd ; 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 - ptIxy ; double dProj1 = - vtC * vtV1 ; double dProj2 = vtC * vtU2 ; if ( dProj1 > 0 && dProj1 < m_dTipHeight && dProj2 > - dMaxRad + dProj1 * dDeltaR / m_dTipHeight && dProj2 < dPLen + dMaxRad - dProj1 * dDeltaR / m_dTipHeight) { /* if ( dProj2 < - dRl + dProj1 * dDl / m_dTipHeight) { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dProj2 * dProj2) ; dMin = dZI - dH ; dMax = dZI + dH ; } else if ( dProj2 >= - dRl + dProj1 * dDl / m_dTipHeight && dProj2 < dRl - dProj1 * dDl / m_dTipHeight) { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dProj2 * dProj2) ; dMin = dZI - dH ; dMax = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ; } else if ( dProj2 >= dRl - dProj1 * dDl / m_dTipHeight && dProj2 < dPLen - dRl + dProj1 * dDl / m_dTipHeight) { dMin = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; dMax = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ; } else if ( dProj2 >= dPLen - dRl + dProj1 * dDl / m_dTipHeight && dProj2 < dPLen + dRl - dProj1 * dDl / m_dTipHeight) { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - ( dProj2 - dPLen) * ( dProj2 - dPLen)) ; dMin = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; dMax = dZI + dDeltaZ + dH ; } else { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - ( dProj2 - dPLen) * ( dProj2 - dPLen)) ; dMin = dZI + dDeltaZ - dH ; dMax = dZI + dDeltaZ + dH ; } */ // Massimi if ( dProj2 < - dRl + dProj1 * dDl / m_dTipHeight) { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dProj2 * dProj2) ; dMax = dZI + dH ; } else if ( dProj2 >= - dRl + dProj1 * dDl / m_dTipHeight && dProj2 < dPLen - dRl + dProj1 * dDl / m_dTipHeight) dMax = ( vtV3.z < 0 ? ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z : ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z) ; else { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - ( dProj2 - dPLen) * ( dProj2 - dPLen)) ; dMax = dZI + dDeltaZ + dH ; } // Minimi if ( dProj2 < dRl - dProj1 * dDl / m_dTipHeight) { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - dProj2 * dProj2) ; dMin = dZI - dH ; } else if ( dProj2 >= dRl - dProj1 * dDl / m_dTipHeight && dProj2 < dPLen + dRl - dProj1 * dDl / m_dTipHeight) dMin = ( vtV3.z < 0 ? ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z : ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z) ; else { double dr = dMaxRad - dProj1 * dDeltaR / m_dTipHeight ; double dH = sqrt( dr * dr - ( dProj2 - dPLen) * ( dProj2 - dPLen)) ; dMin = dZI + dDeltaZ - dH ; } SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingXYPlus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill) return MillingXYPlusCyl( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == BallEndMill) return MillingXYPlusBall( ptLs, ptLe, vtToolDir) ; else if ( m_nToolType == ConusMill) return MillingXYPlusConus( ptLs, ptLe, vtToolDir) ; else return false ; } //---------------------------------------------------------------------------- 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) ; } } } 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) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillingXYPlusConus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { double dMin, dMax ; bool Control = BoundingBox( ptLs, ptLe, vtToolDir, vtToolDir) ; if ( Control == false) return true ; double dMinRad = min( m_dRadius, m_dTipRadius) ; double dMaxRad = max( m_dRadius, m_dTipRadius) ; double dDeltaR = dMaxRad - dMinRad ; double dCylH = m_dHeight - m_dTipHeight ; // Parte cilindrica m_nToolType = CylindricalMill ; m_dHeight = dCylH ; MillingXYPlusCyl( ptLs, ptLe, vtToolDir) ; m_nToolType = ConusMill ; m_dHeight = m_dHeight + m_dTipHeight ; // Variabili di interesse per la parte conica Vector3d vtV1, vtV2, vtV3 ; Point3d ptI, ptF ; double dStem ; // Studio della parte conica if ( m_dRadius > m_dTipRadius) { vtV1 = vtToolDir ; dStem = - dCylH ; } else { vtV1 = - vtToolDir ; dStem = m_dHeight ; } ptI = ( ptLs.z < ptLe.z ? ptLs + vtV1 * dStem : ptLe + vtV1 * dStem) ; ptF = ( ptLs.z < ptLe.z ? ptLe + vtV1 * dStem : ptLs + vtV1 * dStem) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Vector3d vtMove = ptF - ptI ; Vector3d vtMoveLong = ( vtMove * vtV1) * vtV1 ; Vector3d vtMoveOrt = vtMove - vtMoveLong ; Vector3d vtMoveLongXY( vtMoveLong.x, vtMoveLong.y, 0) ; Vector3d vtMoveOrtXY( vtMoveOrt.x, vtMoveOrt.y, 0) ; double dPLen1 = vtMoveLongXY.LenXY() ; double dPLen2 = vtMoveOrtXY.LenXY() ; double dPLen = sqrt( dPLen1 * dPLen1 + dPLen2 * dPLen2) ; vtV2 = ( vtMove * vtV1 > 0 ? vtMoveOrt : - vtMoveOrt) ; vtV2.Normalize() ; vtV3 = vtV1 ^ vtV2 ; Vector3d vtU2 = vtMoveOrtXY ; vtU2.Normalize() ; Point3d ptV = ptI - vtV1 * ( ( dMaxRad * m_dTipHeight) / ( dDeltaR)) ; // Apertura del cono e parametri per determinare i piani double dTan = ( dMaxRad - dMinRad) / m_dTipHeight ; double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ; double dCos = dTan * dRatio ; // dCos è compreso fra 0 e 1 poiché alpha è compreso fra 0 e Pi mezzi double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTan * dTan) ; double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; // double dCornerSlope = atan2( dDeltaZ, dPLen1) ; // dCornerSlope è compreso fra 0 ° e 90 °, per come è costruito il movimento, ma espresso in radianti // Punti di tagenza piano cono Point3d ptPrs = ptI - vtV1 * m_dTipHeight + dMinRad * ( dCos * vtV2 + sqrt( 1 - dCos * dCos) * vtV3) ; Point3d ptPRs = ptI + dMaxRad * ( dCos * vtV2 + sqrt( 1 - dCos * dCos) * vtV3) ; Point3d ptPrd = ptI - vtV1 * m_dTipHeight + dMinRad * ( dCos * vtV2 - sqrt( 1 - dCos * dCos) * vtV3) ; Point3d ptPRd = ptI + dMaxRad * ( dCos * vtV2 - sqrt( 1 - dCos * dCos) * vtV3) ; Point3d ptRInf = ( ptPRs.z < ptPRd.z ? ptPRs : ptPRd) ; Point3d ptRSup = ( ptPRs.z < ptPRd.z ? ptPRd : ptPRs) ; Point3d ptrInf = ( ptPrs.z < ptPrd.z ? ptPrs : ptPrd) ; Point3d ptrSup = ( ptPrs.z < ptPrd.z ? ptPrd : ptPrs) ; // Versori normali e prodotti scalari per per determinare i piani Vector3d vtNs = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNd = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * vtV3 ; Vector3d vtR0 = ptV - ORIG ; double dDots = vtR0 * vtNs ; double dDotd = vtR0 * vtNd ; // Sistema di riferimento del movimento Vector3d vtU3 = vtV1 ^ vtU2 ; Frame3d MoveFrame ; MoveFrame.Set( ptI, vtV1, vtU2, vtU3) ; ptRInf.LocToLoc( m_LocalFrame, MoveFrame) ; double dPRInf = ptRInf.y ; ptRSup.LocToLoc( m_LocalFrame, MoveFrame) ; double dPRSup = ptRSup.y ; ptrInf.LocToLoc( m_LocalFrame, MoveFrame) ; double dPrInf = ptrInf.y ; ptrSup.LocToLoc( m_LocalFrame, MoveFrame) ; double dPrSup = ptrSup.y ; // dMinX dMaxX dMinY dMaxY double dMinX = min( min( ptI.x, ptF.x), min( ptI.x - vtV1.x * m_dTipHeight, ptF.x - vtV1.x * m_dTipHeight)) - dMaxRad; double dMinY = min( min( ptI.y, ptF.y), min( ptI.y - vtV1.y * m_dTipHeight, ptF.y - vtV1.y * m_dTipHeight)) - dMaxRad; double dMaxX = max( max( ptI.x, ptF.x), max( ptI.x - vtV1.x * m_dTipHeight, ptF.x - vtV1.x * m_dTipHeight)) + dMaxRad; double dMaxY = max( max( ptI.y, ptF.y), max( ptI.y - vtV1.y * m_dTipHeight, ptF.y - vtV1.y * m_dTipHeight)) + dMaxRad; // 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 ; // 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 dX, dY ; dX = ( i + 0.5) * m_dStep ; dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptIxy ; double dI1 = vtC * vtV1 ; double dI2 = vtC * vtU2 ; if ( dRatio <= 1 / dTan) { if ( vtMove * vtV1 > 0) { double dLimInf = max( - dMaxRad - dI1 * ( dMaxRad - dMinRad) / m_dTipHeight, - dMaxRad + dI1 * ( dPLen2 / dPLen1)) ; double dLimSup = min( dMinRad + ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1), dPLen2 + dMinRad + ( dI1 - dPLen1 + m_dTipHeight) * ( dMaxRad - dMinRad) / m_dTipHeight) ; if ( dI1 > - m_dTipHeight && dI1 < dPLen1 && dI2 > dLimInf && dI2 < dLimSup) { // Massimi if ( dI1 > 0 && dI2 < dPRSup + dI1 * ( dPLen2 / dPLen1)) { double dr = dI1 * ( dPLen2 / dPLen1) - dI2 ; // Non serve prenderne il valore assoluto poiché viene elevato a quadrato double dl = dI1 * sqrt( 1 + (dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; double dH = ( dMaxRad * dMaxRad - dr * dr > 0 ? sqrt( dMaxRad * dMaxRad - dr * dr) : 0) ; dMax = dZI + dl * ( dDeltaZ / dPLen) + dH ; } else if ( dI1 < dPLen1 - m_dTipHeight && dI2 > dPrSup + ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1)) { double dr = dI2 - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1) ; // Non serve prenderne il valore assoluto poiché viene elevato a quadrato double dl = ( dI1 + m_dTipHeight) * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; double dH = ( dMinRad * dMinRad - dr * dr > 0 ? sqrt( dMinRad * dMinRad - dr * dr) : 0) ; // Controllare da qui dMax = dZI + dl * ( dDeltaZ / dPLen) + dH ; } else if ( dI1 <= 0 && dI2 < dPRSup + dI1 * ( dPRSup - dPrSup) / m_dTipHeight) { double dr = dMaxRad + dI1 * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - dI2 * dI2) ; dMax = dZI + dH ; } else if ( dI1 >= dPLen1 - m_dTipHeight && dI2 > dPLen2 + dPRSup + ( dI1 - dPLen1) * ( dPRSup - dPrSup) / m_dTipHeight) { double dr = dMaxRad + ( dI1 - dPLen1) * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - ( dI2 - dPLen2) * ( dI2 - dPLen2)) ; dMax = dZI + dDeltaZ + dH ; } else dMax = max( ( dDotd - vtNd.x * dX - vtNd.y * dY) / vtNd.z, ( dDots - vtNs.x * dX - vtNs.y * dY) / vtNs.z) ; // Minimi if ( dI1 > 0 && dI2 < dPRInf + dI1 * ( dPLen2 / dPLen1)) { double dr = dI1 * ( dPLen2 / dPLen1) - dI2 ; // Non serve prenderne il valore assoluto poiché viene elevato a quadrato double dl = dI1 * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; double dH = ( dMaxRad * dMaxRad - dr * dr > 0 ? sqrt( dMaxRad * dMaxRad - dr * dr) : 0) ; dMin = dZI + dl * ( dDeltaZ / dPLen) - dH ; } else if ( dI1 < dPLen1 - m_dTipHeight && dI2 > dPrInf + ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1)) { double dr = dI2 - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1) ; // Non serve prenderne il valore assoluto poiché viene elevato a quadrato double dl = ( dI1 + m_dTipHeight) * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; double dH = ( dMinRad * dMinRad - dr * dr > 0 ? sqrt( dMinRad * dMinRad - dr * dr) : 0) ; dMin = dZI + dl * ( dDeltaZ / dPLen) - dH ; } else if ( dI1 <= 0 && dI2 < dPRInf + dI1 * ( dPRInf - dPrInf) / m_dTipHeight) { double dr = dMaxRad + dI1 * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - dI2 * dI2) ; dMin = dZI - dH ; } else if ( dI1 >= dPLen1 - m_dTipHeight && dI2 > dPLen2 + dPRInf + ( dI1 - dPLen1) * ( dPRInf - dPrInf) / m_dTipHeight) { double dr = dMaxRad + ( dI1 - dPLen1) * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - ( dI2 - dPLen2) * ( dI2 - dPLen2)) ; dMin = dZI + dDeltaZ - dH ; } else dMin = min( ( dDotd - vtNd.x * dX - vtNd.y * dY) / vtNd.z, ( dDots - vtNs.x * dX - vtNs.y * dY) / vtNs.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // vtMove * vtV1 < 0 else { double dLimInf = max( - dMaxRad - dI1 * ( dMaxRad - dMinRad) / m_dTipHeight, - dMinRad - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1)) ; double dLimSup = min( dMaxRad - dI1 * ( dPLen2 / dPLen1), dPLen2 + dMaxRad + ( dI1 + dPLen1) * ( dMaxRad - dMinRad) / m_dTipHeight) ; if ( dI1 > - dPLen1 - m_dTipHeight && dI1 < 0 && dI2 > dLimInf && dI2 < dLimSup) { // Massimi if ( dI1 > - m_dTipHeight && dI2 < dPRSup + dI1 * ( dPRSup - dPrSup) / m_dTipHeight) { double dr = dMaxRad + dI1 * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = ( dr * dr - dI2 * dI2 > 0 ? sqrt( dr * dr - dI2 * dI2) : 0) ; dMax = dZI + dH ; } else if ( dI1 < - dPLen1 && dI2 > dPLen2 + dPRSup + (dI1 + dPLen1) * ( dPRSup - dPrSup) / m_dTipHeight) { double dr = dMaxRad + ( dI1 + dPLen1) * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = ( dr * dr - ( dI2 - dPLen2) * ( dI2 - dPLen2) > 0 ? sqrt( dr * dr - ( dI2 - dPLen2) * ( dI2 - dPLen2)) : 0) ; dMax = dZI + dDeltaZ + dH ; } else if ( dI1 < - m_dTipHeight && dI2 < dPrSup - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1)) { double dr = - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1) - dI2 ; double dH = ( dMinRad * dMinRad - dr * dr > 0 ? sqrt( dMinRad * dMinRad - dr * dr) : 0) ; double dl = - ( dI1 + m_dTipHeight) * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; dMax = dZI + dl * ( dDeltaZ / dPLen) + dH ; } else if ( dI1 > - dPLen1 && dI2 > dPRSup - dI1 * ( dPLen2 / dPLen1)) { double dr = dI2 + dI1 * ( dPLen2 / dPLen1) ; double dH = ( dMaxRad * dMaxRad - dr * dr > 0 ? sqrt( dMaxRad * dMaxRad - dr * dr) : 0) ; double dl = - dI1 * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; dMax = dZI + dl * ( dDeltaZ / dPLen) + dH ; } else dMax = max( ( dDots - vtNs.x * dX - vtNs.y * dY) / vtNs.z, ( dDotd - vtNd.x * dX - vtNd.y * dY) / vtNd.z ) ; // Minimi if ( dI1 > - m_dTipHeight && dI2 < dPRInf + dI1 * ( dPRInf - dPrInf) / m_dTipHeight) { double dr = dMaxRad + dI1 * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = ( dr * dr - dI2 * dI2 > 0 ? sqrt( dr * dr - dI2 * dI2) : 0) ; dMin =dZI - dH ; } else if ( dI1 < - dPLen1 && dI2 > dPLen2 + dPRInf + ( dI1 + dPLen1) * ( dPRInf - dPrInf) / m_dTipHeight) { double dr = dMaxRad + ( dI1 + dPLen1) * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = ( dr * dr - ( dI2 - dPLen2) * ( dI2 - dPLen2) > 0 ? sqrt( dr * dr - ( dI2 - dPLen2) * ( dI2 - dPLen2)) : 0) ; dMin = dZI + dDeltaZ - dH ; } else if ( dI1 < - m_dTipHeight && dI2 < dPrInf - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1)) { double dr = - ( dI1 + m_dTipHeight) * ( dPLen2 / dPLen1) - dI2 ; double dH = ( dMinRad * dMinRad - dr * dr > 0 ? sqrt( dMinRad * dMinRad - dr * dr) : 0) ; double dl = - ( dI1 + m_dTipHeight) * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; dMin = dZI + dl * ( dDeltaZ / dPLen) - dH ; } else if ( dI1 > - dPLen1 && dI2 > dPRInf - dI1 * ( dPLen2 / dPLen1)) { double dr = dI2 + dI1 * ( dPLen2 / dPLen1) ; double dH = ( dMaxRad * dMaxRad - dr * dr > 0 ? sqrt( dMaxRad * dMaxRad - dr * dr) : 0) ; double dl = - dI1 * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; dMin = dZI + dl * ( dDeltaZ / dPLen) - dH ; } else dMin = min( ( dDotd - vtNd.x * dX - vtNd.y * dY) / vtNd.z, ( dDots - vtNs.x * dX - vtNs.y * dY) / vtNs.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } } // dRatio <= 1 / dTan else { if ( dI1 > - m_dTipHeight && dI1 < 0 && dI2 > - dMaxRad - dI1 * ( dMaxRad - dMinRad) / m_dTipHeight && dI2 < dMaxRad + dI1 * ( dMaxRad - dMinRad) / m_dTipHeight) { double dr = dMaxRad + dI1 * ( dMaxRad - dMinRad) / m_dTipHeight ; double dH = sqrt( dr * dr - dI2 * dI2) ; dMin = dZI - dH ; dMax = dZI + dH ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( dI1 >= 0 && dI1 < dPLen1 && dI2 > - dMaxRad + dI1 * ( dPLen2 / dPLen1) && dI2 < dMaxRad + dI1 * ( dPLen2 / dPLen1)) { double dl = dI1 * sqrt( 1 + ( dPLen2 * dPLen2) / ( dPLen1 * dPLen1)) ; double dr = dI2 - dI1 * dPLen2 / dPLen1 ; double dH = sqrt( dMaxRad * dMaxRad - dr * dr) ; dMin = dZI + dl * ( dDeltaZ / dPLen) - dH ; dMax = dZI + dl * ( dDeltaZ / dPLen) + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } // Virtual milling per componenti // Versore utensile nella direzione dell'asse Z // Foratura //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- bool VolZmap::DrillZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Posizioni iniziale e finale dell'utensile Point3d ptI = ptLs ; Point3d ptF = ptLe ; // vettore movimento Vector3d vtMove = ptLe - ptLs ; CurveComposite ToolProfile ; // Settaggio profilo if ( m_ToolArcLineApprox.GetCurveCount() == 0) // Se l'utensile non è stato approssimato uso l'originale ToolProfile.CopyFrom( & m_ToolOutline) ; else // altrimenti usi l'approssimazione ToolProfile.CopyFrom( & m_ToolArcLineApprox) ; // Dichiaro un puntatore a curva da usare nel ciclo const ICurve* pCurve ; pCurve = ToolProfile.GetFirstCurve() ; // Ciclo sulle curve while ( pCurve != nullptr) { double dHeight ; int nCurveType = pCurve -> GetType() ; // Caso segmento if ( nCurveType == CRV_LINE) { Point3d ptStart, ptEnd ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) { dHeight = abs( ptStart.y - ptEnd.y) ; // Il componente è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; LongCylV( ptI, ptF, vtToolDir, dHeight, dRadius) ; } // Il componente è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; LongConusV( ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ; } // Il componente è un cono con vettore opposto a quello dell'utesile else if ( ptStart.x < ptEnd.x) { double dMaxRad = ptEnd.x ; double dMinRad = ptStart.x ; Point3d ptIn = ptI - vtToolDir * dHeight ; Point3d ptFn = ptIn + vtMove ; LongConusV( ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ; } } else dHeight = 0 ; } // Caso arco else if ( nCurveType == CRV_ARC) { // Centro e Punti iniziale e finale del cerchio Point3d ptStart, ptEnd, ptO ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; pCurve -> GetCenterPoint( ptO) ; // Determino il raggio Vector3d vtStRad = ptStart - ptO ; Vector3d vtEnRad = ptEnd - ptO ; double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ; // Determino le posizioni iniziale e finale del centrodella sfera Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ; Point3d ptOEn = ptOSt + vtMove ; // Eseguo l'asportazione del materiale Ball( ptOSt, ptOEn, dRadius) ; // aggiorno l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dHeight ; ptF = ptI + vtMove ; // Aggiorno il puntatore pCurve = ToolProfile.GetNextCurve() ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::LongCylV( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dRad) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( Control == false) return true ; Point3d ptI = ( ( ptLe - ptLs) * vtToolDir > 0 ? ptLe : ptLs) ; Point3d ptF = ( ( ptLe - ptLs) * vtToolDir > 0 ? ptLs - dHei * vtToolDir : ptLe - dHei * vtToolDir) ; if ( ptI.z > ptF.z) { Point3d ptTemp = ptI ; ptI = ptF ; ptF = ptTemp ; } Point3d ptO( ptI.x, ptI.y, 0) ; double dZI = ptI.z ; double dZF = ptF.z ; 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 < dRad * dRad) SubtractIntervals( i, j, dZI, dZF) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::LongConusV( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( Control == false) return true ; Point3d ptO( ptLs.x, ptLs.y, 0) ; double dZMin, dZMax ; double dAngC = dHei / ( dMaxRad - dMinRad) ; if ( vtToolDir.z > 0) { dZMin = ( ptLs.z < ptLe.z ? ptLs.z - dHei : ptLe.z - dHei) ; dZMax = ( ptLs.z < ptLe.z ? ptLe.z : ptLs.z) ; } else { dZMin = ( ptLs.z < ptLe.z ? ptLs.z : ptLe.z) ; dZMax = ( ptLs.z < ptLe.z ? ptLe.z + dHei : ptLs.z + dHei) ; } 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 < dMinRad * dMinRad) SubtractIntervals( i, j, dZMin, dZMax) ; else if ( dSqDist < dMaxRad * dMaxRad) { double dr = sqrt( dSqDist) ; if ( vtToolDir.z > 0) SubtractIntervals( i, j, dZMin + dAngC * ( dr - dMinRad), dZMax) ; else SubtractIntervals( i, j, dZMin, dZMax - dAngC * ( dr - dMinRad)) ; } } return true ; } // Fresatura //---------------------------------------------------------------------------- bool VolZmap::MillZ( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Posizioni iniziale e finale dell'utensile Point3d ptI = ptLs ; Point3d ptF = ptLe ; // vettore movimento Vector3d vtMove = ptLe - ptLs ; CurveComposite ToolProfile ; // Settaggio profilo if ( m_ToolArcLineApprox.GetCurveCount() == 0) // Se l'utensile non è stato approssimato uso l'originale ToolProfile.CopyFrom( & m_ToolOutline) ; else // altrimenti usi l'approssimazione ToolProfile.CopyFrom( & m_ToolArcLineApprox) ; // Dichiaro un puntatore a curva da usare nel ciclo const ICurve* pCurve ; pCurve = ToolProfile.GetFirstCurve() ; // Ciclo sulle curve while ( pCurve != nullptr) { double dHeight ; int nCurveType = pCurve -> GetType() ; // Caso segmento if ( nCurveType == CRV_LINE) { Point3d ptStart, ptEnd ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) { dHeight = abs( ptStart.y - ptEnd.y) ; // Il componente è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; MillCylV( ptI, ptF, vtToolDir, dHeight, dRadius) ; } // Il componente è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; MillConusV( ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ; } // Il componente è un cono con vettore opposto a quello dell'utensile else if ( ptStart.x < ptEnd.x) { double dMaxRad = ptEnd.x ; double dMinRad = ptStart.x ; Point3d ptIn = ptI - vtToolDir * dHeight ; Point3d ptFn = ptIn + vtMove ; MillConusV( ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ; } } else dHeight = 0 ; } // Caso arco else if ( nCurveType == CRV_ARC) { // Centro e Punti iniziale e finale del cerchio Point3d ptStart, ptEnd, ptO ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; pCurve -> GetCenterPoint( ptO) ; // Determino il raggio Vector3d vtStRad = ptStart - ptO ; Vector3d vtEnRad = ptEnd - ptO ; double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ; // Determino le posizioni iniziale e finale del centrodella sfera Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ; Point3d ptOEn = ptOSt + vtMove ; // Eseguo l'asportazione del materiale Ball( ptOSt, ptOEn, dRadius) ; // aggiorno l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dHeight ; ptF = ptI + vtMove ; // Aggiorno il puntatore pCurve = ToolProfile.GetNextCurve() ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillCylV( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! Control) return true ; Point3d ptI, ptF ; if ( ( ptLe - ptLs) * vtToolDir < 0 && vtToolDir.z > 0) { ptI = ptLe ; ptF = ptLs ; } else if ( ( ptLe - ptLs) * vtToolDir < 0 && vtToolDir.z < 0) { ptI = ptLs - dHei * vtToolDir ; ptF = ptLe - dHei * vtToolDir ; } else if ( ( ptLe - ptLs) * vtToolDir > 0 && vtToolDir.z < 0) { ptI = ptLe - dHei * vtToolDir ; ptF = ptLs - dHei * vtToolDir ; } else { ptI = ( vtToolDir.z > 0 ? ptLs : ptLs - vtToolDir * dHei) ; ptF = ( vtToolDir.z > 0 ? ptLe : ptLe - vtToolDir * dHei) ; } Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; Vector3d vtV1 = ptFxy - ptIxy ; double dPLen = vtV1.LenXY() ; vtV1.Normalize() ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; 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 - ptIxy ; //Vector3d vtCF = ptC - ptFxy ; double dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; double dLimX1 = sqrt( dRad * dRad - dX2 * dX2) ; if ( dX2 > - dRad && dX2 < dRad && dX1 > - dLimX1 && dX1 < dPLen + dLimX1) { // Massimi if( dX1 > - dLimX1 && dX1 < dPLen - dLimX1) dMax = dZI + ( dX1 + dLimX1) * dDeltaZ / dPLen ; else if ( dX1 >= dPLen - dLimX1 && dX1 < dPLen + dLimX1) dMax = dZI + dDeltaZ ; // Minimi if ( dX1 > - dLimX1 && dX1 < dLimX1) dMin = dZI - dHei ; else if ( dX1 >= dLimX1 && dX1 < dPLen + dLimX1) dMin = dZI - dHei + ( dX1 - dLimX1) * dDeltaZ / dPLen ; SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillConusV( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad) { double dMin, dMax, dPLim, dMLim ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! Control) return true ; Point3d ptI = ( vtToolDir * ( ptLe - ptLs) > 0 ? ptLs : ptLe) ; Point3d ptF = ( vtToolDir * ( ptLe - ptLs) > 0 ? ptLe : ptLs) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ; Vector3d vtMLong = ( vtMove * vtToolDir) * vtToolDir ; double dLLong = vtMLong.Len() ; Vector3d vtMOrt = vtMove - vtMLong ; double dLOrt = vtMOrt.Len() ; Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtMOrt ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; double dZI = ptI.z ; double dZTI = ptI.z - vtV1.z * dHei ; double dDeltaZ = ptF.z - ptI.z ; double dDeltaR = dMaxRad - dMinRad ; double dTan = dDeltaR / dHei ; double dRatio = ( vtMove * vtV1) / ( vtMove * vtV2) ; double dCos = dTan * dRatio ; double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTan * dTan) ; Point3d ptV = ptI - vtV1 * ( dHei * dMaxRad / dDeltaR) ; Vector3d vtNs = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNd = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * vtV3 ; Vector3d vtR0 = ptV - ORIG ; double dDots = vtR0 * vtNs ; double dDotd = vtR0 * vtNd ; 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 vtCI = ptC - ptIxy ; double dSqDI = vtCI.SqLenXY() ; Vector3d vtCF = ptC - ptFxy ; double dSqDF = vtCF.SqLenXY() ; double dIDO = vtCI * vtV3 ; double dIDL = vtCI * vtV2 ; double dIVarCos = dIDL / sqrt( dSqDI) ; double dFDL = vtCF * vtV2 ; double dFVarCos = dFDL / sqrt( dSqDF) ; if ( dSqDI < dMaxRad * dMaxRad || dSqDF < dMaxRad * dMaxRad || (abs( dIDO) < dMaxRad && dIDL > 0 && dIDL < dLOrt)) { // Caso dTan > 1 / dRatio if ( dRatio > 1 / dTan) { // Limiti nella direzione positiva di vtV1 if ( dSqDF < dMaxRad * dMaxRad) dPLim = dZI + dDeltaZ ; else dPLim = dZI + ( dIDL + sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ; // Limiti nella direzione negativa di vtV1 if ( dSqDI < dMinRad * dMinRad) dMLim = dZTI ; else if ( dSqDI < dMaxRad * dMaxRad) dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ; else dMLim = dZI + ( dIDL - sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ; } else { // Limiti nella direzione positiva di vtV1 if ( dSqDF < dMaxRad * dMaxRad) dPLim = dZI + dDeltaZ ; else dPLim = dZI + ( dIDL + sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ; // Limiti nella direzione negativa di vtV1 if ( dSqDI < dMinRad * dMinRad) dMLim = dZTI ; else if ( dSqDI >= dMinRad * dMinRad && dSqDI < dMaxRad * dMaxRad && dIVarCos < dCos) dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ; else if ( dSqDI >= dMinRad * dMinRad && dIVarCos >= dCos && dFVarCos < dCos && abs( dIDO) < dMaxRad * dSin) { // da qui if ( dIDO > - dMaxRad * dSin && dIDO <= - dMinRad * dSin) dMLim = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ; else if ( dIDO > - dMinRad * dSin && dIDO < dMinRad * dSin) dMLim = dZTI + ( dIDL - sqrt( dMinRad * dMinRad - dIDO * dIDO)) * dDeltaZ / dLOrt ; else if ( dIDO >= dMinRad * dSin && dIDO < dMaxRad * dSin) dMLim = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; // a qui } else if ( dFVarCos >= dCos) { if ( dSqDF < dMinRad * dMinRad) dMLim = dZTI + ( dIDL - sqrt( dMinRad * dMinRad - dIDO * dIDO)) * dDeltaZ / dLOrt ; else dMLim = dZTI + dDeltaZ + ( sqrt( dSqDF) - dMinRad) * ( dZI - dZTI) / dDeltaR ; } else dMLim = dZI + ( dIDL - sqrt( dMaxRad * dMaxRad - dIDO * dIDO)) * dDeltaZ / dLOrt ; } dMin = min( dPLim, dMLim) ; dMax = max( dPLim, dMLim) ; SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } // Direzione generica del versore utensile // Foratura //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- bool VolZmap::Drilling( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill) LongCyl( ptLs, ptLe, vtToolDir, m_dHeight, m_dRadius) ; else if ( m_nToolType == BallEndMill) { double dCylH = m_dHeight - m_dTipHeight ; LongCyl( ptLs, ptLe, vtToolDir, dCylH, m_dRadius) ; Point3d ptBs = ptLs - vtToolDir * ( m_dHeight - m_dTipHeight) ; Point3d ptBe = ptLe - vtToolDir * ( m_dHeight - m_dTipHeight) ; Ball( ptBs, ptBe, m_dRadius) ; } else if ( m_nToolType == BullNoseMill) // Caso al momento non gestito return false ; else if ( m_nToolType == ConusMill) { double dCylH = m_dHeight - m_dTipHeight ; LongCyl( ptLs, ptLe, vtToolDir, dCylH, m_dRadius) ; double dMinRad = ( m_dRadius > m_dTipRadius ? m_dTipRadius : m_dRadius) ; double dMaxRad = ( m_dRadius > m_dTipRadius ? m_dRadius : m_dTipRadius) ; Point3d ptCs = ( m_dRadius > m_dTipRadius ? ptLs - dCylH * vtToolDir : ptLs - m_dHeight * vtToolDir) ; Point3d ptCe = ( m_dRadius > m_dTipRadius ? ptLe - dCylH * vtToolDir : ptLe - m_dHeight * vtToolDir) ; Vector3d vtDir = ( m_dRadius > m_dTipRadius ? vtToolDir : - vtToolDir) ; LongConus( ptCs, ptCe, vtDir, m_dTipHeight, dMaxRad, dMinRad) ; } else if ( m_nToolType == GenericTool) // Caso al momento non gestito return false ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::DrillingGT( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Posizioni iniziale e finale dell'utensile Point3d ptI = ptLs ; Point3d ptF = ptLe ; // vettore movimento Vector3d vtMove = ptLe - ptLs ; CurveComposite ToolProfile ; // Settaggio profilo if ( m_ToolArcLineApprox.GetCurveCount() == 0) // Se l'utensile non è stato approssimato uso l'originale ToolProfile.CopyFrom( & m_ToolOutline) ; else // altrimenti usi l'approssimazione ToolProfile.CopyFrom( & m_ToolArcLineApprox) ; // Dichiaro un puntatore a curva da usare nel ciclo const ICurve* pCurve ; pCurve = ToolProfile.GetFirstCurve() ; // Ciclo sulle curve while ( pCurve != nullptr) { double dHeight ; int nCurveType = pCurve -> GetType() ; // Caso di semento if ( nCurveType == CRV_LINE) { Point3d ptStart, ptEnd ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) { dHeight = abs( ptStart.y - ptEnd.y) ; // Il componente è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; LongCyl( ptI, ptF, vtToolDir, dHeight, dRadius) ; } // Il componente è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; LongConus( ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ; } // Il componente è un cono con vettore opposto a quello dell'utensile else if ( ptStart.x < ptEnd.x) { double dMaxRad = ptEnd.x ; double dMinRad = ptStart.x ; Point3d ptIn = ptI - vtToolDir * dHeight ; Point3d ptFn = ptIn + vtMove ; LongConus( ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ; } } else dHeight = 0 ; } // Caso arco else if ( nCurveType == CRV_ARC) { // Centro e Punti iniziale e finale del cerchio Point3d ptStart, ptEnd, ptO ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; pCurve -> GetCenterPoint( ptO) ; // Determino il raggio Vector3d vtStRad = ptStart - ptO ; Vector3d vtEnRad = ptEnd - ptO ; double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ; // Determino le posizioni iniziale e finale del centrodella sfera Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ; Point3d ptOEn = ptOSt + vtMove ; // Eseguo l'asportazione del materiale Ball( ptOSt, ptOEn, dRadius) ; // aggiorno l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dHeight ; ptF = ptI + vtMove ; // Aggiorno il puntatore pCurve = ToolProfile.GetNextCurve() ; } return true ; } // Componenti elementari degli utensili //---------------------------------------------------------------------------- bool VolZmap::LongCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dRad) { double dMin, dMax; unsigned int nStartI, nEndI, nStartJ, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! Control) return true ; // Studio delle simmetrie Vector3d vtMove = ptLe - ptLs ; Point3d ptI = ( vtMove * vtToolDir > 0 ? ptLe : ptLs) ; Point3d ptF = ( vtMove * vtToolDir > 0 ? ptLs - dHei * vtToolDir : ptLe - dHei * vtToolDir) ; if ( ptI.z > ptF.z) { Point3d ptTemp = ptI ; ptI = ptF ; ptF = ptTemp ; } double dDeltaZ = ptF.z - ptI.z ; double dZI = ptI.z ; // Definizione Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; Vector3d vtCyl = ptF - ptI ; double dLen = sqrt( vtCyl * vtCyl) ; Vector3d vtCylVer( 0, 0, vtCyl.z) ; double dLVer = abs( vtCyl.z) ; Vector3d vtCylOri( vtCyl.x, vtCyl.y, 0) ; double dLOri = vtCylOri.LenXY() ; double dCos = dLVer / dLen ; // Coseno dell'angolo formato da vtCyl con l'asse Z. double dSin = dLOri / dLen ; // Seno dell'angolo formato da vtCyl con l'asse Z. double dSemiMin = dRad * dCos ; // Definizione del sistema di riferimento nel piano Vector3d vtU1 = vtCylOri ; if ( vtU1.LenXY() < EPS_SMALL) { double dLenVector = sqrt(vtCyl.x * vtCyl.x + vtCyl.y * vtCyl.y) ; vtU1 = ( 1 + dLenVector) / dLenVector * vtU1 ; } vtU1.Normalize() ; Vector3d vtU2 = vtU1 ; vtU2.Rotate( Z_AX, 90) ; // Definizione piani Vector3d vtV = vtMove ; vtV.Normalize() ; Vector3d vtRI = ptI - ORIG ; double dDotI = vtRI * vtV ; Vector3d vtRF = ptF - ORIG ; double dDotF = vtRF * vtV ; 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 vtCI = ptC - ptIxy ; Vector3d vtCF = ptC - ptFxy ; double dProjI1 = vtCI * vtU1 ; double dProjI2 = vtCI * vtU2 ; double dProjF1 = vtCF * vtU1 ; double dProjF2 = vtCF * vtU2 ; if ( dProjI1 > - dCos * sqrt( dRad * dRad - dProjI2 * dProjI2) && dProjI1 < dLOri + dCos * sqrt( dRad * dRad - dProjI2 * dProjI2) && dProjI2 * dProjI2 < dRad * dRad) { // Massimi if ( dProjI1 < dLOri - dCos * sqrt( dRad * dRad - dProjI2 * dProjI2)) { double dZ0 = dSin * sqrt( dRad * dRad - dProjI2 * dProjI2) ; double dI10 = - dCos * sqrt( dRad * dRad - dProjI2 * dProjI2) ; dMax = dZI + dZ0 + ( dProjI1 - dI10) * dDeltaZ / dLOri ; } else dMax = ( dDotF - vtV.x * dX - vtV.y *dY) / vtV.z ; // Minimi if ( dProjI1 < dCos * sqrt( dRad * dRad - dProjI2 * dProjI2)) dMin = ( dDotI - vtV.x * dX - vtV.y *dY) / vtV.z ; else { double dZ0 = - dSin * sqrt( dRad * dRad - dProjI2 * dProjI2) ; double dI10 = dCos * sqrt( dRad * dRad - dProjI2 * dProjI2) ; dMin = dZI + dZ0 + ( dProjI1 - dI10) * dDeltaZ / dLOri ; } SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::LongBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, 0) ; if ( ! Control) return true ; Point3d ptI = ( ( ptLe - ptLs) * vtToolDir < 0 ? ptLs : ptLe) ; Point3d ptF = ( ( ptLe - ptLs) * vtToolDir < 0 ? ptLe : ptLs) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; double dDeltaZ = ptF.z - ptI.z ; double dZI = ptI.z ; Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ; Vector3d vtMoveVer( 0, 0, vtMove.z) ; double dLVer = abs( vtMove.z) ; Vector3d vtMoveOri( vtMove.x, vtMove.y, 0) ; double dLOri = vtMoveOri.LenXY() ; // Definizione del sistema di riferimento nel piano Vector3d vtU1 = vtMoveOri ; if ( vtU1.LenXY() < EPS_SMALL) { double dLenVector = sqrt(vtMove.x * vtMove.x + vtMove.y * vtMove.y) ; vtU1 = ( 1 + dLenVector) / dLenVector * vtU1 ; } vtU1.Normalize() ; Vector3d vtU2 = vtU1 ; vtU2.Rotate( Z_AX, 90) ; double dCos = dLVer / dLen ; // Sempre positivo double dSin = dLOri / dLen ; // Sempre positivo double dSemiMin = dRad * abs( dCos) ; Vector3d vtV = vtMove ; vtV.Normalize() ; Vector3d vtRI = ptI - ORIG ; double dDotI = vtRI * vtV ; 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 vtCI = ptC - ptIxy ; Vector3d vtCF = ptC - ptFxy ; double dPI1 = vtCI * vtU1 ; double dPI2 = vtCI * vtU2 ; double dPF1 = vtCF * vtU1 ; double dPF2 = vtCF * vtU2 ; double dLimP1 = sqrt( dRad * dRad - dPI2 * dPI2) ; // Dexel nella regione interessata dalla lavorazione if ( ( dPI1 > - dCos * dLimP1 && dPI1 < dLOri && dPI2 * dPI2 < dRad * dRad) || ( dPF1 * dPF1 + dPF2 * dPF2 < dRad * dRad)) { if ( dDeltaZ > 0) { // Massimi if ( dPI1 < dLOri - dCos * dLimP1) { double dPI0 = - dCos * dLimP1 ; double dZ0 = dSin * dLimP1 ; dMax = dZI + dZ0 + ( dPI1 - dPI0) * dDeltaZ / dLOri ; } else { double dSqD = dPF1 * dPF1 + dPF2 * dPF2 ; double dH = sqrt( dRad * dRad - dSqD) ; dMax = dZI + dDeltaZ + dH ; } // Minimi if ( dPI1 < dCos * dLimP1) dMin = ( dDotI - dX * vtV.x - dY * vtV.y) / vtV.z ; else if ( dPI1 < dLOri + dCos * dLimP1) { double dPI0 = dCos * dLimP1 ; double dZ0 = - dSin * dLimP1 ; dMin = dZI + dZ0 + ( dPI1 - dPI0) * dDeltaZ / dLOri ; } else { double dSqD = dPF1 * dPF1 + dPF2 * dPF2 ; double dH = sqrt( dRad * dRad - dSqD) ; dMin = dZI + dDeltaZ - dH ; } } else { // Massimi if ( dPI1 < dCos * dLimP1) dMax = ( dDotI - dX * vtV.x - dY * vtV.y) / vtV.z ; else if ( dPI1 < dLOri + dCos * dLimP1) { double dPI0 = dCos * dLimP1 ; double dZ0 = + dSin * dLimP1 ; dMax = dZI + dZ0 + ( dPI1 - dPI0) * dDeltaZ / dLOri ; } else { double dSqD = dPF1 * dPF1 + dPF2 * dPF2 ; double dH = sqrt( dRad * dRad - dSqD) ; dMax = dZI + dDeltaZ + dH ; } // Minimi if ( dPI1 < dLOri - dCos * dLimP1) { double dPI0 = - dCos * dLimP1 ; double dZ0 = - dSin * dLimP1 ; dMin = dZI + dZ0 + ( dPI1 - dPI0) * dDeltaZ / dLOri ; } else { double dSqD = dPF1 * dPF1 + dPF2 * dPF2 ; double dH = sqrt( dRad * dRad - dSqD) ; dMin = dZI + dDeltaZ - dH ; } } SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::LongConus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! Control) return true ; Vector3d vtMove = ptLe - ptLs ; double dLen = vtMove.Len() ; Vector3d vtMZ( 0, 0, vtMove.z) ; double dLVer = abs( vtMove.z) ; Vector3d vtMXY( vtMove.x, vtMove.y, 0) ; double dLOri = vtMXY.LenXY() ; double dSin = dLOri / dLen ; double dCos = dLVer / dLen ; double dSemiMinR = dMaxRad * dCos ; double dSemiMinr = dMinRad * dCos ; // Sistema di riferimento sul cono Vector3d vtV1 = vtToolDir ; // controllare qui e negli altri coni che le proiezioni non siano troppo piccole FORSE CONVIENE FARE I CONTI CON VTMOVE NORMALIZZATO (QUESTO IN TUTTI I MOVIMENTI) double dCoef23 = ( vtV1.z > 0 ? 1 : - 1) ; double dCoef21 = - dCoef23 * vtV1.z ; // vtV1.z := vtV1 * Z_AX Vector3d vtV2 = dCoef21 * vtV1 + dCoef23 * Z_AX ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; // Simmetrie del problema riguardanti il cono Point3d ptCBot = ( vtV1 * vtMove > 0 ? ptLs : ptLe) ; Point3d ptCTip = ptCBot - dHei * vtV1 ; double dDeltaR = dMaxRad - dMinRad ; double dTan = dDeltaR / dHei ; double dL = ( ( dMaxRad * dHei) / dDeltaR) ; double dl = dL - dHei ; Point3d ptV = ptCBot - vtV1 * dL ; // Simmetrie del problema riguardanti il cilinidro Point3d ptCylI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; Point3d ptCylF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; double dDeltaZ = ptCylF.z - ptCylI.z ; double dZCylI = ptCylI.z ; // Piani cono Vector3d vtR0B = ptCBot - ORIG ; double dDotB = vtR0B * vtV1 ; Vector3d vtR0T = ptCTip - ORIG ; double dDotT = vtR0T * vtV1 ; // Piani cilindro Vector3d vtR0I = ptCylI - ORIG ; double dDotI = vtR0I * vtV1 ; Vector3d vtR0F = ptCylF - ORIG ; double dDotF = vtR0F * vtV1 ; // Punti sul piano Point3d ptCylIxy( ptCylI.x, ptCylI.y, 0) ; Point3d ptCBotxy( ptCBot.x, ptCBot.y, 0) ; // Riferimenti sul piano Vector3d vtU1( ptCylF.x - ptCylI.x, ptCylF.y - ptCylI.y, 0) ; vtU1.Normalize() ; Vector3d vtU2 = vtU1 ; vtU2.Rotate( Z_AX, 90) ; Vector3d vtW1( vtV1.x, vtV1.y, 0) ; vtW1.Normalize() ; Vector3d vtW2 = vtW1 ; vtW2.Rotate( Z_AX, 90) ; // Sistema di riferimento del cono Frame3d ConusFrame ; ConusFrame.Set( ptV, vtV1, vtV2, vtV3) ; // Ciclo 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 - ptCylIxy ; double dPCyl1 = vtC * vtU1 ; double dPCyl2 = vtC * vtU2 ; // Parte cilindrica if ( dPCyl2 * dPCyl2 < dMaxRad * dMaxRad && dPCyl1 > - dSemiMinR * sqrt( 1 - ( dPCyl2 * dPCyl2) / ( dMaxRad * dMaxRad)) && dPCyl1 < dLOri + dSemiMinR * sqrt( 1 - ( dPCyl2 * dPCyl2) / ( dMaxRad * dMaxRad))) { // Massimi if ( dPCyl1 < dLOri - dSemiMinR * sqrt( 1 - ( dPCyl2 * dPCyl2) / ( dMaxRad * dMaxRad))) { double dZ0 = dSin * sqrt( dMaxRad * dMaxRad - dPCyl2 * dPCyl2) ; double dP0 = - dSemiMinR * sqrt( 1 - ( dPCyl2 * dPCyl2) / ( dMaxRad * dMaxRad)) ; dMax = dZCylI + dZ0 + ( dPCyl1 - dP0) * dDeltaZ / ( dLOri) ; } else dMax = ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z ; // Minimi if ( dPCyl1 < dSemiMinR * sqrt( 1 - ( dPCyl2 * dPCyl2) / ( dMaxRad * dMaxRad))) dMin = ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z ; else { double dZ0 = - dSin * sqrt( dMaxRad * dMaxRad - dPCyl2 * dPCyl2) ; double dP0 = dSemiMinR * sqrt( 1 - ( dPCyl2 * dPCyl2) / ( dMaxRad * dMaxRad)) ; dMin = dZCylI + dZ0 + ( dPCyl1 - dP0) * dDeltaZ / ( dLOri) ; } SubtractIntervals( i, j, dMin, dMax) ; } // Parte conica Vector3d vtD = Z_AX ; ptC.LocToLoc( m_LocalFrame, ConusFrame) ; vtD.LocToLoc( m_LocalFrame, ConusFrame) ; std::vector vdCoef(3); std::vector vdRoots; vdCoef[0] = ( dTan * dTan * ptC.x * ptC.x - ptC.y * ptC.y - ptC.z * ptC.z) ; vdCoef[1] = 2 * ( dTan * dTan * ptC.x * vtD.x - ptC.y * vtD.y - ptC.z * vtD.z) ; vdCoef[2] = dTan * dTan * vtD.x * vtD.x - vtD.y * vtD.y - vtD.z * vtD.z ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; if ( nRoot == 1) { Point3d ptR1 = ptC + vdRoots[0] * vtD ; if ( ptR1.x >= dl && ptR1.x < dL) { ptR1.LocToLoc( ConusFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dl) { dMin = min( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nRoot == 2) { Point3d ptR1 = ptC + vdRoots[0] * vtD ; Point3d ptR2 = ptC + vdRoots[1] * vtD ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < 0 && ptR2.x > 0 && ptR2.x < dl) { dMin = min( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < 0 && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( ConusFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( ConusFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dL) { dMin = min( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x < dL) { ptR1.LocToLoc( ConusFrame, m_LocalFrame) ; ptR2.LocToLoc( ConusFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x >= dL) { ptR1.LocToLoc( ConusFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotB - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } // Fresatura //---------------------------------------------------------------------------- bool VolZmap::Milling( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { if ( m_nToolType == CylindricalMill) return MillCyl( ptLs, ptLe, vtToolDir, m_dHeight, m_dRadius) ; else if ( m_nToolType == BallEndMill) { double dCylH = m_dHeight - m_dTipHeight ; MillCyl( ptLs, ptLe, vtToolDir, dCylH, m_dRadius) ; Point3d ptBs = ptLs - vtToolDir * ( m_dHeight - m_dTipHeight) ; Point3d ptBe = ptLe - vtToolDir * ( m_dHeight - m_dTipHeight) ; Ball( ptBs, ptBe, m_dRadius) ; return true ; } else if ( m_nToolType == BullNoseMill) // Caso al momento non gestito return false ; else if ( m_nToolType == ConusMill) { double dCylH = m_dHeight - m_dTipHeight ; MillCyl( ptLs, ptLe, vtToolDir, dCylH, m_dRadius) ; double dMinRad = ( m_dRadius > m_dTipRadius ? m_dTipRadius : m_dRadius) ; double dMaxRad = ( m_dRadius > m_dTipRadius ? m_dRadius : m_dTipRadius) ; Point3d ptCs = ( m_dRadius > m_dTipRadius ? ptLs - dCylH * vtToolDir : ptLs - m_dHeight * vtToolDir) ; Point3d ptCe = ( m_dRadius > m_dTipRadius ? ptLe - dCylH * vtToolDir : ptLe - m_dHeight * vtToolDir) ; Vector3d vtDir = ( m_dRadius > m_dTipRadius ? vtToolDir : - vtToolDir) ; MillConus( ptCs, ptCe, vtDir, m_dTipHeight, dMaxRad, dMinRad) ; return true ; } else if ( m_nToolType == GenericTool) // Caso al momento non gestito return false ; else return false ; } //---------------------------------------------------------------------------- bool VolZmap::MillingGT( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir) { // Posizioni iniziale e finale dell'utensile Point3d ptI = ptLs ; Point3d ptF = ptLe ; // vettore movimento Vector3d vtMove = ptLe - ptLs ; CurveComposite ToolProfile ; int i = m_ToolArcLineApprox.GetCurveCount() ; // Settaggio profilo if ( m_ToolArcLineApprox.GetCurveCount() == 0) // Se l'utensile non è stato approssimato uso l'originale ToolProfile.CopyFrom( & m_ToolOutline) ; else // altrimenti usi l'approssimazione ToolProfile.CopyFrom( & m_ToolArcLineApprox) ; // Dichiaro un puntatore a curva da usare nel ciclo const ICurve* pCurve = ToolProfile.GetFirstCurve() ; // Ciclo sulle curve while ( pCurve != nullptr) { double dHeight ; int nCurveType = pCurve -> GetType() ; // Caso di semento if ( nCurveType == CRV_LINE) { Point3d ptStart, ptEnd ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; if ( abs( ptStart.y - ptEnd.y) > EPS_SMALL) { dHeight = abs( ptStart.y - ptEnd.y) ; // Il componente è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; MillCyl( ptI, ptF, vtToolDir, dHeight, dRadius) ; } // Il componente è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; MillConus( ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ; } // Il componente è un cono con vettore opposto a quello dell'utensile else if ( ptStart.x < ptEnd.x) { double dMaxRad = ptEnd.x ; double dMinRad = ptStart.x ; Point3d ptIn = ptI - vtToolDir * dHeight ; Point3d ptFn = ptIn + vtMove ; MillConus( ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ; } } else dHeight = 0 ; } // Caso arco else if ( nCurveType == CRV_ARC) { // Centro e Punti iniziale e finale del cerchio Point3d ptStart, ptEnd, ptO ; pCurve -> GetStartPoint( ptStart) ; pCurve -> GetEndPoint( ptEnd) ; pCurve -> GetCenterPoint( ptO) ; // Determino il raggio Vector3d vtStRad = ptStart - ptO ; Vector3d vtEnRad = ptEnd - ptO ; double dRadius = 0.5 * ( vtStRad.LenXY() + vtEnRad.LenXY()) ; // Determino le posizioni iniziale e finale del centrodella sfera Point3d ptOSt = ptI - vtToolDir * ( ptStart.y - ptO.y) ; Point3d ptOEn = ptOSt + vtMove ; // Eseguo l'asportazione del materiale Ball( ptOSt, ptOEn, dRadius) ; // aggiorno l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dHeight ; ptF = ptI + vtMove ; // Aggiorno il puntatore pCurve = ToolProfile.GetNextCurve() ; } return true ; } // Componenti elementari degli utensili //---------------------------------------------------------------------------- bool VolZmap::MillCyl( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! Control) return true ; Point3d ptI ; Point3d ptF ; Vector3d vtV1 ; // Studio delle simmetrie if ( vtToolDir.z < 0) { vtV1 = - vtToolDir ; ptI = ( vtV1 * ( ptLe - ptLs) > 0 ? ptLs + dHei * vtV1 : ptLe + dHei * vtV1) ; ptF = ( vtV1 * ( ptLe - ptLs) > 0 ? ptLe + dHei * vtV1 : ptLs + dHei * vtV1) ; } else { vtV1 = vtToolDir ; ptI = ( vtV1 * ( ptLe - ptLs) > 0 ? ptLs : ptLe) ; ptF = ( vtV1 * ( ptLe - ptLs) > 0 ? ptLe : ptLs) ; } Point3d ptIT = ptI - vtV1 * dHei ; Point3d ptFT = ptF - vtV1 * dHei ; // Definizione di un sintema di riferimento nel piano Vector3d vtU1( - vtV1.x, - vtV1.y, 0) ; double dCos = vtV1.z ; double dSin = vtU1.LenXY() ; vtU1.Normalize() ; // Ocio che la sua lunghezza sia maggiore di EPS_SMALL Vector3d vtU2 = vtU1 ; vtU2.Rotate( Z_AX, 90) ; double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = ptIT.z - ptI.z ; //double dDeltaFz = ptFT.z - ptF.z ; double dL = dSin * dHei ; Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ; Vector3d vtMLong = ( vtMove * vtV1) * vtV1 ; double dLLong = vtMLong.Len() ; Vector3d vtMOrt = vtMove - vtMLong ; double dLOrt = vtMOrt.Len() ; double dCoef = dLOrt / dLLong ; double dAng = atan( 1 / dCoef) ; // vtV1, vtV2 e vtV3 definiscono gli assi dei sistemi di riferimento intrinseci Vector3d vtV2 = vtMOrt ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; Frame3d CylFrame ; CylFrame.Set( ptI, vtV1, vtV2, vtV3) ; Frame3d FCylFrame ; FCylFrame.Set( ptF, vtV1, vtV2, vtV3) ; Frame3d TCylFrame ; TCylFrame.Set( ptIT, vtV1, vtV2, vtV3) ; Frame3d FTCylFrame ; FTCylFrame.Set( ptFT, vtV1, vtV2, vtV3) ; // Altri punti notevoli Point3d ptIPlus = ptI + dRad * vtV3 ; Point3d ptIMinus = ptI - dRad * vtV3 ; Point3d ptFPlus = ptIPlus + vtMove ; Point3d ptFMinus = ptIMinus + vtMove ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; // Grandezze per la definizione dei piani Vector3d vtRI = ptI - ORIG ; double dDotI = vtV1 * vtRI ; Vector3d vtRF = ptF - ORIG ; double dDotF = vtV1 * vtRF ; Vector3d vtRIT = ptIT - ORIG ; double dDotIT = vtV1 * vtRIT ; Vector3d vtRFT = ptFT - ORIG ; double dDotFT = vtV1 * vtRFT ; Vector3d vtRIPlus = ptIPlus - ORIG ; Vector3d vtRIMinus = ptIMinus - ORIG ; Vector3d vtRFPlus = ptFPlus - ORIG ; Vector3d vtW1 = vtV1 ; vtW1.Rotate( vtV3, - 180 * dAng / PIGRECO) ; Vector3d vtW2 = vtV2 ; vtW2.Rotate( vtV3, - 180 * dAng / PIGRECO) ; Vector3d vtRITPlus = ptIPlus - ORIG - vtV1 * dHei ; Frame3d RotFrame ; RotFrame.Set( ptI, vtW1, vtW2, vtV3) ; Frame3d TRotFrame ; TRotFrame.Set( ptIT, vtW1, vtW2, vtV3) ; 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 vtCI = ptC - ptIxy ; Vector3d vtCF = ptC - ptFxy ; Vector3d vtC = ptC - ORIG ; double dPI1 = vtCI * vtU1 ; double dPI2 = vtCI * vtU2 ; double dPF1 = vtCF * vtU1 ; double dPF2 = vtCF * vtU2 ; // Forse queste parti cilindriche andrebbero fatte per intersezione se il versoreutensile è molto verticale // Parte cilindrica I if ( dPI1 > - dCos * sqrt( dRad * dRad - dPI2 * dPI2) && dPI1 < dL + dCos * sqrt( dRad * dRad - dPI2 * dPI2) && dPI2 * dPI2 < dRad * dRad) { // Minimi if ( dPI1 < dL - dCos * sqrt( dRad * dRad - dPI2 * dPI2)) { double dZ0 = - dSin * sqrt( dRad * dRad - dPI2 * dPI2) ; double dI10 = - dCos * sqrt( dRad * dRad - dPI2 * dPI2) ; dMin = dZI + dZ0 + ( dPI1 - dI10) * dDeltaZ / dL ; } else dMin = ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; // Massimi if ( dPI1 < dCos * sqrt( dRad * dRad - dPI2 * dPI2)) dMax = ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; else { double dZ0 = dSin * sqrt( dRad * dRad - dPI2 * dPI2) ; double dI10 = dCos * sqrt( dRad * dRad - dPI2 * dPI2) ; dMax = dZI + dZ0 + ( dPI1 - dI10) * dDeltaZ / dL ; } SubtractIntervals( i, j, dMin, dMax) ; } // Parte cilindrica F if ( dPF1 > - dCos * sqrt( dRad * dRad - dPF2 * dPF2) && dPF1 < dL + dCos * sqrt( dRad * dRad - dPF2 * dPF2) && dPF2 * dPF2 < dRad * dRad) { // Minimi if ( dPF1 < dL - dCos * sqrt( dRad * dRad - dPF2 * dPF2)) { double dZ0 = - dSin * sqrt( dRad * dRad - dPF2 * dPF2) ; double dI10 = - dCos * sqrt( dRad * dRad - dPF2 * dPF2) ; dMin = dZF + dZ0 + ( dPF1 - dI10) * dDeltaZ / dL ; } else dMin = ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; // Massimi if ( dPF1 < dCos * sqrt( dRad * dRad - dPF2 * dPF2)) dMax = ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; else { double dZ0 = dSin * sqrt( dRad * dRad - dPF2 * dPF2) ; double dI10 = dCos * sqrt( dRad * dRad - dPF2 * dPF2) ; dMax = dZF + dZ0 + ( dPF1 - dI10) * dDeltaZ / dL ; } SubtractIntervals( i, j, dMin, dMax) ; } // Parallelepipedo Point3d ptInt1 = ptC + ( ( ( vtRIPlus - vtC) * vtV3) / ( Z_AX * vtV3)) * Z_AX ; Point3d ptInt2 = ptC + ( ( ( vtRIMinus - vtC) * vtV3) / ( Z_AX * vtV3)) * Z_AX ; Point3d ptInt3 = ptC + ( ( ( vtRIPlus - vtC) * vtV2) / ( Z_AX * vtV2)) * Z_AX ; Point3d ptInt4 = ptC + ( ( ( vtRIPlus - vtC) * vtW1) / ( Z_AX * vtW1)) * Z_AX ; Point3d ptInt5 = ptC + ( ( ( vtRFPlus - vtC) * vtV2) / ( Z_AX * vtV2)) * Z_AX ; Point3d ptInt6 = ptC + ( ( ( vtRITPlus - vtC) * vtW1) / ( Z_AX * vtW1)) * Z_AX ; ptInt1.LocToLoc( m_LocalFrame, CylFrame) ; ptInt2.LocToLoc( m_LocalFrame, CylFrame) ; ptInt3.LocToLoc( m_LocalFrame, CylFrame) ; ptInt4.LocToLoc( m_LocalFrame, RotFrame) ; ptInt5.LocToLoc( m_LocalFrame, CylFrame) ; ptInt6.LocToLoc( m_LocalFrame, TRotFrame) ; bool bFlag = false ; double dLim1, dLim2 ; if ( ptInt1.y >= 0 && ptInt1.y <= dLOrt && ptInt1.x >= - dHei + ptInt1.y * ( dLLong / dLOrt) && ptInt1.x <= ptInt1.y * ( dLLong / dLOrt)) { ptInt1.LocToLoc( CylFrame, m_LocalFrame) ; dLim1 = ptInt1.z ; bFlag = true ; } if ( ptInt2.y >= 0 && ptInt2.y <= dLOrt && ptInt2.x >= - dHei + ptInt2.y * ( dLLong / dLOrt) && ptInt2.x <= ptInt2.y * ( dLLong / dLOrt)) { ptInt2.LocToLoc( CylFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt2.z ; bFlag = true ; } else dLim2 = ptInt2.z ; } if ( ptInt3.z >= - dRad && ptInt3.z <= dRad && ptInt3.x >= - dHei && ptInt3.x <= 0) { ptInt3.LocToLoc( CylFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt3.z ; bFlag = true ; } else dLim2 = ptInt3.z ; } if ( ptInt4.z >= - dRad && ptInt4.z <= dRad && ptInt4.y >= 0 && ptInt4.y <= dLen) { ptInt4.LocToLoc( RotFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt4.z ; bFlag = true ; } else dLim2 = ptInt4.z ; } if ( ptInt5.z >= - dRad && ptInt5.z <= dRad && ptInt5.x >= dLLong- dHei && ptInt5.x <= dLLong) { ptInt5.LocToLoc( CylFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt5.z ; bFlag = true ; } else dLim2 = ptInt5.z ; } if ( ptInt6.z >= - dRad && ptInt6.z <= dRad && ptInt6.y >= 0 && ptInt6.y <= dLen) { ptInt6.LocToLoc( TRotFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt6.z ; bFlag = true ; } else dLim2 = ptInt6.z ; } if ( bFlag == true) { // Una linea non confinata se entra in un volume chiuso ci deve uscire dMin = min( dLim1, dLim2) ; dMax = max( dLim1, dLim2) ; SubtractIntervals( i, j, dMin, dMax) ; } // Traslazione dell'ellisse Vector3d vtK = Z_AX ; vtK.LocToLoc( m_LocalFrame, CylFrame) ; ptC.LocToLoc( m_LocalFrame, CylFrame) ; std::vector vdCoef(3); std::vector vdRoots; vdCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dRad * dRad ; vdCoef[1] = 2 * ( dCoef * dCoef * vtK.x * ptC.x + vtK.y * ptC.y + vtK.z * ptC.z - dCoef * ( vtK.x * ptC.y + vtK.y * ptC.x)) ; vdCoef[2] = dCoef * dCoef * vtK.x * vtK.x + vtK.y * vtK.y + vtK.z * vtK.z - 2 * dCoef * vtK.x * vtK.y ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; if ( nRoot == 0 || nRoot == 1) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, CylFrame) ; ptPf.LocToLoc( m_LocalFrame, FCylFrame) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dRad * dRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dRad * dRad) { ptPi.LocToLoc( CylFrame, m_LocalFrame) ; ptPf.LocToLoc( FCylFrame, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nRoot == 2) { Point3d ptInter1 = ptC + vdRoots[0] * vtK ; Point3d ptInter2 = ptC + vdRoots[1] * vtK ; if ( ptInter1.x > ptInter2.x) { Point3d ptTemp = ptInter1 ; ptInter1 = ptInter2 ; ptInter2 = ptTemp ; } if ( ptInter1.x > 0 && ptInter1.x < dLLong && ptInter2.x > dLLong) { ptInter1.LocToLoc( CylFrame, m_LocalFrame) ; dMin = min( ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter1.z) ; dMax = max( ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x > 0 && ptInter2.x < dLLong) { ptInter1.LocToLoc( CylFrame, m_LocalFrame) ; ptInter2.LocToLoc( CylFrame, m_LocalFrame) ; dMin = min( ptInter1.z, ptInter2.z) ; dMax = max( ptInter1.z, ptInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x < 0 && ptInter2.x > dLLong) { dMin = min( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x < 0 && ptInter2.x > 0 && ptInter2.x < dLLong) { ptInter2.LocToLoc( CylFrame, m_LocalFrame) ; dMin = min( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter2.z) ; dMax = max( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } ptC.LocToLoc( CylFrame, TCylFrame) ; vtK.LocToLoc( CylFrame, TCylFrame) ; std::vector vdTCoef(3); std::vector vdTRoots; vdTCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dRad * dRad ; vdTCoef[1] = 2 * ( dCoef * dCoef * vtK.x * ptC.x + vtK.y * ptC.y + vtK.z * ptC.z - dCoef * ( vtK.x * ptC.y + vtK.y * ptC.x)) ; vdTCoef[2] = dCoef * dCoef * vtK.x * vtK.x + vtK.y * vtK.y + vtK.z * vtK.z - 2 * dCoef * vtK.x * vtK.y ; int nTRoot = PolynomialRoots( 2, vdTCoef, vdTRoots) ; if ( nTRoot == 0 || nTRoot == 1) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, TCylFrame) ; ptPf.LocToLoc( m_LocalFrame, FTCylFrame) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dRad * dRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dRad * dRad) { ptPi.LocToLoc( TCylFrame, m_LocalFrame) ; ptPf.LocToLoc( FTCylFrame, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nTRoot == 2) { Point3d ptTInter1 = ptC + vdTRoots[0] * vtK ; Point3d ptTInter2 = ptC + vdTRoots[1] * vtK ; if ( ptTInter1.x > ptTInter2.x) { Point3d ptTemp = ptTInter1 ; ptTInter1 = ptTInter2 ; ptTInter2 = ptTemp ; } if ( ptTInter1.x > 0 && ptTInter1.x < dLLong && ptTInter2.x > dLLong) { ptTInter1.LocToLoc( TCylFrame, m_LocalFrame) ; dMin = min( ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter1.z) ; dMax = max( ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptTInter1.x > 0 && ptTInter2.x < dLLong) { ptTInter1.LocToLoc( TCylFrame, m_LocalFrame) ; ptTInter2.LocToLoc( TCylFrame, m_LocalFrame) ; dMin = min( ptTInter1.z, ptTInter2.z) ; dMax = max( ptTInter1.z, ptTInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptTInter1.x < 0 && ptTInter2.x > dLLong) { dMin = min( ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptTInter1.x < 0 && ptTInter2.x > 0 && ptTInter2.x < dLLong) { ptTInter2.LocToLoc( TCylFrame, m_LocalFrame) ; dMin = min( ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter2.z) ; dMax = max( ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillCyl2( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! Control) return true ; // Punti notevoli Point3d ptI = ptLs ; Point3d ptF = ptLe ; Point3d ptIT = ptI - vtToolDir * dHei ; Point3d ptFT = ptF - vtToolDir * dHei ; // Vettori notevoli Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ; Vector3d vtLong = ( vtMove * vtToolDir) * vtToolDir ; double dLong = vtLong.Len() ; Vector3d vtOrt = vtMove - vtLong ; double dOrt = vtOrt.Len() ; double dCoef = dOrt / dLong ; double dAng = atan( 1 / dCoef) ; Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtOrt ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; // Definizione dei sistemi di riferimento Frame3d ICylFrame ; ICylFrame.Set( ptI, vtV1, vtV2, vtV3) ; Frame3d FCylFrame ; FCylFrame.Set( ptF, vtV1, vtV2, vtV3) ; Frame3d ITCylFrame ; ITCylFrame.Set( ptIT, vtV1, vtV2, vtV3) ; Frame3d FTCylFrame ; FTCylFrame.Set( ptFT, vtV1, vtV2, vtV3) ; Vector3d vtW1 = vtV1 ; vtW1.Rotate( vtV3, - 180 * dAng / PIGRECO) ; Vector3d vtW2 = vtV2 ; vtW2.Rotate( vtV3, - 180 * dAng / PIGRECO) ; Vector3d vtW3 = vtV3 ; Frame3d RotFrame ; RotFrame.Set( ptI, vtW1, vtW2, vtW3) ; Frame3d TRotFrame ; TRotFrame.Set( ptIT, vtW1, vtW2, vtW3) ; // Altri vettori notevoi Vector3d vtKC = Z_AX ; vtKC.LocToLoc( m_LocalFrame, ICylFrame) ; Vector3d vtRI = ptI - ORIG ; double dDotI = vtRI * vtV1 ; Vector3d vtRF = ptF - ORIG ; double dDotF = vtRF * vtV1 ; Vector3d vtRIT = ptIT - ORIG ; double dDotIT = vtRIT * vtV1 ; Vector3d vtRFT = ptFT - ORIG ; double dDotFT = vtRFT * vtV1 ; Vector3d vtRIPlus = vtRI + dRad * vtW3 ; Vector3d vtRIMinus = vtRI - dRad * vtW3 ; 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 - ORIG ; // Cilindro iniziale ptC.LocToLoc( m_LocalFrame, ICylFrame) ; std::vector vdICylCoef(3); std::vector vdICylRoots; vdICylCoef[0] = ptC.y * ptC.y + ptC.z * ptC.z - dRad * dRad ; vdICylCoef[1] = 2 * ( ptC.y * vtKC.y + ptC.z * vtKC.z) ; vdICylCoef[2] = vtKC.y * vtKC.y + vtKC.z * vtKC.z ; int nICylRoot = PolynomialRoots( 2, vdICylCoef, vdICylRoots) ; if ( nICylRoot == 0 || nICylRoot == 1) { Point3d ptPb ; ptPb.x = dX ; ptPb.y = dY ; ptPb.z = ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPt ; ptPt.x = dX ; ptPt.y = dY ; ptPt.z = ( dDotIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPb.LocToLoc( m_LocalFrame, ICylFrame) ; ptPt.LocToLoc( m_LocalFrame, ITCylFrame) ; if ( ptPb.y * ptPb.y + ptPb.z * ptPb.z < dRad * dRad && ptPt.y * ptPt.y + ptPt.z * ptPt.z < dRad * dRad) { ptPb.LocToLoc( ICylFrame, m_LocalFrame) ; ptPt.LocToLoc( ITCylFrame, m_LocalFrame) ; dMin = min( ptPb.z, ptPt.z) ; dMax = max( ptPb.z, ptPt.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nICylRoot == 2) { Point3d ptR1 = ptC + vdICylRoots[0] * vtKC ; Point3d ptR2 = ptC + vdICylRoots[1] * vtKC ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < - dHei && ptR2.x >= - dHei && ptR2.x < 0) { ptR2.LocToLoc( ICylFrame, m_LocalFrame) ; dMin = min( ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; dMax = max( ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < - dHei && ptR2.x >= 0) { dMin = min( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; dMax = max( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= - dHei && ptR1.x < 0 && ptR2.x < 0) { ptR1.LocToLoc( ICylFrame, m_LocalFrame) ; ptR2.LocToLoc( ICylFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= - dHei && ptR1.x < 0 && ptR2.x >= 0) { ptR1.LocToLoc( ICylFrame, m_LocalFrame) ; dMin = min( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; dMax = max( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Cilindro finale ptC.LocToLoc( ICylFrame, FCylFrame) ; std::vector vdFCylCoef(3); std::vector vdFCylRoots; vdFCylCoef[0] = ptC.y * ptC.y + ptC.z * ptC.z - dRad * dRad ; vdFCylCoef[1] = 2 * ( ptC.y * vtKC.y + ptC.z * vtKC.z) ; vdFCylCoef[2] = vtKC.y * vtKC.y + vtKC.z * vtKC.z ; int nFCylRoot = PolynomialRoots( 2, vdFCylCoef, vdFCylRoots) ; if ( nFCylRoot == 0 || nFCylRoot == 1) { Point3d ptPb ; ptPb.x = dX ; ptPb.y = dY ; ptPb.z = ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPt ; ptPt.x = dX ; ptPt.y = dY ; ptPt.z = ( dDotFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPb.LocToLoc( m_LocalFrame, FCylFrame) ; ptPt.LocToLoc( m_LocalFrame, FTCylFrame) ; if ( ptPb.y * ptPb.y + ptPb.z * ptPb.z < dRad * dRad && ptPt.y * ptPt.y + ptPt.z * ptPt.z < dRad * dRad) { ptPb.LocToLoc( FCylFrame, m_LocalFrame) ; ptPt.LocToLoc( FTCylFrame, m_LocalFrame) ; dMin = min( ptPb.z, ptPt.z) ; dMax = max( ptPb.z, ptPt.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nFCylRoot == 2) { Point3d ptR1 = ptC + vdFCylRoots[0] * vtKC ; Point3d ptR2 = ptC + vdFCylRoots[1] * vtKC ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < - dHei && ptR2.x >= - dHei && ptR2.x < 0) { ptR2.LocToLoc( FCylFrame, m_LocalFrame) ; dMin = min( ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; dMax = max( ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < - dHei && ptR2.x >= 0) { dMin = min( ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; dMax = max( ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= - dHei && ptR1.x < 0 && ptR2.x < 0) { ptR1.LocToLoc( FCylFrame, m_LocalFrame) ; ptR2.LocToLoc( FCylFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= - dHei && ptR1.x < 0 && ptR2.x >= 0) { ptR1.LocToLoc( FCylFrame, m_LocalFrame) ; dMin = min( ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; dMax = max( ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Traslazione ellisse fondo ptC.LocToLoc( FCylFrame, ICylFrame) ; std::vector vdEllipseCoef(3); std::vector vdEllipseRoots; vdEllipseCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dRad * dRad ; vdEllipseCoef[1] = 2 * ( dCoef * dCoef * vtKC.x * ptC.x + vtKC.y * ptC.y + vtKC.z * ptC.z - dCoef * ( vtKC.x * ptC.y + vtKC.y * ptC.x)) ; vdEllipseCoef[2] = dCoef * dCoef * vtKC.x * vtKC.x + vtKC.y * vtKC.y + vtKC.z * vtKC.z - 2 * dCoef * vtKC.x * vtKC.y ; int nEllipseRoot = PolynomialRoots( 2, vdEllipseCoef, vdEllipseRoots) ; if ( nEllipseRoot == 0 || nEllipseRoot == 1) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, ICylFrame) ; ptPf.LocToLoc( m_LocalFrame, FCylFrame) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dRad * dRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dRad * dRad) { ptPi.LocToLoc( ICylFrame, m_LocalFrame) ; ptPf.LocToLoc( FCylFrame, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nEllipseRoot == 2) { Point3d ptR1 = ptC + vdEllipseRoots[0] * vtKC ; Point3d ptR2 = ptC + vdEllipseRoots[1] * vtKC ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < 0 && ptR2.x >= 0 && ptR2.x < dLong) { ptR2.LocToLoc( ICylFrame, m_LocalFrame) ; dMin = min( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; dMax = max( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < 0 && ptR2.x >= dLong) { dMin = min( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; dMax = max( ( dDotI - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dLong && ptR2.x < dLong) { ptR1.LocToLoc( ICylFrame, m_LocalFrame) ; ptR2.LocToLoc( ICylFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dLong && ptR2.x >= dLong) { ptR1.LocToLoc( ICylFrame, m_LocalFrame) ; dMin = min( ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; dMax = max( ( dDotF - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Traslazione ellisse punta ptC.LocToLoc( ICylFrame, ITCylFrame) ; std::vector vdTEllipseCoef(3); std::vector vdTEllipseRoots; vdTEllipseCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dRad * dRad ; vdTEllipseCoef[1] = 2 * ( dCoef * dCoef * vtKC.x * ptC.x + vtKC.y * ptC.y + vtKC.z * ptC.z - dCoef * ( vtKC.x * ptC.y + vtKC.y * ptC.x)) ; vdTEllipseCoef[2] = dCoef * dCoef * vtKC.x * vtKC.x + vtKC.y * vtKC.y + vtKC.z * vtKC.z - 2 * dCoef * vtKC.x * vtKC.y ; int nTEllipseRoot = PolynomialRoots( 2, vdTEllipseCoef, vdTEllipseRoots) ; if ( nTEllipseRoot == 0 || nTEllipseRoot == 1) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, ITCylFrame) ; ptPf.LocToLoc( m_LocalFrame, FTCylFrame) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dRad * dRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dRad * dRad) { ptPi.LocToLoc( ITCylFrame, m_LocalFrame) ; ptPf.LocToLoc( FTCylFrame, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nTEllipseRoot == 2) { Point3d ptR1 = ptC + vdTEllipseRoots[0] * vtKC ; Point3d ptR2 = ptC + vdTEllipseRoots[1] * vtKC ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < 0 && ptR2.x >= 0 && ptR2.x < dLong) { ptR2.LocToLoc( ITCylFrame, m_LocalFrame) ; dMin = min( ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; dMax = max( ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < 0 && ptR2.x >= dLong) { dMin = min( ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; dMax = max( ( dDotIT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dLong && ptR2.x < dLong) { ptR1.LocToLoc( ITCylFrame, m_LocalFrame) ; ptR2.LocToLoc( ITCylFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dLong && ptR2.x >= dLong) { ptR1.LocToLoc( ITCylFrame, m_LocalFrame) ; dMin = min( ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; dMax = max( ( dDotFT - dX * vtV1.x - dY * vtV1.y) / vtV1.z, ptR1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Parallelepipedo Point3d ptInt1 = ptC + ( ( ( vtRI - vtC) * vtV2) / ( Z_AX * vtV2)) * Z_AX ; Point3d ptInt2 = ptC + ( ( ( vtRI - vtC) * vtW1) / ( Z_AX * vtW1)) * Z_AX ; Point3d ptInt3 = ptC + ( ( ( vtRF - vtC) * vtV2) / ( Z_AX * vtV2)) * Z_AX ; Point3d ptInt4 = ptC + ( ( ( vtRIT - vtC) * vtW1) / ( Z_AX * vtW1)) * Z_AX ; Point3d ptInt5 = ptC + ( ( ( vtRIPlus - vtC) * vtV3) / ( Z_AX * vtV3)) * Z_AX ; Point3d ptInt6 = ptC + ( ( ( vtRIMinus - vtC) * vtV3) / ( Z_AX * vtV3)) * Z_AX ; ptInt1.LocToLoc( m_LocalFrame, ICylFrame) ; ptInt2.LocToLoc( m_LocalFrame, RotFrame) ; ptInt3.LocToLoc( m_LocalFrame, FCylFrame) ; ptInt4.LocToLoc( m_LocalFrame, TRotFrame) ; ptInt5.LocToLoc( m_LocalFrame, ICylFrame) ; ptInt6.LocToLoc( m_LocalFrame, ICylFrame) ; bool bFlag = false ; double dLim1, dLim2 ; if ( ptInt1.x >= - dHei && ptInt1.x <= 0 && ptInt1.z >= - dRad && ptInt1.z <= dRad) { ptInt1.LocToLoc( ICylFrame, m_LocalFrame) ; dLim1 = ptInt1.z ; bFlag = true ; } if ( ptInt2.y >= 0 && ptInt2.y <= dLen && ptInt2.z >= - dRad && ptInt2.z <= dRad) { ptInt2.LocToLoc( RotFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt2.z ; bFlag = true ; } else dLim2 = ptInt2.z ; } if ( ptInt3.z >= - dRad && ptInt3.z <= dRad && ptInt3.x >= - dHei && ptInt3.x <= 0) { ptInt3.LocToLoc( FCylFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt3.z ; bFlag = true ; } else dLim2 = ptInt3.z ; } if ( ptInt4.z >= - dRad && ptInt4.z <= dRad && ptInt4.y >= 0 && ptInt4.y <= dLen) { ptInt4.LocToLoc( TRotFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt4.z ; bFlag = true ; } else dLim2 = ptInt4.z ; } if ( ptInt5.y >= 0 && ptInt5.y <= dOrt && ptInt5.x >= - dHei + dCoef * ptInt5.y && ptInt5.x <= dCoef * ptInt5.y) { ptInt5.LocToLoc( ICylFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt5.z ; bFlag = true ; } else dLim2 = ptInt5.z ; } if ( ptInt6.y >= 0 && ptInt6.y <= dOrt && ptInt6.x >= - dHei + dCoef * ptInt6.y && ptInt6.x <= dCoef * ptInt6.y) { ptInt6.LocToLoc( ICylFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt6.z ; bFlag = true ; } else dLim2 = ptInt6.z ; } if ( bFlag == true) { // Una linea non confinata se entra in un volume chiuso ci deve uscire dMin = min( dLim1, dLim2) ; dMax = max( dLim1, dLim2) ; SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillBall( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dRad) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bControl = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, 0, 0) ; if ( ! bControl) return true ; Point3d ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; Point3d ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Vector3d vtMove = ptF - ptI ; Vector3d vtV1( vtMove.x, vtMove.y, 0) ; vtV1.Normalize() ; Vector3d vtV2( vtV1) ; vtV2.Rotate( Z_AX, 90) ; double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; double dPLen = vtMove.LenXY() ; double dSin = dPLen / vtMove.Len() ; double dCos = dDeltaZ / vtMove.Len() ; 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 - ptIxy ; double dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ; if ( ( dP1 >= 0 && dP1 <= dPLen && abs( dP2) < dRad) || ( dP1 * dP1 + dP2 * dP2 < dRad * dRad) || ( ( dP1 - dPLen) * ( dP1 - dPLen) + dP2 * dP2 < dRad * dRad)) { // Massimi if ( dP1 < - dRad * dCos * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad))) { double dH = sqrt( dRad * dRad - dP1 * dP1 - dP2 * dP2) ; dMax = dZI + dH ; } else if ( dP1 < dPLen - dRad * dCos * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad))) { double dP0 = - dRad * dCos * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad)) ; double dZ0 = dRad * dSin * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad)) ; dMax = dZI + dZ0 + ( dP1 - dP0) * dDeltaZ / dPLen ; } else { double dH = sqrt( dRad * dRad - ( dP1 - dPLen) * ( dP1 - dPLen) - dP2 * dP2) ; dMax = dZI + dDeltaZ + dH ; } // Minimi if ( dP1 < dRad * dCos * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad))) { double dH = sqrt( dRad * dRad - dP1 * dP1 - dP2 * dP2) ; dMin = dZI - dH ; } else if ( dP1 < dPLen + dRad * dCos * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad))) { double dP0 = dRad * dCos * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad)) ; double dZ0 = - dRad * dSin * sqrt( 1 - ( dP2 * dP2) / ( dRad * dRad)) ; dMin = dZI + dZ0 + ( dP1 - dP0) * dDeltaZ / dPLen ; } else { double dH = sqrt( dRad * dRad - ( dP1 - dPLen) * ( dP1 - dPLen) - dP2 * dP2) ; dMin = dZI + dDeltaZ - dH ; } SubtractIntervals( i, j, dMin, dMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillConus( const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, vtToolDir, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! Control) return true ; double dDeltaR = dMaxRad - dMinRad ; Point3d ptI = ( vtToolDir * ( ptLe - ptLs) > 0 ? ptLs : ptLe) ; Point3d ptF = ( vtToolDir * ( ptLe - ptLs) > 0 ? ptLe : ptLs) ; Point3d ptIT = ptI - vtToolDir * dHei ; Point3d ptFT = ptF - vtToolDir * dHei ; double dL = ( ( dMaxRad * dHei) / ( dDeltaR)) ; double dl = dL - dHei ; Point3d ptIV = ptI - vtToolDir * dL ; Point3d ptFV = ptF - vtToolDir * dL ; Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ; Vector3d vtMLong = ( vtMove * vtToolDir) * vtToolDir ; double dLLong = vtMLong.Len() ; Vector3d vtMOrt = vtMove - vtMLong ; double dLOrt = vtMOrt.Len() ; Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtMOrt ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; // Apertura del cono e parametri per determinare i piani double dTan = dDeltaR / dHei ; double dRatio = dLLong / dLOrt ; double dCos = dTan * dRatio ; double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTan * dTan) ; double dCoef = dLOrt / dLLong ; // Per traslazione ellissi if ( dRatio > 1 / dTan) return MillConusAux( ptI, ptF, vtV1, vtV2, vtV3, nStartI, nStartJ, nEndI, nEndJ, dHei, dMaxRad, dMinRad, dCoef) ; // Versori normali e prodotti scalari per per determinare i piani // Piani laterali: Vector3d vtNs = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 + ( dSin / dDen) * vtV3 ; Vector3d vtNd = - ( dTan / dDen) * vtV1 + ( dCos / dDen) * vtV2 - ( dSin / dDen) * vtV3 ; Vector3d vtRIV = ptIV - ORIG ; // double dDots = vtRIV * vtNs ; // forse qui è meglio due punti ptIT + vtV3 * dMinRad e ptIT - vtV3 * dMinRad // double dDotd = vtRIV * vtNd ; Vector3d vtS1 = vtNs ; Vector3d vtS2 = vtMove ; vtS2.Normalize() ; // double dDotTestqs = vtS1 * vtS2 ; Vector3d vtS3 = vtS1 ^ vtS2 ; Vector3d vtD1 = vtNd ; Vector3d vtD2 = vtS2 ; // double dDotTestD = vtD1 * vtD2 ; Vector3d vtD3 = vtD1 ^ vtD2 ; Point3d ptS = ptI + vtV2 * ( dMaxRad * dCos) + vtV3 * ( dMaxRad * dSin) ; Point3d ptD = ptI + vtV2 * ( dMaxRad * dCos) - vtV3 * ( dMaxRad * dSin) ; Point3d ptST = ptIT + vtV2 * ( dMinRad * dCos) + vtV3 * ( dMinRad * dSin) ; Vector3d vtLen = ptST - ptS ; double dPLong = abs( vtLen * vtS3) ; double dPOrt = abs( vtLen * vtS2) ; // Vector3d vtLTr = vtLen - dPLong * vtS3 ; // double dPOrt = vtLTr.Len() ; // Piani di fondo e punta: Vector3d vtU1 = - dLOrt * vtV1 + dLLong * vtV2 ; vtU1.Normalize() ; Vector3d vtU2 = vtMove ; vtU2.Normalize() ; // double dDotTest = vtU1 * vtU2 ; Vector3d vtU3 = vtU1 ^ vtU2 ; Point3d ptU = ptI + vtV2 * ( dMaxRad * dCos) ; Point3d ptTU = ptIT + vtV2 * ( dMinRad * dCos) ; Vector3d vtRU = ptU - ORIG ; // double dDotB = vtRU * vtU1 ; Vector3d vtRUT = ptTU - ORIG ; // double dDotT = vtRUT * vtU1 ; // Piani finale e iniziale: Vector3d vtVAux = ptTU - ptU ; double dAuxOrt = vtVAux * vtV2 ; double dAuxLong = vtVAux * vtV1 ; // Tenere in considerazione per tronchi con dimensioni tali da poter approssimare tori Vector3d vtW1 = - dAuxOrt * vtV1 + dAuxLong * vtV2 ; double dLAux1 = vtW1.Len() ; vtW1.Normalize() ; Vector3d vtW2 = vtVAux ; double dLAux2 = vtW2.Len() ; vtW2.Normalize() ; // double dDottest = vtW1 * vtW2 ; Vector3d vtW3 = vtW1 ^ vtW2 ; double dPr2 = vtLen * vtW2 ; double prova1 = vtLen * vtW3 ; double prova2 = dSin * dDeltaR ; Point3d ptFU = ptU + vtMove ; Vector3d vtRFU = ptFU - ORIG ; // double dDotPF = vtRFU * vtW1 ; // Piani cono: Vector3d vtRCI = ptI - ORIG ; double dDotCI = vtRCI * vtV1 ; Vector3d vtRCIT = ptIT - ORIG ; double dDotCIT = vtRCIT * vtV1 ; Vector3d vtRCF = ptF - ORIG ; double dDotCF = vtRCF * vtV1 ; Vector3d vtRCFT = ptFT - ORIG ; double dDotCFT = vtRCFT * vtV1 ; // Sistemi di riferimento Frame3d IConeFrame ; IConeFrame.Set( ptIV, vtV1, vtV2, vtV3) ; Frame3d FConeFrame ; FConeFrame.Set( ptFV, vtV1, vtV2, vtV3) ; Frame3d PlSFrame ; PlSFrame.Set( ptS, vtS1, vtS2, vtS3) ; Frame3d PlDFrame ; PlDFrame.Set( ptD, vtD1, vtD2, vtD3) ; Frame3d PlBFrame ; PlBFrame.Set( ptU, vtU1, vtU2, vtU3) ; Frame3d PlTFrame ; PlTFrame.Set( ptTU, vtU1, vtU2, vtU3) ; Frame3d PlIFrame ; PlIFrame.Set( ptU, vtW1, vtW2, vtW3) ; Frame3d PlFFrame ; PlFFrame.Set( ptFU, vtW1, vtW2, vtW3) ; Frame3d LargeEllipse ; LargeEllipse.Set( ptI, vtV1, vtV2, vtV3) ; Frame3d FLargeEllipse ; FLargeEllipse.Set( ptF, vtV1, vtV2, vtV3) ; Frame3d SmallEllipse ; SmallEllipse.Set( ptIT, vtV1, vtV2, vtV3) ; Frame3d FSmallEllipse ; FSmallEllipse.Set( ptFT, vtV1, vtV2, vtV3) ; 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 - ORIG ; Vector3d vtK = Z_AX ; // Cono I ptC.LocToLoc( m_LocalFrame, IConeFrame) ; vtK.LocToLoc( m_LocalFrame, IConeFrame) ; std::vector vdIConeCoef(3); std::vector vdIConeRoots; vdIConeCoef[0] = dTan * dTan * ptC.x * ptC.x - ptC.y * ptC.y - ptC.z * ptC.z ; vdIConeCoef[1] = 2 * ( dTan * dTan * ptC.x * vtK.x - ptC.y * vtK.y - ptC.z * vtK.z) ; vdIConeCoef[2] = dTan * dTan * vtK.x * vtK.x - vtK.y * vtK.y - vtK.z * vtK.z ; int nIConeRoot = PolynomialRoots( 2, vdIConeCoef, vdIConeRoots) ; if ( nIConeRoot == 1) { Point3d ptR1 = ptC + vdIConeRoots[0] * vtK ; if ( ptR1.x >= dl && ptR1.x < dL) { ptR1.LocToLoc( IConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dl) { dMin = min( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nIConeRoot == 2) { Point3d ptR1 = ptC + vdIConeRoots[0] * vtK ; Point3d ptR2 = ptC + vdIConeRoots[1] * vtK ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < 0 && ptR2.x > 0 && ptR2.x < dl) { dMin = min( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < 0 && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( IConeFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( IConeFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dL) { dMin = min( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x < dL) { ptR1.LocToLoc( IConeFrame, m_LocalFrame) ; ptR2.LocToLoc( IConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x >= dL) { ptR1.LocToLoc( IConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Cono F ptC.LocToLoc( IConeFrame, FConeFrame) ; vtK.LocToLoc( IConeFrame, FConeFrame) ; std::vector vdFConeCoef(3); std::vector vdFConeRoots; vdFConeCoef[0] = dTan * dTan * ptC.x * ptC.x - ptC.y * ptC.y - ptC.z * ptC.z ; vdFConeCoef[1] = 2 * ( dTan * dTan * ptC.x * vtK.x - ptC.y * vtK.y - ptC.z * vtK.z) ; vdFConeCoef[2] = dTan * dTan * vtK.x * vtK.x - vtK.y * vtK.y - vtK.z * vtK.z ; int nFConeRoot = PolynomialRoots( 2, vdFConeCoef, vdFConeRoots) ; if ( nFConeRoot == 1) { Point3d ptR1 = ptC + vdFConeRoots[0] * vtK ; if ( ptR1.x >= dl && ptR1.x < dL) { ptR1.LocToLoc( FConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dl) { dMin = min( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nFConeRoot == 2) { Point3d ptR1 = ptC + vdFConeRoots[0] * vtK ; Point3d ptR2 = ptC + vdFConeRoots[1] * vtK ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < 0 && ptR2.x > 0 && ptR2.x < dl) { dMin = min( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < 0 && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( FConeFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( FConeFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dL) { dMin = min( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x < dL) { ptR1.LocToLoc( FConeFrame, m_LocalFrame) ; ptR2.LocToLoc( FConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x >= dL) { ptR1.LocToLoc( FConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Solido interno ptC.LocToLoc( FConeFrame, m_LocalFrame) ; vtK.LocToLoc( FConeFrame, m_LocalFrame) ; Point3d ptInt1 = ptC + ( ( ( vtRIV - vtC) * vtS1) / ( vtK * vtS1)) * vtK ; Point3d ptInt2 = ptC + ( ( ( vtRIV - vtC) * vtD1) / ( vtK * vtD1)) * vtK ; Point3d ptInt3 = ptC + ( ( ( vtRU - vtC) * vtU1) / ( vtK * vtU1)) * vtK ; Point3d ptInt4 = ptC + ( ( ( vtRUT - vtC) * vtU1) / ( vtK * vtU1)) * vtK ; Point3d ptInt5 = ptC + ( ( ( vtRU - vtC) * vtW1) / ( vtK * vtW1)) * vtK ; Point3d ptInt6 = ptC + ( ( ( vtRFU - vtC) * vtW1) / ( vtK * vtW1)) * vtK ; ptInt1.LocToLoc( m_LocalFrame, PlSFrame) ; ptInt2.LocToLoc( m_LocalFrame, PlDFrame) ; ptInt3.LocToLoc( m_LocalFrame, PlBFrame) ; ptInt4.LocToLoc( m_LocalFrame, PlTFrame) ; ptInt5.LocToLoc( m_LocalFrame, PlIFrame) ; ptInt6.LocToLoc( m_LocalFrame, PlFFrame) ; double dLim1, dLim2 ; bool bFlag = false ; if ( ptInt1.z >= 0 && ptInt1.z <= dPLong && ptInt1.y >= - ptInt1.z * dPOrt / dPLong && ptInt1.y <= dLen - ptInt1.z * dPOrt / dPLong ) { ptInt1.LocToLoc( PlSFrame, m_LocalFrame) ; dLim1 = ptInt1.z ; bFlag = true ; } if ( ptInt2.z >= - dPLong && ptInt2.z <= 0 && ptInt2.y >= ptInt2.z * dPOrt / dPLong && ptInt2.y <= dLen + ptInt2.z * dPOrt / dPLong) { ptInt2.LocToLoc( PlDFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt2.z ; bFlag = true ; } else dLim2 = ptInt2.z ; } if ( ptInt3.y >= 0 && ptInt3.y <= dLen && ptInt3.z > - dMaxRad * dSin && ptInt3.z < dMaxRad * dSin) { ptInt3.LocToLoc( PlBFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt3.z ; bFlag = true ; } else dLim2 = ptInt3.z ; } if ( ptInt4.y >= 0 && ptInt4.y <= dLen && ptInt4.z > - dMinRad * dSin && ptInt4.z < dMinRad * dSin) { ptInt4.LocToLoc( PlTFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt4.z ; bFlag = true ; } else dLim2 = ptInt4.z ; } if ( ptInt5.y >= 0 && ptInt5.y <= dPr2 && ptInt5.z > - dSin * dMaxRad + ptInt5.y * prova1 / dPr2 && ptInt5.z < dSin * dMaxRad - ptInt5.y * prova1 / dPr2) { ptInt5.LocToLoc( PlIFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt5.z ; bFlag = true ; } else dLim2 = ptInt5.z ; } if ( ptInt6.y >= 0 && ptInt6.y <= dPr2 && ptInt6.z > - dSin * dMaxRad + ptInt6.y * prova1 / dPr2 && ptInt6.z < dSin * dMaxRad - ptInt6.y * prova1 / dPr2) { ptInt6.LocToLoc( PlFFrame, m_LocalFrame) ; if ( bFlag == false) { dLim1 = ptInt6.z ; bFlag = true ; } else dLim2 = ptInt6.z ; } if( bFlag == true) { dMin = min( dLim1, dLim2) ; dMax = max( dLim1, dLim2) ; SubtractIntervals( i, j, dMin, dMax) ; } // Traslazioni ellissi ptC.LocToLoc( m_LocalFrame, LargeEllipse) ; vtK.LocToLoc( m_LocalFrame, LargeEllipse) ; std::vector vdLargeCoef(3); std::vector vdLargeRoots; vdLargeCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dMaxRad * dMaxRad ; vdLargeCoef[1] = 2 * ( dCoef * dCoef * vtK.x * ptC.x + vtK.y * ptC.y + vtK.z * ptC.z - dCoef * ( vtK.x * ptC.y + vtK.y * ptC.x)) ; vdLargeCoef[2] = dCoef * dCoef * vtK.x * vtK.x + vtK.y * vtK.y + vtK.z * vtK.z - 2 * dCoef * vtK.x * vtK.y ; int nLRoot = PolynomialRoots( 2, vdLargeCoef, vdLargeRoots) ; if ( nLRoot == 0) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, LargeEllipse) ; ptPf.LocToLoc( m_LocalFrame, FLargeEllipse) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dMaxRad * dMaxRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dMaxRad * dMaxRad) { ptPi.LocToLoc( LargeEllipse, m_LocalFrame) ; ptPf.LocToLoc( FLargeEllipse, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nLRoot == 2) { Point3d ptInter1 = ptC + vdLargeRoots[0] * vtK ; Point3d ptInter2 = ptC + vdLargeRoots[1] * vtK ; if ( ptInter1.x > ptInter2.x) { Point3d ptTemp = ptInter1 ; ptInter1 = ptInter2 ; ptInter2 = ptTemp ; } if ( ptInter1.x > 0 && ptInter1.x < dLLong && ptInter2.x > dLLong) { ptInter1.LocToLoc( LargeEllipse, m_LocalFrame) ; dMin = min( ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter1.z) ; dMax = max( ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x > 0 && ptInter2.x < dLLong) { ptInter1.LocToLoc( LargeEllipse, m_LocalFrame) ; ptInter2.LocToLoc( LargeEllipse, m_LocalFrame) ; dMin = min( ptInter1.z, ptInter2.z) ; dMax = max( ptInter1.z, ptInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x < 0 && ptInter2.x > dLLong) { dMin = min( ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x < 0 && ptInter2.x > 0 && ptInter2.x < dLLong) { ptInter2.LocToLoc( LargeEllipse, m_LocalFrame) ; dMin = min( ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter2.z) ; dMax = max( ( dDotCI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } ptC.LocToLoc( LargeEllipse, SmallEllipse) ; vtK.LocToLoc( LargeEllipse, SmallEllipse) ; std::vector vdSmallCoef(3); std::vector vdSmallRoots; vdSmallCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dMinRad * dMinRad ; vdSmallCoef[1] = 2 * ( dCoef * dCoef * vtK.x * ptC.x + vtK.y * ptC.y + vtK.z * ptC.z - dCoef * ( vtK.x * ptC.y + vtK.y * ptC.x)) ; vdSmallCoef[2] = dCoef * dCoef * vtK.x * vtK.x + vtK.y * vtK.y + vtK.z * vtK.z - 2 * dCoef * vtK.x * vtK.y ; int nSRoot = PolynomialRoots( 2, vdSmallCoef, vdSmallRoots) ; if ( nSRoot == 0) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, SmallEllipse) ; ptPf.LocToLoc( m_LocalFrame, FSmallEllipse) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dMinRad * dMinRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dMinRad * dMinRad) { ptPi.LocToLoc( SmallEllipse, m_LocalFrame) ; ptPf.LocToLoc( FSmallEllipse, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nSRoot == 2) { Point3d ptTInter1 = ptC + vdSmallRoots[0] * vtK ; Point3d ptTInter2 = ptC + vdSmallRoots[1] * vtK ; if ( ptTInter1.x > ptTInter2.x) { Point3d ptTemp = ptTInter1 ; ptTInter1 = ptTInter2 ; ptTInter2 = ptTemp ; } if ( ptTInter1.x > 0 && ptTInter1.x < dLLong && ptTInter2.x > dLLong) { ptTInter1.LocToLoc( SmallEllipse, m_LocalFrame) ; dMin = min( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter1.z) ; dMax = max( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptTInter1.x > 0 && ptTInter2.x < dLLong) { ptTInter1.LocToLoc( SmallEllipse, m_LocalFrame) ; ptTInter2.LocToLoc( SmallEllipse, m_LocalFrame) ; dMin = min( ptTInter1.z, ptTInter2.z) ; dMax = max( ptTInter1.z, ptTInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptTInter1.x < 0 && ptTInter2.x > dLLong) { dMin = min( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotCFT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptTInter1.x < 0 && ptTInter2.x > 0 && ptTInter2.x < dLLong) { ptTInter2.LocToLoc( SmallEllipse, m_LocalFrame) ; dMin = min( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter2.z) ; dMax = max( ( dDotCIT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptTInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::MillConusAux( const Point3d& ptI, const Point3d& ptF, const Vector3d& vtV1, const Vector3d& vtV2, const Vector3d& vtV3, unsigned int & nStI, unsigned int & nStJ, unsigned int & nEnI, unsigned int & nEnJ, double dHei, double dMaxRad, double dMinRad, double dCoef) { double dDeltaR = dMaxRad - dMinRad ; double dL = ( ( dMaxRad * dHei) / ( dDeltaR)) ; double dTan = dDeltaR / dHei ; double dl = dL - dHei ; double dLLong = abs( ( ptF - ptI) * vtV1) ; double dLOrt = abs( ( ptF - ptI) * vtV2) ; Point3d ptV = ptI - vtV1 * dL ; Point3d ptT = ptI - vtV1 * dHei ; Frame3d ConeFrame ; ConeFrame.Set( ptV, vtV1, vtV2, vtV3) ; Frame3d IEllipseFrame ; IEllipseFrame.Set( ptI, vtV1, vtV2, vtV3) ; Frame3d FEllipseFrame ; FEllipseFrame.Set( ptF, vtV1, vtV2, vtV3) ; Vector3d vtI = ptI - ORIG ; double dDotI = vtI * vtV1 ; Vector3d vtT = ptT - ORIG ; double dDotT = vtT * vtV1 ; Vector3d vtF = ptF - ORIG ; double dDotF = vtF * vtV1 ; Vector3d vtK = Z_AX ; Vector3d vtKC = vtK ; vtKC.LocToLoc( m_LocalFrame, ConeFrame) ; Vector3d vtKE = vtK ; vtKE.LocToLoc( m_LocalFrame, IEllipseFrame) ; double dMin, dMax ; for ( unsigned int i = nStI ; i <= nEnI ; ++ i) { for ( unsigned int j = nStJ ; j <= nEnJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ORIG ; // Cono ptC.LocToLoc( m_LocalFrame, ConeFrame) ; std::vector vdConeCoef(3); std::vector vdConeRoots; vdConeCoef[0] = dTan * dTan * ptC.x * ptC.x - ptC.y * ptC.y - ptC.z * ptC.z ; vdConeCoef[1] = 2 * ( dTan * dTan * ptC.x * vtKC.x - ptC.y * vtKC.y - ptC.z * vtKC.z) ; vdConeCoef[2] = dTan * dTan * vtKC.x * vtKC.x - vtKC.y * vtKC.y - vtKC.z * vtKC.z ; int nConeRoot = PolynomialRoots( 2, vdConeCoef, vdConeRoots) ; if ( nConeRoot == 1) { Point3d ptR1 = ptC + vdConeRoots[0] * vtKC ; if ( ptR1.x >= dl && ptR1.x < dL) { ptR1.LocToLoc( ConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= 0 && ptR1.x < dl) { dMin = min( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } else if ( nConeRoot == 2) { Point3d ptR1 = ptC + vdConeRoots[0] * vtKC ; Point3d ptR2 = ptC + vdConeRoots[1] * vtKC ; if ( ptR1.x > ptR2.x) { Point3d ptTemp = ptR1 ; ptR1 = ptR2 ; ptR2 = ptTemp ; } if ( ptR1.x < 0 && ptR2.x > 0 && ptR2.x < dl) { dMin = min( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x < 0 && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( ConeFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dl && ptR2.x < dL) { ptR2.LocToLoc( ConeFrame, m_LocalFrame) ; dMin = min( ptR2.z, ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR2.z, ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x > 0 && ptR1.x < dl && ptR2.x >= dL) { dMin = min( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotT - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x < dL) { ptR1.LocToLoc( ConeFrame, m_LocalFrame) ; ptR2.LocToLoc( ConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ptR2.z) ; dMax = max( ptR1.z, ptR2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptR1.x >= dl && ptR1.x < dL && ptR2.x >= dL) { ptR1.LocToLoc( ConeFrame, m_LocalFrame) ; dMin = min( ptR1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ptR1.z, ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } // Tralsazione dell'ellisse ptC.LocToLoc( ConeFrame, IEllipseFrame) ; std::vector vdEllipseCoef(3); std::vector vdEllipseRoots; vdEllipseCoef[0] = dCoef * dCoef * ptC.x * ptC.x + ptC.y * ptC.y + ptC.z * ptC.z - 2 * dCoef * ptC.x * ptC.y - dMaxRad * dMaxRad ; vdEllipseCoef[1] = 2 * ( dCoef * dCoef * vtKE.x * ptC.x + vtKE.y * ptC.y + vtKE.z * ptC.z - dCoef * ( vtKE.x * ptC.y + vtKE.y * ptC.x)) ; vdEllipseCoef[2] = dCoef * dCoef * vtKE.x * vtKE.x + vtKE.y * vtKE.y + vtKE.z * vtKE.z - 2 * dCoef * vtKE.x * vtKE.y ; int nEllipseRoot = PolynomialRoots( 2, vdEllipseCoef, vdEllipseRoots) ; if ( nEllipseRoot == 0 || nEllipseRoot == 1) { Point3d ptPi ; ptPi.x = dX ; ptPi.y = dY ; ptPi.z = ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; Point3d ptPf ; ptPf.x = dX ; ptPf.y = dY ; ptPf.z = ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z ; ptPi.LocToLoc( m_LocalFrame, IEllipseFrame) ; ptPf.LocToLoc( m_LocalFrame, FEllipseFrame) ; if ( ptPi.y * ptPi.y + ptPi.z * ptPi.z < dMaxRad * dMaxRad && ptPf.y * ptPf.y + ptPf.z * ptPf.z < dMaxRad * dMaxRad) { ptPi.LocToLoc( IEllipseFrame, m_LocalFrame) ; ptPf.LocToLoc( FEllipseFrame, m_LocalFrame) ; dMin = min( ptPi.z, ptPf.z) ; dMax = max( ptPi.z, ptPf.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } if ( nEllipseRoot == 2) { Point3d ptInter1 = ptC + vdEllipseRoots[0] * vtKE ; Point3d ptInter2 = ptC + vdEllipseRoots[1] * vtKE ; if ( ptInter1.x > ptInter2.x) { Point3d ptTemp = ptInter1 ; ptInter1 = ptInter2 ; ptInter2 = ptTemp ; } if ( ptInter1.x > 0 && ptInter1.x < dLLong && ptInter2.x > dLLong) { ptInter1.LocToLoc( IEllipseFrame, m_LocalFrame) ; dMin = min( ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter1.z) ; dMax = max( ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x > 0 && ptInter2.x < dLLong) { ptInter1.LocToLoc( IEllipseFrame, m_LocalFrame) ; ptInter2.LocToLoc( IEllipseFrame, m_LocalFrame) ; dMin = min( ptInter1.z, ptInter2.z) ; dMax = max( ptInter1.z, ptInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x < 0 && ptInter2.x > dLLong) { dMin = min( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; dMax = max( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ( dDotF - vtV1.x * dX - vtV1.y * dY) / vtV1.z) ; SubtractIntervals( i, j, dMin, dMax) ; } else if ( ptInter1.x < 0 && ptInter2.x > 0 && ptInter2.x < dLLong) { ptInter2.LocToLoc( IEllipseFrame, m_LocalFrame) ; dMin = min( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter2.z) ; dMax = max( ( dDotI - vtV1.x * dX - vtV1.y * dY) / vtV1.z, ptInter2.z) ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } // Traslazioni //---------------------------------------------------------------------------- bool VolZmap::Ball( const Point3d& ptLs, const Point3d& ptLe, double dRad) { double dMin, dMax ; unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool Control = BBoxComponent( ptLs, ptLe, V_NULL, V_NULL, nStartI, nStartJ, nEndI, nEndJ, dRad, 0, 0) ; if ( ! Control) return true ; Point3d ptI = ( ptLs.z < ptLe.z ? ptLs : ptLe) ; Point3d ptF = ( ptLs.z < ptLe.z ? ptLe : ptLs) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dVLen = abs( vtMove.z) ; // Verticale e planare rispetto ai dexel double dPLen = vtMoveXY.LenXY() ; double dLen = vtMove.Len() ; double dR1 = dVLen / dLen ; double dR2 = dPLen / dLen ; double dZI = ptI.z ; double dDeltaZ = ptF.z - ptI.z ; if ( dPLen < EPS_SMALL) { 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 - ptIxy ; double dSqLen = vtC.SqLen() ; if ( dSqLen < dRad * dRad) { double dH = sqrt( dRad * dRad - dSqLen) ; dMin = dZI - dH ; dMax = dZI + dDeltaZ + dH ; SubtractIntervals( i, j, dMin, dMax) ; } } } } else { Vector3d vtV1 = vtMoveXY ; vtV1.Normalize() ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; 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 vtCI = ptC - ptIxy ; Vector3d vtCF = ptC - ptFxy ; double dX1 = vtCI * vtV1 ; double dX2 = vtCI * vtV2 ; double dISqDist = vtCI * vtCI ; double dFSqDist = vtCF * vtCF ; if ( dISqDist < dRad * dRad || dFSqDist < dRad * dRad || ( dX1 > 0 && dX1 < dPLen && dX2 * dX2 < dRad * dRad)) { // Massimi if ( dX1 < - dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad * dR2 * dR2)) && dISqDist < dRad * dRad) dMax = dZI + sqrt( dRad * dRad - dISqDist) ; else if ( dX1 >= - dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad)) && dX1 < dPLen - dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad))) dMax = dZI + dR2 * sqrt( dRad * dRad - dX2 * dX2) + ( dX1 + dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad))) * dVLen / dPLen ; else if ( dX1 >= dPLen - dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad)) && dFSqDist < dRad * dRad) dMax = dZI + dDeltaZ + sqrt( dRad * dRad - dFSqDist) ; // Minimi if ( dX1 < dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad)) && dISqDist < dRad * dRad) dMin = dZI - sqrt( dRad * dRad - dISqDist) ; else if ( dX1 >= dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad)) && dX1 < dPLen + dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad))) dMin = dZI - dR2 * sqrt( dRad * dRad - dX2 * dX2) + ( dX1 - dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad))) * dVLen / dPLen ; else if ( dX1 >= dPLen + dRad * dR1 * sqrt( 1 - ( dX2 * dX2) / ( dRad * dRad)) && dFSqDist < dRad * dRad) dMin = dZI + dDeltaZ - sqrt( dRad * dRad - dFSqDist) ; SubtractIntervals( i, j, dMin, dMax) ; } } } } return true ; } // Bounding Box, interferenza dell'utensile con lo Zmap e limiti su indici //---------------------------------------------------------------------------- inline bool VolZmap::BoundingBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV1, const Vector3d& vtV2, unsigned int & nStI, unsigned int & nStJ, unsigned int & nEnI, unsigned int & nEnJ) { // Determinazione del raggio massimo dell'utensile double dMaxRad = max( m_dRadius, m_dTipRadius) ; // Determinazione delle posizioni della punta dell'utensile nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - m_dHeight * vtV1 ; Point3d ptP2T = ptP2 - m_dHeight * vtV2 ; // Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento double dMinX = min( min( ptP1.x, ptP1T.x), min( ptP2.x, ptP2T.x)) - dMaxRad; double dMinY = min( min( ptP1.y, ptP1T.y), min( ptP2.y, ptP2T.y)) - dMaxRad; double dMinZ = min( min( ptP1.z, ptP1T.z), min( ptP2.z, ptP2T.z)) - dMaxRad; double dMaxX = max( max( ptP1.x, ptP1T.x), max( ptP2.x, ptP2T.x)) + dMaxRad; double dMaxY = max( max( ptP1.y, ptP1T.y), max( ptP2.y, ptP2T.y)) + dMaxRad; double dMaxZ = max( max( ptP1.z, ptP1T.z), max( ptP2.z, ptP2T.z)) + dMaxRad; // Verifica dell'interferenza dell'utensile con lo Zmap if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) return false ; if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) return false ; if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) return false ; // Limiti su indici nStI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; nEnI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; nEnJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; return true ; } //---------------------------------------------------------------------------- inline bool VolZmap::BoundingBox( unsigned int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV1, const Vector3d& vtV2, unsigned int& nStI, unsigned int& nStJ, unsigned int& nEnI, unsigned int& nEnJ) { // NB: E' vitale che vengano passati i punti e i vettori nel sistema di riferimento // di riferimento opportuno. unsigned int nMaxNx, nMaxNy ; double dMaxXValue, dMaxYValue ; double dMinZValue, dMaxZValue ; if ( nGrid == 1) { nMaxNx = m_nNx ; nMaxNy = m_nNy ; dMaxXValue = m_nNx * m_dStep ; dMaxYValue = m_nNy * m_dStep ; dMinZValue = m_dMinZ ; dMaxZValue = m_dMaxZ ; } else if ( nGrid == 2) { nMaxNx = m_nNx2 ; nMaxNy = m_nNy2 ; dMaxXValue = m_nNx2 * m_dStep ; dMaxYValue = m_nNy2 * m_dStep ; dMinZValue = m_dMinZ2 ; dMaxZValue = m_dMaxZ2 ; } else if ( nGrid == 3) { nMaxNx = m_nNx3 ; nMaxNy = m_nNy3 ; dMaxXValue = m_nNx3 * m_dStep ; dMaxYValue = m_nNy3 * m_dStep ; dMinZValue = m_dMinZ3 ; dMaxZValue = m_dMaxZ3 ; } // Determinazione del raggio massimo dell'utensile double dMaxRad = max( m_dRadius, m_dTipRadius) ; // Determinazione delle posizioni della punta dell'utensile nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - m_dHeight * vtV1 ; Point3d ptP2T = ptP2 - m_dHeight * vtV2 ; // Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento double dMinX = min( min( ptP1.x, ptP1T.x), min( ptP2.x, ptP2T.x)) - dMaxRad ; double dMinY = min( min( ptP1.y, ptP1T.y), min( ptP2.y, ptP2T.y)) - dMaxRad ; double dMinZ = min( min( ptP1.z, ptP1T.z), min( ptP2.z, ptP2T.z)) - dMaxRad ; double dMaxX = max( max( ptP1.x, ptP1T.x), max( ptP2.x, ptP2T.x)) + dMaxRad ; double dMaxY = max( max( ptP1.y, ptP1T.y), max( ptP2.y, ptP2T.y)) + dMaxRad ; double dMaxZ = max( max( ptP1.z, ptP1T.z), max( ptP2.z, ptP2T.z)) + dMaxRad ; // Verifica dell'interferenza dell'utensile con lo Zmap if ( dMaxX < EPS_SMALL || dMinX > dMaxXValue - EPS_SMALL) return false ; if ( dMaxY < EPS_SMALL || dMinY > dMaxYValue - EPS_SMALL) return false ; if ( dMaxZ < dMinZValue + EPS_SMALL || dMinZ > dMaxZValue - EPS_SMALL) return false ; // Limiti su indici nStI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; nEnI = ( dMaxX > dMaxXValue - EPS_SMALL ? nMaxNx - 1 : static_cast ( dMaxX / m_dStep)) ; nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; nEnJ = ( dMaxY > dMaxYValue - EPS_SMALL ? nMaxNy - 1 : static_cast ( dMaxY / m_dStep)) ; return true ; } //---------------------------------------------------------------------------- inline bool VolZmap::BoundingBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV1, const Vector3d& vtV2) { // Determinazione del raggio massimo dell'utensile double dMaxRad = max( m_dRadius, m_dTipRadius) ; // Determinazione delle posizioni della punta dell'utensile nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - m_dHeight * vtV1 ; Point3d ptP2T = ptP2 - m_dHeight * vtV2 ; // Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento double dMinX = min( min( ptP1.x, ptP1T.x), min( ptP2.x, ptP2T.x)) - dMaxRad ; double dMinY = min( min( ptP1.y, ptP1T.y), min( ptP2.y, ptP2T.y)) - dMaxRad ; double dMinZ = min( min( ptP1.z, ptP1T.z), min( ptP2.z, ptP2T.z)) - dMaxRad ; double dMaxX = max( max( ptP1.x, ptP1T.x), max( ptP2.x, ptP2T.x)) + dMaxRad ; double dMaxY = max( max( ptP1.y, ptP1T.y), max( ptP2.y, ptP2T.y)) + dMaxRad ; double dMaxZ = max( max( ptP1.z, ptP1T.z), max( ptP2.z, ptP2T.z)) + dMaxRad ; // Verifica dell'interferenza dell'utensile con lo Zmap if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) return false ; if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) return false ; if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) return false ; return true ; } //---------------------------------------------------------------------------- inline bool VolZmap::BBoxComponent( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV1, const Vector3d& vtV2, unsigned int & nStI, unsigned int & nStJ, unsigned int & nEnI, unsigned int & nEnJ, double dRad, double dTipRad, double dHei) { // Determinazione del raggio massimo dell'utensile double dMaxRad = max( dRad, dTipRad) ; // Determinazione delle posizioni della punta dell'utensile nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - dHei * vtV1 ; Point3d ptP2T = ptP2 - dHei * vtV2 ; // Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento double dMinX = min( min( ptP1.x, ptP1T.x), min( ptP2.x, ptP2T.x)) - dMaxRad; double dMinY = min( min( ptP1.y, ptP1T.y), min( ptP2.y, ptP2T.y)) - dMaxRad; double dMinZ = min( min( ptP1.z, ptP1T.z), min( ptP2.z, ptP2T.z)) - dMaxRad; double dMaxX = max( max( ptP1.x, ptP1T.x), max( ptP2.x, ptP2T.x)) + dMaxRad; double dMaxY = max( max( ptP1.y, ptP1T.y), max( ptP2.y, ptP2T.y)) + dMaxRad; double dMaxZ = max( max( ptP1.z, ptP1T.z), max( ptP2.z, ptP2T.z)) + dMaxRad; // Verifica dell'interferenza dell'utensile con lo Zmap if ( dMaxX < EPS_SMALL || dMinX > m_nNx * m_dStep - EPS_SMALL) return false ; if ( dMaxY < EPS_SMALL || dMinY > m_nNy * m_dStep - EPS_SMALL) return false ; if ( dMaxZ < m_dMinZ + EPS_SMALL || dMinZ > m_dMaxZ - EPS_SMALL) return false ; // Limiti su indici nStI = ( dMinX < EPS_SMALL ? 0 : static_cast ( dMinX / m_dStep)) ; nEnI = ( dMaxX > m_nNx * m_dStep - EPS_SMALL ? m_nNx - 1 : static_cast ( dMaxX / m_dStep)) ; nStJ = ( dMinY < EPS_SMALL ? 0 : static_cast ( dMinY / m_dStep)) ; nEnJ = ( dMaxY > m_nNy * m_dStep - EPS_SMALL ? m_nNy - 1 : static_cast ( dMaxY / m_dStep)) ; return true ; }