//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 // Contenuto : Implementazione della classe Volume Zmap (tre griglie) // // // // Modifiche : 22.01.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" #include "CurveArc.h" #include "VolZmap.h" #include "GeoConst.h" #include "IntersLineSurfTm.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkStringUtils3d.h" using namespace std ; // ------------------------- OPERAZIONI SU INTERVALLI -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::SubtractIntervals( unsigned int nGrid, unsigned int nI, unsigned int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax) { const double dTol = EPS_ZERO ; // Controllo che dMin e dMax non siano quasi coincidenti if ( abs( dMax - dMin) < dTol) return true ; // Controllo che il numero di griglia sia entro i limiti if ( nGrid < 0 || nGrid > 2) return false ; // Controllo che dMin < dMax if ( dMin > dMax) swap( dMin, dMax) ; // Controllo che indici nI, nJ siano entro i limiti if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid]) return false ; // Riporto le coordinate cicliche nell'ordine di partenza Vector3d vtNmi = vtNMin ; Vector3d vtNma = vtNMax ; // Passo dalla grilgia al sistema intrinseco if ( nGrid == 1) { swap( vtNmi.x, vtNmi.z) ; swap( vtNmi.y, vtNmi.z) ; swap( vtNma.x, vtNma.z) ; swap( vtNma.y, vtNma.z) ; } else if ( nGrid == 2) { swap( vtNmi.y, vtNmi.z) ; swap( vtNmi.x, vtNmi.z) ; swap( vtNma.y, vtNma.z) ; swap( vtNma.x, vtNma.z) ; } // Calcolo nPos unsigned int nPos = nJ * m_nNx[nGrid] + nI ; // Ciclo sugli intervalli del singolo dexel bool bModified = false ; unsigned int i = 0 ; while ( i < m_Values[nGrid][nPos].size()) { // Casi: // Intervallo da sottrarre è tutto a sinistra di quello corrente, non vi è intersezione if ( m_Values[nGrid][nPos][i].dMin > dMax - dTol) { ; } // Intersezione else if ( m_Values[nGrid][nPos][i].dMax > dMax + dTol) { // L'intervallo corrente viene limitato a sinistra if ( m_Values[nGrid][nPos][i].dMin > dMin - dTol) { bModified = true ; // Aggiornamento dati del tratto di dexel m_Values[nGrid][nPos][i].dMin = dMax ; m_Values[nGrid][nPos][i].vtMinN = vtNma ; m_Values[nGrid][nPos][i].nToolMin = m_Tool.GetCurrentToolNum() ; } // L'intervallo si divide in due intervalli else { bModified = true ; // Aumento la dimensione del dexel m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 1) ; size_t nStartT = max( 0, int( m_Values[nGrid][nPos].size()) - 1) ; // Sposto i tratti successivi a quello corrente in avanti di una posizione for ( size_t j = nStartT ; j >= i + 2 ; -- j) { // Quote estreme m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j - 1].dMax ; m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j - 1].dMin ; // Normali m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j - 1].vtMaxN ; m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j - 1].vtMinN ; // Numero utensile m_Values[nGrid][nPos][j].nToolMax = m_Values[nGrid][nPos][j - 1].nToolMax ; m_Values[nGrid][nPos][j].nToolMin = m_Values[nGrid][nPos][j - 1].nToolMin ; // Indice di componente m_Values[nGrid][nPos][j].nCompo = m_Values[nGrid][nPos][j - 1].nCompo ; } // Divido in due il tratto corrente // Parte superiore m_Values[nGrid][nPos][i + 1].dMax = m_Values[nGrid][nPos][i].dMax ; m_Values[nGrid][nPos][i + 1].vtMaxN = m_Values[nGrid][nPos][i].vtMaxN ; m_Values[nGrid][nPos][i + 1].nToolMax = m_Values[nGrid][nPos][i].nToolMax ; m_Values[nGrid][nPos][i + 1].dMin = dMax ; m_Values[nGrid][nPos][i + 1].vtMinN = vtNma ; m_Values[nGrid][nPos][i + 1].nToolMin = m_Tool.GetCurrentToolNum() ; m_Values[nGrid][nPos][i + 1].nCompo = m_Values[nGrid][nPos][i].nCompo ; // Parte inferiore m_Values[nGrid][nPos][i].dMax = dMin ; m_Values[nGrid][nPos][i].vtMaxN = vtNmi ; m_Values[nGrid][nPos][i].nToolMax = m_Tool.GetCurrentToolNum() ; i = i + 1 ; } } else { // L'intervallo corrente viene eliminato if ( m_Values[nGrid][nPos][i].dMin > dMin - dTol) { bModified = true ; // Sposto i tratti successivi a quello corrente indietro di una posizione for ( unsigned int j = i ; j < m_Values[nGrid][nPos].size() - 1 ; ++ j) { m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j + 1].dMin ; m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j + 1].dMax ; m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j + 1].vtMinN ; m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j + 1].vtMaxN ; m_Values[nGrid][nPos][j].nToolMin = m_Values[nGrid][nPos][j + 1].nToolMin ; m_Values[nGrid][nPos][j].nToolMax = m_Values[nGrid][nPos][j + 1].nToolMax ; m_Values[nGrid][nPos][j].nCompo = m_Values[nGrid][nPos][j + 1].nCompo ; } // Riduco la dimensione del dexel m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 1) ; i = i - 1 ; } // L'intervallo corrente viene limitato a destra else if ( m_Values[nGrid][nPos][i].dMax > dMin + dTol) { bModified = true ; m_Values[nGrid][nPos][i].dMax = dMin ; m_Values[nGrid][nPos][i].vtMaxN = vtNmi ; m_Values[nGrid][nPos][i].nToolMax = m_Tool.GetCurrentToolNum() ; } // L'intervallo da sottrarre è tutto a destra di quello corrente, non vi è intersezione else { ; } } i = i + 1 ; } // Se eseguita modifica, imposto ricalcolo della grafica if ( bModified) { // Dichiaro numero di componenti connesse da ricalcolare m_nConnectedCompoCount = - 1 ; // Determino quali blocchi sono stati modificati int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ; if ( nGrid == 0) { int nXStop = 1 ; int nYStop = 1 ; int nXBlock[2] ; int nYBlock[2] ; // Passo dal dexel al voxel nI /= N_DEXVOXRATIO ; nJ /= N_DEXVOXRATIO ; nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } // Numero di voxel lungo Z int nVoxNumZ = int( m_nNy[1] / N_DEXVOXRATIO + ( m_nNy[1] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ; int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ; for ( int tI = 0 ; tI < nXStop ; ++ tI) { for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) { for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) { int nBlockNum = k * nLayerBlock + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 1) { int nYStop = 1 ; int nZStop = 1 ; int nYBlock[2] ; int nZBlock[2] ; // Passo dal dexel al voxel nI /= N_DEXVOXRATIO ; nJ /= N_DEXVOXRATIO ; nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Numero di voxel lungo X int nVoxNumX = int( m_nNx[0] / N_DEXVOXRATIO + ( m_nNx[0] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ; int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ; int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ; int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ; for ( int tI = 0 ; tI < nYStop ; ++ tI) { for ( int tJ = 0 ; tJ < nZStop ; ++ tJ) { for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) { int nBlockNum = nZBlock[tJ] * nLayerBlock + nYBlock[tI] * m_nFracLin[0] + k ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 2) { int nXStop = 1 ; int nZStop = 1 ; int nXBlock[2] ; int nZBlock[2] ; // Passo dal dexel al voxel nI /= N_DEXVOXRATIO ; nJ /= N_DEXVOXRATIO ; nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Numero di voxel lungo Y int nVoxNumY = int( m_nNy[0] / N_DEXVOXRATIO + ( m_nNy[0] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( N_DEXVOXRATIO * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ; int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ; int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ; for ( int tI = 0 ; tI < nZStop ; ++ tI) { for ( int tJ = 0 ; tJ < nXStop ; ++ tJ) { for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) { int nBlockNum = nZBlock[tI] * nLayerBlock + k * m_nFracLin[0] + nXBlock[tJ] ; m_BlockToUpdate[nBlockNum] = true ; } } } } m_OGrMgr.Reset() ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::AddIntervals( unsigned int nGrid, unsigned int nI, unsigned int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax) { // // Controllo che dMin e dMax non siano quasi coincidenti // if ( abs( dMax - dMin) < EPS_SMALL) // return true ; // // // Controllo che il numero di griglia sia entro i limiti // if ( nGrid < 0 || nGrid > 2) // return false ; // // // Controllo che dMin < dMax // if ( dMin > dMax) // swap( dMin, dMax) ; // // // Controllo che indici nI, nJ siano entro i limiti // if ( nI < 0 && nI >= m_nNx[nGrid] && // nJ < 0 && nJ >= m_nNy[nGrid]) // return false ; // // // Riporto le coordinate cicliche nell'ordine di partenza // Vector3d vtNmi = vtNMin ; // Vector3d vtNma = vtNMax ; // if ( nGrid == 1) { // swap( vtNmi.x, vtNmi.z) ; // swap( vtNmi.y, vtNmi.z) ; // swap( vtNma.x, vtNma.z) ; // swap( vtNma.y, vtNma.z) ; // } // else if ( nGrid == 2) { // swap( vtNmi.y, vtNmi.z) ; // swap( vtNmi.x, vtNmi.z) ; // swap( vtNma.y, vtNma.z) ; // swap( vtNma.x, vtNma.z) ; // } // // // Calcolo nPos // unsigned int nPos = nJ * m_nNx[nGrid] + nI ; // // // // Se spillone vuoto // if ( m_Values[nGrid][nPos].size() == 0) { // // m_Values[nGrid][nPos].resize( 1) ; // // m_Values[nGrid][nPos][0].dMin = dMin ; // m_Values[nGrid][nPos][0].dMax = dMax ; // // m_Values[nGrid][nPos][0].vtMinN = vtNmi ; // m_Values[nGrid][nPos][0].vtMaxN = vtNma ; // // if ( dMax > m_dMaxZ[nGrid]) // m_dMinZ[nGrid] = dMax ; // // if ( dMin < m_dMinZ[nGrid]) // m_dMinZ[nGrid] = dMin ; // // m_OGrMgr.Reset() ; // // return true ; // } // // // Ciclo sugli intervalli dello spillone // bool bModified = false ; // unsigned int i = 0 ; // while ( i < m_Values[nGrid][nPos].size()) { // // // Eventuale aggiustamento di intervalli sovrapposti // if ( i < m_Values[nGrid][nPos].size() - 1) { // if ( m_Values[nGrid][nPos][i].dMax > m_Values[nGrid][nPos][i + 1].dMin - EPS_SMALL) { // // // Se l'intervallo corrente non è contenuto totalmente si esegue l'istruzione successiva // if ( m_Values[nGrid][nPos][i].dMin < m_Values[nGrid][nPos][i + 1].dMin + EPS_SMALL) { // // m_Values[nGrid][nPos][i].dMax = m_Values[nGrid][nPos][i + 1].dMax ; // m_Values[nGrid][nPos][i].vtMaxN = m_Values[nGrid][nPos][i + 1].vtMaxN ; // } // // altrimenti // else { // // m_Values[nGrid][nPos][i].dMin = m_Values[nGrid][nPos][i].dMin ; // m_Values[nGrid][nPos][i].vtMinN = m_Values[nGrid][nPos][i].vtMinN ; // // m_Values[nGrid][nPos][i].dMax = m_Values[nGrid][nPos][i].dMax ; // m_Values[nGrid][nPos][i].vtMaxN = m_Values[nGrid][nPos][i].vtMaxN ; // } // // for ( unsigned int j = i + 1 ; j < m_Values[nGrid][nPos].size() - 1 ; ++ j) { // // m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j + 1].dMin ; // m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j + 1].vtMinN ; // // m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j + 1].dMax ; // m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j + 1].vtMaxN ; // } // // m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 1) ; // // i = i - 1 ; // } // } // // // // Caso in cui devo aggiungere un intervallo a sinistra dell'intervallo corrente // if ( m_Values[nGrid][nPos][i].dZVal > dMax + EPS_SMALL) { // // bModified = true ; // // m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ; // // for ( size_t j = m_Values[nGrid][nPos].size() - 1 ; j >= i + 2 ; -- j) { // // m_Values[nGrid][nPos][j].dZVal = m_Values[nGrid][nPos][j - 2].dZVal ; // m_Values[nGrid][nPos][j].vtN = m_Values[nGrid][nPos][j - 2].vtN ; // } // // // m_Values[nGrid][nPos][i].dZVal = dMin ; // m_Values[nGrid][nPos][i + 1].dZVal = dMax ; // // m_Values[nGrid][nPos][i].vtN = vtNMin ; // m_Values[nGrid][nPos][i + 1].vtN = vtNMax ; // // i = i + 2 ; // } // // // Casi d'intersezione: // else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMax - EPS_SMALL) { // // // Se l'intervallo da aggiungere sconfina a sinistra modifico il minimo dell'intervalo corrente // if ( m_Values[nGrid][nPos][i].dZVal > dMin - EPS_SMALL) { // // bModified = true ; // m_Values[nGrid][nPos][i].dZVal = dMin ; // m_Values[nGrid][nPos][i].vtN = vtNmi ; // } // } // // else { // // Se l'intervallo corrente è tutto contenuto nell'intervallo da aggungere modifico gli estremi // if ( m_Values[nGrid][nPos][i].dZVal > dMin + EPS_SMALL) { // // bModified = true ; // m_Values[nGrid][nPos][i].dZVal = dMin ; // m_Values[nGrid][nPos][i + 1].dZVal = dMax ; // m_Values[nGrid][nPos][i].vtN = vtNMin ; // m_Values[nGrid][nPos][i + 1].vtN = vtNma ; // } // // Se l'intervallo da aggiungere sconfina a destra modifico il massimo dell'intervallo corrente // else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMin - EPS_SMALL) { // // bModified = true ; // m_Values[nGrid][nPos][i + 1].dZVal = dMax ; // m_Values[nGrid][nPos][i + 1].vtN = vtNma ; // } // else { // // Aggiungo intervallo a destra dell'ultimo intervallo // if ( i == m_Values[nGrid][nPos].size() - 2) { // // bModified = true ; // m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ; // // m_Values[nGrid][nPos][i + 2].dZVal = dMin ; // m_Values[nGrid][nPos][i + 3].dZVal = dMax ; // m_Values[nGrid][nPos][i + 2].vtN = vtNmi ; // m_Values[nGrid][nPos][i + 3].vtN = vtNma ; // // i = i + 2 ; // } // } // } // // i = i + 2 ; // } // // // se eseguita modifica, imposto ricalcolo della grafica // if ( bModified) { // // // Determino quali blocchi sono stati modificati // int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ; // // if ( nGrid == 0) { // // int nXBlock = min( nI / m_nDexNumPBlock, m_nFracLin[0] - 1) ; // int nYBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[1] - 1) ; // int nMinZBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ; // int nMaxZBlock = min( int( m_nFracLin[2] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ; // // for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) // // m_BlockToUpdate[k * nLayerBlock + nYBlock * m_nFracLin[0] + nXBlock] = true ; // } // else if ( nGrid == 1) { // // int nYBlock = min( nI / m_nDexNumPBlock, m_nFracLin[1] - 1) ; // int nZBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[2] - 1) ; // int nMinXBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ; // int nMaxXBlock = min( int( m_nFracLin[0] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ; // // for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) // // m_BlockToUpdate[nZBlock * nLayerBlock + nYBlock * m_nFracLin[0] + k] = true ; // } // else if ( nGrid == 2) { // // int nXBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[0] - 1) ; // int nZBlock = min( nI / m_nDexNumPBlock, m_nFracLin[2] - 1) ; // int nMinYBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ; // int nMaxYBlock = min( int( m_nFracLin[1] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ; // // for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) // // m_BlockToUpdate[nZBlock * nLayerBlock + k * m_nFracLin[0] + nXBlock] = true ; // } // // m_OGrMgr.Reset() ; // // // Aggiorno massima e minima Z // // sullo Zmap // if ( dMax > m_dMaxZ[nGrid]) // m_dMinZ[nGrid] = dMax ; // // if ( dMin < m_dMinZ[nGrid]) // m_dMinZ[nGrid] = dMin ; // } // return true ; } // ------------------------- LAVORAZIONI -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Point3d& ptPe, const Vector3d& vtDe) { return MillingStep( ptPs, vtDs, Vector3d(), ptPe, vtDe, Vector3d()) ; } //---------------------------------------------------------------------------- bool VolZmap::MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs, const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) { // Controllo sull'effettiva esistenza del movimento if ( AreSamePointApprox( ptPs, ptPe) && AreSameVectorApprox( vtDs, vtDe)) return true ; // Punti nei sistemi di riferimento intrinseci dello Zmap Point3d ptLs[3] ; Point3d ptLe[3] ; ptLs[0] = ptPs ; ptLs[0].ToLoc( m_MapFrame) ; ptLe[0] = ptPe ; ptLe[0].ToLoc( m_MapFrame) ; if ( m_nMapNum > 1) { ptLs[1].x = ptLs[0].y ; ptLs[1].y = ptLs[0].z ; ptLs[1].z = ptLs[0].x ; ptLs[2].x = ptLs[0].z ; ptLs[2].y = ptLs[0].x ; ptLs[2].z = ptLs[0].y ; ptLe[1].x = ptLe[0].y ; ptLe[1].y = ptLe[0].z ; ptLe[1].z = ptLe[0].x ; ptLe[2].x = ptLe[0].z ; ptLe[2].y = ptLe[0].x ; ptLe[2].z = ptLe[0].y ; } // Vettori nei sistemi di riferimento intrinseci dello Zmap Vector3d vtLs[3] ; Vector3d vtLe[3] ; vtLs[0] = vtDs ; vtLs[0].ToLoc( m_MapFrame) ; vtLs[0].Normalize() ; vtLe[0] = vtDe ; vtLe[0].ToLoc( m_MapFrame) ; vtLe[0].Normalize() ; if ( m_nMapNum > 1) { vtLs[1].x = vtLs[0].y ; vtLs[1].y = vtLs[0].z ; vtLs[1].z = vtLs[0].x ; vtLs[2].x = vtLs[0].z ; vtLs[2].y = vtLs[0].x ; vtLs[2].z = vtLs[0].y ; vtLe[1].x = vtLe[0].y ; vtLe[1].y = vtLe[0].z ; vtLe[1].z = vtLe[0].x ; vtLe[2].x = vtLe[0].z ; vtLe[2].y = vtLe[0].x ; vtLe[2].z = vtLe[0].y ; } // Vettori ausiliari nei sistemi di riferimento intrinseci dello Zmap Vector3d vtALs[3] ; Vector3d vtALe[3] ; vtALs[0] = vtAs ; vtALs[0].ToLoc( m_MapFrame) ; vtALs[0].Normalize() ; vtALe[0] = vtAe ; vtALe[0].ToLoc( m_MapFrame) ; vtALe[0].Normalize() ; if ( m_nMapNum > 1) { vtALs[1].x = vtALs[0].y ; vtALs[1].y = vtALs[0].z ; vtALs[1].z = vtALs[0].x ; vtALs[2].x = vtALs[0].z ; vtALs[2].y = vtALs[0].x ; vtALs[2].z = vtALs[0].y ; vtALe[1].x = vtALe[0].y ; vtALe[1].y = vtALe[0].z ; vtALe[1].z = vtALe[0].x ; vtALe[2].x = vtALe[0].z ; vtALe[2].y = vtALe[0].x ; vtALe[2].z = vtALe[0].y ; } // Ciclo sulle mappe for ( unsigned int i = 0 ; i < m_nMapNum ; ++ i) { // Direzione utensile costante: pura traslazione if ( AreSameVectorApprox( vtLs[i], vtLe[i])) { // Proiezione dei vettori sulle rispettive griglie Vector3d vtLsXY( vtLs[i].x, vtLs[i].y, 0) ; // Versore utensile parallelo all'asse Z if ( vtLsXY.SqLen() < EPS_SMALL * EPS_SMALL) { Vector3d vtMove = ptLe[i] - ptLs[i] ; vtMove.Normalize() ; // Foratura if ( vtMove.SqLenXY() < EPS_SMALL) { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : Mrt_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : Chs_ZDrilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } // Fresatura con vettore movimento perpendicolare all'utensile else if ( abs( vtMove.z) < EPS_SMALL) { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_ZPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_ZPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : Mrt_ZMilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : Chs_ZMilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_ZMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; } } } // Versore utensile nel piano else if ( abs( vtLs[i].z) < EPS_SMALL) { Vector3d vtMove = ptLe[i] - ptLs[i] ; vtMove.Normalize() ; Vector3d vtMLong = ( vtMove * vtLs[i]) * vtLs[i] ; Vector3d vtMOrt = vtMove - vtMLong ; double dSqLOrt = vtMOrt.SqLen() ; // Foratura if ( dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_XYDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_XYDrilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : Mrt_Drilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : Chs_Drilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } // Fresatura con vettore movimento perpendicolare all'utensile else if ( 1 - dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : Mrt_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : Chs_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_XYMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_XYMilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; } } } // Versore utensile con direzione generica else { Vector3d vtMove = ptLe[i] - ptLs[i] ; vtMove.Normalize() ; Vector3d vtMLong = ( vtMove * vtLs[i]) * vtLs[i] ; Vector3d vtMOrt = vtMove - vtMLong ; double dSqLOrt = vtMOrt.SqLen() ; // Foratura if ( dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_Drilling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : Mrt_Drilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : Chs_Drilling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } else { switch ( m_Tool.GetType()) { case Tool::GEN : GenTool_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::CONUSMILL : Conus_Milling( i, ptLs[i], ptLe[i], vtLs[i]) ; break ; case Tool::MORTISER : Mrt_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; case Tool::CHISEL : Chs_Milling( i, ptLs[i], ptLe[i], vtLs[i], vtALs[i]) ; break ; } } } } else ; // Altri casi al momento non gestiti // return false ; } m_nConnectedCompoCount = - 1 ; return true ; } // ---------- VERSORE UTENSILE DERETTO COME Z -------------------------------- // ---------- Cilindro e sfera ----------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::CylBall_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; // Verifica sull'interferenza utensile Zmap bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Proiezione dei punti sul piano Point3d ptSxy( ptS.x, ptS.y, 0) ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; // Punte del gambo Point3d ptTStemS = ptS - vtToolDir * dStemHeigth ; Point3d ptTStemE = ptE - vtToolDir * dStemHeigth ; // Quote estreme del gambo double dMinStemZ = min( min( ptS.z, ptTStemS.z), min( ptE.z, ptTStemE.z)) ; double dMaxStemZ = max( max( ptS.z, ptTStemS.z), max( ptE.z, ptTStemE.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 - ptSxy ; double dSqLen = vtC.SqLen() ; // Se il punto si trova dentro il cerchio taglio if ( dSqLen < dSqRad - 2 * m_Tool.GetRadius() * EPS_SMALL) // utensile cilindrico if ( m_Tool.GetType() == Tool::CYLMILL) SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ; // utensile sferico else if ( m_Tool.GetType() == Tool::BALLMILL) { double dH = sqrt( dSqRad - dSqLen) ; if ( vtToolDir.z > 0) { Vector3d vtNorm = Point3d( ptSxy.x, ptSxy.y, dMinStemZ) - Point3d( dX, dY, dMinStemZ - dH) ; vtNorm.Normalize() ; SubtractIntervals( nGrid, i, j, dMinStemZ - dH, dMaxStemZ, vtNorm, - vtToolDir) ; } else { Vector3d vtNorm = Point3d( ptSxy.x, ptSxy.y, dMinStemZ) - Point3d( dX, dY, dMinStemZ + dH) ; vtNorm.Normalize() ; SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ + dH, - vtToolDir, vtNorm) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CylBall_ZPerp( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; double dSafeRad = m_Tool.GetRadius() - EPS_SMALL ; double dSafeSqRad = dSafeRad * dSafeRad ; // Punte del gambo Point3d ptTStemS = ptS - vtToolDir * dStemHeigth ; Point3d ptTStemE = ptE - vtToolDir * dStemHeigth ; // Quote estreme del gambo double dMinStemZ = min( ptS.z, ptTStemS.z) ; double dMaxStemZ = max( ptS.z, ptTStemS.z) ; // Vettore movimento e sua lunghezza Vector3d vtMove = ptE - ptS ; double dLen = vtMove.LenXY() ; // Definizione di un sistema di riferimento ad hoc Point3d ptSxy( ptS.x, ptS.y, 0) ; Vector3d vtV1 = vtMove ; vtV1.Normalize() ; // se |vtMove| < EPS è un buco con dz = 0 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 vtC = ptC - ptSxy ; double dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ; // Utensile cilindrico if ( m_Tool.GetType() == Tool::CYLMILL) { // Se il punto cade nella zona di interesse taglio if ( ( dP1 * dP1 + dP2 * dP2 < dSafeSqRad) || ( ( dP1 - dLen) * ( dP1 - dLen) + dP2 * dP2) < dSafeSqRad || ( dP1 > 0 && dP1 < dLen && abs( dP2) < dSafeRad)) SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ; } // Utensile sferico else if ( m_Tool.GetType() == Tool::BALLMILL) { if ( abs( dP2) < dSafeRad) { if ( dP1 < 0) { if ( dP1 * dP1 + dP2 * dP2 < dSafeSqRad) { double dH = sqrt( dSafeSqRad - dP1 * dP1 - dP2 * dP2) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, ptTStemS.z - dH) ; Vector3d vtN = ptTStemS - ptInt ; vtN.Normalize() ; SubtractIntervals( nGrid, i, j, ptTStemS.z - dH, ptS.z, vtN, - Z_AX) ; } else { Point3d ptInt( dX, dY, ptTStemS.z + dH) ; Vector3d vtN = ptTStemS - ptInt ; vtN.Normalize() ; SubtractIntervals( nGrid, i, j, ptS.z, ptTStemS.z + dH, Z_AX, vtN) ; } } } else if ( dP1 < dLen) { double dH = sqrt( dSafeSqRad - dP2 * dP2) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, ptTStemS.z - dH) ; Vector3d vtN = - ( ptInt - ptTStemS) + ( ptInt - ptTStemS) * vtV1 * vtV1 ; vtN.Normalize() ; SubtractIntervals( nGrid, i, j, ptTStemS.z - dH, ptS.z, vtN, - Z_AX) ; } else { Point3d ptInt( dX, dY, ptTStemS.z + dH) ; Vector3d vtN = - ( ptInt - ptTStemS) + ( ptInt - ptTStemS) * vtV1 * vtV1 ; vtN.Normalize() ; SubtractIntervals( nGrid, i, j, ptS.z, ptTStemS.z + dH, Z_AX, vtN) ; } } else { if ( ( dP1 - dLen) * ( dP1 - dLen) + dP2 * dP2 < dSafeSqRad) { double dH = sqrt( dSafeSqRad - ( dP1 - dLen) * ( dP1 - dLen) - dP2 * dP2) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, ptTStemE.z - dH) ; Vector3d vtN = ptTStemE - ptInt ; vtN.Normalize() ; SubtractIntervals( nGrid, i, j, ptTStemE.z - dH, ptS.z, vtN, - Z_AX) ; } else { Point3d ptInt( dX, dY, ptTStemE.z + dH) ; Vector3d vtN = ptTStemE - ptInt ; vtN.Normalize() ; SubtractIntervals( nGrid, i, j, ptS.z, ptTStemE.z + dH, Z_AX, vtN) ; } } } } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CylBall_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dSafeRadius = m_Tool.GetRadius() - EPS_SMALL ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; double dSafeSqRad = dSqRad - 2 * m_Tool.GetRadius() * EPS_SMALL ; // Studio delle simmetrie Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ; Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ; Point3d ptIT = ptI - vtToolDir * dStemHeigth ; Point3d ptFT = ptF - vtToolDir * dStemHeigth ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptIUp( ptI.x, ptI.y, max( ptI.z, ptIT.z)) ; Point3d ptIDw( ptI.x, ptI.y, min( ptI.z, ptIT.z)) ; // Quote iniziali e finali massime e // minime del gambo dell'utensile e DeltaZ double dZMaxI = max( ptI.z, ptIT.z) ; double dZMaxF = max( ptF.z, ptFT.z) ; double dZMinI = dZMaxI - dStemHeigth ; double dZMinF = dZMaxF - dStemHeigth ; double dDeltaZ = dZMaxF - dZMaxI ; // Vettori caratterizzanti il moto Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMove.Len() ; double dLenXY = vtMoveXY.LenXY() ; vtMove.Normalize() ; // Parametri per determinare l'ellisse proiettata double dCos = vtToolDir * vtMove ; double dSin = ( abs( dCos) < 1 ? 1 - dCos * dCos : 0) ; double dSemiAxMin = m_Tool.GetRadius() * dCos ; // x1^2 = a^2 - (a / b)^2 x2^2 ; a = r dCos e b = r; double dSqSemiAxMin = dSemiAxMin * dSemiAxMin ; // da cui si ottiene x1^2 = a^2 - dCos^2 x2^2 double dSqRatio = dSqSemiAxMin / dSqRad ; // Definizione di un sistema di riferimento ad hoc Vector3d vtV1, vtV2 ; // Se la lunghezza è troppo piccola lo allungo if ( dLenXY < EPS_SMALL) vtV1 = ( 1 / dLenXY) * vtMoveXY ; else vtV1 = vtMoveXY ; // Normalizzo vtV1 vtV1.Normalize() ; // Definisco vtV2 vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; 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 dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; // Se il punto appartiene alla proiezione del volume spazzato valuto massimo e minimo if ( ( dX1 > 0 && dX1 < dLenXY && abs( dX2) < dSafeRadius) || ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSafeSqRad || dX1 * dX1 + dX2 * dX2 < dSafeSqRad) { double dX1_0 = sqrt( dSqRad - dX2 * dX2) ; Vector3d vtNmin, vtNmax ; // Massimo if ( ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad) { vtNmax = - Z_AX ; dMax = dZMaxF ; } else { //vtNmax = - ( dX2 / dX1_0) * vtMove ^ vtV1 - vtMove ^ vtV2 ; dMax = dZMaxI + dDeltaZ * ( dX1 + dX1_0) / dLenXY ; Vector3d vtCirc = dX1_0 * vtV1 - dX2 * vtV2 ; // Punta verso il centro Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; // Tangente alla circonferenza Vector3d vtCross = vtTan ^ vtMove ; vtNmax = ( vtCross * vtCirc > - EPS_ZERO ? vtCross : - vtCross) ; vtNmax.Normalize() ; } // Minimo if ( dX1 * dX1 + dX2 * dX2 < dSqRad) { vtNmin = Z_AX ; dMin = dZMinI ; } else { //vtNmin = - ( dX2 / dX1_0) * vtMove ^ vtV1 + vtMove ^ vtV2 ; dMin = dZMinI + dDeltaZ * ( dX1 - dX1_0) / dLenXY ; Vector3d vtCirc = - dX1_0 * vtV1 - dX2 * vtV2 ; // Punta verso il centro Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; // Tangente alla circonferenza Vector3d vtCross = vtTan ^ vtMove ; vtNmin = ( vtCross * vtCirc > - EPS_ZERO ? vtCross : - vtCross) ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } if ( m_Tool.GetType() == Tool::BALLMILL) CompBall_Milling( nGrid, ptIT, ptFT, m_Tool.GetRadius()) ; return true ; } // ---------- Coni ----------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Conus_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dMinRad = min( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dMaxRad = max( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dDeltaRad = dMaxRad - dMinRad ; double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; // Proiezione delle posizioni sul piano Point3d ptO( ptS.x, ptS.y, 0) ; // Quote massime e minime dell'utensile durante il moto double dZMax = max( max( ptS.z, ptS.z - vtToolDir.z * m_Tool.GetHeigth()), max( ptE.z, ptE.z - vtToolDir.z * m_Tool.GetHeigth())) ; double dZMin = min( min( ptS.z, ptS.z - vtToolDir.z * m_Tool.GetHeigth()), min( ptE.z, ptE.z - vtToolDir.z * m_Tool.GetHeigth())) ; // Parametri geometrici per // determinare il vettore normale double dL = m_Tool.GetTipHeigth() * dMaxRad / dDeltaRad ; // Trapano if ( m_Tool.GetTipRadius() < m_Tool.GetRadius()) { // Ciclo sui punti 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.SqLenXY() ; if ( dSqDist < dSqMinRad) SubtractIntervals( nGrid, i, j, dZMin, dZMax, Z_AX, - Z_AX) ; else if ( dSqDist < dSqMaxRad) { double dr = sqrt( dSqDist) ; double dl = dr * dMaxRad / dL ; if ( vtToolDir.z > 0) { double dMin = dZMin + m_Tool.GetTipHeigth() * ( dr - dMinRad) / dDeltaRad ; double dMax = dZMax ; Point3d ptInt( dX, dY, dMin) ; Point3d ptPn( ptO.x, ptO.y, dMin + dl) ; Vector3d vtNmin = ptPn - ptInt ; vtNmin.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, - Z_AX) ; } else { double dMin = dZMin ; double dMax = dZMax - m_Tool.GetTipHeigth() * ( dr - dMinRad) / dDeltaRad ; Point3d ptInt( dX, dY, dMax) ; Point3d ptPn( ptO.x, ptO.y, dMax - dl) ; Vector3d vtNmax = ptPn - ptInt ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, vtNmax) ; } } } } } // Coda di rondine else { // Ciclo sui punti 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.SqLenXY() ; if ( dSqDist < dSqMinRad) { SubtractIntervals( nGrid, i, j, dZMin, dZMax, Z_AX, - Z_AX) ; } else if ( dSqDist < dSqMaxRad) { double dr = sqrt( dSqDist) ; double dl = dr * dMaxRad / dL ; if ( vtToolDir.z > 0) { double dMin = dZMin ; double dMax = dZMax - dStemHeigth - m_Tool.GetTipHeigth() * ( dr - dMinRad) / dDeltaRad ; Point3d ptInt( dX, dY, dMax) ; Point3d ptPn( ptO.x, ptO.y, dMax - dl) ; Vector3d vtNmax = ptPn - ptInt ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, vtNmax) ; } else { double dMin = dZMin + dStemHeigth + m_Tool.GetTipHeigth() * ( dr - dMinRad) / dDeltaRad ; double dMax = dZMax ; Point3d ptInt( dX, dY, dMin) ; Point3d ptPn( ptO.x, ptO.y, dMin + dl) ; Vector3d vtNmin = ptPn - ptInt ; vtNmin.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, - Z_AX) ; } } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_ZPerp( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dMinRad = min( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dMaxRad = max( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dDeltaRad = dMaxRad - dMinRad ; double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; double dSafeMinRad = dMinRad - EPS_SMALL ; double dSafeMaxRad = dMaxRad - EPS_SMALL ; double dSafeSqMaxRad = dSafeMaxRad * dSafeMaxRad ; double dSafeSqMinRad = dSafeMinRad * dSafeMinRad ; Point3d ptSxy( ptS.x, ptS.y, 0) ; Point3d ptExy( ptE.x, ptE.y, 0) ; Vector3d vtV1( ptE.x - ptS.x, ptE.y - ptS.y, 0) ; Vector3d vtV2( - vtV1.y, vtV1.x, 0) ; double dLen = vtV1.LenXY() ; vtV1.Normalize() ; vtV2.Normalize() ; double dBaseZ = ptS.z ; double dStemZ = ptS.z - vtToolDir.z * dStemHeigth ; double dTipZ = ptS.z - vtToolDir.z * m_Tool.GetHeigth() ; // Lunghezza cono double dL = m_Tool.GetTipHeigth() * dMaxRad / dDeltaRad ; // Punta a trapano if ( m_Tool.GetTipRadius() < m_Tool.GetRadius()) { double dMin, dMax ; Vector3d vtV = vtToolDir ; Point3d ptVS = ptS - vtToolDir * ( dStemHeigth + dL) ; Point3d ptVE = ptE - vtToolDir * ( dStemHeigth + dL) ; 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 vtCS = ptC - ptSxy ; Vector3d vtCE = ptC - ptExy ; double dP1 = vtCS * vtV1 ; double dP2 = vtCS * vtV2 ; double dSqLenS = vtCS.SqLenXY() ; double dSqLenE = vtCE.SqLenXY() ; if ( dSqLenS < dSafeSqMaxRad || dSqLenE < dSafeSqMaxRad || ( abs( dP2) < dSafeMaxRad && dP1 >= 0 && dP1 <= dLen)) { if ( dSqLenS < dSqMinRad || dSqLenE < dSqMinRad || ( abs( dP2) < dMinRad && dP1 >= 0 && dP1 <= dLen)) { dMin = min( dBaseZ, dTipZ) ; dMax = max( dBaseZ, dTipZ) ; SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, - Z_AX) ; } else { Vector3d vtNmin, vtNmax ; if ( dP1 < 0) { double dr = sqrt( dSqLenS) ; dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; dMax = max( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ; vtU.Normalize() ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; vtNmax = - Z_AX ; } else { Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ; vtU.Normalize() ; vtNmin = Z_AX ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else if ( dP1 <= dLen) { double dr = abs( dP2) ; dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; dMax = max( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; Point3d ptVtemp = ptVS + vtV1 * dP1 ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ; vtU.Normalize() ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; vtNmax = - Z_AX ; } else { Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ; vtU.Normalize() ; vtNmin = Z_AX ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else { double dr = sqrt( dSqLenE) ; dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; dMax = max( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ; vtU.Normalize() ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; vtNmax = -Z_AX ; } else { Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ; vtU.Normalize() ; vtNmin = Z_AX ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } } } // Coda di rondine else { double dMin, dMax ; Vector3d vtV = - vtToolDir ; Point3d ptVS = ptS - vtToolDir * ( m_Tool.GetHeigth() - dL) ; Point3d ptVE = ptE - vtToolDir * ( m_Tool.GetHeigth() - dL) ; 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 vtCS = ptC - ptSxy ; Vector3d vtCE = ptC - ptExy ; double dP1 = vtCS * vtV1 ; double dP2 = vtCS * vtV2 ; double dSqLenS = vtCS.SqLenXY() ; double dSqLenE = vtCE.SqLenXY() ; if ( dSqLenS < dSqMaxRad || dSqLenE < dSqMaxRad || ( abs( dP2) < dMaxRad && dP1 >= 0 && dP1 <= dLen)) { if ( dSqLenS < dSafeSqMinRad || dSqLenE < dSafeSqMinRad || ( abs( dP2) < dSafeMinRad && dP1 >= 0 && dP1 <= dLen)) { dMin = min( dBaseZ, dTipZ) ; dMax = max( dBaseZ, dTipZ) ; SubtractIntervals( nGrid, i, j, dMin, dMax, Z_AX, - Z_AX) ; } else { Vector3d vtNmin, vtNmax ; if ( dP1 < 0) { double dr = sqrt( dSqLenS) ; dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; dMax = max( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ; vtU.Normalize() ; vtNmin = Z_AX ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } else { Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVS) - ( ptInt - ptVS) * vtV * vtV ; vtU.Normalize() ; vtNmax = -Z_AX ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else if ( dP1 <= dLen) { double dr = abs( dP2) ; Point3d ptVtemp = ptVS + vtV1 * dP1 ; dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; dMax = max( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ; vtU.Normalize() ; vtNmin = Z_AX ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } else { Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVtemp) - ( ptInt - ptVtemp) * vtV * vtV ; vtU.Normalize() ; vtNmax = -Z_AX ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else { double dr = sqrt( dSqLenE) ; dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; dMax = max( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; if ( vtToolDir.z > 0) { Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ; vtU.Normalize() ; vtNmin = Z_AX ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } else { Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVE) - ( ptInt - ptVE) * vtV * vtV ; vtU.Normalize() ; vtNmax = -Z_AX ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_ZMilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemH = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; CompCyl_ZMilling( nGrid, ptS, ptE, vtToolDir, dStemH, m_Tool.GetRadius()) ; if ( m_Tool.GetTipRadius() < m_Tool.GetRadius()) { Point3d ptSC = ptS - vtToolDir * dStemH ; Point3d ptEC = ptE - vtToolDir * dStemH ; CompConus_ZMilling( nGrid, ptSC, ptEC, vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; } else { Point3d ptSC = ptS - vtToolDir * m_Tool.GetHeigth() ; Point3d ptEC = ptE - vtToolDir * m_Tool.GetHeigth() ; CompConus_ZMilling( nGrid, ptSC, ptEC, - vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetTipRadius(), m_Tool.GetRadius()) ; } return true ; } // --------- Mortasatrice ----------------------------------------------------- // ---------------------------------------------------------------------------- bool VolZmap::Mrt_ZDrilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano dei movimenti possibili Vector3d vtMoveOnP = ( ptE - ptS) * vtToolDir * vtToolDir ; Point3d ptEOnP = ptS + vtMoveOnP ; // Scompongo la mortasatrice in solidi semplici // Parallelepipedo di base double dLenX = m_Tool.GetMrtChsWidth() ; double dLenY = m_Tool.GetMrtChsThickness() ; double dLenZ = m_Tool.GetHeigth() - m_Tool.GetCornRadius() ; CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux) ; // Se la punta è di tipo bull-nose if ( abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipS = ptS - dLenZ * vtToolDir ; Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ; dLenX = abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) ; dLenZ = m_Tool.GetCornRadius() ; CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux) ; Vector3d vtVOnP = vtToolDir ^ vtAux ; // Cilindri Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptEminus = ptTipE - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptSplus = ptTipS + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } // se la punta è di tipo sfera else { // Cilindro Point3d ptCylS = ptS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; Point3d ptCylE = ptEOnP - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Mrt_ZMilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano di movimento Vector3d vtPlV = vtToolDir ^ vtAux ; if ( vtPlV * ( ptE - ptS) < 0) vtPlV *= - 1 ; Point3d ptPlS = ptS ; Point3d ptPlE = ptS + ( ptE - ptS) * vtPlV * vtPlV ; // Scompongo la mortasatrice in solidi semplici // Parallelepipedo di base double dLenX = m_Tool.GetMrtChsWidth() ; double dLenY = m_Tool.GetMrtChsThickness() ; double dLenZ = m_Tool.GetHeigth() - m_Tool.GetCornRadius() ; CompPar_ZMilling( nGrid, dLenX, dLenY, dLenZ, ptPlS, ptPlE, vtToolDir, vtAux) ; // Se la punta è di tipo bull-nose if ( abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipS = ptPlS - dLenZ * vtToolDir ; Point3d ptTipE = ptPlE - dLenZ * vtToolDir ; dLenX = abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) ; dLenZ = m_Tool.GetCornRadius() ; // Cilindro ( il moto dei due cilindri si sovrappone, quindi è inutile // eseguire due volte il conto Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtPlV + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptSminus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } // se la punta è di tipo sfera else { // Cilindro Point3d ptCylS = ptPlS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; Point3d ptCylE = ptPlE - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } return true ; } // --------- Chisel ---------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Chs_ZDrilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { CompPar_ZDrilling( nGrid, m_Tool.GetMrtChsWidth(), m_Tool.GetMrtChsThickness(), m_Tool.GetHeigth(), ptS, ptE, vtToolDir, vtAux) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::Chs_ZMilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano dei moti possibili Point3d ptSp = ptS ; Vector3d vtMoveOnP = ( ptE - ptS) - ( ptE - ptS) * vtToolDir * vtToolDir ; Point3d ptEp = ptS + vtMoveOnP ; CompPar_ZMilling( nGrid, m_Tool.GetMrtChsWidth(), m_Tool.GetMrtChsThickness(), m_Tool.GetHeigth(), ptSp, ptEp, vtToolDir, vtAux) ; return true ; } // --------- Utensile generico ------------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::GenTool_ZDrilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Posizioni iniziale e finale dell'utensile Point3d ptI = ptS ; Point3d ptF = ptE ; // Vettore movimento Vector3d vtMove = ptE - ptS ; // Ciclo sulle curve const CurveComposite* pToolProfile = m_Tool.GetOutline() ; const ICurve* pCurve = pToolProfile->GetFirstCurve() ; while ( pCurve != nullptr) { double dHeight ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; // Ne determino l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; if ( dHeight > EPS_SMALL) { // Se X costante, è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; CompCyl_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ; } // Se X crescente, è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; CompConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ; } // Se X decrescente, è 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 ; CompConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ; } } } // se altrimenti arco else if ( pCurve->GetType() == CRV_ARC) { // Recupero estremi, centro e raggio const ICurveArc* pArc = GetCurveArc( pCurve) ; Point3d ptStart ; pArc->GetStartPoint( ptStart) ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; Point3d ptCen = pArc->GetCenter() ; double dRadius = pArc->GetRadius() ; // Determino le posizioni iniziale e finale del centro della sfera Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ; Point3d ptCenE = ptCenS + vtMove ; // Eseguo l'asportazione del materiale CompBall_Milling( nGrid, ptCenS, ptCenE, 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 ; // Passo alla curva successiva del profilo pCurve = pToolProfile->GetNextCurve() ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::GenTool_ZMilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Posizioni iniziale e finale dell'utensile Point3d ptI = ptS ; Point3d ptF = ptE ; // vettore movimento Vector3d vtMove = ptE - ptS ; // Ciclo sulle curve del profilo utensile const CurveComposite* pToolProfile = m_Tool.GetOutline() ; const ICurve* pCurve = pToolProfile->GetFirstCurve() ; while ( pCurve != nullptr) { double dHeight ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; // Ne determino l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; if ( dHeight > EPS_SMALL) { // Se X costante, è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; CompCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ; } // Se X crescente, è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; CompConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad) ; } // Se X decrescente, è 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 ; CompConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad) ; } } } // se altrimenti arco else if ( pCurve->GetType() == CRV_ARC) { // Recupero estremi, centro e raggio const ICurveArc* pArc = GetCurveArc( pCurve) ; Point3d ptStart ; pArc->GetStartPoint( ptStart) ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; Point3d ptCen = pArc->GetCenter() ; double dRadius = pArc->GetRadius() ; // Determino le posizioni iniziale e finale del centro della sfera Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ; Point3d ptCenE = ptCenS + vtMove ; // Eseguo l'asportazione del materiale CompBall_Milling( nGrid, ptCenS, ptCenE, 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 ; // Passo alla curva successiva del profilo pCurve = pToolProfile->GetNextCurve() ; } return true ; } // ---------- VERSORE UTENSILE NEL PIANO XY ---------------------------------- // --------- Cilindro e sfera ------------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::CylBall_XYDrilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile e quota Z del movimento double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; double dZ = ptS.z ; // Vettore movimento e sua lunghezza Vector3d vtMove = ptE - ptS ; double dLen = vtMove.LenXY() ; // Definizione di un sistema di riferimento ad hoc Point3d ptI = ( vtMove * vtToolDir > 0 ? ptE : ptS) ; Point3d ptF = ( vtMove * vtToolDir > 0 ? ptS - dStemHeigth * vtToolDir : ptE - dStemHeigth * vtToolDir) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ; 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 vtC = ptC - ptIxy ; double dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ; Vector3d vtBall = ptC - ptFxy ; double dSqLen = vtBall.SqLenXY() ; // Zona lavorata dalla parte cilindrica if ( dP1 > EPS_SMALL && dP1 < dStemHeigth + dLen - EPS_SMALL && abs( dP2) < m_Tool.GetRadius()) { double dH = sqrt( dSqRad - dP2 * dP2) ; double dMin = dZ - dH ; double dMax = dZ + dH ; Point3d ptIntMin( dX, dY, dMin) ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtMin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtToolDir * vtToolDir ; Vector3d vtMax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtToolDir * vtToolDir ; vtMin.Normalize() ; vtMax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } // Se l'utensile è sferico sottraggo anche la punta if ( m_Tool.GetType() == Tool::BALLMILL) if ( dSqLen < dSqRad) { // LA SOLUZIONE MOMENTANEA è CREARE UTENSILE GENERICO SE LO STELO è PIù CORTO DEL RAGGIO double dH = sqrt( dSqRad - dSqLen) ; double dMin = dZ - dH ; double dMax = dZ + dH ; Vector3d vtMin = ptF - Point3d( dX, dY, dMin) ; Vector3d vtMax = ptF - Point3d( dX, dY, dMax) ; vtMin.Normalize() ; vtMax.Normalize() ; SubtractIntervals( nGrid, i, j, dZ - dH, dZ + dH, vtMin, vtMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CylBall_XYPerp( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; double dSafeSqRad = dSqRad - 2 * m_Tool.GetRadius() * EPS_SMALL ; // Studio simmetrie del problema Point3d ptI = ( ptS.z <= ptE.z ? ptS : ptE) ; Point3d ptF = ( ptS.z <= ptE.z ? ptE : ptS) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptIStemT = ptI - vtToolDir * dStemHeigth ; Point3d ptFStemT = ptF - vtToolDir * dStemHeigth ; // Quote punti iniziale e finale double dZI = ptI.z ; double dZF = ptF.z ; double dDeltaZ = ptF.z - ptI.z ; // Vettori caratterizzanti il moto Vector3d vtMove = ptF - ptI ; double dLen = vtMove.Len() ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLenXY = vtMoveXY.LenXY() ; vtMove.Normalize() ; // Sistema di riferimento ad hoc Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ; vtV1.Normalize() ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; if ( vtV2 * vtMove < 0) vtV2 = - vtV2 ; // Vettori e punti determinanti i piani Vector3d vtP = vtMove ; // Se dLen < EPS_SMALL non si usa vtP.Rotate( vtToolDir, 90) ; Point3d ptUp = ptI + m_Tool.GetRadius() * ( vtP.z > 0 ? vtP : - vtP) ; Point3d ptDw = ptI + m_Tool.GetRadius() * ( vtP.z > 0 ? - vtP : vtP) ; Vector3d vtPXY( vtP.x, vtP.y, 0) ; Vector3d vtUp = ptUp - ORIG ; double dDotUp = vtUp * vtP ; Vector3d vtDw = ptDw - ORIG ; double dDotDw = vtDw * vtP ; double dSmall = m_Tool.GetRadius() * vtPXY.LenXY() ; // Parte sferica double dCos = vtMove.z ; // vtMove.z > 0 : ptF.z >= ptI.z double dSin = ( dCos < 1 ? sqrt( 1 - dCos * dCos) : 0) ; double dSemiAxMin = m_Tool.GetRadius() * dCos ; double dInfZ, dSupZ ; if ( dLenXY < 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 dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ; Vector3d vtNmin, vtNmax ; if ( dP1 > EPS_SMALL && dP1 < dStemHeigth - EPS_SMALL && dP2 > - m_Tool.GetRadius() + EPS_SMALL && dP2 < m_Tool.GetRadius() - EPS_SMALL) { dInfZ = ptI.z - sqrt( dSqRad - dP2 * dP2) ; dSupZ = ptF.z + sqrt( dSqRad - dP2 * dP2) ; Point3d ptIntInf( dX, dY, dInfZ) ; Point3d ptIntSup( dX, dY, dSupZ) ; vtNmin = - ( ptIntInf - ptI) + ( ptIntInf - ptI) * vtV1 * vtV1 ; vtNmax = - ( ptIntSup - ptF) + ( ptIntSup - ptF) * vtV1 * vtV1 ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, vtNmin, vtNmax) ; } if ( m_Tool.GetType() == Tool::BALLMILL) { if ( dP1 > dStemHeigth - 2 * EPS_SMALL && ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + dP2 * dP2 < dSafeSqRad) { dInfZ = ptI.z - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ; dSupZ = ptF.z + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ; Point3d ptIntInf( dX, dY, dInfZ) ; Point3d ptIntSup( dX, dY, dSupZ) ; vtNmin = ptIStemT - ptIntInf ; vtNmax = ptFStemT - ptIntSup ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, vtNmin, vtNmax) ; } } } } } else { 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 ; // Parte cilindrica if ( dP1 > EPS_SMALL && dP1 < dStemHeigth - EPS_SMALL) { if ( dP2 > - m_Tool.GetRadius() && dP2 < dLenXY + m_Tool.GetRadius()) { Vector3d vtNmin, vtNmax ; // Massimi if ( dP2 < - dSmall + EPS_SMALL) { double dHsq = dSqRad - dP2 * dP2 ; double dH = ( dHsq > 0 ? sqrt( dHsq) : 0) ; dSupZ = dZI + dH ; Point3d ptInt( dX, dY, dSupZ) ; vtNmax = - ( ptInt - ptI - ( ptInt - ptI) * vtToolDir * vtToolDir) ; vtNmax.Normalize() ; } else if ( dP2 < dLenXY - dSmall - EPS_SMALL) { dSupZ = ( dDotUp - dX * vtP.x - dY * vtP.y) / vtP.z ; Vector3d vtT = vtToolDir ^ vtMove ; vtNmax = ( vtT.z < 0 ? vtT : - vtT) ; vtNmax.Normalize() ; } else { double dH = sqrt( dSqRad - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ; dSupZ = dZF + dH ; Point3d ptInt( dX, dY, dSupZ) ; vtNmax = - ( ptInt - ptF - ( ptInt - ptF) * vtToolDir * vtToolDir) ; vtNmax.Normalize() ; } // Minimi if ( dP2 < dSmall + EPS_SMALL) { double dHsq = dSqRad - dP2 * dP2 ; double dH = ( dHsq > 0 ? sqrt( dHsq) : 0) ; dInfZ = dZI - dH ; Point3d ptInt( dX, dY, dInfZ) ; vtNmin = - ( ( ptInt - ptI) - ( ptInt - ptI) * vtToolDir * vtToolDir) ; vtNmin.Normalize() ; } else if ( dP2 < dLenXY + dSmall - EPS_SMALL) { dInfZ = ( dDotDw - dX * vtP.x - dY * vtP.y) / vtP.z ; Vector3d vtT = vtToolDir ^ vtMove ; vtNmin = ( vtT.z < 0 ? - vtT : vtT) ; vtNmin.Normalize() ; } else { double dH = sqrt( dSqRad - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ; dInfZ = dZF - dH ; Point3d ptInt( dX, dY, dInfZ) ; vtNmin = - ( ( ptInt - ptF) - ( ptInt - ptF) * vtToolDir * vtToolDir) ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dInfZ, dSupZ, vtNmin, vtNmax) ; } } // Se l'utensile è ball-end sottraggo la punta if ( m_Tool.GetType() == Tool::BALLMILL) { if ( ( ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + dP2 * dP2 < dSqRad || ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) + ( dP2 - dLenXY) * ( dP2 - dLenXY) < dSqRad || ( dP2 > 0 && dP2 < dLenXY && dP1 < m_Tool.GetHeigth())) && ( dP1 > dStemHeigth - 2 * EPS_SMALL)) { double dSqRoot = sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth)) ; double dP2_0 = dCos * dSqRoot ; double dH0 = dSin * dSqRoot ; double dMin, dMax ; Vector3d vtNmin, vtNmax ; // Massimo if ( dP2 < - dP2_0) { dMax = dZI + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ; Point3d ptInt( dX, dY, dMax) ; vtNmax = ptIStemT - ptInt ; vtNmax.Normalize() ; } else if ( dP2 < dLenXY - dP2_0) { dMax = dZI + dH0 + dDeltaZ * ( dP2 + dP2_0) / dLenXY ; Point3d ptInt( dX, dY, dMax) ; vtNmax = - ( ptInt - ptIStemT) + ( ptInt - ptIStemT) * vtMove * vtMove ; vtNmax.Normalize() ; } else { dMax = dZF + sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ; Point3d ptInt( dX, dY, dMax) ; vtNmax = ptFStemT - ptInt; vtNmax.Normalize() ; } // Minimo if ( dP2 < dP2_0) { dMin = dZI - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - dP2 * dP2) ; Point3d ptInt( dX, dY, dMin) ; vtNmin = ptIStemT - ptInt ; vtNmin.Normalize() ; } else if ( dP2 < dLenXY + dP2_0) { dMin = dZI - dH0 + dDeltaZ * ( dP2 - dP2_0) / dLenXY ; Point3d ptInt( dX, dY, dMin) ; vtNmin = - ( ptInt - ptIStemT) + ( ptInt - ptIStemT) * vtMove * vtMove ; vtNmin.Normalize() ; } else { dMin = dZF - sqrt( dSqRad - ( dP1 - dStemHeigth) * ( dP1 - dStemHeigth) - ( dP2 - dLenXY) * ( dP2 - dLenXY)) ; Point3d ptInt( dX, dY, dMin) ; vtNmin = ptFStemT - ptInt ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CylBall_XYMilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { if ( m_Tool.GetType() == Tool::CYLMILL) return CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, m_Tool.GetHeigth(), m_Tool.GetRadius(), false, false) ; else if ( m_Tool.GetType() == Tool::BALLMILL) { double dHei = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dHei, m_Tool.GetRadius(), false, false) ; CompBall_Milling( nGrid, ptS - dHei * vtToolDir, ptE - dHei * vtToolDir, m_Tool.GetRadius()) ; return true ; } else return false ; } // --------- Coni ------------------------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::Conus_XYDrilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; // Verifica sull'interferenza utensile Zmap bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dMinRad = min( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dMaxRad = max( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dDeltaRad = dMaxRad - dMinRad ; double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; // Geometria del moto double dLenXY = ( ptE - ptS).LenXY() ; Point3d ptI = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) ; double dMatStemLen = ( m_Tool.GetRadius() > m_Tool.GetTipRadius() ? dStemHeigth + dLenXY : dStemHeigth) ; double dSqTipRad = m_Tool.GetTipRadius() * m_Tool.GetTipRadius() ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; // Determinazione del vertice del cono double dL = m_Tool.GetTipHeigth() * dMaxRad / dDeltaRad ; Point3d ptV ; // Vertice Vector3d vtV ; // Vettore riferimento con origine nel vertice if ( m_Tool.GetRadius() > m_Tool.GetTipRadius()) { vtV = vtToolDir ; ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * ( dStemHeigth + dL) ;//dStemHeigth ; } else { vtV = - vtToolDir ; ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) - vtToolDir * ( m_Tool.GetHeigth() - dL) ;//dStemHeigth ; } // Sistema di riferimento sul piano Vector3d vtV1 = - vtToolDir ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; // Proiezione di ptI sul piano Point3d ptIxy( ptI.x, ptI.y, 0) ; // Ciclo sui punti 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 dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; double dr = m_Tool.GetRadius() + ( dX1 - dMatStemLen) * ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) / m_Tool.GetTipHeigth() ; if ( dX1 > EPS_SMALL && dX1 < dMatStemLen && abs( dX2) < m_Tool.GetRadius()) { double dH = sqrt( dSqRad - dX2 * dX2) ; double dMin = ptI.z - dH ; double dMax = ptI.z + dH ; Point3d ptIntMin( dX, dY, dMin) ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ; Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ; } else if ( dX1 >= dMatStemLen && dX1 < dMatStemLen + m_Tool.GetTipHeigth() - EPS_SMALL && abs( dX2) < dr) { double dH = sqrt( dr * dr - dX2 * dX2) ; double dMin = ptI.z - dH ; double dMax = ptI.z + dH ; Point3d ptIntMin( dX, dY, dMin) ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtUmin = ( ptIntMin - ptV) - ( ptIntMin - ptV) * vtV * vtV ; Vector3d vtUmax = ( ptIntMax - ptV) - ( ptIntMax - ptV) * vtV * vtV ; vtUmin.Normalize() ; vtUmax.Normalize() ; Vector3d vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtUmin ; Vector3d vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtUmax ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } if ( m_Tool.GetTipRadius() >= m_Tool.GetRadius()) { if ( dX1 > dMatStemLen + m_Tool.GetTipHeigth() - 2 * EPS_SMALL && dX1 < dMatStemLen + m_Tool.GetTipHeigth() + dLenXY - EPS_SMALL && abs( dX2) < dSqTipRad) { double dH = sqrt( dSqTipRad - dX2 * dX2) ; double dMin = ptI.z - dH ; double dMax = ptI.z + dH ; Point3d ptIntMin( dX, dY, dMin) ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ; Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_XYPerp( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bTest = BoundingBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bTest) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; double dMinRad = min( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dMaxRad = max( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; double dSqTipRad = m_Tool.GetTipRadius() * m_Tool.GetTipRadius() ; double dSqRad = m_Tool.GetRadius() * m_Tool.GetRadius() ; double dDeltaRad = dMaxRad - dMinRad ; double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; // Studio delle simmetrie del moto Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ; Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; // Cinematica del moto Vector3d vtMove = ptF - ptI ; double dLenPath = vtMove.Len() ; double dLengthPathXY = vtMove.LenXY() ; double dDeltaZ = ptF.z - ptI.z ; double dZI = ptI.z ; double dZF = ptF.z ; vtMove.Normalize() ; // Riferimento coni double dL = m_Tool.GetTipHeigth() * dMaxRad / dDeltaRad ; Vector3d vtV = ( m_Tool.GetRadius() > m_Tool.GetTipRadius() ? vtToolDir : - vtToolDir) ; Point3d ptVI = ptI - ( m_Tool.GetRadius() > m_Tool.GetTipRadius() ? dStemHeigth + dL : m_Tool.GetHeigth() - dL) * vtToolDir ; Point3d ptVF = ptF - ( m_Tool.GetRadius() > m_Tool.GetTipRadius() ? dStemHeigth + dL : m_Tool.GetHeigth() - dL) * vtToolDir ; // Movimento verticale if ( dLengthPathXY < EPS_SMALL) { // Riferimento sul piano Vector3d vtV1 = - vtToolDir ; Vector3d vtV2( - vtV1.y, vtV1.x, 0) ; double dMin, dMax ; Vector3d vtNmin, vtNmax ; Point3d ptIntMin, ptIntMax ; 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 ; // Parte cilindrica if ( dP1 > EPS_SMALL && dP1 <= dStemHeigth && dP2 > - m_Tool.GetRadius() + EPS_SMALL && dP2 < m_Tool.GetRadius() - EPS_SMALL) { dMin = dZI - sqrt( dSqRad - dP2 * dP2) ; dMax = dZF + sqrt( dSqRad - dP2 * dP2) ; ptIntMin.Set( dX, dY, dMin) ; ptIntMax.Set( dX, dY, dMax) ; vtNmin = - ( ptIntMin - ptI) + ( ptIntMin - ptI) * vtV1 * vtV1 ; vtNmax = - ( ptIntMax - ptF) + ( ptIntMax - ptF) * vtV1 * vtV1 ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Parte conica else if ( dP1 > dStemHeigth && dP1 < m_Tool.GetHeigth() - EPS_SMALL && abs( dP2) < m_Tool.GetRadius() + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() - EPS_SMALL) { double dr = dP2 ; double dMr = m_Tool.GetRadius() + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() ; dMin = dZI - sqrt( dMr * dMr - dr * dr) ; dMax = dZF + sqrt( dMr * dMr - dr * dr) ; ptIntMin.Set( dX, dY, dMin) ; ptIntMax.Set( dX, dY, dMax) ; Vector3d vtUmin = ( ptIntMin - ptVI) - ( ptIntMin - ptVI) * vtV * vtV ; Vector3d vtUmax = ( ptIntMax - ptVF) - ( ptIntMax - ptVF) * vtV * vtV ; vtUmin.Normalize() ; vtUmax.Normalize() ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtUmin ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtUmax ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } else { // Riferimento sul piano Vector3d vtV1 = - vtToolDir ; Vector3d vtV2( vtMove.x, vtMove.y, 0) ; vtV2.Normalize() ; // Vettore per individuare i punti di tangenza // dei piani con il cilindro Vector3d vtCross = vtToolDir ^ vtMove ; if ( vtCross.z < 0) vtCross = - vtCross ; // Punti di tangenza Point3d ptUp = ptI - vtToolDir * dStemHeigth + m_Tool.GetRadius() * vtCross ; Point3d ptDw = ptI - vtToolDir * dStemHeigth - m_Tool.GetRadius() * vtCross ; double dSmallLength = m_Tool.GetRadius() * vtCross.LenXY() ; // Punti di tangenza in corrispondenza della punta Point3d ptTipUp = ptI - vtToolDir * m_Tool.GetHeigth() + m_Tool.GetTipRadius() * vtCross ; Point3d ptTipDw = ptI - vtToolDir * m_Tool.GetHeigth() - m_Tool.GetTipRadius() * vtCross ; Vector3d vtUpTan = ptTipUp - ptUp ; Vector3d vtDwTan = ptTipDw - ptDw ; Vector3d vtUpTanXY( vtUpTan.x, vtUpTan.y, 0) ; double dDeltaSmallAbs = abs( vtUpTanXY * vtV2) ; double dDeltaSmall = ( m_Tool.GetRadius() > m_Tool.GetTipRadius() ? dDeltaSmallAbs : - dDeltaSmallAbs) ; vtUpTan.Normalize() ; vtDwTan.Normalize() ; Vector3d vtUpCross = vtMove ^ vtUpTan ; Vector3d vtDwCross = - vtMove ^ vtDwTan ; if ( vtUpCross.z > 0) vtUpCross = - vtUpCross ; if ( vtDwCross.z < 0) vtDwCross = - vtDwCross ; // Descrizione piani tangenti al cono Vector3d vtR0Up = ptUp - ORIG ; Vector3d vtR0Dw = ptDw - ORIG ; double dDotUp = vtR0Up * vtUpCross ; double dDotDw = vtR0Dw * vtDwCross ; double dMin, dMax ; Vector3d vtNmin, vtNmax ; Point3d ptInt ; 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 ; // Parte cilindrica if ( dP1 > EPS_SMALL && dP1 <= dStemHeigth && // vedere se conviene dP1 < dStemHeigth + eps oppure dP1 <= dStemHeigth dP2 > - m_Tool.GetRadius() && dP2 < dLengthPathXY + m_Tool.GetRadius()) { // Massimi if ( dP2 < - dSmallLength) { dMax = dZI + sqrt( dSqRad - dP2 * dP2) ; ptInt.Set( dX, dY, dMax) ; vtNmax = - ( ptInt - ptI) + ( ptInt - ptI) * vtV1 * vtV1 ; vtNmax.Normalize() ; } else if ( dP2 < dLengthPathXY - dSmallLength) { dMax = ptUp.z + dDeltaZ * ( dP2 + dSmallLength) / dLengthPathXY ; vtNmax = - vtCross ; } else { dMax = dZF + sqrt( dSqRad - ( dP2 - dLengthPathXY) * ( dP2 - dLengthPathXY)) ; ptInt.Set( dX, dY, dMax) ; vtNmax = - ( ptInt - ptF) + ( ptInt - ptF) * vtV1 * vtV1 ; vtNmax.Normalize() ; } // Minimi if ( dP2 < dSmallLength) { dMin = dZI - sqrt( dSqRad - dP2 * dP2) ; ptInt.Set( dX, dY, dMin) ; vtNmin = - ( ptInt - ptI) + ( ptInt - ptI) * vtV1 * vtV1 ; vtNmin.Normalize() ; } else if ( dP2 < dLengthPathXY + dSmallLength) { dMin = ptDw.z + dDeltaZ * ( dP2 - dSmallLength) / dLengthPathXY ; vtNmin = vtCross ; } else { dMin = dZF - sqrt( dSqRad - ( dP2 - dLengthPathXY) * ( dP2 - dLengthPathXY)) ; ptInt.Set( dX, dY, dMin) ; vtNmin = - ( ptInt - ptF) + ( ptInt - ptF) * vtV1 * vtV1 ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Parte conica else if ( dP1 > dStemHeigth && dP1 < m_Tool.GetHeigth() - EPS_SMALL && dP2 > - m_Tool.GetRadius() - ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() && dP2 < m_Tool.GetRadius() + dLengthPathXY + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth()) { // Massimi if ( dP2 < - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth()) { double dr = dP2 ; double dMr = m_Tool.GetRadius() + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() ; dMax = dZI + sqrt( dMr * dMr - dr * dr) ; ptInt.Set( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVI) - ( ptInt - ptVI) * vtV * vtV ; vtU.Normalize() ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } else if ( dP2 < dLengthPathXY - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth()) { dMax = ( dDotUp - dX * vtUpCross.x - dY * vtUpCross.y) / vtUpCross.z ; vtNmax = vtUpCross ; } else { double dr = dP2 - dLengthPathXY ; double dMr = m_Tool.GetRadius() + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() ; dMax = dZF + sqrt( dMr * dMr - dr * dr) ; ptInt.Set( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptVF) - ( ptInt - ptVF) * vtV * vtV ; vtU.Normalize() ; vtNmax = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmax.Normalize() ; } // Minimi if ( dP2 < dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth()) { double dr = dP2 ; double dMr = m_Tool.GetRadius() + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() ; dMin = dZI - sqrt( dMr * dMr - dr * dr) ; ptInt.Set( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVI) - ( ptInt - ptVI) * vtV * vtV ; vtU.Normalize() ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; } else if ( dP2 < dLengthPathXY + dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth()) { dMin = ( dDotDw - dX * vtDwCross.x - dY * vtDwCross.y) / vtDwCross.z ; vtNmin = vtDwCross ; } else { double dr = dP2 - dLengthPathXY ; double dMr = m_Tool.GetRadius() + ( m_Tool.GetTipRadius() - m_Tool.GetRadius()) * ( dP1 - dStemHeigth) / m_Tool.GetTipHeigth() ; dMin = dZF - sqrt( dMr * dMr - dr * dr) ; ptInt.Set( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptVF) - ( ptInt - ptVF) * vtV * vtV ; vtU.Normalize() ; vtNmin = dDeltaRad * vtV - m_Tool.GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_XYMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_Tool.GetRadius(), false, true) ; if ( m_Tool.GetTipRadius() < m_Tool.GetRadius()) { Point3d ptSTip = ptS - dStemHeigth * vtToolDir ; Point3d ptETip = ptE - dStemHeigth * vtToolDir ; CompConus_Milling( nGrid, ptSTip, ptETip, vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetRadius(), m_Tool.GetTipRadius(), true, false) ; } else { Point3d ptSTip = ptS - m_Tool.GetHeigth() * vtToolDir ; Point3d ptETip = ptE - m_Tool.GetHeigth() * vtToolDir ; CompConus_Milling( nGrid, ptSTip, ptETip, - vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetTipRadius(), m_Tool.GetRadius(), false, true) ; } return true ; } // ---------- VERSORE UTENSILE CON ORIENTAZIONE GENERICA --------------------- // ---------- Cilindro e sfera ----------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::CylBall_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Altezza cilindro double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; // Sottraggo cilindro CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_Tool.GetRadius(), false, false) ; // Se è sfera la sottraggo if ( m_Tool.GetType() == Tool::BALLMILL) { Point3d ptSBall = ptS - dStemHeigth * vtToolDir ; Point3d ptEBall = ptE - dStemHeigth * vtToolDir ; CompBall_Milling( nGrid, ptSBall, ptEBall, m_Tool.GetRadius()) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CylBall_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Altezza cilindro double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; // Sottraggo cilindro CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_Tool.GetRadius(), false, false) ; // Se è sfera la sottraggo if ( m_Tool.GetType() == Tool::BALLMILL) { Point3d ptSBall = ptS - dStemHeigth * vtToolDir ; Point3d ptEBall = ptE - dStemHeigth * vtToolDir ; CompBall_Milling( nGrid, ptSBall, ptEBall, m_Tool.GetRadius()) ; } return true ; } // ---------- Coni ----------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Conus_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_Tool.GetRadius(), false, true) ; // Trapano if ( m_Tool.GetTipRadius() < m_Tool.GetRadius()) { Point3d ptSCone = ptS - dStemHeigth * vtToolDir ; Point3d ptECone = ptE - dStemHeigth * vtToolDir ; CompConus_Drilling( nGrid, ptSCone, ptECone, vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetRadius(), m_Tool.GetTipRadius(), true, false) ; } else { Point3d ptSCone = ptS - m_Tool.GetHeigth() * vtToolDir ; Point3d ptECone = ptE - m_Tool.GetHeigth() * vtToolDir ; CompConus_Drilling( nGrid, ptSCone, ptECone, - vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetTipRadius(), m_Tool.GetRadius(), false, true) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemHeigth = m_Tool.GetHeigth() - m_Tool.GetTipHeigth() ; CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_Tool.GetRadius(), false, true) ; // Trapano if ( m_Tool.GetTipRadius() < m_Tool.GetRadius()) { Point3d ptSBall = ptS - dStemHeigth * vtToolDir ; Point3d ptEBall = ptE - dStemHeigth * vtToolDir ; CompConus_Milling( nGrid, ptSBall, ptEBall, vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetRadius(), m_Tool.GetTipRadius(), true, false) ; } else { Point3d ptSBall = ptS - m_Tool.GetHeigth() * vtToolDir ; Point3d ptEBall = ptE - m_Tool.GetHeigth() * vtToolDir ; CompConus_Milling( nGrid, ptSBall, ptEBall, - vtToolDir, m_Tool.GetTipHeigth(), m_Tool.GetTipRadius(), m_Tool.GetRadius(), false, true) ; } return true ; } // ---------- Mortasatrice --------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Mrt_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano dei movimenti possibili Point3d ptEOnP = ptS + ( ptE - ptS) * vtToolDir * vtToolDir ; // Scompongo la mortasatrice in solidi semplici // Parallelepipedo di base double dLenX = m_Tool.GetMrtChsWidth() ; double dLenY = m_Tool.GetMrtChsThickness() ; double dLenZ = m_Tool.GetHeigth() - m_Tool.GetCornRadius() ; CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux) ; // Se la punta è di tipo bull-nose if ( abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipS = ptS - dLenZ * vtToolDir ; Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ; dLenX = abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) ; dLenZ = m_Tool.GetCornRadius() ; CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptTipS, ptTipE, vtToolDir, vtAux) ; Vector3d vtVOnP = vtToolDir ^ vtAux ; // Cilindri Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptEminus = ptTipE - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptSplus = ptTipS + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } // se la punta è di tipo sfera else { // Cilindro Point3d ptCylS = ptS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; Point3d ptCylE = ptEOnP - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Mrt_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano dei movimenti possibili Point3d ptSp = ptS ; Vector3d vtMoveDir = vtToolDir ^ vtAux ; Point3d ptEp = ptS + ( ptE - ptS) * vtMoveDir * vtMoveDir ; // Scompongo la mortasatrice in solidi semplici // Parallelepipedo di base double dLenX = m_Tool.GetMrtChsWidth() ; double dLenY = m_Tool.GetMrtChsThickness() ; double dLenZ = m_Tool.GetHeigth() - m_Tool.GetCornRadius() ; CompPar_Milling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEp, vtToolDir, vtAux) ; // Se la punta è di tipo bull-nose if ( abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipS = ptS - dLenZ * vtToolDir ; Point3d ptTipE = ptEp - dLenZ * vtToolDir ; dLenX = abs( m_Tool.GetMrtChsWidth() - 2 * m_Tool.GetCornRadius()) ; dLenZ = m_Tool.GetCornRadius() ; Vector3d vtVOnP = vtToolDir ^ vtAux ; if ( vtVOnP * ( ptTipE - ptTipS) < 0) vtVOnP *= - 1 ; // Cilindri Point3d ptSminus = ptTipS - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptEminus = ptTipE - ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptSplus = ptTipS + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; Point3d ptEplus = ptTipE + ( 0.5 * dLenX) * vtVOnP + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptSminus, ptEplus, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } // se la punta è di tipo sfera else { // Cilindro Point3d ptCylS = ptS - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; Point3d ptCylE = ptEp - dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_Tool.GetCornRadius(), false, false) ; } return true ; } // ---------- Chisel --------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Chs_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sulla varietà del movimento Point3d ptProjE = ptS + ( ptE - ptS) * vtToolDir * vtToolDir ; CompPar_Drilling( nGrid, m_Tool.GetMrtChsWidth(), m_Tool.GetMrtChsThickness(), m_Tool.GetHeigth(), ptS, ptProjE, vtToolDir, vtAux) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::Chs_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Proiezione della traiettoria sul piano dei movimenti possibili Point3d ptSp = ptS ; Vector3d vtMoveOnP = ( ptE - ptS) - ( ptE - ptS) * vtToolDir * vtToolDir ; Point3d ptProjE = ptS + vtMoveOnP ; CompPar_Milling( nGrid, m_Tool.GetMrtChsWidth(), m_Tool.GetMrtChsThickness(), m_Tool.GetHeigth(), ptS, ptProjE, vtToolDir, vtAux) ; return true ; } // ---------- Utensile generico ---------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::GenTool_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Descrizione geometrica del moto Point3d ptI = ptS ; Point3d ptF = ptE ; Vector3d vtMove = ptE - ptS ; // Ciclo sulle curve del profilo const CurveComposite* pToolProfile = m_Tool.GetOutline() ; const ICurve* pPrevCurve = nullptr ; const ICurve* pCurve = pToolProfile->GetFirstCurve() ; while ( pCurve != nullptr) { double dHeight ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; // Ne determino l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; if ( dHeight > EPS_SMALL) { // Verifiche curva precedente per eventuale tappo sopra bool bTapT = false ; if ( pPrevCurve != nullptr && pPrevCurve->GetType() == CRV_LINE) { const ICurveLine* pOthLine = GetCurveLine( pPrevCurve) ; Point3d ptOthStart = pOthLine->GetStart() ; Point3d ptOthEnd = pOthLine->GetEnd() ; if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x < ptOthEnd.x) bTapT = true ; } // Verifiche curva successiva per eventuale tappo sotto bool bTapB = false ; const ICurve* pNextCurve = pToolProfile->GetNextCurve() ; if ( pNextCurve != nullptr && pNextCurve->GetType() == CRV_LINE) { const ICurveLine* pOthLine = GetCurveLine( pNextCurve) ; Point3d ptOthStart = pOthLine->GetStart() ; Point3d ptOthEnd = pOthLine->GetEnd() ; if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x > ptOthEnd.x) bTapB = true ; } // Se X costante, è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; CompCyl_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ; } // Se X crescente, è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; CompConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT) ; } // Se X decrescente, è 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 ; CompConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB) ; } // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = pNextCurve ; } else { // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = pToolProfile->GetNextCurve() ; } } // Se arco else if ( pCurve->GetType() == CRV_ARC) { // Recupero estremi, centro e raggio const ICurveArc* pArc = GetCurveArc( pCurve) ; Point3d ptStart ; pArc->GetStartPoint( ptStart) ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; Point3d ptCen = pArc->GetCenter() ; double dRadius = pArc->GetRadius() ; // Determino le posizioni iniziale e finale del centro della sfera Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ; Point3d ptCenE = ptCenS + vtMove ; // Eseguo l'asportazione del materiale CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ; // aggiorno l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = pToolProfile->GetNextCurve() ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dHeight ; ptF = ptI + vtMove ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::GenTool_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Descrizione geometrica del moto Point3d ptI = ptS ; Point3d ptF = ptE ; Vector3d vtMove = ptE - ptS ; // Ciclo sulle curve del profilo const CurveComposite* pToolProfile = m_Tool.GetOutline() ; const ICurve* pPrevCurve = nullptr ; const ICurve* pCurve = pToolProfile->GetFirstCurve() ; while ( pCurve != nullptr) { double dHeight ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; // Ne determino l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; if ( dHeight > EPS_SMALL) { // verifiche curva precedente per eventuale tappo sopra bool bTapT = false ; if ( pPrevCurve != nullptr && pPrevCurve->GetType() == CRV_LINE) { const ICurveLine* pOthLine = GetCurveLine( pPrevCurve) ; Point3d ptOthStart = pOthLine->GetStart() ; Point3d ptOthEnd = pOthLine->GetEnd() ; if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x < ptOthEnd.x) bTapT = true ; } // verifiche curva successiva per eventuale tappo sotto bool bTapB = false ; const ICurve* pNextCurve = pToolProfile->GetNextCurve() ; if ( pNextCurve != nullptr && pNextCurve->GetType() == CRV_LINE) { const ICurveLine* pOthLine = GetCurveLine( pNextCurve) ; Point3d ptOthStart = pOthLine->GetStart() ; Point3d ptOthEnd = pOthLine->GetEnd() ; if ( abs( ptOthStart.y - ptOthEnd.y) < EPS_SMALL && ptOthStart.x > ptOthEnd.x) bTapB = true ; } // Se X costante, è un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ; } // Se X crescente, è un cono con vettore equiverso a quello dell'utensile else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; CompConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT) ; } // Se X decrescente, è 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 ; CompConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB) ; } // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = pNextCurve ; } else { // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = pToolProfile->GetNextCurve() ; } } // Se arco else if ( pCurve->GetType() == CRV_ARC) { // Recupero estremi, centro e raggio const ICurveArc* pArc = GetCurveArc( pCurve) ; Point3d ptStart ; pArc->GetStartPoint( ptStart) ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; Point3d ptCen = pArc->GetCenter() ; double dRadius = pArc->GetRadius() ; // Determino le posizioni iniziale e finale del centro della sfera Point3d ptCenS = ptI - vtToolDir * ( ptStart.y - ptCen.y) ; Point3d ptCenE = ptCenS + vtMove ; // Eseguo l'asportazione del materiale CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ; // aggiorno l'altezza dHeight = abs( ptStart.y - ptEnd.y) ; // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = pToolProfile->GetNextCurve() ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dHeight ; ptF = ptI + vtMove ; } return true ; } // ------------------------- SOLIDI ELEMENTARI ----------------------------------------------------------------------------- // Asse di simmetria diretto come l'asse Z: FORATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dRad) { // Verifica sull'interferenza con lo Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! bInterf) return true ; // Proiezione dei punti sul piano Point3d ptSxy( ptS.x, ptS.y, 0) ; // Parametri geometrici dell'utensile double dSafeSqRad = dRad * dRad - 2 * dRad * EPS_SMALL ; // Punte del gambo Point3d ptTStemS = ptS - vtToolDir * dHei ; Point3d ptTStemE = ptE - vtToolDir * dHei ; // Quote estreme del gambo double dMinStemZ = min( min( ptS.z, ptTStemS.z), min( ptE.z, ptTStemE.z)) ; double dMaxStemZ = max( max( ptS.z, ptTStemS.z), max( ptE.z, ptTStemE.z)) ; // Ciclo sui punti 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 - ptSxy ; double dSqLen = vtC.SqLen() ; // Se il punto si trova dentro il cerchio taglio if ( dSqLen < dSafeSqRad) SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, -Z_AX) ; } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompConus_ZDrilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dMaxRad, double dMinRad) { // Verifica sull'interferenza con lo Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! bInterf) return true ; Point3d ptO( ptS.x, ptS.y, 0) ; double dZMin, dZMax ; double dAngC = dHei / ( dMaxRad - dMinRad) ; double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; double dSafeSqMaxRad = dSqMaxRad - 2 * dMaxRad * EPS_SMALL ; // Questa variabile è sperimentale: serve per evitare il taglio di un dexel dalla parte cilindrica del volume spazzato dalla traslazione del cono. double dDeltaR = dMaxRad - dMinRad ; // Per tornare alla versione precedente basta sostituire dSafeSqMaxRad con dSqMaxRad. Per risolvere il problema in modo forse più sicuro, ma // computazionalmente più pesante è sottrarre prima il cilindro con dSafeSqMaxRad e dopo il cono con dSqMaxRad. // Studio delle simmetrie if ( vtToolDir.z > 0) { dZMin = ( ptS.z < ptE.z ? ptS.z - dHei : ptE.z - dHei) ; dZMax = ( ptS.z < ptE.z ? ptE.z : ptS.z) ; } else { dZMin = ( ptS.z < ptE.z ? ptS.z : ptE.z) ; dZMax = ( ptS.z < ptE.z ? ptE.z + dHei : ptS.z + dHei) ; } double dL = dMaxRad * dAngC ; Point3d ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * dL ; double dMin, dMax ; Vector3d vtMin, vtMax ; // Ciclo sui punti 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 < dSqMinRad) { SubtractIntervals( nGrid, i, j, dZMin, dZMax, Z_AX, -Z_AX) ; } else if ( dSqDist < dSafeSqMaxRad) { // dSafeSqMaxRad è sperimentale double dr = sqrt( dSqDist) ; if ( vtToolDir.z > 0) { dMin = dZMin + dAngC * ( dr - dMinRad) ; dMax = dZMax ; vtMax = - Z_AX ; Point3d ptInt( dX, dY, dMin) ; Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ; vtU.Normalize() ; vtMin = dDeltaR * vtToolDir - dHei * vtU ; vtMin.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } else { dMin = dZMin ; dMax = dZMax - dAngC * ( dr - dMinRad) ; vtMin = Z_AX ; Point3d ptInt( dX, dY, dMax) ; Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ; vtU.Normalize() ; vtMax = dDeltaR * vtToolDir - dHei * vtU ; vtMax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompPar_ZDrilling( unsigned int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Controllo sull'interferenza utensile-solido unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxParaComp( nGrid, dLenX, dLenY, dLenZ, ptS, ptE, vtToolDir, vtAux, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bInterf) return true ; // Costruisco un sistema di riferimento nel piano Point3d ptOXY( ptS.x, ptS.y, 0) ; Vector3d vtV1 = vtToolDir ^ vtAux ; Vector3d vtV2 = vtAux ; // Quote estreme del volume asportato double dMinZ = min( min( ptS.z, ptS.z - vtToolDir.z * dLenZ), min( ptE.z, ptE.z - vtToolDir.z * dLenZ)) ; double dMaxZ = max( max( ptS.z, ptS.z - vtToolDir.z * dLenZ), max( ptE.z, ptE.z - vtToolDir.z * dLenZ)) ; 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 vtR = ptC - ptOXY ; double dR1 = vtR * vtV1 ; double dR2 = vtR * vtV2 ; if ( abs( dR1) < 0.5 * dLenX - EPS_SMALL && abs( dR2) < 0.5 * dLenY - EPS_SMALL) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; } } return true ; } // Asse di simmetria diretto come l'asse Z: FRESATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_ZMilling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dRad) { // Verifica sull'interferenza con lo Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! bInterf) return true ; // Parametri geometrici double dSqRad = dRad * dRad ; // Studio delle simmetrie Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ; Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ; Point3d ptIT = ptI - vtToolDir * dHei ; Point3d ptFT = ptF - vtToolDir * dHei ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptIUp( ptI.x, ptI.y, max( ptI.z, ptIT.z)) ; Point3d ptIDw( ptI.x, ptI.y, min( ptI.z, ptIT.z)) ; // Quote iniziali e finali massime e // minime del gambo dell'utensile e DeltaZ double dZMaxI = max( ptI.z, ptIT.z) ; double dZMaxF = max( ptF.z, ptFT.z) ; double dZMinI = dZMaxI - dHei ; double dZMinF = dZMaxF - dHei ; double dDeltaZ = dZMaxF - dZMaxI ; // Vettori caratterizzanti il moto Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLen = vtMove.Len() ; double dLenXY = vtMoveXY.LenXY() ; vtMove.Normalize() ; // Parametri per determinare l'ellisse proiettata double dCos = vtToolDir * vtMove ; double dSin = ( abs( dCos) < 1 ? 1 - dCos * dCos : 0) ; double dSemiAxMin = dRad * dCos ; // x1^2 = a^2 - (a / b)^2 x2^2 ; a = r dCos e b = r; double dSqSemiAxMin = dSemiAxMin * dSemiAxMin ; // da cui si ottiene x1^2 = a^2 - dCos^2 x2^2 double dSqRatio = dSqSemiAxMin / dSqRad ; double dSafeRad = dRad - EPS_SMALL ; // Definizione di un sistema di riferimento ad hoc Vector3d vtV1, vtV2 ; // Se la lunghezza è troppo piccola lo allungo if ( dLenXY < EPS_SMALL) vtV1 = ( 1 / dLenXY) * vtMoveXY ; else vtV1 = vtMoveXY ; // Normalizzo vtV1 vtV1.Normalize() ; // Definisco vtV2 vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; double dMin, dMax ; Vector3d vtMin, vtMax ; 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 dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; Point3d ptInt ; // Se il punto appartiene alla proiezione del volume spazzato valuto massimo e minimo if ( ( dX1 > 0 && dX1 < dLenXY && abs( dX2) < dSafeRad) || ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad || dX1 * dX1 + dX2 * dX2 < dSqRad) { double dX1_0 = sqrt( dSqRad - dX2 * dX2) ; // Massimo if ( ( dX1 - dLenXY) * ( dX1 - dLenXY) + dX2 * dX2 < dSqRad) { dMax = dZMaxF ; vtMax = - Z_AX ; } else { dMax = dZMaxI + dDeltaZ * ( dX1 + dX1_0) / dLenXY ; if ( abs( vtMove * vtToolDir) < EPS_SMALL) { vtMax = - Z_AX ; } else { Vector3d vtCirc = dX1_0 * vtV1 - dX2 * vtV2 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtMove ; vtMax = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; vtMax.Normalize() ; } } // Minimo if ( dX1 * dX1 + dX2 * dX2 < dSqRad) { dMin = dZMinI ; vtMin = Z_AX ; } else { dMin = dZMinI + dDeltaZ * ( dX1 - dX1_0) / dLenXY ; if ( abs( vtMove * vtToolDir) < EPS_SMALL) { vtMin = Z_AX ; } else { Vector3d vtCirc = - dX1_0 * vtV1 - dX2 * vtV2 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtMove ; vtMin = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; vtMin.Normalize() ; } } SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompConus_ZMilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! bInterf) return true ; Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ; Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ; Point3d ptIT = ptI - vtToolDir * dHei ; Point3d ptFT = ptF - vtToolDir * dHei ; 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) ; bool bCase = ( dRatio * dTan > 1) ; 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) ; Point3d ptVF = ptV + vtMove ; 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 ; vtNs.Normalize() ; vtNd.Normalize() ; double dDots = vtR0 * vtNs ; double dDotd = vtR0 * vtNd ; double dMin, dMax, dPLim, dMLim ; Vector3d vtMin, vtMax, vtP, vtM ; Vector3d vtUmv = vtMove ; vtUmv.Normalize() ; Point3d ptInt ; 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 * dRatio > 1 if ( bCase) { // Limiti nella direzione positiva di vtV1 if ( dSqDF < dMaxRad * dMaxRad) { dPLim = dZI + dDeltaZ ; vtP = - vtV1 ; } else { double dIDL_0 = - sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ; dPLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ; if ( abs( vtV1 * vtUmv) < EPS_SMALL) { vtP = - vtV1 ; } else { Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtUmv ; vtP = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; vtP.Normalize() ; } } // Limiti nella direzione negativa di vtV1 if ( dSqDI < dMinRad * dMinRad) { dMLim = dZTI ; vtM = vtToolDir ; } else if ( dSqDI < dMaxRad * dMaxRad) { dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ; ptInt.Set( dX, dY, dMLim) ; Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ; vtU.Normalize() ; vtM = dDeltaR * vtToolDir - dHei * vtU ; vtM.Normalize() ; } else { double dIDL_0 = sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ; dMLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ; if ( abs( vtUmv * vtV1) < EPS_SMALL) { vtM = vtV1 ; } else { Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtUmv ; vtM = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; vtM.Normalize() ; } } } else { // Limiti nella direzione positiva di vtV1 if ( dSqDF < dMaxRad * dMaxRad) { dPLim = dZI + dDeltaZ ; vtP = - vtV1 ; } else { double dIDL_0 = - sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ; dPLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ; if ( abs( vtUmv * vtToolDir) < EPS_SMALL) { vtP = - vtV1 ; } else { Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtUmv ; vtP = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; // vtCross * vtCirc o vtCross * vtMove? vtP.Normalize() ; } } // Limiti nella direzione negativa di vtV1 if ( dSqDI < dMinRad * dMinRad) { dMLim = dZTI ; vtM = vtV1 ; } else if ( dSqDI >= dMinRad * dMinRad && dSqDI < dMaxRad * dMaxRad && dIVarCos < dCos) { dMLim = dZTI + ( sqrt( dSqDI) - dMinRad) * ( dZI - dZTI) / dDeltaR ; ptInt.Set( dX, dY, dMLim) ; Vector3d vtU = ( ptInt - ptV) - ( ptInt - ptV) * vtToolDir * vtToolDir ; vtU.Normalize() ; vtM = dDeltaR * vtToolDir - dHei * vtU ; vtM.Normalize() ; } 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 ; vtM = - vtNd ; } else if ( dIDO > - dMinRad * dSin && dIDO < dMinRad * dSin) { double dIDL_0 = sqrt( dMinRad * dMinRad - dIDO * dIDO) ; dMLim = dZTI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ; if ( abs( vtUmv * vtV1) < EPS_SMALL) { vtM = vtV1 ; } else { Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtUmv ; double dDotCrossCirc = vtCross * vtCirc ; vtM = ( dDotCrossCirc > 0 ? vtCross : - vtCross) ; vtM.Normalize() ; } } else if ( dIDO >= dMinRad * dSin && dIDO < dMaxRad * dSin) { dMLim = ( dDots - dX * vtNs.x - dY * vtNs.y) / vtNs.z ; // a qui vtM = - vtNs ; } } else if ( dFVarCos >= dCos) { if ( dSqDF < dMinRad * dMinRad) { double dIDL_0 = sqrt( dMinRad * dMinRad - dIDO * dIDO) ; dMLim = dZTI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ; if ( abs( vtUmv * vtV1) < EPS_SMALL) { vtM = vtV1 ; } else { Vector3d vtCirc = - dIDL_0 * vtV2 - dIDO * vtV3 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtUmv ; vtM = ( vtCross * vtCirc > 0 ? vtCross : - vtCross) ; vtM.Normalize() ; } } else { dMLim = dZTI + dDeltaZ + ( sqrt( dSqDF) - dMinRad) * ( dZI - dZTI) / dDeltaR ; ptInt.Set( dX, dY, dMLim) ; Vector3d vtU = ( ptInt - ptVF) - ( ptInt - ptVF) * vtToolDir * vtToolDir ; vtU.Normalize() ; vtM = dDeltaR * vtToolDir - dHei * vtU ; vtM.Normalize() ; } } else { double dIDL_0 = sqrt( dMaxRad * dMaxRad - dIDO * dIDO) ; dMLim = dZI + ( dIDL - dIDL_0) * dDeltaZ / dLOrt ; if ( abs( vtUmv * vtV1) < EPS_SMALL) { vtM = vtV1 ; } else { Vector3d vtCirc = - dIDL * vtV2 - dIDO * vtV3 ; Vector3d vtTan( - vtCirc.y, vtCirc.x, 0) ; Vector3d vtCross = vtTan ^ vtMove ; vtM = ( vtCross * vtMove > 0 ? vtCross : - vtCross) ; vtM.Normalize() ; } } } if ( dMLim < dPLim) { dMin = dMLim ; dMax = dPLim ; vtMin = vtM ; vtMax = vtP ; } else { dMin = dPLim ; dMax = dMLim ; vtMin = vtP ; vtMax = vtM ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool // E' in realtà MillingPerp VolZmap::CompPar_ZMilling( unsigned int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Controllo sull'interferenza utensile-solido unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxParaComp( nGrid, dLenX, dLenY, dLenZ, ptS, ptE, vtToolDir, vtAux, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bInterf) return true ; // Materiale asportato nelle posizioni iniziale e finale // Costruisco un sistema di riferimento nel piano Point3d ptSXY( ptS.x, ptS.y, 0) ; Point3d ptEXY( ptE.x, ptE.y, 0) ; Vector3d vtV1 = vtToolDir ^ vtAux ; Vector3d vtV2 = vtAux ; if ( vtV1 * ( ptE - ptS) < 0) vtV1 *= - 1 ; double dLenMove = ( ( ( ptE - ptS) * vtV1) * vtV1).Len() ; // Quote estreme del volume asportato double dMinZ = min( min( ptS.z, ptS.z - vtToolDir.z * dLenZ), min( ptE.z, ptE.z - vtToolDir.z * dLenZ)) ; double dMaxZ = max( max( ptS.z, ptS.z - vtToolDir.z * dLenZ), max( ptE.z, ptE.z - vtToolDir.z * dLenZ)) ; // Studio del volume asportato durante il moto // Studio delle simmetrieto Point3d ptLs = ( ( ptE - ptS) * vtAux > 0 ? ptS : ptE) ; Point3d ptLe = ( ( ptE - ptS) * vtAux > 0 ? ptE : ptS) ; Vector3d vtMove = ptLe - ptLs ; Vector3d vtW3 = vtAux ; Vector3d vtAnsatz = ( vtW3 ^ vtToolDir) ; bool bSymmetry = vtMove * ( vtW3 ^ vtToolDir) > 0 ; Vector3d vtW2 = ( bSymmetry ? vtAnsatz : - vtAnsatz) ; Vector3d vtW1 = ( bSymmetry ? vtToolDir : - vtToolDir) ; Frame3d MotionFrame ; Point3d ptDiagMin = ptLs - vtW2 * ( 0.5 * dLenX) + vtW3 * ( 0.5 * dLenY) ; Point3d ptDiagMax = ptLs + vtW2 * ( 0.5 * dLenX) - vtW3 * ( 0.5 * dLenY) ; Vector3d vtU1 = ptDiagMax - ptDiagMin ; vtU1.Normalize() ; Vector3d vtU2 = ( vtU1 * vtMove > 0 ? vtMove - vtMove * vtU1 * vtU1 : vtMove * vtU1 * vtU1 - vtMove) ; vtU2.Normalize() ; Vector3d vtU3 = vtU1 ^ vtU2 ; Point3d ptOMot = ( vtMove * vtU1 > 0 ? ptDiagMin : ptDiagMin + vtMove) ; Point3d ptOMotXY( ptOMot.x, ptOMot.y, 0) ; double dLen1 = vtMove * vtU1 ; double dLen2 = vtMove * vtU2 ; double dHx = ( ptDiagMax - ptDiagMin).Len() ; 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 vtRS = ptC - ptSXY ; Vector3d vtRE = ptC - ptEXY ; double dRS1 = vtRS * vtV1 ; double dRS2 = vtRS * vtV2 ; double dRE1 = vtRE * vtV1 ; double dRE2 = vtRE * vtV2 ; // Asportazione materiale nella posizione iniziale if ( abs( dRS1) < 0.5 * dLenX - EPS_SMALL && abs( dRS2) < 0.5 * dLenY - EPS_SMALL) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; // Asportazione materiale nella posizione finale if ( abs( dRE1) < 0.5 * dLenX - EPS_SMALL && abs( dRE2) < 0.5 * dLenY - EPS_SMALL) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; // Asportazione materiale nel moto Vector3d vtR = ptC - ptOMotXY ; double dR1 = vtR * vtU1 ; double dR2 = vtR * vtU2 ; if ( dR2 > EPS_SMALL && dR2 < dLen2 - EPS_SMALL && dR1 * dLen2 > dLen1 * dR2 + EPS_SMALL && dR1 * dLen2 < dHx * dLen2 + dLen1 * dR2 - EPS_SMALL) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; } } return true ; } // Asse di simmetria con orientazione generica: FORATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad, bool bTapB, bool bTapT) { // Verifico che il cilindro con il suo movimento intersechi la griglia unsigned int nStartI, nEndI, nStartJ, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! bInterf) return true ; // Studio delle simmetrie Point3d ptI = ( ( ptE - ptS) * vtToolDir > 0 ? ptE : ptS) ; Point3d ptF = ( ( ptE - ptS) * vtToolDir > 0 ? ptS - vtToolDir * dHei : ptE - vtToolDir * dHei) ; // Altezza cilindro totale altezza + moto double dH = ( ptF - ptI).Len() ; // Sistema di riferimento del cilindro Frame3d CylFrame ; CylFrame.Set( ptF, vtToolDir) ; for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompConus_Drilling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! bInterf) return true ; // Apertura del cono double dDeltaR = dMaxRad - dMinRad ; double dTan = dDeltaR / dHei ; double dConeMaxH = ( ( dMaxRad * dHei) / dDeltaR) ; double dConeMinH = dConeMaxH - dHei ; bool bTapCylEn = bTapB ; Point3d ptVertex = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) - vtToolDir * dConeMaxH ; // Sistemi di riferimento del cono e del cilindro Frame3d ConusFrame ; ConusFrame.Set( ptVertex, vtToolDir) ; Frame3d CylFrame = ConusFrame ; CylFrame.Translate( vtToolDir * dConeMaxH) ; // L'altezza del cilindro è il movimento double dH = ( ptE - ptS).Len() ; 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) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Cilindro if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapCylEn, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Cono if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dConeMinH, dConeMaxH, bTapT, true, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompPar_Drilling( unsigned int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Controllo sull'interferenza utensile-solido unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxParaComp( nGrid, dLenX, dLenY, dLenZ, ptS, ptE, vtToolDir, vtAux, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bInterf) return true ; // Costruzione di un sistema di riferimento per il volume // asportato dal solido nelle posizioni iniziale e finale. Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtAux ^ vtV1 ; Vector3d vtV3 = vtAux ; double dLenMove = ( ptE - ptS).Len() ; Point3d ptO = ptS - ( ( ptE - ptS) * vtV1 > 0 ? dLenZ : dLenZ + dLenMove) * vtV1 - ( 0.5 * dLenX) * vtV2 ; Frame3d ParaFrame ; ParaFrame.Set( ptO, vtV2, vtV3, vtV1) ; 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) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ + dLenMove, 0, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } // Asse di simmetria con orientazione generica: FRESATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_Milling( unsigned int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad, bool bTapB, bool bTapT) { // Verifica sull'interferenza utensile Zmap unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dRad, dRad, dHei) ; if ( ! bInterf) return true ; // Studio delle simmetrie Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ; Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ; Point3d ptITip = ptI - vtToolDir * dHei ; Point3d ptFTip = ptF - vtToolDir * dHei ; // Definizione terne vettoriali e sistemi di riferimento intrinseci al movimento Vector3d vtMove = ptF - ptI ; Vector3d vtMoveLong = ( vtMove * vtToolDir) * vtToolDir ; Vector3d vtMoveOrt = vtMove - vtMoveLong ; Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtMoveOrt ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; Frame3d CylFrame ; CylFrame.Set( ptITip, vtV2, vtV3, vtV1) ; // Parametri geometrici di moto e cilindro double dLongLen = vtMoveLong.Len() ; double dOrtLen = vtMoveOrt.Len() ; // Variabili booleane per i tappi Vector3d vtUmv = vtMove ; vtUmv.Normalize() ; bool bCylSt = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ; bool bCylEn = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ; bool bElpsB = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ; bool bElpsT = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ; for ( unsigned int i = nStartI ; i <= nEndI ; ++ i) { for ( unsigned int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Cilindro iniziale if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bCylSt, bCylEn, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Cilindro finale:L'unica differenza rispetto a prima è l'origine // del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC // il vettore che congiunge le due origini. if ( IntersLineCylinder( ptC - vtMove, Z_AX, CylFrame, dHei, dRad, bCylSt, bCylEn, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + vtMove.z ; dMax = ptInt2.z + vtMove.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + vtMove.z ; dMax = ptInt1.z + vtMove.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Poliedro interno if ( IntersLineMyPolyhedron( ptC, Z_AX, CylFrame, dOrtLen, 2 * dRad, dHei, dLongLen, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Cilindro ellittico di punta if ( IntersLineEllipticalCylinder( Z_AX, ptC, CylFrame, dRad, dLongLen, dOrtLen, bElpsT, bElpsT, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Cilindro ellittico di base: L'unica differenza rispetto a prima è l'origine // del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC // il vettore che congiunge le due origini. if ( IntersLineEllipticalCylinder( Z_AX, ptC - dHei * vtV1, CylFrame, dRad, dLongLen, dOrtLen, bElpsB, bElpsB, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + dHei * vtV1.z ; dMax = ptInt2.z + dHei * vtV1.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + dHei * vtV1.z ; dMax = ptInt1.z + dHei * vtV1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompConus_Milling( unsigned int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir, double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ, dMaxRad, dMinRad, dHei) ; if ( ! bInterf) return true ; // Geometria del cono double dDeltaR = dMaxRad - dMinRad ; // Studio simmetrie Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ; Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ; Point3d ptIT = ptI - vtToolDir * dHei ; Point3d ptFT = ptF - vtToolDir * dHei ; double dL = ( ( dMaxRad * dHei) / ( dDeltaR)) ; double dl = dL - dHei ; Point3d ptV = ptI - vtToolDir * dL ; // Vettori caratteristici del movimento Vector3d vtMove = ptF - ptI ; Vector3d vtMvLong = ( vtMove * vtToolDir) * vtToolDir ; Vector3d vtMvOrt = vtMove - vtMvLong ; // Terna destrorsa e unitaria Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = vtMvOrt ; vtV2.Normalize() ; Vector3d vtV3 = vtV1 ^ vtV2 ; // Sistema di riferimento intrinseco del movimento Frame3d ConusFrame ; ConusFrame.Set( ptV, vtV2, vtV3, vtV1) ; // Dimensioni lineari movimento double dLongLen = vtMvLong.Len() ; double dOrtLen = vtMvOrt.Len() ; // Apertura del cono double dTan = dDeltaR / dHei ; double dRatio = dLongLen / dOrtLen ; // Per costruire piani laterali poliedro interno double dCos = dTan * dRatio ; double dSin = ( 1 - dCos * dCos > 0 ? sqrt( 1 - dCos * dCos) : 0) ; double dDen = sqrt( 1 + dTan * dTan) ; // Dimensioni lineari descriventi il poliedro interno double dLenX = dLongLen ; double dLenY = dOrtLen ; double dLenZ = dSin * dMinRad ; double dDeltaX = dHei ; double dDeltaY = dCos * dDeltaR ; double dDeltaZ = dSin * dDeltaR ; // Sistema di riferimento poliedro Point3d ptO = ptV + vtV1 * dl + vtV2 * ( dCos * dMinRad) ; Frame3d PolyFrame ; PolyFrame.Set( ptO, vtV1, vtV2, vtV3) ; // Versori piani nel riferimento poliedro // (Sx, Dx, Iniziale, Finale, Up, Down sono riferiti // al sistema di riferimento): // Sx, Dx Vector3d vtNs( - ( dTan / dDen), ( dCos / dDen), ( dSin / dDen)) ; Vector3d vtNd( - ( dTan / dDen), ( dCos / dDen), - ( dSin / dDen)) ; // Iniziale e finale Vector3d vtIF( - dDeltaY, dDeltaX, 0) ; // Up e Down Vector3d vtUD( - dLenY, dLenX, 0) ; vtNs.Normalize() ; vtNd.Normalize() ; vtIF.Normalize() ; vtUD.Normalize() ; // Punti dei piani (sempre espressi nel sistema PolyFrame) Point3d ptFacet135( 0, 0, dLenZ) ; Point3d ptFacet246( dLenX + dDeltaX, dLenY + dDeltaY, - dLenZ - dDeltaZ) ; double dSqIndet = EPS_SMALL * EPS_SMALL ; Vector3d vtUmv = vtMove ; vtUmv.Normalize() ; // Variabili booleane per i tappi bool bConeT = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ; bool bConeB = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ; bool bElpsB = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapB) ; bool bElpsT = ( abs( vtToolDir * vtUmv) > EPS_SMALL ? true : bTapT) ; if ( dRatio * dTan <= 1) { 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) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Cono iniziale if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bConeT, bConeB, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Cono finale if ( IntersLineConus( ptC - vtMove, Z_AX, ConusFrame, dTan, dl, dL, bConeT, bConeB, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + vtMove.z ; dMax = ptInt2.z + vtMove.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + vtMove.z ; dMax = ptInt1.z + vtMove.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Solido interno Point3d ptPoly = ptC ; Vector3d vtPoly = Z_AX ; ptPoly.ToLoc( PolyFrame) ; vtPoly.ToLoc( PolyFrame) ; Point3d ptPoly1 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtNs) / ( vtPoly * vtNs)) * vtPoly ; Point3d ptPoly2 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtNd) / ( vtPoly * vtNd)) * vtPoly ; Point3d ptPoly3 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtIF) / ( vtPoly * vtIF)) * vtPoly ; Point3d ptPoly4 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtIF) / ( vtPoly * vtIF)) * vtPoly ; Point3d ptPoly5 = ptPoly + ( ( ( ptFacet135 - ptPoly) * vtUD) / ( vtPoly * vtUD)) * vtPoly ; Point3d ptPoly6 = ptPoly + ( ( ( ptFacet246 - ptPoly) * vtUD) / ( vtPoly * vtUD)) * vtPoly ; int nIntNum = 0 ; // Intersezione con la prima faccia if ( abs( vtPoly * vtNs) > COS_ORTO_ANG_ZERO) { if ( dLenY * ptPoly1.x >= dLenX * ptPoly1.y && dLenY * ( ptPoly1.x - dDeltaX) <= dLenX * ( ptPoly1.y - dDeltaY) && dDeltaX * ptPoly1.y >= dDeltaY * ptPoly1.x && dDeltaX * ( ptPoly1.y - dLenY) <= dDeltaY * ( ptPoly1.x - dLenX)) { ptInt1 = ptPoly1 ; vtN1 = - vtNs ; ++ nIntNum ; } } // Intersezione con la seconda faccia if ( abs( vtPoly * vtNd) > COS_ORTO_ANG_ZERO) { if ( dLenY * ptPoly2.x >= dLenX * ptPoly2.y && dLenY * ( ptPoly2.x - dDeltaX) <= dLenX * ( ptPoly2.y - dDeltaY) && dDeltaX * ptPoly2.y >= dDeltaY * ptPoly2.x && dDeltaX * ( ptPoly2.y - dLenY) <= dDeltaY * ( ptPoly2.x - dLenX)) { if ( nIntNum == 0) { ptInt1 = ptPoly2 ; vtN1 = - vtNd ; ++ nIntNum ; } else if ( ( ptInt1 - ptPoly2).SqLen() > dSqIndet) { ptInt2 = ptPoly2 ; vtN2 = - vtNd ; ++ nIntNum ; } } } // Intersezione con la terza faccia if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) { if ( nIntNum < 2 && ptPoly3.x >= 0 && ptPoly3.x <= dDeltaX && dDeltaX * abs( ptPoly3.z) < dDeltaX * dLenZ + dDeltaZ * ptPoly3.x) { if ( nIntNum == 0) { ptInt1 = ptPoly3 ; vtN1 = vtIF ; ++ nIntNum ; } else if ( ( ptInt1 - ptPoly3).SqLen() > dSqIndet) { ptInt2 = ptPoly3 ; vtN2 = vtIF ; ++ nIntNum ; } } } // Intersezione con la quarta faccia if ( abs( vtPoly * vtIF) > COS_ORTO_ANG_ZERO) { if ( nIntNum < 2 && ptPoly4.x >= dLenX && ptPoly4.x <= dLenX + dDeltaX && dDeltaX * abs( ptPoly4.z) < dDeltaX * dLenZ + dDeltaZ * ( ptPoly4.x - dLenX)) { if ( nIntNum == 0) { ptInt1 = ptPoly4 ; vtN1 = - vtIF ; ++ nIntNum ; } else if ( ( ptInt1 - ptPoly4).SqLen() > dSqIndet) { ptInt2 = ptPoly4 ; vtN2 = - vtIF ; ++ nIntNum ; } } } // Intersezione con la quinta faccia if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) { if ( nIntNum < 2 && ptPoly5.y >= 0 && ptPoly5.y <= dLenY && abs( ptPoly5.z) <= dLenZ) { if ( nIntNum == 0) { ptInt1 = ptPoly5 ; vtN1 = - vtUD ; ++ nIntNum ; } else if ( ( ptInt1 - ptPoly5).SqLen() > dSqIndet) { ptInt2 = ptPoly5 ; vtN2 = - vtUD ; ++ nIntNum ; } } } // Intersezione con la sesta faccia if ( abs( vtPoly * vtUD) > COS_ORTO_ANG_ZERO) { if ( nIntNum < 2 && ptPoly6.y >= dDeltaY && ptPoly6.y <= dLenY + dDeltaY && abs( ptPoly6.z) <= dLenZ + dDeltaZ) { if ( nIntNum == 0) { ptInt1 = ptPoly6; vtN1 = vtUD ; ++ nIntNum ; } else if ( ( ptInt1 - ptPoly6).SqLen() > dSqIndet) { ptInt2 = ptPoly6; vtN2 = vtUD ; ++ nIntNum ; } } } // Se il poliedro è attraversato taglio if ( nIntNum == 2) { // Riporto le intersezioni nel sistema griglia ptInt1.ToGlob( PolyFrame) ; ptInt2.ToGlob( PolyFrame) ; vtN1.ToGlob( PolyFrame) ; vtN2.ToGlob( PolyFrame) ; double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Traslazione ellisse di punta if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dl, ConusFrame, dMinRad, dLongLen, dOrtLen, bElpsT, bElpsT, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + vtV1.z * dl ; dMax = ptInt2.z + vtV1.z * dl ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + vtV1.z * dl ; dMax = ptInt1.z + vtV1.z * dl ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Traslazione ellisse di base if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dL, ConusFrame, dMaxRad, dLongLen, dOrtLen, bElpsB, bElpsB, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + vtV1.z * dL ; dMax = ptInt2.z + vtV1.z * dL ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + vtV1.z * dL ; dMax = ptInt1.z + vtV1.z * dL ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } else { 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) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Cono if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bConeT, bConeB, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Traslazione ellisse if ( IntersLineEllipticalCylinder( Z_AX, ptC - vtV1 * dL, ConusFrame, dMaxRad, dLongLen, dOrtLen, bConeB, bConeB, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + vtV1.z * dL ; dMax = ptInt2.z + vtV1.z * dL ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + vtV1.z * dL ; dMax = ptInt1.z + vtV1.z * dL ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } } //---------------------------------------------------------------------------- bool VolZmap::CompPar_Milling( unsigned int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Controllo sull'interferenza utensile-solido unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxParaComp( nGrid, dLenX, dLenY, dLenZ, ptS, ptE, vtToolDir, vtAux, nStartI, nStartJ, nEndI, nEndJ) ; if ( ! bInterf) return true ; // Vettore di movimento Vector3d vtMove = ptE - ptS ; // Sistema di riferimento del solido // nelle posizioni iniziale e finale. Vector3d vtV1 = vtToolDir ; Vector3d vtV2 = ( vtMove * ( vtV1 ^ vtAux) > 0 ? ( vtV1 ^ vtAux) : ( vtAux ^ vtV1)) ; Vector3d vtV3 = vtV1 ^ vtV2 ; Point3d ptO = ptS - dLenZ * vtV1 - vtV2 * ( 0.5 * dLenX) ; Frame3d ParaFrame ; ParaFrame.Set( ptO, vtV2, vtV3, vtV1) ; // Studio del volume asportato durante il moto Point3d ptLs = ( vtMove * vtAux >= 0 ? ptS : ptE) ; Point3d ptLe = ( vtMove * vtAux >= 0 ? ptE : ptS) ; Vector3d vtW3 = vtAux ; Vector3d vtAnsatz = ( vtW3 ^ vtToolDir) ; Vector3d vtMv = ptLe - ptLs ; bool bSymmetry = vtMv * vtAnsatz > 0 ; Vector3d vtW2 = ( bSymmetry ? vtAnsatz : - vtAnsatz) ; Vector3d vtW1 = ( bSymmetry ? vtToolDir : - vtToolDir) ; Point3d ptBase = bSymmetry ? ptLs - dLenZ * vtW1 : ptLs ; Frame3d MotionFrame ; Point3d ptDiagMin = ptBase - vtW2 * ( 0.5 * dLenX) + vtW3 * ( 0.5 * dLenY) ; Point3d ptDiagMax = ptBase + vtW2 * ( 0.5 * dLenX) - vtW3 * ( 0.5 * dLenY) ; Vector3d vtU1 = ptDiagMax - ptDiagMin ; double dDimLong = ( ptDiagMax - ptDiagMin).Len() ; vtU1.Normalize() ; bool bSymmetry2 = vtU1 * vtMv > 0 ; Vector3d vtU2 = ( bSymmetry2 ? vtMv - vtMv * vtU1 * vtU1 : vtMv * vtU1 * vtU1 - vtMv) ; vtU2.Normalize() ; Vector3d vtU3 = vtU1 ^ vtU2 ; Point3d ptOMotion = ( bSymmetry2 ? ptDiagMin : ptDiagMin + vtMv) + vtU3 * ( 0.5 * dLenZ) ; MotionFrame.Set( ptOMotion, vtU2, vtU3, vtU1) ; double dDeltaLong = abs( vtMv * vtU1) ; double dDimOrt = abs( vtMv * vtU2) ; 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) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Solido nella posizione iniziale if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ, 0, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Solido nella posizione finale if ( IntersLineMyPolyhedron( ptC - vtMove, Z_AX, ParaFrame, dLenX, dLenY, dLenZ, 0, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z + vtMove.z ; dMax = ptInt2.z + vtMove.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z + vtMove.z ; dMax = ptInt1.z + vtMove.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Volume spazzato nel moto if ( IntersLineMyPolyhedron( ptC, Z_AX, MotionFrame, dDimOrt, dLenZ, dDimLong, dDeltaLong, ptInt1, ptInt2, vtN1, vtN2)) { double dMin, dMax ; Vector3d vtNmin, vtNmax ; if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } // ---------- SFERA ---------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::CompBall_Milling( unsigned int nGrid, const Point3d & ptLs, const Point3d & ptLe, double dRad) { unsigned int nStartI, nStartJ, nEndI, nEndJ ; bool bInterf = BBoxComponent( nGrid, ptLs, ptLe, V_NULL, nStartI, nStartJ, nEndI, nEndJ, dRad, 0, 0) ; if ( ! bInterf) return true ; Vector3d vtV = ptLe - ptLs ; double dLengthPath = vtV.Len() ; vtV.Normalize() ; Vector3d vtW ; // Costruisco sistema di riferimento if ( vtV.x * vtV.x > 0.09) vtW.Set( - ( vtV.y + vtV.z) / vtV.x, 1, 1) ; else if ( vtV.y * vtV.y > 0.09) vtW.Set( 1, - ( vtV.x + vtV.z) / vtV.y, 1) ; else vtW.Set( 1, 1, - ( vtV.x + vtV.y) / vtV.z) ; //Point3d ptOnX = ptLs + vtW ; Frame3d CylFrame ; CylFrame.Set( ptLs, vtV, vtW) ; double dSqRad = dRad * dRad ; double dMin, dMax ; Vector3d vtNmin, vtNmax ; 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) ; double dStSqDXY = SqDistXY( ptC, ptLs) ; double dEnSqDXY = SqDistXY( ptC, ptLe) ; // Prima sfera if ( dStSqDXY < dSqRad) { dMin = ptLs.z - sqrt( dSqRad - dStSqDXY) ; dMax = ptLs.z + sqrt( dSqRad - dStSqDXY) ; Point3d ptIntMin( dX, dY, dMin) ; Point3d ptIntMax( dX, dY, dMax) ; vtNmin = ptLs - ptIntMin ; vtNmax = ptLs - ptIntMax ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Seconda sfera if ( dEnSqDXY < dSqRad) { dMin = ptLe.z - sqrt( dSqRad - dEnSqDXY) ; dMax = ptLe.z + sqrt( dSqRad - dEnSqDXY) ; Point3d ptIntMin( dX, dY, dMin) ; Point3d ptIntMax( dX, dY, dMax) ; vtNmin = ptLe - ptIntMin ; vtNmax = ptLe - ptIntMax ; vtNmin.Normalize() ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Cilindro if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, ptInt2, vtN1, vtN2)) { if ( ptInt1.z < ptInt2.z) { dMin = ptInt1.z ; dMax = ptInt2.z ; vtNmin = vtN1 ; vtNmax = vtN2 ; } else { dMin = ptInt2.z ; dMax = ptInt1.z ; vtNmin = vtN2 ; vtNmax = vtN1 ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } return true ; } // ------------------------- BOUNDING BOX -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- inline bool VolZmap::BoundingBox( unsigned int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, unsigned int& nStI, unsigned int& nStJ, unsigned int& nEnI, unsigned int& nEnJ) { // I punti e i vettori devono essere nel sistema di riferimento opportuno // Controllo sull'ammissibilità del numero di griglia if ( nGrid < 0 || nGrid > 2) return false ; unsigned int nMaxNx = m_nNx[nGrid] ; unsigned int nMaxNy = m_nNy[nGrid] ; double dMaxXValue = nMaxNx * m_dStep ; double dMaxYValue = nMaxNy * m_dStep ; double dMinZValue = m_dMinZ[nGrid] ; double dMaxZValue = m_dMaxZ[nGrid] ; // Determinazione del raggio massimo dell'utensile double dMaxRad = max( m_Tool.GetRadius(), m_Tool.GetTipRadius()) ; // Determinazione delle posizioni della punta dell'utensile nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - m_Tool.GetHeigth() * vtV ; Point3d ptP2T = ptP2 - m_Tool.GetHeigth() * vtV ; // 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::BBoxComponent( unsigned int nGrid, const Point3d & ptP1, const Point3d & ptP2, const Vector3d & vtV, unsigned int & nStI, unsigned int & nStJ, unsigned int & nEnI, unsigned int & nEnJ, double dRad, double dTipRad, double dHei) { // I punti e i vettori devono essere nel sistema di riferimento opportuno // Controllo sull'ammissibilità del numero di griglia if ( nGrid < 0 || nGrid > 2) return false ; unsigned int nMaxNx = m_nNx[nGrid] ; unsigned int nMaxNy = m_nNy[nGrid] ; double dMaxXValue = nMaxNx * m_dStep ; double dMaxYValue = nMaxNy * m_dStep ; double dMinZValue = m_dMinZ[nGrid] ; double dMaxZValue = m_dMaxZ[nGrid] ; // Determinazione del raggio massimo del componente double dMaxRad = max( dRad, dTipRad) ; // Determinazione delle posizioni della punta del componente nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - dHei * vtV ; Point3d ptP2T = ptP2 - dHei * vtV ; // 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::BBoxParaComp( unsigned int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA, unsigned int& nStI, unsigned int& nStJ, unsigned int& nEnI, unsigned int& nEnJ) { // I punti e i vettori devono essere nel sistema di riferimento opportuno // Determino le posizioni iniziale e // finale della punta dell'utensile. Point3d ptSTip = ptS - vtD * dLenZ ; Point3d ptETip = ptE - vtD * dLenZ ; double dMaxDim = max( dLenX, dLenY) ; // Determinazione dei limiti del più piccolo parallelepipedo contenente il movimento double dMinX = min( min( ptS.x, ptSTip.x), min( ptE.x, ptETip.x)) - dMaxDim ; double dMinY = min( min( ptS.y, ptSTip.y), min( ptE.y, ptETip.y)) - dMaxDim ; double dMinZ = min( min( ptS.z, ptSTip.z), min( ptE.z, ptETip.z)) - dMaxDim ; double dMaxX = max( max( ptS.x, ptSTip.x), max( ptE.x, ptETip.x)) + dMaxDim ; double dMaxY = max( max( ptS.y, ptSTip.y), max( ptE.y, ptETip.y)) + dMaxDim ; double dMaxZ = max( max( ptS.z, ptSTip.z), max( ptE.z, ptETip.z)) + dMaxDim ; unsigned int nMaxNx = m_nNx[nGrid] ; unsigned int nMaxNy = m_nNy[nGrid] ; double dMaxXValue = nMaxNx * m_dStep ; double dMaxYValue = nMaxNy * m_dStep ; double dMinZValue = m_dMinZ[nGrid] ; double dMaxZValue = m_dMaxZ[nGrid] ; // 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 ; }