//---------------------------------------------------------------------------- // EgalTech 2015-2020 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 05.10.20 Versione : 2.2j1 // 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 "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLineSphere.h" #include "/EgtDev/Include/ENkPolynomialRoots.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include using namespace std ; // ------------------------- OPERAZIONI SU INTERVALLI -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::SubtractIntervals( int nGrid, int nI, 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_ZERO) return true ; // Controllo che il numero di griglia sia entro i limiti if ( nGrid < 0 || nGrid > 2) return false ; // Controllo che gli indici nI, nJ siano entro i limiti if ( nI < 0 || nI >= m_nNx[nGrid] || nJ < 0 || nJ >= m_nNy[nGrid]) return false ; // Controllo che dMin < dMax Vector3d vtNmi = vtNMin ; Vector3d vtNma = vtNMax ; if ( dMin > dMax) { swap( dMin, dMax) ; swap( vtNmi, vtNma) ; } // Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a 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) ; } // Recupero dexel da modificare int nPos = nJ * m_nNx[nGrid] + nI ; vector& vDexel = m_Values[nGrid][nPos] ; // Ciclo sugli intervalli del dexel (ordinati in senso crescente) bool bModified = false ; for ( int i = 0 ; i < int( vDexel.size()) ; ++i) { // Se interseca l'intervallo corrente if ( dMin < vDexel[i].dMax - EPS_ZERO && dMax > vDexel[i].dMin + EPS_ZERO) { bModified = true ; // se devo limitarlo inferiormente if ( dMin <= vDexel[i].dMin + EPS_ZERO && dMax < vDexel[i].dMax - EPS_ZERO) { vDexel[i].dMin = dMax ; vDexel[i].vtMinN = vtNma ; vDexel[i].nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; } // se devo limitarlo superiormente else if ( dMin > vDexel[i].dMin + EPS_ZERO && dMax >= vDexel[i].dMax - EPS_ZERO) { vDexel[i].dMax = dMin ; vDexel[i].vtMaxN = vtNmi ; vDexel[i].nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; } // se devo dividerlo in due parti else if ( dMin > vDexel[i].dMin + EPS_ZERO && dMax < vDexel[i].dMax - EPS_ZERO) { // inserisco nuovo intervallo (parte superiore) vDexel.insert( vDexel.begin() + i + 1, { dMax, vtNma, m_vTool[m_nCurrTool].GetCurrentToolNum(), vDexel[i].dMax, vDexel[i].vtMaxN, vDexel[i].nToolMax, vDexel[i].nCompo}) ; // aggiorno il vecchio (parte inferiore) vDexel[i].dMax = dMin ; vDexel[i].vtMaxN = vtNmi ; vDexel[i].nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; ++ i ; } // altrimenti devo eliminarlo else { vDexel.erase( vDexel.begin() + i) ; -- i ; } } // se � tutto minore dell'intervallo corrente, ho finito else if ( dMax <= vDexel[i].dMin + EPS_ZERO) break ; // altrimenti � tutto maggiore dell'intervallo corrente, passo al successivo else // dMin >= vDexel[i].dMax - EPS_ZERO ; } // Se nessuna modifica, esco if ( ! bModified) return true ; // Elimino residui di intervalli inutili for ( int i = 0 ; i < int( vDexel.size()) ; ++ i) { int nMaxN = int( floor( ( vDexel[i].dMax + 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ; int nMinN = int( floor( ( vDexel[i].dMin - 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ; if ( nMinN == nMaxN) { vDexel.erase( vDexel.begin() + i) ; -- i ; } } // Imposto ricalcolo della grafica m_OGrMgr.Reset() ; // Imposto forma generica m_nShape = GENERIC ; // Imposto ricalcolo numero di componenti connesse m_nConnectedCompoCount = - 1 ; // Passo da indici di dexel a indici di voxel nI /= m_nDexVoxRatio ; nJ /= m_nDexVoxRatio ; // Determino quali blocchi sono stati modificati if ( nGrid == 0) { // Voxel lungo X int nXStop = 1 ; int nXBlock[2] ; nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } // Voxel lungo Y int nYStop = 1 ; int nYBlock[2] ; nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } // Voxel lungo Z int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * 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)) ; // Assegno flag ai voxel for ( int tI = 0 ; tI < nXStop ; ++ tI) { for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) { for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) { int nBlockNum = k * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 1) { // Voxel lungo Y int nYStop = 1 ; int nYBlock[2] ; nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } // Voxel lungo Z int nZStop = 1 ; int nZBlock[2] ; nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Voxel lungo X int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ; int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * 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)) ; // Assegno flag ai voxel 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] * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tI] * m_nFracLin[0] + k ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 2) { // Voxel lungo X int nXStop = 1 ; int nXBlock[2] ; nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } // Voxel lungo Z int nZStop = 1 ; int nZBlock[2] ; nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Voxel lungo Y int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * 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)) ; // Assegno flag ai voxel 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] * m_nFracLin[0] * m_nFracLin[1] + k * m_nFracLin[0] + nXBlock[tJ] ; m_BlockToUpdate[nBlockNum] = true ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::AddIntervals( int nGrid, int nI, 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 indici nI, nJ siano entro i limiti if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid]) return false ; // Controllo che dMin < dMax Vector3d vtNmi = vtNMin ; Vector3d vtNma = vtNMax ; if ( dMin > dMax) { swap( dMin, dMax) ; swap( vtNmi, vtNma) ; } // 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 ; vector& vDexel = m_Values[nGrid][nPos] ; bool bModified = false ; // Non esistono segmenti if ( m_Values[nGrid][nPos].size() == 0) { vDexel.emplace_back() ; vDexel.back().dMin = dMin ; vDexel.back().vtMinN = vtNmi ; vDexel.back().nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; vDexel.back().dMax = dMax ; vDexel.back().vtMaxN = vtNma ; vDexel.back().nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; if ( dMax > m_dMaxZ[nGrid]) m_dMaxZ[nGrid] = dMax ; if ( dMin < m_dMinZ[nGrid]) m_dMinZ[nGrid] = dMin ; m_OGrMgr.Reset() ; bModified = true ; } // Esiste almeno un segmento else { // Cerco l'ultimo intervallo a sinistra e l'ultimo intervallo a destra // di quello da aggiungere, che non interferiscono con quest'ultimo. auto itLastLeft = vDexel.end() ; auto itFirstRight = vDexel.end() ; for ( auto it = vDexel.begin() ; it != vDexel.end() ; ++ it) { if ( dMin > it->dMax + EPS_SMALL) itLastLeft = it ; if ( dMax < it->dMin - EPS_SMALL && itFirstRight == vDexel.end()) itFirstRight = it ; } // Esistono intervalli a sinistra. if ( itLastLeft != vDexel.end()) { // Intervallo successivo all'ultimo a sinistra auto itNextToLastLeft = itLastLeft ; ++ itNextToLastLeft ; // Il successivo non esiste. if ( itNextToLastLeft == vDexel.end()) { // Aggiungo il nuovo semgento vDexel.emplace_back() ; vDexel.back().dMin = dMin ; vDexel.back().dMax = dMax ; vDexel.back().vtMinN = vtNmi ; vDexel.back().vtMaxN = vtNma; vDexel.back().nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; vDexel.back().nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //m_Values[nGrid][nPos].back().nCompo = ; bModified = true ; } // Il successivo esiste. else { // Il successivo è il primo a destra. if ( itNextToLastLeft == itFirstRight) { // Inserisco nuovo segmento- Data NewSegment ; NewSegment.dMin = dMin ; NewSegment.dMax = dMax ; NewSegment.vtMinN = vtNmi ; NewSegment.vtMaxN = vtNma ; NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //NewSegment.nCompo = ; vDexel.insert( itFirstRight, NewSegment) ; bModified = true ; } else { // Il successivo non esce a sinistra da quello da aggiungere. if ( itNextToLastLeft->dMin > dMin + EPS_SMALL) { itNextToLastLeft->dMin = dMin ; itNextToLastLeft->vtMinN = vtNmi ; itNextToLastLeft->nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; } // Cerco l'ultimo segmento che interferisce con quello da aggiungere. auto itPrevToFirstRight = vDexel.end() ; for ( auto it = itNextToLastLeft ; it != itFirstRight ; ++ it) { itPrevToFirstRight = it ; } // L'ultimo che interferisce non esce a destra da quello da aggiungere. if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) { itNextToLastLeft->dMax = dMax ; itNextToLastLeft->vtMaxN = vtNma ; itNextToLastLeft->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //itNextToLastLeft->nCompo = ; bModified = true ; } else { itNextToLastLeft->dMax = itPrevToFirstRight->dMax ; itNextToLastLeft->vtMaxN = itPrevToFirstRight->vtMaxN ; itNextToLastLeft->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //itNextToLastLeft->nCompo = ; bModified = true ; } auto itFirstToCancel = itNextToLastLeft ; ++ itFirstToCancel ; vDexel.erase( itFirstToCancel, itFirstRight) ; } } } // Non esistono neanche a destra. else if ( itFirstRight == m_Values[nGrid][nPos].end()) { // Il primo intervallo non sporge a sinistra if ( vDexel.begin()->dMin > dMin + EPS_SMALL) { vDexel.begin()->dMin = dMin ; vDexel.begin()->vtMinN = vtNmi ; vDexel.begin()->nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //vDexel.begin().nCompo = ; bModified = true ; } // L'ultimo intervallo sporge a destra. if ( m_Values[nGrid][nPos].back().dMax > dMax + EPS_SMALL) { // Ci sono più segmenti, inglobo tutti nel primo. if ( vDexel.back().dMax > vDexel.begin()->dMax + EPS_SMALL) { vDexel.begin()->dMax = vDexel.back().dMax ; vDexel.begin()->vtMaxN = vDexel.back().vtMaxN ; vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //vDexel.begin().nCompo = ; bModified = true ; } } // L'ultimo intervallo non sporge a destra. else { vDexel.begin()->dMax = dMax ; vDexel.begin()->vtMaxN = vtNma ; vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //vDexel.begin().nCompo = ; bModified = true ; } vDexel.erase( vDexel.begin() + 1, vDexel.end()) ; } // A destra esistono. else { // Tutti i segmenti sono a destra di qullo da aggiungere. if ( itFirstRight == vDexel.begin()) { // Inserisco nuovo segmento- Data NewSegment ; NewSegment.dMin = dMin ; NewSegment.dMax = dMax ; NewSegment.vtMinN = vtNmi ; NewSegment.vtMaxN = vtNma ; NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; NewSegment.nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //NewSegment.nCompo = ; vDexel.insert( vDexel.begin(), NewSegment) ; bModified = true ; } else { // Se il primo segmento non esce a sinistra da quello da aggiungere, cambio l'inizio. if ( vDexel.begin()->dMin > dMin + EPS_SMALL) { vDexel.begin()->dMin = dMin ; vDexel.begin()->vtMinN = vtNmi ; vDexel.begin()->nToolMin = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //vDexel.begin().nCompo = ; bModified = true ; } // Cerco l'ultimo segmento che interferisce con quello da aggiungere. auto itPrevToFirstRight = vDexel.begin() ; for ( auto it = m_Values[nGrid][nPos].begin() ; it != itFirstRight ; ++ it) { itPrevToFirstRight = it ; } // L'ultimo che interferisce non esce a destra da quello da aggiungere. if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) { vDexel.begin()->dMax = dMax ; vDexel.begin()->vtMaxN = vtNma ; vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //vDexel.begin().nCompo = ; bModified = true ; } else { vDexel.begin()->dMax = itPrevToFirstRight->dMax ; vDexel.begin()->vtMaxN = itPrevToFirstRight->vtMaxN ; vDexel.begin()->nToolMax = m_vTool[m_nCurrTool].GetCurrentToolNum() ; //vDexel.begin().nCompo = ; bModified = true ; } auto itFirstToCancel = vDexel.begin() ; ++ itFirstToCancel ; vDexel.erase( itFirstToCancel, itFirstRight) ; } } } // Se nessuna modifica, esco if ( ! bModified) return true ; // Elimino residui di intervalli inutili for ( int i = 0 ; i < int( vDexel.size()) ; ++ i) { int nMaxN = int( floor( ( vDexel[i].dMax + 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ; int nMinN = int( floor( ( vDexel[i].dMin - 2 * EPS_SMALL - 0.5 * m_dStep) / m_dStep)) ; if ( nMinN == nMaxN) { vDexel.erase( vDexel.begin() + i) ; -- i ; } } // Imposto ricalcolo della grafica m_OGrMgr.Reset() ; // Imposto forma generica m_nShape = GENERIC ; // Imposto ricalcolo numero di componenti connesse m_nConnectedCompoCount = - 1 ; // Passo da indici di dexel a indici di voxel nI /= m_nDexVoxRatio ; nJ /= m_nDexVoxRatio ; // Determino quali blocchi sono stati modificati if ( nGrid == 0) { // Voxel lungo X int nXStop = 1 ; int nXBlock[2] ; nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } // Voxel lungo Y int nYStop = 1 ; int nYBlock[2] ; nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } // Voxel lungo Z int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * 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)) ; // Assegno flag ai voxel for ( int tI = 0 ; tI < nXStop ; ++ tI) { for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) { for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) { int nBlockNum = k * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 1) { // Voxel lungo Y int nYStop = 1 ; int nYBlock[2] ; nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) { nYBlock[1] = nYBlock[0] - 1 ; ++ nYStop ; } // Voxel lungo Z int nZStop = 1 ; int nZBlock[2] ; nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Voxel lungo X int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ; int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * 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)) ; // Assegno flag ai voxel 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] * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tI] * m_nFracLin[0] + k ; m_BlockToUpdate[nBlockNum] = true ; } } } } else if ( nGrid == 2) { // Voxel lungo X int nXStop = 1 ; int nXBlock[2] ; nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) { nXBlock[1] = nXBlock[0] - 1 ; ++ nXStop ; } // Voxel lungo Z int nZStop = 1 ; int nZBlock[2] ; nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) { nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } // Voxel lungo Y int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * 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)) ; // Assegno flag ai voxel 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] * m_nFracLin[0] * m_nFracLin[1] + k * m_nFracLin[0] + nXBlock[tJ] ; m_BlockToUpdate[nBlockNum] = true ; } } } } 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) { // Se non � definito l'utensile, non devo fare alcunch� if ( m_nCurrTool < 0 || m_vTool[m_nCurrTool].GetType() == Tool::UNDEF) return true ; // Controllo definizione vettori direzione if ( vtDs.IsSmall() || vtDe.IsSmall()) return false ; // Controllo sull'effettiva esistenza del movimento if ( AreSamePointApprox( ptPs, ptPe) && AreSameVectorApprox( vtDs, vtDe)) return true ; // Se utensile chisel o mortise, controllo definizione vettori ausiliari if ( m_vTool[m_nCurrTool].GetType() == Tool::MORTISER || m_vTool[m_nCurrTool].GetType() == Tool::CHISEL) { if ( vtAs.IsSmall() || vtAe.IsSmall()) return false ; } // Reset numero di parti m_nConnectedCompoCount = - 1 ; // Punti e vettori descriventi il moto nel sistema intrinseco dello Zmap Point3d ptPLs = ptPs ; ptPLs.ToLoc( m_MapFrame) ; Point3d ptPLe = ptPe ; ptPLe.ToLoc( m_MapFrame) ; Vector3d vtDLs = vtDs ; vtDLs.ToLoc( m_MapFrame) ; vtDLs.Normalize() ; Vector3d vtDLe = vtDe ; vtDLe.ToLoc( m_MapFrame) ; vtDLe.Normalize() ; Vector3d vtALs = vtAs ; vtALs.ToLoc( m_MapFrame) ; vtALs.Normalize() ; Vector3d vtALe = vtAe ; vtALe.ToLoc( m_MapFrame) ; vtALe.Normalize() ; //static PerformanceCounter Counter ; //{ //string sOut = "Draw=" + ToString( Counter.Stop(), 3) ; //LOG_INFO( GetEGkLogger(), sOut.c_str()) //Counter.Start() ; //} // Se pura traslazione bool bOk ; if ( AreSameVectorApprox( vtDLs, vtDLe)) bOk = MillingTranslationStep( ptPLs, ptPLe, vtDLs, vtALs) ; else bOk = MillingGeneralMotionStep( ptPLs, vtDLs, vtALs, ptPLe, vtDLe, vtALe) ; //{ //string sOut = "Calc=" + ToString( Counter.Stop(), 3) ; //LOG_INFO( GetEGkLogger(), sOut.c_str()) //Counter.Start() ; //} return bOk ; } //---------------------------------------------------------------------------- bool VolZmap::MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs, const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) { // Divido il movimento in tratti con direzione utensile costante const double ANG_STEP = 0.5 ; double dAngDeg ; vtDs.GetAngle( vtDe, dAngDeg) ; int nStepCnt = int( abs( dAngDeg) / ANG_STEP) + 1 ; bool bOk = true ; Point3d ptSt = ptPs ; for ( int i = 0 ; i <= nStepCnt && bOk ; ++ i) { double dPosCoeff, dDirCoeff ; if ( i < nStepCnt) { dPosCoeff = ( i + 0.5) / nStepCnt ; dDirCoeff = double( i) / nStepCnt ; } else { dPosCoeff = 1 ; dDirCoeff = 1 ; } Point3d ptEn = Media( ptPs, ptPe, dPosCoeff) ; Vector3d vtD = Media( vtDs, vtDe, dDirCoeff) ; vtD.Normalize() ; Vector3d vtA = Media( vtAs, vtAe, dDirCoeff) ; vtA.Normalize() ; bOk = bOk && MillingTranslationStep( ptSt, ptEn, vtD, vtA) ; // aggiorno prossimo inizio ptSt = ptEn ; } return bOk ; } //---------------------------------------------------------------------------- bool VolZmap::MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) { Point3d ptLs[N_MAPS] ; Point3d ptLe[N_MAPS] ; Vector3d vtLs[N_MAPS] ; Vector3d vtALs[N_MAPS] ; InitializePointsAndVectors( ptPs, ptPe, vtD, vtA, ptLs, ptLe, vtLs, vtALs) ; // Ciclo sulle mappe vector< future> vRes ; vRes.resize( m_nMapNum) ; for ( int i = 0 ; i < m_nMapNum ; ++ i) { vRes[i] = async( launch::async, &VolZmap::SelectMotion, this, i, cref( ptLs[i]), cref( ptLe[i]), cref( vtLs[i]), cref( vtALs[i])) ; } bool bOk = true ; int nTerminated = 0 ; while ( nTerminated < m_nMapNum) { for ( int i = 0 ; i < m_nMapNum ; ++ i) { if ( vRes[i].valid() && vRes[i].wait_for( chrono::nanoseconds{ 1}) == future_status::ready) { bOk = vRes[i].get() && bOk ; ++ nTerminated ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::InitializePointsAndVectors( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtDs, const Vector3d& vtAs, Point3d ptLs[3], Point3d ptLe[3], Vector3d vtLs[3], Vector3d vtALs[3]) { // Punti posizione ptLs[0] = ptPs ; ptLe[0] = ptPe ; 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 asse utensile vtLs[0] = vtDs ; 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 ; } // Vettori ausiliari vtALs[0] = vtAs ; 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 ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::SelectMotion( int nGrid, const Point3d& ptLs, const Point3d& ptLe, const Vector3d& vtL, const Vector3d& vtAL) { // Versore utensile parallelo all'asse Z (coincide con spillone) if ( vtL.SqLenXY() < EPS_ZERO * EPS_ZERO) { Vector3d vtMove = ptLe - ptLs ; // Foratura if ( vtMove.SqLenXY() < EPS_SMALL * EPS_SMALL) { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_ZDrilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_ZDrilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_ZDrilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::CHISEL : Chs_ZDrilling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } // Fresatura con vettore movimento perpendicolare all'utensile else if ( abs( vtMove.z) < EPS_SMALL) { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_ZPerp( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_ZPerp( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::CHISEL : Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::ADDITIVE : // Chiama metodo break ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_ZMilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_ZMilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_ZMilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } } // Versore utensile nel piano XY (perpendicolare allo spillone) else if ( abs( vtL.z) < EPS_ZERO) { Vector3d vtMove = ptLe - ptLs ; Vector3d vtMLong = ( vtMove * vtL) * vtL ; Vector3d vtMOrt = vtMove - vtMLong ; double dSqLLong = vtMLong.SqLen() ; double dSqLOrt = vtMOrt.SqLen() ; // Foratura if ( dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_XYDrilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_XYDrilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::CHISEL : Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } // Fresatura con vettore movimento perpendicolare all'utensile else if ( dSqLLong < EPS_SMALL * EPS_SMALL) { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_Milling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_XYPerp( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : // Usiamo la generica per via dell'intsabilit� di Conus_XYPerp //Conus_XYPerp( i, ptLs[i], ptLe[i], vtLs[i]) ; Conus_Milling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::CHISEL : Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::ADDITIVE : // Chiama metodo break ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_Milling( nGrid, ptLs, ptLe, vtL); break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_XYMilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_XYMilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } } // Versore utensile con direzione generica else { Vector3d vtMove = ptLe - ptLs ; Vector3d vtMLong = ( vtMove * vtL) * vtL ; Vector3d vtMOrt = vtMove - vtMLong ; double dSqLLong = vtMLong.SqLen() ; double dSqLOrt = vtMOrt.SqLen() ; // Foratura if ( dSqLOrt < EPS_SMALL * EPS_SMALL) { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_Drilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_Drilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_Drilling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::CHISEL : Chs_Drilling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } // Fresatura con vettore movimento generico rispetto all'utensile else { switch ( m_vTool[m_nCurrTool].GetType()) { case Tool::GEN : GenTool_Milling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CYLMILL : case Tool::BALLMILL : CylBall_Milling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::CONEMILL : Conus_Milling( nGrid, ptLs, ptLe, vtL) ; break ; case Tool::MORTISER : Mrt_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; case Tool::CHISEL : // ammesso solo movimento perpendicolare all'asse utensile if ( dSqLLong < EPS_SMALL * EPS_SMALL) Chs_Milling( nGrid, ptLs, ptLe, vtL, vtAL) ; break ; } } } return true ; } // ---------- VERSORE UTENSILE DERETTO COME Z -------------------------------- // ---------- Cilindro e sfera ----------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::CylBall_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Proiezione dei punti sul piano Point3d ptSxy( ptS.x, ptS.y, 0) ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].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 ( int i = nStartI ; i <= nEndI ; ++ i) { for( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].GetRadius() * EPS_SMALL) { // utensile cilindrico if ( m_vTool[m_nCurrTool].GetType() == Tool::CYLMILL) SubtractIntervals( nGrid, i, j, dMinStemZ, dMaxStemZ, Z_AX, - Z_AX) ; // utensile sferico else if ( m_vTool[m_nCurrTool].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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dSafeRad = m_vTool[m_nCurrTool].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, 0, 1) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtC = ptC - ptSxy ; double dP1 = vtC * vtV1 ; double dP2 = vtC * vtV2 ; // Utensile cilindrico if ( m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dSafeRadius = m_vTool[m_nCurrTool].GetRadius() - EPS_SMALL ; double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ; double dSafeSqRad = dSqRad - 2 * m_vTool[m_nCurrTool].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 dDeltaZ = dZMaxF - dZMaxI ; // Vettori caratterizzanti il moto Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLenXY = vtMoveXY.LenXY() ; vtMove.Normalize() ; // 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, 0, 1) ; double dMin, dMax ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) CompBall_Milling( nGrid, ptIT, ptFT, m_vTool[m_nCurrTool].GetRadius()) ; return true ; } // ---------- Coni ----------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Conus_ZDrilling( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetHeigth()), max( ptE.z, ptE.z - vtToolDir.z * m_vTool[m_nCurrTool].GetHeigth())) ; double dZMin = min( min( ptS.z, ptS.z - vtToolDir.z * m_vTool[m_nCurrTool].GetHeigth()), min( ptE.z, ptE.z - vtToolDir.z * m_vTool[m_nCurrTool].GetHeigth())) ; // Parametri geometrici per // determinare il vettore normale double dL = m_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ; // Trapano if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) { // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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( int nGrid, const Point3d & ptS, const Point3d & ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetHeigth() ; // Lunghezza cono double dL = m_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ; // Punta a trapano if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) { Vector3d vtV = vtToolDir ; Point3d ptVS = ptS - vtToolDir * ( dStemHeigth + dL) ; Point3d ptVE = ptE - vtToolDir * ( dStemHeigth + dL) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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)) { double dMin = min( dBaseZ, dTipZ) ; double 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) ; double dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; double 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else if ( dP1 <= dLen) { double dr = abs( dP2) ; double dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; double 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else { double dr = sqrt( dSqLenE) ; double dMin = min( dBaseZ, dTipZ + ( dStemZ - dTipZ) * ( dr - dMinRad) / dDeltaRad) ; double 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } } } // Coda di rondine else { Vector3d vtV = - vtToolDir ; Point3d ptVS = ptS - vtToolDir * ( m_vTool[m_nCurrTool].GetHeigth() - dL) ; Point3d ptVE = ptE - vtToolDir * ( m_vTool[m_nCurrTool].GetHeigth() - dL) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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)) { double dMin = min( dBaseZ, dTipZ) ; double 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) ; double dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; double 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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 ; double dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; double 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } else { double dr = sqrt( dSqLenE) ; double dMin = min( dTipZ, dStemZ + ( dTipZ - dStemZ) * ( dr - dMinRad) / dDeltaRad) ; double 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemH = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; CompCyl_ZMilling( nGrid, ptS, ptE, vtToolDir, dStemH, m_vTool[m_nCurrTool].GetRadius()) ; if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) { Point3d ptSC = ptS - vtToolDir * dStemH ; Point3d ptEC = ptE - vtToolDir * dStemH ; CompConus_ZMilling( nGrid, ptSC, ptEC, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; } else { Point3d ptSC = ptS - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() ; Point3d ptEC = ptE - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() ; CompConus_ZMilling( nGrid, ptSC, ptEC, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius()) ; } return true ; } // --------- Mortasatrice ----------------------------------------------------- // ---------------------------------------------------------------------------- bool VolZmap::Mrt_ZDrilling( 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_vTool[m_nCurrTool].GetMrtChsWidth() ; double dLenY = m_vTool[m_nCurrTool].GetMrtChsThickness() ; double dLenZ = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetCornRadius() ; CompPar_ZDrilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux) ; // Se la punta � di tipo bull-nose if ( abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipS = ptS - dLenZ * vtToolDir ; Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ; dLenX = abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) ; dLenZ = m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetCornRadius(), false, false) ; CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetCornRadius(), false, false) ; } return true ; } // --------- Chisel ---------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Chs_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { CompPar_ZDrilling( nGrid, m_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(), ptS, ptE, vtToolDir, vtAux) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::Chs_ZMilling( 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_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(), ptSp, ptEp, vtToolDir, vtAux) ; return true ; } // --------- Utensile generico ------------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::GenTool_ZDrilling( 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 ; // Vettore delle normali agli archi const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ; // Poinch� l'asse utensile � parallelo all'asse Z, definisco un sistema di // riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ. Frame3d frNormFrame ; frNormFrame.Set( ORIG, X_AX, - Z_AX, Y_AX) ; // Ciclo sulle curve const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ; int i = - 1 ; const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ; while ( pCurve != nullptr) { double dHeight = 0 ; double dSignedHeight = 0 ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; int nNormNum = pLine->GetTempProp() ; Vector3d vtNormSt, vtNormEn ; if ( nNormNum != 0) { vtNormSt = vArcNorm[nNormNum - 1] ; vtNormEn = vArcNorm[nNormNum] ; vtNormSt.ToLoc( frNormFrame) ; vtNormEn.ToLoc( frNormFrame) ; } // Ne determino l'altezza dSignedHeight = ptStart.y - ptEnd.y ; dHeight = abs( dSignedHeight) ; // Cilindro o cono if ( dHeight > EPS_SMALL) { // Se X costante, � un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; if ( dRadius > 10 * EPS_SMALL && m_vTool[m_nCurrTool].GetCuttingFlag()) 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 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, vtNormSt, vtNormEn) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormSt, vtNormEn) ; else { Point3d ptIn = ptI ; Point3d ptFn = ptIn + vtMove ; /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormEn, vtNormSt) ; } } } // 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 * dSignedHeight ; Point3d ptFn = ptIn + vtMove ; vtNormEn.z *= -1 ; vtNormSt.z *= -1 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, vtNormEn, vtNormSt) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_ZDrilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormEn, vtNormSt) ; else { vtNormEn.z *= -1 ; vtNormSt.z *= -1 ; SurfConus_ZDrilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormSt, vtNormEn) ; } } } } // Corona circolare else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) { if ( ptStart.x < ptEnd.x) { SurfCircCrown_ZDrilling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ; } else { SurfCircCrown_ZDrilling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ; } } } // 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 if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ; else if ( pCurve->GetTempProp( 1) == 1) { double dStH = ptStart.y - ptCen.y ; double dEnH = ptEnd.y - ptCen.y ; // Tagliente esterno if ( dEnH < dStH) { if ( dEnH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ; } else if ( dStH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ; } } // Tagliente interno else { if ( dEnH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } else if ( dStH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } } dSignedHeight = ptStart.y - ptEnd.y ; } // aggiorno l'altezza //dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dSignedHeight ; ptF = ptI + vtMove ; // Passo alla curva successiva del profilo pCurve = ToolProfile.GetCurve( ++ i) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::GenTool_ZMilling( 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 ; // Vettore delle normali agli archi const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ; // Poinch� l'asse utensile � parallelo all'asse Z, definisco un sistema di // riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ. Frame3d frNormFrame; frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ; // Ciclo sulle curve del profilo utensile const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ; int i = - 1 ; const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ; while ( pCurve != nullptr) { double dHeight = 0 ; double dSignedHeight = 0 ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; int nNormNum = pLine->GetTempProp() ; Vector3d vtNormSt, vtNormEn ; if ( nNormNum != 0) { vtNormSt = vArcNorm[nNormNum - 1] ; vtNormEn = vArcNorm[nNormNum] ; vtNormSt.ToLoc( frNormFrame) ; vtNormEn.ToLoc( frNormFrame) ; } // Ne determino l'altezza dSignedHeight = ptStart.y - ptEnd.y ; dHeight = abs( dSignedHeight) ; if ( dHeight > EPS_SMALL) { // Se X costante, � un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; if ( dRadius > 10 * EPS_SMALL) { if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfCyl_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, true) ; else { SurfCyl_ZMilling( nGrid, ptI, ptF, - vtToolDir, dHeight, dRadius, false) ; } } } } // 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 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, vtNormSt, vtNormEn) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormSt, vtNormEn) ; else { Point3d ptIn = ptI ; Point3d ptFn = ptIn + vtMove ; /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormEn, vtNormSt) ; } } } // 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 * dSignedHeight ; Point3d ptFn = ptIn + vtMove ; vtNormEn.z *= -1 ; vtNormSt.z *= -1 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, vtNormEn, vtNormSt) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_ZMilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, vtNormEn, vtNormSt) ; else { /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_ZMilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, vtNormSt, vtNormEn) ; } } } } else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) { if ( ptStart.x < ptEnd.x) { SurfCircCrown_ZMilling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ; } else { SurfCircCrown_ZMilling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ; } } } // 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 if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ; else if ( pCurve->GetTempProp( 1) == 1) { double dStH = ptStart.y - ptCen.y ; double dEnH = ptEnd.y - ptCen.y ; // Tagliente esterno if ( dEnH < dStH) { if ( dEnH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ; } else if ( dStH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ; } } // Tagliente interno else { if ( dEnH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } else if ( dStH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } } dSignedHeight = ptStart.y - ptEnd.y ; } // aggiorno l'altezza //dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dSignedHeight ; ptF = ptI + vtMove ; // Passo alla curva successiva del profilo pCurve = ToolProfile.GetCurve( ++ i) ; } return true ; } // ---------- VERSORE UTENSILE NEL PIANO XY ---------------------------------- // --------- Cilindro e sfera ------------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::CylBall_XYDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile e quota Z del movimento double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].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, 0, 1) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d & vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ; double dSafeSqRad = dSqRad - 2 * m_vTool[m_nCurrTool].GetRadius() * EPS_SMALL ; // Studio simmetrie del problema Point3d ptI = ( ptS.z <= ptE.z ? ptS : ptE) ; Point3d ptF = ( ptS.z <= ptE.z ? ptE : ptS) ; // elimino eventuale piccolo errore di perpendicolarit� del movimento rispetto all'utensile Vector3d vtErr = 0.5 * ( ( ptF - ptI) * vtToolDir) * vtToolDir ; ptI += vtErr ; ptF -= vtErr ; 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 dLenXY = vtMove.LenXY() ; vtMove.Normalize() ; // Sistema di riferimento ad hoc Vector3d vtV1( - vtToolDir.x, - vtToolDir.y, 0) ; vtV1.Normalize() ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 0, 1) ; 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, 0, 1) ; Point3d ptUp = ptI + m_vTool[m_nCurrTool].GetRadius() * ( vtP.z > 0 ? vtP : - vtP) ; Point3d ptDw = ptI + m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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 dInfZ, dSupZ ; if ( dLenXY < EPS_SMALL) { for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].GetRadius() + EPS_SMALL && dP2 < m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].GetRadius() && dP2 < dLenXY + m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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_vTool[m_nCurrTool].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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { if ( m_vTool[m_nCurrTool].GetType() == Tool::CYLMILL) return CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, m_vTool[m_nCurrTool].GetHeigth(), m_vTool[m_nCurrTool].GetRadius(), false, false) ; else if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) { double dHei = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dHei, m_vTool[m_nCurrTool].GetRadius(), false, false) ; CompBall_Milling( nGrid, ptS - dHei * vtToolDir, ptE - dHei * vtToolDir, m_vTool[m_nCurrTool].GetRadius()) ; return true ; } else return false ; } // --------- Coni ------------------------------------------------------------ //---------------------------------------------------------------------------- bool VolZmap::Conus_XYDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; double dDeltaRad = dMaxRad - dMinRad ; // Geometria del moto double dLenXY = ( ptE - ptS).LenXY() ; Point3d ptI = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) ; double dMatStemLen = ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? dStemHeigth + dLenXY : dStemHeigth) ; double dSqTipRad = m_vTool[m_nCurrTool].GetTipRadius() * m_vTool[m_nCurrTool].GetTipRadius() ; double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ; // Determinazione del vertice del cono double dL = m_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ; Point3d ptV ; // Vertice Vector3d vtV ; // Vettore riferimento con origine nel vertice if ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius()) { vtV = vtToolDir ; ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptE : ptS) - vtToolDir * ( dStemHeigth + dL) ; } else { vtV = - vtToolDir ; ptV = ( vtToolDir * ( ptE - ptS) < 0 ? ptS : ptE) - vtToolDir * ( m_vTool[m_nCurrTool].GetHeigth() - dL) ; } // Sistema di riferimento sul piano Vector3d vtV1 = - vtToolDir ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 0, 1) ; // Proiezione di ptI sul piano Point3d ptIxy( ptI.x, ptI.y, 0) ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC ( dX, dY, 0) ; Vector3d vtC = ptC - ptIxy ; double dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; double dr = m_vTool[m_nCurrTool].GetRadius() + ( dX1 - dMatStemLen) * ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) / m_vTool[m_nCurrTool].GetTipHeigth() ; if ( dX1 > EPS_SMALL && dX1 < dMatStemLen && abs( dX2) < m_vTool[m_nCurrTool].GetRadius()) { double dH = sqrt( dSqRad - dX2 * dX2) ; double dMin = ptI.z - dH ; double dMax = ptI.z + dH ; Point3d ptIntMin( dX, dY, dMin) ; Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ; vtNmin.Normalize() ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ; } else if ( dX1 >= dMatStemLen && dX1 < dMatStemLen + m_vTool[m_nCurrTool].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) ; Vector3d vtUmin = ( ptIntMin - ptV) - ( ptIntMin - ptV) * vtV * vtV ; vtUmin.Normalize() ; Vector3d vtNmin = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmin ; vtNmin.Normalize() ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtUmax = ( ptIntMax - ptV) - ( ptIntMax - ptV) * vtV * vtV ; vtUmax.Normalize() ; Vector3d vtNmax = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmax ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } if ( m_vTool[m_nCurrTool].GetTipRadius() >= m_vTool[m_nCurrTool].GetRadius()) { if ( dX1 > dMatStemLen + m_vTool[m_nCurrTool].GetTipHeigth() - 2 * EPS_SMALL && dX1 < dMatStemLen + m_vTool[m_nCurrTool].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) ; Vector3d vtNmin = ( ptI - ptIntMin) - ( ptI - ptIntMin) * vtV1 * vtV1 ; vtNmin.Normalize() ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtNmax = ( ptI - ptIntMax) - ( ptI - ptIntMax) * vtV1 * vtV1 ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, ptI.z - dH, ptI.z + dH, vtNmin, vtNmax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_XYPerp( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestToolBBox( nGrid, ptS, ptE, vtToolDir, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Parametri geometrici dell'utensile double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; double dMinRad = min( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; double dMaxRad = max( m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius()) ; double dSqRad = m_vTool[m_nCurrTool].GetRadius() * m_vTool[m_nCurrTool].GetRadius() ; double dDeltaRad = dMaxRad - dMinRad ; // Studio delle simmetrie del moto Point3d ptI = ( ptS.z < ptE.z ? ptS : ptE) ; Point3d ptF = ( ptS.z < ptE.z ? ptE : ptS) ; // elimino eventuale piccolo errore di perpendicolarit� del movimento rispetto all'utensile Vector3d vtErr = 0.5 * ( ( ptF - ptI) * vtToolDir) * vtToolDir ; ptI += vtErr ; ptF -= vtErr ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; // Cinematica del moto Vector3d vtMove = ptF - ptI ; 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_vTool[m_nCurrTool].GetTipHeigth() * dMaxRad / dDeltaRad ; Vector3d vtV = ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? vtToolDir : - vtToolDir) ; Point3d ptVI = ptI - ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? dStemHeigth + dL : m_vTool[m_nCurrTool].GetHeigth() - dL) * vtToolDir ; Point3d ptVF = ptF - ( m_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].GetTipRadius() ? dStemHeigth + dL : m_vTool[m_nCurrTool].GetHeigth() - dL) * vtToolDir ; // Movimento verticale if ( dLengthPathXY < EPS_SMALL) { // Riferimento sul piano Vector3d vtV1 = - vtToolDir ; Vector3d vtV2( - vtV1.y, vtV1.x, 0) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].GetRadius() + EPS_SMALL && dP2 < m_vTool[m_nCurrTool].GetRadius() - EPS_SMALL) { double dMin = dZI - sqrt( dSqRad - dP2 * dP2) ; double dMax = dZF + sqrt( dSqRad - dP2 * dP2) ; Point3d ptIntMin( dX, dY, dMin) ; Vector3d vtNmin = - ( ptIntMin - ptI) + ( ptIntMin - ptI) * vtV1 * vtV1 ; vtNmin.Normalize() ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtNmax = - ( ptIntMax - ptF) + ( ptIntMax - ptF) * vtV1 * vtV1 ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Parte conica else if ( dP1 > dStemHeigth && dP1 < m_vTool[m_nCurrTool].GetHeigth() - EPS_SMALL && abs( dP2) < m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() - EPS_SMALL) { double dr = dP2 ; double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() ; double dMin = dZI - sqrt( dMr * dMr - dr * dr) ; double dMax = dZF + sqrt( dMr * dMr - dr * dr) ; Point3d ptIntMin( dX, dY, dMin) ; Vector3d vtUmin = ( ptIntMin - ptVI) - ( ptIntMin - ptVI) * vtV * vtV ; vtUmin.Normalize() ; Vector3d vtNmin = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmin ; vtNmin.Normalize() ; Point3d ptIntMax( dX, dY, dMax) ; Vector3d vtUmax = ( ptIntMax - ptVF) - ( ptIntMax - ptVF) * vtV * vtV ; vtUmax.Normalize() ; Vector3d vtNmax = dDeltaRad * vtV - m_vTool[m_nCurrTool].GetTipHeigth() * vtUmax ; 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_vTool[m_nCurrTool].GetRadius() * vtCross ; Point3d ptDw = ptI - vtToolDir * dStemHeigth - m_vTool[m_nCurrTool].GetRadius() * vtCross ; double dSmallLength = m_vTool[m_nCurrTool].GetRadius() * vtCross.LenXY() ; // Punti di tangenza in corrispondenza della punta Point3d ptTipUp = ptI - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() + m_vTool[m_nCurrTool].GetTipRadius() * vtCross ; Point3d ptTipDw = ptI - vtToolDir * m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetRadius() > m_vTool[m_nCurrTool].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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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_vTool[m_nCurrTool].GetRadius() && dP2 < dLengthPathXY + m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetHeigth() - EPS_SMALL && dP2 > - m_vTool[m_nCurrTool].GetRadius() - ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth() && dP2 < m_vTool[m_nCurrTool].GetRadius() + dLengthPathXY + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) { // Massimi if ( dP2 < - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) { double dr = dP2 ; double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmax.Normalize() ; } else if ( dP2 < dLengthPathXY - dSmallLength + dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) { dMax = ( dDotUp - dX * vtUpCross.x - dY * vtUpCross.y) / vtUpCross.z ; vtNmax = vtUpCross ; } else { double dr = dP2 - dLengthPathXY ; double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmax.Normalize() ; } // Minimi if ( dP2 < dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) { double dr = dP2 ; double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmin.Normalize() ; } else if ( dP2 < dLengthPathXY + dSmallLength - dDeltaSmall * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].GetTipHeigth()) { dMin = ( dDotDw - dX * vtDwCross.x - dY * vtDwCross.y) / vtDwCross.z ; vtNmin = vtDwCross ; } else { double dr = dP2 - dLengthPathXY ; double dMr = m_vTool[m_nCurrTool].GetRadius() + ( m_vTool[m_nCurrTool].GetTipRadius() - m_vTool[m_nCurrTool].GetRadius()) * ( dP1 - dStemHeigth) / m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetTipHeigth() * vtU ; vtNmin.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_XYMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, true) ; if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) { Point3d ptSTip = ptS - dStemHeigth * vtToolDir ; Point3d ptETip = ptE - dStemHeigth * vtToolDir ; CompConus_Milling( nGrid, ptSTip, ptETip, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), true, false) ; } else { Point3d ptSTip = ptS - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ; Point3d ptETip = ptE - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ; CompConus_Milling( nGrid, ptSTip, ptETip, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius(), false, true) ; } return true ; } // ---------- VERSORE UTENSILE CON ORIENTAZIONE GENERICA --------------------- // ---------- Cilindro e sfera ----------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::CylBall_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Altezza cilindro double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; // Sottraggo cilindro CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, false) ; // Se � sfera la sottraggo if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) { Point3d ptSBall = ptS - dStemHeigth * vtToolDir ; Point3d ptEBall = ptE - dStemHeigth * vtToolDir ; CompBall_Milling( nGrid, ptSBall, ptEBall, m_vTool[m_nCurrTool].GetRadius()) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CylBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { // Altezza cilindro double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; // Sottraggo cilindro CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, false) ; // Se � sfera la sottraggo if ( m_vTool[m_nCurrTool].GetType() == Tool::BALLMILL) { Point3d ptSBall = ptS - dStemHeigth * vtToolDir ; Point3d ptEBall = ptE - dStemHeigth * vtToolDir ; CompBall_Milling( nGrid, ptSBall, ptEBall, m_vTool[m_nCurrTool].GetRadius()) ; } return true ; } // ---------- Coni ----------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Conus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; CompCyl_Drilling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, true) ; // Trapano if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) { Point3d ptSCone = ptS - dStemHeigth * vtToolDir ; Point3d ptECone = ptE - dStemHeigth * vtToolDir ; CompConus_Drilling( nGrid, ptSCone, ptECone, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), true, false) ; } else { Point3d ptSCone = ptS - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ; Point3d ptECone = ptE - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ; CompConus_Drilling( nGrid, ptSCone, ptECone, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius(), false, true) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Conus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir) { double dStemHeigth = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetTipHeigth() ; CompCyl_Milling( nGrid, ptS, ptE, vtToolDir, dStemHeigth, m_vTool[m_nCurrTool].GetRadius(), false, true) ; // Trapano if ( m_vTool[m_nCurrTool].GetTipRadius() < m_vTool[m_nCurrTool].GetRadius()) { Point3d ptSBall = ptS - dStemHeigth * vtToolDir ; Point3d ptEBall = ptE - dStemHeigth * vtToolDir ; CompConus_Milling( nGrid, ptSBall, ptEBall, vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), true, false) ; } else { Point3d ptSBall = ptS - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ; Point3d ptEBall = ptE - m_vTool[m_nCurrTool].GetHeigth() * vtToolDir ; CompConus_Milling( nGrid, ptSBall, ptEBall, - vtToolDir, m_vTool[m_nCurrTool].GetTipHeigth(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetRadius(), false, true) ; } return true ; } // ---------- Mortasatrice --------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Mrt_Drilling( 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_vTool[m_nCurrTool].GetMrtChsWidth() ; double dLenY = m_vTool[m_nCurrTool].GetMrtChsThickness() ; double dLenZ = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetCornRadius() ; CompPar_Drilling( nGrid, dLenX, dLenY, dLenZ, ptS, ptEOnP, vtToolDir, vtAux) ; // Se la punta � di tipo bull-nose if ( abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipS = ptS - dLenZ * vtToolDir ; Point3d ptTipE = ptEOnP - dLenZ * vtToolDir ; dLenX = abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) ; dLenZ = m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetCornRadius(), false, false) ; CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_vTool[m_nCurrTool].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_vTool[m_nCurrTool].GetCornRadius(), false, false) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::Mrt_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { // Scompongo la mortasatrice in solidi semplici // Parallelepipedo di base double dLenX = m_vTool[m_nCurrTool].GetMrtChsWidth() ; double dLenY = m_vTool[m_nCurrTool].GetMrtChsThickness() ; double dLenZ = m_vTool[m_nCurrTool].GetHeigth() - m_vTool[m_nCurrTool].GetCornRadius() ; Point3d ptBasePS = ptS - 0.5 * dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; Point3d ptBasePE = ptE - 0.5 * dLenZ * vtToolDir + 0.5 * dLenY * vtAux ; CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptBasePS, ptBasePE, vtAux, vtToolDir) ; // Se la punta � di tipo bull-nose if ( abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) > EPS_SMALL) { // Parallelepipedo di punta Point3d ptTipPS = ptBasePS - 0.5 * dLenZ * vtToolDir ; Point3d ptTipPE = ptBasePE - 0.5 * dLenZ * vtToolDir ; dLenX = abs( m_vTool[m_nCurrTool].GetMrtChsWidth() - 2 * m_vTool[m_nCurrTool].GetCornRadius()) ; dLenZ = m_vTool[m_nCurrTool].GetCornRadius() ; ptTipPS -= 0.5 * dLenZ * vtToolDir ; ptTipPE -= 0.5 * dLenZ * vtToolDir ; CompPar_Milling( nGrid, dLenX, dLenZ, dLenY, ptTipPS, ptTipPE, vtAux, vtToolDir) ; // Cilindri // Vettore nel piano Vector3d vtVOnP = vtToolDir ^ vtAux ; if ( vtVOnP * ( ptE - ptS) < 0) vtVOnP *= -1 ; Point3d ptSminus = ptTipPS + 0.5 * dLenZ * vtToolDir - ( 0.5 * dLenX) * vtVOnP ; Point3d ptEminus = ptTipPE + 0.5 * dLenZ * vtToolDir - ( 0.5 * dLenX) * vtVOnP ; CompCyl_Milling( nGrid, ptSminus, ptEminus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ; Point3d ptSplus = ptTipPS + 0.5 * dLenZ * vtToolDir + ( 0.5 * dLenX) * vtVOnP ; Point3d ptEplus = ptTipPE + 0.5 * dLenZ * vtToolDir + ( 0.5 * dLenX) * vtVOnP ; CompCyl_Milling( nGrid, ptSplus, ptEplus, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ; } // se la punta � di tipo sfera else { // Cilindro Point3d ptCylS = ptBasePS - 0.5 * dLenZ * vtToolDir ; Point3d ptCylE = ptBasePE - 0.5 * dLenZ * vtToolDir ; CompCyl_Milling( nGrid, ptCylS, ptCylE, vtAux, dLenY, m_vTool[m_nCurrTool].GetCornRadius(), false, false) ; } return true ; } // ---------- Chisel --------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::Chs_Drilling( 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_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(), ptS, ptProjE, vtToolDir, vtAux) ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::Chs_Milling( 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) - ( ptE - ptS) * vtToolDir * vtToolDir ; Point3d ptProjE = ptS + vtMoveOnP ; CompPar_Milling( nGrid, m_vTool[m_nCurrTool].GetMrtChsWidth(), m_vTool[m_nCurrTool].GetMrtChsThickness(), m_vTool[m_nCurrTool].GetHeigth(), ptS, ptProjE, vtToolDir, vtAux) ; return true ; } // ---------- Utensile generico ---------------------------------------------- //---------------------------------------------------------------------------- //bool //VolZmap::GenTool_Drilling( 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 ; // // Vettore delle normali agli archi // const VCT3DVECTOR& vArcNorm = m_Tool.GetArcNormalVec() ; // // Poinch� l'asse utensile � parallelo all'asse Z, definisco un sistema di // // riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ. // Frame3d frNormFrame ; // frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ; // // Ciclo sulle curve del profilo // const CurveComposite& ToolProfile = m_Tool.GetApproxOutline() ; // int i = - 1 ; // const ICurve* pPrevCurve = nullptr ; // const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ; // while ( pCurve != nullptr) { // // double dHeight = 0 ; // // // Se segmento // if ( pCurve->GetType() == CRV_LINE) { // // Recupero gli estremi // const ICurveLine* pLine = GetCurveLine( pCurve) ; // Point3d ptStart = pLine->GetStart() ; // Point3d ptEnd = pLine->GetEnd() ; // int nNormNum = pLine->GetTempProp(); // Vector3d vtNormSt, vtNormEn; // if ( nNormNum != 0) { // vtNormSt = vArcNorm[nNormNum - 1] ; // vtNormEn = vArcNorm[nNormNum] ; // vtNormSt.ToLoc(frNormFrame); // vtNormEn.ToLoc(frNormFrame); // } // // 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 = ToolProfile.GetCurve( ++ i) ; // 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 ; // if ( dRadius > 10 * EPS_SMALL) // 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, vtNormSt, vtNormEn) ; // } // // 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 ; // vtNormEn.z *= -1 ; // vtNormSt.z *= -1 ; // CompConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt) ; // } // // Passo alla curva successiva // pPrevCurve = pCurve ; // pCurve = pNextCurve ; // } // else { // // Passo alla curva successiva // pPrevCurve = pCurve ; // pCurve = ToolProfile.GetCurve( ++ i) ; // } // } // // // 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 = ToolProfile.GetCurve( ++ i) ; // } // // // Determino le posizioni iniziale e finale del componente successivo // ptI = ptI - vtToolDir * dHeight ; // ptF = ptI + vtMove ; // } // // return true ; //} bool VolZmap::GenTool_Drilling( 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 ; // Vettore delle normali agli archi const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ; // Poinch� l'asse utensile � parallelo all'asse Z, definisco un sistema di // riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ. Frame3d frNormFrame ; frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ; // Ciclo sulle curve del profilo const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ; int i = - 1 ; const ICurve* pPrevCurve = nullptr ; const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ; while ( pCurve != nullptr) { double dHeight = 0 ; double dSignedHeight = 0 ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; int nNormNum = pLine->GetTempProp(); Vector3d vtNormSt, vtNormEn; if ( nNormNum != 0) { vtNormSt = vArcNorm[nNormNum - 1] ; vtNormEn = vArcNorm[nNormNum] ; vtNormSt.ToLoc(frNormFrame); vtNormEn.ToLoc(frNormFrame); } // Ne determino l'altezza dSignedHeight = ptStart.y - ptEnd.y ; dHeight = abs( dSignedHeight) ; 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 ; int j = i ; const ICurve* pNextCurve = ToolProfile.GetCurve( ++ j) ; 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 ; if ( dRadius > 10 * EPS_SMALL && m_vTool[m_nCurrTool].GetCuttingFlag()) 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 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT, vtNormSt, vtNormEn) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapB, bTapT, vtNormSt, vtNormEn) ; else { Point3d ptIn = ptI /*- vtToolDir * dSignedHeight*/ ; Point3d ptFn = ptIn + vtMove ; /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapT, bTapB, vtNormEn, vtNormSt) ; } } } // 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 * dSignedHeight ; Point3d ptFn = ptIn + vtMove ; vtNormEn.z *= -1 ; vtNormSt.z *= -1 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_Drilling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapT, bTapB, vtNormEn, vtNormSt) ; else { /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_Drilling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapB, bTapT, vtNormSt, vtNormEn) ; } } } } else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) { if ( ptStart.x < ptEnd.x) { SurfCircCrown_Drilling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ; } else { SurfCircCrown_Drilling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ; } } } // 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 if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ; else if ( pCurve->GetTempProp( 1) == 1) { double dStH = ptStart.y - ptCen.y ; double dEnH = ptEnd.y - ptCen.y ; // Tagliente esterno if ( dEnH < dStH) { if ( dEnH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ; } else if ( dStH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ; } } // Tagliente interno else { if ( dEnH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } else if ( dStH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } } dSignedHeight = ptStart.y - ptEnd.y ; } // aggiorno l'altezza //dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dSignedHeight ; ptF = ptI + vtMove ; // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = ToolProfile.GetCurve( ++ i) ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::GenTool_Milling( 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 ; // Vettore delle normali agli archi const VCT3DVECTOR& vArcNorm = m_vTool[m_nCurrTool].GetArcNormalVec() ; // Poinch� l'asse utensile � parallelo all'asse Z, definisco un sistema di // riferimento ad hoc in cui le normali agli archi giacciano nel piano XZ. Frame3d frNormFrame ; frNormFrame.Set( ORIG, X_AX, -Z_AX, Y_AX) ; // Ciclo sulle curve del profilo const CurveComposite& ToolProfile = m_vTool[m_nCurrTool].GetApproxOutline() ; int i = - 1 ; const ICurve* pPrevCurve = nullptr ; const ICurve* pCurve = ToolProfile.GetCurve( ++ i) ; while ( pCurve != nullptr) { double dHeight = 0 ; double dSignedHeight = 0 ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi const ICurveLine* pLine = GetCurveLine( pCurve) ; Point3d ptStart = pLine->GetStart() ; Point3d ptEnd = pLine->GetEnd() ; int nNormNum = pLine->GetTempProp(); Vector3d vtNormSt, vtNormEn; if ( nNormNum != 0) { vtNormSt = vArcNorm[nNormNum - 1] ; vtNormEn = vArcNorm[nNormNum] ; vtNormSt.ToLoc(frNormFrame); vtNormEn.ToLoc(frNormFrame); } // Ne determino l'altezza dSignedHeight = ptStart.y - ptEnd.y ; dHeight = abs( dSignedHeight) ; if ( dHeight > EPS_SMALL) { // verifiche curva precedente per eventuale tappo sopra bool bTapT = true ; 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 = false ; } // verifiche curva successiva per eventuale tappo sotto bool bTapB = false ; int j = i ; const ICurve* pNextCurve = ToolProfile.GetCurve( ++ j) ; 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 = false ; } // Se X costante, � un cilindro if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; if ( dRadius > 10 * EPS_SMALL) { if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, bTapB, bTapT) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfCyl_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dRadius, true, bTapB, bTapT) ; else SurfCyl_Milling( nGrid, ptI, ptF, - vtToolDir, dHeight, dRadius, false, 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 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, bTapB, bTapT, vtNormSt, vtNormEn) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapB, bTapT, vtNormSt, vtNormEn) ; else { Point3d ptIn = ptI /*- vtToolDir * dSignedHeight*/ ; Point3d ptFn = ptIn + vtMove ; /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapT, bTapB, vtNormEn, vtNormSt) ; } } } // 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 * dSignedHeight ; Point3d ptFn = ptIn + vtMove ; vtNormEn.z *= -1 ; vtNormSt.z *= -1 ; if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, bTapT, bTapB, vtNormEn, vtNormSt) ; else if ( pCurve->GetTempProp( 1) == 1) { if ( ptStart.y > ptEnd.y) SurfConus_Milling( nGrid, ptIn, ptFn, - vtToolDir, dHeight, dMaxRad, dMinRad, true, bTapT, bTapB, vtNormEn, vtNormSt) ; else { /*vtNormEn.z *= -1 ; vtNormSt.z *= -1 ;*/ SurfConus_Milling( nGrid, ptI, ptF, vtToolDir, dHeight, dMaxRad, dMinRad, false, bTapB, bTapT, vtNormSt, vtNormEn) ; } } } } else if ( ! m_vTool[m_nCurrTool].GetCuttingFlag() && pCurve->GetTempProp( 1) == 1) { if ( ptStart.x < ptEnd.x) { SurfCircCrown_Milling( nGrid, ptI, ptF, vtToolDir, ptEnd.x, ptStart.x) ; } else { SurfCircCrown_Milling( nGrid, ptI, ptF, - vtToolDir, ptStart.x, ptEnd.x) ; } } } // 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 if ( m_vTool[m_nCurrTool].GetCuttingFlag()) CompBall_Milling( nGrid, ptCenS, ptCenE, dRadius) ; else if ( pCurve->GetTempProp( 1) == 1) { double dStH = ptStart.y - ptCen.y ; double dEnH = ptEnd.y - ptCen.y ; // Tagliente esterno if ( dEnH < dStH) { if ( dEnH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, dEnH, dStH, true) ; } else if ( dStH > 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, dStH, true) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, - dEnH, true) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, - dEnH, - dStH, true) ; } } // Tagliente interno else { if ( dEnH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } else if ( dStH < 0) { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, vtToolDir, dRadius, 0, abs( dStH), false) ; SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, 0, abs( dEnH), false) ; } else { SurfSphericalShellPart_Milling( nGrid, ptCenS, ptCenE, - vtToolDir, dRadius, abs( dEnH), abs( dStH), false) ; } } dSignedHeight = ptStart.y - ptEnd.y ; } // aggiorno l'altezza //dHeight = abs( ptStart.y - ptEnd.y) ; } // Determino le posizioni iniziale e finale del componente successivo ptI = ptI - vtToolDir * dSignedHeight ; ptF = ptI + vtMove ; // Passo alla curva successiva pPrevCurve = pCurve ; pCurve = ToolProfile.GetCurve( ++ i) ; } return true ; } // ------------------------- SOLIDI ELEMENTARI ----------------------------------------------------------------------------- // Asse di simmetria diretto come l'asse Z: FORATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad) { // Verifica sull'interferenza con lo Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) 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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { // Verifica sull'interferenza con lo Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) 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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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() ; if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) { vtMin = dDeltaR * vtToolDir - dHei * vtU ; vtMin.Normalize() ; } else { Vector3d vtOriginalN = ( ( dDeltaR - dr + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dr - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN.Normalize() ; vtMin = - vtOriginalN.z * vtToolDir - vtOriginalN.x * 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() ; if ( vtArcNormMinR.IsSmall() || vtArcNormMaxR.IsSmall()) { vtMax = dDeltaR * vtToolDir - dHei * vtU ; vtMax.Normalize() ; } else { Vector3d vtOriginalN = ( ( dDeltaR - dr + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dr - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN.Normalize() ; vtMax = - vtOriginalN.z * vtToolDir - vtOriginalN.x * vtU ; vtMax.Normalize() ; } SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompPar_ZDrilling( int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ; Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ; dLenX -= ( 2 * EPS_SMALL) ; dLenY -= ( 2 * EPS_SMALL) ; dLenZ -= ( 2 * EPS_SMALL) ; // Controllo sull'interferenza utensile-solido int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Costruisco un sistema di riferimento nel piano Point3d ptOXY( ptMyS.x, ptMyS.y, 0) ; Vector3d vtV1 = vtToolDir ^ vtAux ; Vector3d vtV2 = vtAux ; // Quote estreme del volume asportato double dMinZ = min( min( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), min( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ; double dMaxZ = max( max( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), max( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Vector3d vtR = ptC - ptOXY ; double dR1 = vtR * vtV1 ; double dR2 = vtR * vtV2 ; if ( abs( dR1) < 0.5 * dLenX && abs( dR2) < 0.5 * dLenY) 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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad) { // Verifica sull'interferenza con lo Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) 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 dDeltaZ = dZMaxF - dZMaxI ; // Vettori caratterizzanti il moto Vector3d vtMove = ptF - ptI ; Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; double dLenXY = vtMoveXY.LenXY() ; vtMove.Normalize() ; 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, 0, 1) ; double dMin, dMax ; Vector3d vtMin, vtMax ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; Point3d ptI = ( vtToolDir * ( ptE - ptS) > 0 ? ptS : ptE) ; Point3d ptF = ( vtToolDir * ( ptE - ptS) > 0 ? ptE : ptS) ; Point3d ptIxy( ptI.x, ptI.y, 0) ; Point3d ptFxy( ptF.x, ptF.y, 0) ; Vector3d vtMove = ptF - ptI ; Vector3d vtMLong = ( vtMove * vtToolDir) * vtToolDir ; 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 = 0, dMax = 0, dPLim = 0, dMLim = 0 ; Vector3d vtMin, vtMax, vtP, vtM ; Vector3d vtUmv = vtMove ; vtUmv.Normalize() ; Point3d ptInt ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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) ; vtCI.Normalize() ; vtCF.Normalize() ; 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() ; if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) { vtM = dDeltaR * vtToolDir - dHei * vtU ; vtM.Normalize() ; } else { Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtCI - vtArcNormMaxR.z * vtV1 ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtCI - vtArcNormMinR.z * vtV1 ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtM = ( ( dDeltaR - sqrt( dSqDI) + dMinRad) / dDeltaR) * vtOrigMinR + ( ( sqrt(dSqDI) - dMinRad) / dDeltaR) * vtOrigMaxR ; 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() ; if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) { vtM = dDeltaR * vtToolDir - dHei * vtU ; vtM.Normalize() ; } else { Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtCI - vtArcNormMaxR.z * vtV1 ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtCI - vtArcNormMinR.z * vtV1 ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtM = ( ( dDeltaR - sqrt( dSqDI) + dMinRad) / dDeltaR) * vtOrigMinR + ( ( sqrt( dSqDI) - dMinRad) / dDeltaR) * vtOrigMaxR ; vtM.Normalize() ; } } else if ( dSqDI >= dMinRad * dMinRad && dIVarCos >= dCos && dFVarCos < dCos && abs( dIDO) < dMaxRad * dSin) { if ( dIDO > - dMaxRad * dSin && dIDO <= - dMinRad * dSin) { dMLim = ( dDotd - dX * vtNd.x - dY * vtNd.y) / vtNd.z ; if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) { vtM = - vtNd ; } else { double dLatMin = dMinRad * dSin ; double dDeltaLat = dDeltaR * dSin ; Vector3d vtRadial = dCos * vtV2 - dSin * vtV3 ; vtRadial.Normalize() ; Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * vtV1 ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * vtV1 ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtM = ( ( dDeltaLat - abs( dIDO) + dLatMin) / dDeltaLat) * vtOrigMinR + ( ( abs( dIDO) - dLatMin) / dDeltaLat) * vtOrigMaxR ; vtM.Normalize() ; } } 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 ; if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) { vtM = - vtNs ; } else { double dLatMin = dMinRad * dSin ; double dDeltaLat = dDeltaR * dSin ; Vector3d vtRadial = dCos * vtV2 + dSin * vtV3 ; vtRadial.Normalize() ; Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * vtV1 ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * vtV1 ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtM = ( ( dDeltaLat - dIDO + dLatMin) / dDeltaLat) * vtOrigMinR + ( ( dIDO - dLatMin) / dDeltaLat) * vtOrigMaxR ; vtM.Normalize() ; } } } 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() ; if ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall()) { vtM = dDeltaR * vtToolDir - dHei * vtU ; vtM.Normalize() ; } else { Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtCF - vtArcNormMaxR.z * vtV1 ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtCF - vtArcNormMinR.z * vtV1 ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtM = ( ( dDeltaR - sqrt( dSqDF) + dMinRad) / dDeltaR) * vtOrigMinR + ( ( sqrt( dSqDF) - dMinRad) / dDeltaR) * vtOrigMaxR ; 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( int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ; Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ; dLenX -= ( 2 * EPS_SMALL) ; dLenY -= ( 2 * EPS_SMALL) ; dLenZ -= ( 2 * EPS_SMALL) ; // Controllo sull'interferenza utensile-solido int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Quote estreme Z double dMinZ = min( min( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), min( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ; double dMaxZ = max( max( ptMyS.z, ptMyS.z - vtToolDir.z * dLenZ), max( ptMyE.z, ptMyE.z - vtToolDir.z * dLenZ)) ; // Vettore di movimento Vector3d vtMove = ptMyE - ptMyS ; // Sistemi di riferimento del solido nella posizione iniziale e finale Vector3d vtV2 = vtAux ; Vector3d vtV1 = vtV2 ^ vtToolDir ; vtV1.Normalize() ; Point3d ptSXY( ptMyS.x, ptMyS.y, 0) ; Point3d ptEXY( ptMyE.x, ptMyE.y, 0) ; // Studio del volume asportato durante il moto Frame3d MotionFrame ; Vector3d vtDiagA = dLenX * vtV1 + dLenY * vtV2 ; Vector3d vtDiagB = dLenX * vtV1 - dLenY * vtV2 ; Vector3d vtW1 = ( abs( vtDiagA * vtMove) <= abs( vtDiagB * vtMove) ? vtDiagA : vtDiagB) ; Point3d ptOrigXY = ptSXY - vtW1 / 2 ; double dLenW1 = vtW1.Len() ; vtW1 /= dLenW1 ; double dDeltaW1 = vtMove * vtW1 ; Vector3d vtW2 = vtMove - dDeltaW1 * vtW1 ; double dLenW2 = vtW2.Len() ; vtW2 /= dLenW2 ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d 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 && abs( dRS2) < 0.5 * dLenY) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; // Asportazione materiale nella posizione finale if ( abs( dRE1) < 0.5 * dLenX && abs( dRE2) < 0.5 * dLenY) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; // Asportazione materiale nel moto Vector3d vtR = ptC - ptOrigXY ; double dR1 = vtR * vtW1 ; double dR2 = vtR * vtW2 ; if ( dR2 > 0 && dR2 < dLenW2 && dR1 * dLenW2 > dDeltaW1 * dR2 && dR1 * dLenW2 < dLenW1 * dLenW2 + dDeltaW1 * dR2) SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, Z_AX, - Z_AX) ; } } return true ; } // Asse di simmetria con orientazione generica: FORATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_Drilling( 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 int nStartI, nEndI, nStartJ, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) 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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( 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, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Apertura del cono double dDeltaR = dMaxRad - dMinRad ; double dTan = dDeltaR / dHei ; double dConeMaxH = ( ( dMaxRad * dHei) / dDeltaR) ; double dConeMinH = dConeMaxH - dHei ; 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 ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Cilindro if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Cono if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dConeMinH, dConeMaxH, bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) { if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { if ( ! AreSameOrOppositeVectorEpsilon(vtN1, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL1 = ptInt1 - ptVertex ; vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; double dL1 = vtL1.Len() ; vtL1 /= dL1 ; Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN1.Normalize() ; vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; } if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL2 = ptInt2 - ptVertex ; vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ; double dL2 = vtL2.Len() ; vtL2 /= dL2 ; Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN2.Normalize() ; vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; } } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompPar_Drilling( int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ; Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ; dLenX -= ( 2 * EPS_SMALL) ; dLenY -= ( 2 * EPS_SMALL) ; dLenZ -= ( 2 * EPS_SMALL) ; // Controllo sull'interferenza utensile-solido int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ)) 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 = ( ptMyE - ptMyS).Len() ; Point3d ptO = ptMyS - ( ( ptMyE - ptMyS) * vtV1 > 0 ? dLenZ : dLenZ + dLenMove) * vtV1 - ( 0.5 * dLenX) * vtV2 ; Frame3d ParaFrame ; ParaFrame.Set( ptO, vtV2, vtV3, vtV1) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ + dLenMove, 0, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } return true ; } // Asse di simmetria con orientazione generica: FRESATURA //---------------------------------------------------------------------------- bool VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dRad, bool bTapB, bool bTapT) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) 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 ; // 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() ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( 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 CylFrame.ChangeOrig( ptITip) ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // 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. CylFrame.ChangeOrig( ptITip + vtMove) ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Poliedro interno CylFrame.ChangeOrig( ptITip) ; if ( IntersLineMyPolyhedron( ptC, Z_AX, CylFrame, dOrtLen, 2 * dRad, dHei, dLongLen, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Se movimento non ortogonale all'asse cilindro ellittico di punta if ( dLongLen > EPS_SMALL) { CylFrame.ChangeOrig( ptITip) ; if ( IntersLineEllipticalCylinder( ptC, Z_AX, CylFrame, dRad, dLongLen, dOrtLen, bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // 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. CylFrame.ChangeOrig( ptITip + dHei * vtV1) ; if ( IntersLineEllipticalCylinder( ptC, Z_AX, CylFrame, dRad, dLongLen, dOrtLen, true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::CompConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad, bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { // Verifico interferenza int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtToolDir, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) 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) ; 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) ; // 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 ( riferiti al sistema di riferimento) : // Sx, Dx Vector3d vtNs( - dTan, dCos, dSin) ; vtNs.Normalize() ; Vector3d vtNd( - dTan, dCos, - dSin) ; vtNd.Normalize() ; // Iniziale e finale Vector3d vtIF( - dDeltaY, dDeltaX, 0) ; vtIF.Normalize() ; // Up e Down Vector3d vtUD( - dLenY, dLenX, 0) ; vtUD.Normalize() ; // Punti dei piani (sempre espressi nel sistema PolyFrame) Point3d ptFacet135( 0, 0, dLenZ) ; Point3d ptFacet246( dLenX + dDeltaX, dLenY + dDeltaY, - dLenZ - dDeltaZ) ; Vector3d vtUmv = vtMove ; vtUmv.Normalize() ; if ( dRatio * dTan <= 1) { for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( 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 ; // Cono iniziale ConusFrame.ChangeOrig( ptV) ; if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL1 = ptInt1 - ptV ; vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; double dL1 = vtL1.Len() ; vtL1 /= dL1 ; Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ((dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR; vtOriginalN1.Normalize() ; vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; vtN1.Normalize() ; } if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL2 = ptInt2 - ptV ; vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ; double dL2 = vtL2.Len() ; vtL2 /= dL2 ; Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN2.Normalize() ; vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; vtN2.Normalize() ; } } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Cono finale ConusFrame.ChangeOrig( ptV + vtMove) ; if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL1 = ptInt1 - ptV - vtMove ; vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; double dL1 = vtL1.Len() ; vtL1 /= dL1 ; Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN1.Normalize() ; vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; vtN1.Normalize() ; } if ( ! AreSameOrOppositeVectorEpsilon(vtN2, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL2 = ptInt2 - ptV - vtMove ; vtL2 -= (vtL2 * vtToolDir) * vtToolDir; double dL2 = vtL2.Len() ; vtL2 /= dL2 ; Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN2.Normalize() ; vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; vtN2.Normalize() ; } } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // 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 ; if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { Vector3d vtRadial( 0, dMinRad * dCos, dMinRad * dSin) ; vtRadial.Normalize() ; Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtN1 = ( ( dDeltaZ - ptInt1.z + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( ptInt1.z - dLenZ) / dDeltaZ) * vtOrigMaxR ; vtN1.Normalize() ; } ++ 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 ; if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { Vector3d vtRadial( 0, dMinRad * dCos, - dMinRad * dSin) ; vtRadial.Normalize() ; Vector3d vtOrigMaxR = - vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; Vector3d vtOrigMinR = - vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtN1 = ( ( dDeltaZ - abs( ptInt1.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt1.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ; vtN1.Normalize() ; } ++ nIntNum ; } else if ( ( ptInt1 - ptPoly2).SqLen() > SQ_EPS_SMALL) { ptInt2 = ptPoly2 ; vtN2 = - vtNd ; if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { Vector3d vtRadial( 0, dMinRad * dCos, -dMinRad * dSin) ; vtRadial.Normalize() ; Vector3d vtOrigMaxR = -vtArcNormMaxR.x * vtRadial - vtArcNormMaxR.z * X_AX ; Vector3d vtOrigMinR = -vtArcNormMinR.x * vtRadial - vtArcNormMinR.z * X_AX ; vtOrigMaxR.Normalize() ; vtOrigMinR.Normalize() ; vtN2 = ( ( dDeltaZ - abs( ptInt2.z) + dLenZ) / dDeltaZ) * vtOrigMinR + ( ( abs( ptInt2.z) - dLenZ) / dDeltaZ) * vtOrigMaxR ; vtN2.Normalize() ; } ++ 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() > SQ_EPS_SMALL) { 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() > SQ_EPS_SMALL) { 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() > SQ_EPS_SMALL) { 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() > SQ_EPS_SMALL) { ptInt2 = ptPoly6; vtN2 = vtUD ; ++ nIntNum ; } } } // Se il poliedro � attraversato taglio if ( nIntNum == 2) { // Riporto le intersezioni nel sistema griglia ptInt1.ToGlob( PolyFrame) ; vtN1.ToGlob( PolyFrame) ; ptInt2.ToGlob( PolyFrame) ; vtN2.ToGlob( PolyFrame) ; SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Se movimento non ortogonale all'asse sottraggo i cilindri ellittici if ( dLongLen > EPS_SMALL) { // Traslazione ellisse di punta ConusFrame.ChangeOrig( ptV + vtV1 * dl) ; if ( IntersLineEllipticalCylinder( ptC, Z_AX, ConusFrame, dMinRad, dLongLen, dOrtLen, bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Traslazione ellisse di base ConusFrame.ChangeOrig( ptV + vtV1 * dL) ; if ( IntersLineEllipticalCylinder( ptC, Z_AX, ConusFrame, dMaxRad, dLongLen, dOrtLen, true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } } return true ; } else { for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( 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 ; // Cono ConusFrame.ChangeOrig( ptV) ; if ( IntersLineConus( ptC, Z_AX, ConusFrame, dTan, dl, dL, bTapB, true, ptInt1, vtN1, ptInt2, vtN2)) { if ( ! ( vtArcNormMaxR.IsSmall() || vtArcNormMinR.IsSmall())) { if ( ! AreSameOrOppositeVectorEpsilon( vtN1, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL1 = ptInt1 - ptV ; vtL1 -= ( vtL1 * vtToolDir) * vtToolDir ; double dL1 = vtL1.Len() ; vtL1 /= dL1 ; Vector3d vtOriginalN1 = ( ( dDeltaR - dL1 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL1 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN1.Normalize() ; vtN1 = - vtOriginalN1.z * vtToolDir - vtOriginalN1.x * vtL1 ; vtN1.Normalize() ; } if ( ! AreSameOrOppositeVectorEpsilon( vtN2, vtToolDir, 0.1 * EPS_SMALL)) { Vector3d vtL2 = ptInt2 - ptV ; vtL2 -= ( vtL2 * vtToolDir) * vtToolDir ; double dL2 = vtL2.Len() ; vtL2 /= dL2 ; Vector3d vtOriginalN2 = ( ( dDeltaR - dL2 + dMinRad) / dDeltaR) * vtArcNormMinR + ( ( dL2 - dMinRad) / dDeltaR) * vtArcNormMaxR ; vtOriginalN2.Normalize() ; vtN2 = - vtOriginalN2.z * vtToolDir - vtOriginalN2.x * vtL2 ; vtN2.Normalize() ; } } SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Traslazione ellisse ConusFrame.ChangeOrig( ptV + vtV1 * dL) ; if ( IntersLineEllipticalCylinder( ptC, Z_AX, ConusFrame, dMaxRad, dLongLen, dOrtLen, true, bTapT, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } return true ; } } //---------------------------------------------------------------------------- bool VolZmap::CompPar_Milling( int nGrid, double dLenX, double dLenY, double dLenZ, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, const Vector3d& vtAux) { Point3d ptMyS = ptS - EPS_SMALL * vtToolDir ; Point3d ptMyE = ptE - EPS_SMALL * vtToolDir ; dLenX -= ( 2 * EPS_SMALL) ; dLenY -= ( 2 * EPS_SMALL) ; dLenZ -= ( 2 * EPS_SMALL) ; // Controllo sull'interferenza utensile-solido int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestParaBBox( nGrid, ptMyS, ptMyE, vtToolDir, vtAux, dLenX, dLenY, dLenZ, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore di movimento Vector3d vtMove = ptMyE - ptMyS ; // Sistema di riferimento del solido nella posizione iniziale (con vtMove derivo quello finale) Frame3d ParaFrame ; Vector3d vtV3 = vtToolDir ; Vector3d vtV1 = vtAux ^ vtV3 ; Vector3d vtV2 = vtV3 ^ vtV1 ; ParaFrame.Set( ORIG, vtV1, vtV2, vtV3) ; Point3d ptV = ptMyS - dLenZ * ParaFrame.VersZ() - ( 0.5 * dLenX) * ParaFrame.VersX() ; ParaFrame.ChangeOrig( ptV) ; // Studio del volume asportato durante il moto Frame3d MotionFrame ; Vector3d vtDiagA = dLenX * ParaFrame.VersX() + dLenY * ParaFrame.VersY() ; Vector3d vtDiagB = dLenX * ParaFrame.VersX() - dLenY * ParaFrame.VersY() ; Vector3d vtW3 = ( abs( vtDiagA * vtMove) <= abs( vtDiagB * vtMove) ? vtDiagA : vtDiagB) ; Point3d ptOrig = ptMyS - vtW3 / 2 - vtToolDir * ( dLenZ / 2) ; double dLenW3 = vtW3.Len() ; vtW3 /= dLenW3 ; double dDeltaW3 = vtMove * vtW3 ; Vector3d vtW1 = vtMove - dDeltaW3 * vtW3 ; double dLenW1 = vtW1.Len() ; vtW1 /= dLenW1 ; Vector3d vtW2 = vtW3 ^ vtW1 ; MotionFrame.Set( ptOrig, vtW1, vtW2, vtW3) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( 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 ; // Solido nella posizione iniziale ParaFrame.ChangeOrig( ptV) ; if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ, 0, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Solido nella posizione finale ParaFrame.ChangeOrig( ptV + vtMove) ; if ( IntersLineMyPolyhedron( ptC, Z_AX, ParaFrame, dLenX, dLenY, dLenZ, 0, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } // Volume spazzato nel moto if ( IntersLineMyPolyhedron( ptC, Z_AX, MotionFrame, dLenW1, dLenZ, dLenW3, dDeltaW3, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } return true ; } // ---------- SFERA ---------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe, double dRad) { // Verifico interferisca int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptLs, ptLe, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore modivemnto Vector3d vtV = ptLe - ptLs ; double dLengthPath = vtV.Len() ; if ( dLengthPath > EPS_ZERO) vtV /= dLengthPath ; // Riferimento per cilindro inviluppo della sfera lungo il movimento Frame3d CylFrame ; CylFrame.Set( ptLs, vtV) ; double dSqRad = dRad * dRad ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; Point3d ptC( dX, dY, 0) ; // Sfera in posizione start double dStSqDXY = SqDistXY( ptC, ptLs) ; if ( dStSqDXY < dSqRad) { double dMin = ptLs.z - sqrt( dSqRad - dStSqDXY) ; Vector3d vtNmin = ptLs - Point3d( dX, dY, dMin) ; vtNmin.Normalize() ; double dMax = ptLs.z + sqrt( dSqRad - dStSqDXY) ; Vector3d vtNmax = ptLs - Point3d( dX, dY, dMax) ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Sfera in posizione end double dEnSqDXY = SqDistXY( ptC, ptLe) ; if ( dEnSqDXY < dSqRad) { double dMin = ptLe.z - sqrt( dSqRad - dEnSqDXY) ; Vector3d vtNmin = ptLe - Point3d( dX, dY, dMin) ; vtNmin.Normalize() ; double dMax = ptLe.z + sqrt( dSqRad - dEnSqDXY) ; Vector3d vtNmax = ptLe - Point3d( dX, dY, dMax) ; vtNmax.Normalize() ; SubtractIntervals( nGrid, i, j, dMin, dMax, vtNmin, vtNmax) ; } // Cilindro inviluppo della sfera Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) { SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2) ; } } } return true ; } // Superfici laterali // Superfici ausiliarie //---------------------------------------------------------------------------- // Calcola l'intersezione di una retta, descritta da punto iniziale ptLineP e versore della direzione // vtLineDir, e la superficie definita da una corona circolare nello spazio, descritta dal centro delle // circonferenze di frontiera, dal versore del loro asse di simmetria rotazionale e dai loro raggi. // Il versore normale alla superficie coincide con quello dell'asse di simmetria e quello vtN // dell'intersezione � opposto ad'esso. int VolZmap::IntersLineCircCrown( const Point3d& ptLineP, const Vector3d& vtLineDir, const Point3d& ptCen, const Vector3d& vtAx, double dMaxRad, double dMinRad, Point3d& ptInt, Vector3d& vtN) const { // Definisco il versore normale al piano e il piano stesso. Plane3d plMyPlane ; Vector3d vtPlaneN = vtAx ; if ( ! vtPlaneN.Normalize() || ! plMyPlane.Set( ptCen, vtPlaneN)) return 0 ; // Quadrati dei raggi double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; // Se la corona circolare defenera in un disco (dMinRad < EPS), forzo dSqSafeMinRad a - 1 // in modo da tagliare i dexel giacenti sul suo asse di simmetria. if ( dMinRad < EPS_SMALL) dSqMinRad = - 1 ; // Intersezione retta piano int nIntType = IntersLinePlane( ptLineP, vtLineDir, 1000, plMyPlane, ptInt, false) ; if ( nIntType == ILPT_YES /* || nIntType == ILPT_START || nIntType == ILPT_END*/) { // Se il punto d'intersezione sta nella corona double dSqIntCenDist = ( ptInt - ptCen) * ( ptInt - ptCen) ; if ( dSqIntCenDist > dSqMinRad && dSqIntCenDist < dSqMaxRad) { vtN = - vtAx ; return 1 ; } } return 0 ; } //---------------------------------------------------------------------------- // Calcola l'intersezione di una retta, descritta da punto iniziale ptLineP e versore della // direzione vtLineDir, e la superficie definita da un parallelogramma nello spazio, descritto da un punto // ptParOrig e i vettori che da esso spiccano. // Se bExtNorm � true la normale alla superficie ha lo stesso verso di vtSeg2 ^ vtSeg1, altrimenti // quello opposto. int VolZmap::IntersLineParallelogram( const Point3d& ptLineP, const Vector3d& vtLineDir, const Point3d& ptParOrig, const Vector3d& vtSeg1, const Vector3d& vtSeg2, bool bExtNorm, Point3d& ptInt, Vector3d& vtN) const { // Definisco il versore normale al piano e il piano stesso. Plane3d plMyPlane ; Vector3d vtPlaneN = vtSeg2 ^ vtSeg1 ; if ( ! vtPlaneN.Normalize() || ! plMyPlane.Set( ptParOrig, vtPlaneN)) return 0 ; // Intersezione retta piano int nIntType = IntersLinePlane( ptLineP, vtLineDir, 1000, plMyPlane, ptInt, false) ; if ( nIntType == ILPT_YES /* || nIntType == ILPT_START || nIntType == ILPT_END*/) { // Creo un sistema di riferimento per stabilire se l'intersezione avviene in un // punto del piano interno alla superficie o meno. Vector3d vtUnit2 = vtSeg2 ; double dLen2 = vtUnit2.Len() ; vtUnit2 /= dLen2 ; Vector3d vtPerpToUnit2 = vtPlaneN ^ vtUnit2 ; double dSegProjPerpLen1 = vtSeg1 * vtPerpToUnit2 ; double dSegProjLongLen1 = vtSeg1 * vtUnit2 ; Vector3d vtIntV = ptInt - ptParOrig ; double dIntPerp = vtIntV * vtPerpToUnit2 ; double dIntLong = vtIntV * vtUnit2 ; if ( dIntPerp > 0 - EPS_SMALL && dIntPerp < dSegProjPerpLen1 + EPS_SMALL && ( dIntLong + EPS_SMALL) * dSegProjPerpLen1 > dIntPerp * dSegProjLongLen1 && ( dIntLong - dLen2 - EPS_SMALL) * dSegProjPerpLen1 < dIntPerp * dSegProjLongLen1) { vtN = bExtNorm ? vtPlaneN : - vtPlaneN ; return 1 ; } /*if ( dIntPerp >= 0 && dIntPerp <= dSegProjPerpLen1 && ( dIntLong) * dSegProjPerpLen1 >= dIntPerp * dSegProjLongLen1 && ( dIntLong - dLen2) * dSegProjPerpLen1 <= dIntPerp * dSegProjLongLen1) { vtN = bExtNorm ? vtPlaneN : - vtPlaneN ; return 1 ; }*/ // Oppure crei polyline e chiami la funzione per testare se // un punto � interno o meno a una polyline chiusa e piana. } return 0 ; } //---------------------------------------------------------------------------- // Calcola le intersezioni di una retta con la superficie ottenuta dal taglio di un cilindro, inteso come la sola superficie // laterale, con un numero arbitrario di piani. // Nel taglio del cilindro si esclude la parte che sta nel semispazio verso cui punta la normale al piano. // Il cilindro � descritto dal centro della base ptBaseCen, dal versore vtAx del suo asse di simmetria, dal raggio dRad, // dall'altezza dH e da un flag bInOut che indica se il campo delle normali al cilindro volge verso l'asse di simmetria o meno. // I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono // retta e cilindro. // Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale // della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione. // La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2). int VolZmap::IntersLineCylinderCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir, const Point3d& ptBaseCen, const Vector3d& vtAx, double dRad, double dH, bool bInOut, const vector& vPlanesVec, Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const { // Se il raggio non � sufficientemente grande, non devo fare alcunch�. if ( dRad < EPS_SMALL) return 0 ; // Definisco il sistema di riferimento S; se non � possibile, c'� un errore. Frame3d frFrameS ; if ( ! frFrameS.Set( ptBaseCen, vtAx)) return 0 ; // Se l'altezza � negativa, cambio sistema di riferimento. if ( dH < 0) { frFrameS.Translate( dH * frFrameS.VersZ()) ; dH *= - 1 ; } // Porto la linea nel riferimento del cilindro Point3d ptP = ptLineP ; ptP.ToLoc( frFrameS) ; Vector3d vtV = vtLineDir ; vtV.ToLoc( frFrameS) ; // Se la retta � parallela all'asse, non ci sono intersezioni. if ( vtV.SqLenXY() < EPS_ZERO * EPS_ZERO) return 0 ; // Determino le intersezioni con la superficie cilindrica DBLVECTOR vdCoef( 3) ; double dSqRad = dRad * dRad ; vdCoef[0] = ptP.x * ptP.x + ptP.y * ptP.y - dSqRad ; vdCoef[1] = 2 * ( ptP.x * vtV.x + ptP.y * vtV.y) ; vdCoef[2] = vtV.x * vtV.x + vtV.y * vtV.y ; DBLVECTOR vdRoots ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Se non ho trovato soluzioni, ho terminato. if ( nRoot == 0) return nRoot ; // Punti di intersezione e versori alla superficie in corrispondenza di essi ptInt1 = ptP + vdRoots[0] * vtV ; vtN1.Set( ptInt1.x, ptInt1.y, 0) ; vtN1.Normalize() ; if ( nRoot == 2) { ptInt2 = ptP + vdRoots[1] * vtV ; vtN2.Set( ptInt2.x, ptInt2.y, 0) ; vtN2.Normalize() ; } if ( ! bInOut) { vtN1 *= - 1 ; vtN2 *= - 1 ; } // Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z. if ( ptInt1.z < 0 || ptInt1.z > dH) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nRoot ; } if ( nRoot > 0 && ( ptInt2.z < 0 || ptInt2.z > dH)) { -- nRoot ; } // Esprimo punti e vettori nel sistema in cui � immerso S. if ( nRoot > 0) { ptInt1.ToGlob( frFrameS) ; vtN1.ToGlob( frFrameS) ; if ( nRoot == 2) { ptInt2.ToGlob( frFrameS) ; vtN2.ToGlob( frFrameS) ; } } // Elimino le intersezioni sul cono che non fanno parte della superficie. bool bSecIntToTest = nRoot > 1 ; for ( int n = 0 ; n < int( vPlanesVec.size()) && nRoot > 0 ; ++ n) { if ( /*DistPointPlane( ptInt1, vPlanesVec[n]) > 0*/ DistPointPlane( ptInt1, vPlanesVec[n]) >= 0) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nRoot ; } if ( /*bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0*/bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0) { bSecIntToTest = false ; -- nRoot ; } } return nRoot ; } //---------------------------------------------------------------------------- // Calcola le intersezioni di una retta con una superficie di traslazione di una circonferenza di un vettore vtSweptVec // tagliata da un numero arbitrario di piani. // Nel taglio della superficie di traslazione si esclude la parte che sta nel semispazio verso cui punta la normale al piano. // La circonferenza � descritta dal centro ptCen, dal versore vtAx del suo asse di simmetria rotazionale e dal raggio dRad. // Il flag bInOut indica se la proiezione sul piano della circonferenza del campo delle normail alla superficie volge verso il // centro di quest'ultima o meno. // I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono // retta e la superficie di traslazione. // Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale // della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione. // La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2). int VolZmap::IntersLineCircSweptSurfCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir, const Point3d& ptCen, const Vector3d& vtAx, double dRad, const Vector3d& vtSweptVec, bool bInOut, const vector& vPlanesVec, Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const { // Se il raggio non � sufficientemente grande, non devo fare alcunch�. if ( dRad < EPS_SMALL) return 0 ; // Studio delle simmetrie Point3d ptMyCen = ptCen ; Vector3d vtMySweptVec = vtSweptVec ; if ( vtSweptVec * vtAx < 0) { ptMyCen += vtSweptVec ; vtMySweptVec *= - 1 ; } // Calcolo le lunghezze del moto nella direzione dell'asse di simmetria rotazionale e // in quella ortogonale. double dLongVecLen = vtMySweptVec * vtAx ; double dOrtVecLen = sqrt( max( vtMySweptVec.SqLen() - dLongVecLen * dLongVecLen, 0.)) ; // Definisco il sistema di riferimento S; se non � possibile, c'� un errore. Vector3d vtV1 = vtMySweptVec - dLongVecLen * vtAx ; Frame3d frFrameS ; if ( ! vtV1.Normalize()) { if ( ! frFrameS.Set( ptMyCen, vtAx)) return 0 ; } else if ( ! frFrameS.Set( ptMyCen, vtV1, vtAx ^ vtV1, vtAx)) return 0 ; // Se la suerficie degenera in un piano, non bisogna tagliare if ( abs( dLongVecLen) < /*EPS_SMALL*/EPS_ZERO) return 0 ; // Porto la linea nel riferimento S Point3d ptP = ptLineP ; ptP.ToLoc( frFrameS) ; Vector3d vtV = vtLineDir ; vtV.ToLoc( frFrameS) ; // Asse cilindro ellittico Vector3d vtSurfAx( dOrtVecLen, 0, dLongVecLen) ; vtSurfAx.Normalize() ; // Retta parallela a quella del moto if ( AreSameOrOppositeVectorExact( vtV, vtSurfAx)) return 0 ; // Quadrato del raggio, coefficiente angolare della retta di movimento nel // piano ZX del sistema di riferimento del movimento e suo quadrato double dSqRad = dRad * dRad ; double dSqLongLen = dLongVecLen * dLongVecLen ; double dSqOrtLen = dOrtVecLen * dOrtVecLen ; // Setto i coeficienti dell'equazione d'intersezione della // retta con la superficie di traslazione della circonferenza. DBLVECTOR vdCoef(3) ; vdCoef[0] = dSqLongLen * ( ptP.x * ptP.x + ptP.y * ptP.y) + dSqOrtLen * ptP.z * ptP.z - 2 * dLongVecLen * dOrtVecLen * ptP.x * ptP.z - dSqLongLen * dSqRad ; vdCoef[1] = 2 * dSqLongLen * ( ptP.x * vtV.x + ptP.y * vtV.y) + 2 * dSqOrtLen * ptP.z * vtV.z - 2 * dLongVecLen * dOrtVecLen * ( ptP.x * vtV.z + ptP.z * vtV.x) ; vdCoef[2] = dSqLongLen * ( vtV.x * vtV.x + vtV.y * vtV.y) + dSqOrtLen * vtV.z * vtV.z - 2 * dLongVecLen * dOrtVecLen * vtV.x * vtV.z ; // Numero di soluzioni DBLVECTOR vdRoots ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // L'equazione ammette o due soluzioni (eventualmente // coincidenti) oppure nessuna o infinite se la la retta // appartiene alla superficie // Se numero di soluzioni diverso da due le eventuali intersezioni sono gi� state trovate if ( nRoot != 2) return 0 ; // Punti di intersezione e versori alla superficie in corrispondenza di essi ptInt1 = ptP + vdRoots[0] * vtV ; ptInt2 = ptP + vdRoots[1] * vtV ; vtN1.Set( dSqLongLen * ptInt1.x - dLongVecLen * dOrtVecLen * ptInt1.z, dSqLongLen * ptInt1.y, dSqOrtLen * ptInt1.z - dLongVecLen * dOrtVecLen * ptInt1.x) ; vtN1.Normalize( EPS_ZERO) ; vtN2.Set( dSqLongLen * ptInt2.x - dLongVecLen * dOrtVecLen * ptInt2.z, dSqLongLen * ptInt2.y, dSqOrtLen * ptInt2.z - dLongVecLen * dOrtVecLen * ptInt2.x) ; vtN2.Normalize( EPS_ZERO) ; if ( ! bInOut) { vtN1 *= - 1 ; vtN2 *= - 1 ; } // Elimino le soluzioni cha non stanno sulla superficie di traslazione, ovvero le intersezioni fuori dai limiti in Z. if ( ptInt1.z < 0 || ptInt1.z > dLongVecLen) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nRoot ; } if ( ptInt2.z < 0 || ptInt2.z > dLongVecLen) { -- nRoot ; } // Esprimo punti e vettori nel sistema in cui � immerso S. if ( nRoot > 0) { ptInt1.ToGlob( frFrameS) ; vtN1.ToGlob( frFrameS) ; if ( nRoot == 2) { ptInt2.ToGlob( frFrameS) ; vtN2.ToGlob( frFrameS) ; } } // Escludo le soluzioni che non stanno dalla parte ammissibile rispetto al piano. bool bSecIntToTest = nRoot > 1 ; for ( int n = 0 ; n < int( vPlanesVec.size()) && nRoot > 0 ; ++ n) { //double dDist1 = DistPointPlane(ptInt1, vPlanesVec[n]); if ( DistPointPlane( ptInt1, vPlanesVec[n]) > 0 + EPS_SMALL/*DistPointPlane( ptInt1, vPlanesVec[n]) >= 0*/) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nRoot ; } //double dDist2 = DistPointPlane(ptInt2, vPlanesVec[n]); if ( bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0 + EPS_SMALL/*bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0*/) { bSecIntToTest = false ; -- nRoot ; } } return nRoot ; } //---------------------------------------------------------------------------- // Calcola le intersezioni di una retta con la superficie ottenuta dal taglio di un cono, inteso come la sola superficie // laterale, con un numero arbitrario di piani. // Nel taglio del cono si esclude la parte che sta nel semispazio verso cui punta la normale al piano. // Il cono � descritto dal vertice ptVert, dal versore vtAx del suo asse di simmetria, dal raggio dRad, dall'altezza dH // e da un flag bInOut che indica se il campo delle normali al cono volge verso l'asse di simmetria o meno. // I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono // retta e cono. // Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale // della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione. // La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2). int VolZmap::IntersLineConeCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir, const Point3d& ptVert, const Vector3d& vtAx, double dRad, double dH, bool bInOut, const vector& vPlanesVec, Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const { // Definisco il sistema di riferimento S; se non � possibile, c'� un errore. Frame3d frFrameS ; if ( ! frFrameS.Set( ptVert, vtAx)) return 0 ; // Porto la linea nel riferimento del cilindro Point3d ptP = ptLineP ; ptP.ToLoc( frFrameS) ; Vector3d vtV = vtLineDir ; vtV.ToLoc( frFrameS) ; // Tangente dell'angolo di semi-apertura double dTan = dRad / dH ; // Determino le intersezioni con la superficie laterale del cono DBLVECTOR vdCoef( 3) ; double dSqTan = dTan * dTan ; vdCoef[0] = dSqTan * ptP.z * ptP.z - ptP.x * ptP.x - ptP.y * ptP.y ; vdCoef[1] = 2 * ( dSqTan * ptP.z * vtV.z - ptP.x * vtV.x - ptP.y * vtV.y) ; vdCoef[2] = dSqTan * vtV.z * vtV.z - vtV.x * vtV.x - vtV.y * vtV.y ; DBLVECTOR vdRoots ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Se non ho trovato soluzioni, ovvero si � stata trovata una soluzione di tangenza, ho terminato. if ( nRoot == 0 || ( nRoot == 1 && abs( vtV.z) < EPS_ZERO)) return 0 ; // Intersezioni ptInt1 = ptP + vdRoots[0] * vtV ; vtN1 = Vector3d( ptInt1.x, ptInt1.y, - dSqTan * ptInt1.z) ; vtN1.Normalize() ; if ( nRoot == 2) { ptInt2 = ptP + vdRoots[1] * vtV ; vtN2 = Vector3d( ptInt2.x, ptInt2.y, - dSqTan * ptInt2.z) ; vtN2.Normalize() ; } if ( ! bInOut) { vtN1 *= - 1 ; vtN2 *= - 1 ; } // Elimino le intersezioni che non fanno parte del cono. if ( ptInt1.z < 0 || ptInt1.z > dH) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nRoot ; } if ( nRoot > 0 && ( ptInt2.z < 0 || ptInt2.z > dH)) -- nRoot ; // Esprimo punti e vettori nel sistema in cui � immerso S. if ( nRoot > 0) { ptInt1.ToGlob( frFrameS) ; vtN1.ToGlob( frFrameS) ; if ( nRoot == 2) { ptInt2.ToGlob( frFrameS) ; vtN2.ToGlob( frFrameS) ; } } // Elimino le intersezioni sul cono che non fanno parte della superficie. bool bSecIntToTest = nRoot > 1 ; for ( int n = 0 ; n < int( vPlanesVec.size()) && nRoot > 0 ; ++ n) { if ( /*DistPointPlane( ptInt1, vPlanesVec[n]) > 0*/DistPointPlane( ptInt1, vPlanesVec[n]) >= 0) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nRoot ; } if ( /*bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0*/bSecIntToTest && nRoot > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0) { bSecIntToTest = false ; -- nRoot ; } } return nRoot ; } //---------------------------------------------------------------------------- // Calcola le intersezioni di una retta con una superficie sferica tagliata da un numero arbitrario di piani. // Nel taglio della sfera si esclude la parte che sta nel semispazio verso cui punta la normale al piano. // Il cono � descritto dal vertice ptVert, dal versore vtAx del suo asse di simmetria, dal raggio dRad, dall'altezza dH // e da un flag bInOut che indica se il campo delle normali volge verso l'interno della sfera o meno. // I piani devono essere espressi nello stesso sistema di riferimento in cui sono espressi i punti e i vettori che descrivono // retta e cono. // Le soluzioni verranno espresse nel medesimo sistema di riferimeno. I versori normali vtN1 e vtN2 saranno opposti alla normale // della superficie nei punti ptInt1 e ptInt2 rispettivamente in cui avviene l'intersezione. // La funzione restituisce 0 in caso di errore o assenza di soluzioni, altrimenti il numero di soluzioni trovate (al massimo 2). int VolZmap::IntersLineSphereCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineD, const Point3d& ptCen, double dRad, bool bInOut, const vector& vPlanesVec, Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const { // Intersezione fra retta e sfera int nSol = IntersLineSphere( ptLineP, vtLineD, ptCen, dRad, ptInt1, ptInt2) ; // Non ci sono soluzioni. if ( nSol == ILST_NO) return nSol ; // Calcolo le normali vtN1 = ( ptInt1 - ptCen) ; vtN1.Normalize() ; vtN2 = ( ptInt2 - ptCen) ; vtN2.Normalize() ; if ( ! bInOut) { vtN1 *= - 1 ; vtN2 *= - 1 ; } // Escludo le soluzioni fuori dalla parte ammissibile. bool bSecIntToTest = nSol > 1 ; for ( int n = 0 ; n < int( vPlanesVec.size()) && nSol != 0 ; ++ n) { if ( /*DistPointPlane( ptInt1, vPlanesVec[n]) > 0*/DistPointPlane( ptInt1, vPlanesVec[n]) >= 0) { ptInt1 = ptInt2 ; vtN1 = vtN2 ; -- nSol ; } if ( /*bSecIntToTest && nSol > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) > 0*/bSecIntToTest && nSol > 0 && DistPointPlane( ptInt2, vPlanesVec[n]) >= 0) { bSecIntToTest = false ; -- nSol ; } } return nSol ; } //---------------------------------------------------------------------------- // Il vettore normale alla superficie deve essere passato gi� normalizzato. int VolZmap::IntersLineCatTongue( const Point3d& ptLineP, const Vector3d& vtLineD, const Point3d& ptCenSt, const Point3d& ptCenEn, const Vector3d& vtNorm, double dRad, Point3d& ptInt, Vector3d& vtN) const { // Definisco il piano. Plane3d plPlane ; if ( ! plPlane.Set( ptCenSt, vtNorm)) return 0 ; // Intersezione retta piano int nIntType = IntersLinePlane( ptLineP, vtLineD, 1000, plPlane, ptInt, false) ; if ( nIntType == ILPT_YES /* || nIntType == ILPT_START || nIntType == ILPT_END*/) { // Creo un sistema di riferimento per stabilire se l'intersezione avviene in un // punto del piano interno alla superficie o meno. Vector3d vtLong = ptCenEn - ptCenSt ; double dLongLen = vtLong.Len() ; vtLong /= dLongLen ; Vector3d vtTrasv = vtNorm ^ vtLong ; // Determino se l'intersezione � sulla superficie Vector3d vtIntV = ptInt - ptCenSt ; double dIntLong = vtIntV * vtLong ; double dIntTrasv = vtIntV * vtTrasv ; double dInfLongLim = sqrt( max( dRad * dRad - dIntTrasv * dIntTrasv, 0.)) ; double dSupLongLim = dLongLen + dInfLongLim ; if ( abs( dIntTrasv) < dRad && dIntLong > dInfLongLim && dIntLong < dSupLongLim) { vtN = - vtNorm ; return 1 ; } } return 0 ; } // Filtro per le intersezioni typedef vector> DexelSurfIntersVector ; //---------------------------------------------------------------------------- bool IntersectionsFilter( const Vector3d& vtDexDir, const DexelSurfIntersVector& vOrigineIntersVec, DexelSurfIntersVector& vFilteredIntersVec) { // Tolleranze double dDotEps = EPS_ZERO ; double dLenEps = EPS_SMALL ; // Separo gli ingressi dalle uscite. DexelSurfIntersVector vEntrancesVec, vExitsVec, vIndefVec ; for ( int n = 0 ; n < int( vOrigineIntersVec.size()) ; ++ n) { if ( vOrigineIntersVec[n].second * vtDexDir < - dDotEps) { vExitsVec.emplace_back( vOrigineIntersVec[n]) ; } else if ( vOrigineIntersVec[n].second * vtDexDir > dDotEps) { vEntrancesVec.emplace_back( vOrigineIntersVec[n]) ; } else { vIndefVec.emplace_back( vOrigineIntersVec[n]) ; } } // Riordino le entrate e le uscite in funzione del parametro lungo la retta in corrispondenza del quale occorrono. sort( vEntrancesVec.begin(), vEntrancesVec.end(), [] ( pair Int1, pair Int2) { return Int1.first < Int2.first ; }) ; sort( vExitsVec.begin(), vExitsVec.end(), [] ( pair Int1, pair Int2) { return Int1.first < Int2.first ; }) ; if ( int( vEntrancesVec.size()) == 2 && int( vExitsVec.size()) == 2 && abs( vEntrancesVec[0].first - vExitsVec[0].first) < dLenEps && abs( vEntrancesVec[1].first - vExitsVec[1].first) < dLenEps) return true ; // Modo 1 for ( int n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) { for ( int m = 0 ; m < int( vExitsVec.size()) ; ++ m) { if ( vExitsVec[m].first > vEntrancesVec[n].first) { if ( n == 0 || ( int( vFilteredIntersVec.size()) > 0 && vEntrancesVec[n].first > vFilteredIntersVec.back().first)) { vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ; vFilteredIntersVec.emplace_back( vExitsVec[m]) ; break ; } } } } // Modo 2 // Media e deviazione standard delle entrate //double dEntrancesAvarage = 0 ; //double dEntrancesStdDev = 0 ; //if ( int( vEntrancesVec.size()) != 0) { // for ( int n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) { // dEntrancesAvarage += vEntrancesVec[n].first ; // } // dEntrancesAvarage /= int( vEntrancesVec.size()) ; // for ( int n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) { // dEntrancesStdDev += ( vEntrancesVec[n].first - dEntrancesAvarage) * ( vEntrancesVec[n].first - dEntrancesAvarage) ; // } // dEntrancesStdDev = sqrt( dEntrancesStdDev / int( vEntrancesVec.size())) ; //} // //// Media e deviazione standard delle uscite //double dExitsAvarage = 0 ; //double dExitsStdDev = 0 ; //if ( int( vExitsVec.size()) != 0) { // for ( int n = 0 ; n < int( vExitsVec.size()) ; ++ n) { // dExitsAvarage += vExitsVec[n].first ; // } // dExitsAvarage /= int( vExitsVec.size()) ; // for ( int n = 0 ; n < int( vExitsVec.size()) ; ++ n) { // dExitsStdDev += ( vExitsVec[n].first - dExitsAvarage) * ( vExitsVec[n].first - dExitsAvarage) ; // } // dExitsStdDev = sqrt( dExitsStdDev / int( vExitsVec.size())) ; //} // //// Deve esserci almeno un entrata e un uscita //if ( int( vEntrancesVec.size()) != 0 && int( vExitsVec.size()) != 0) { // // Caso di un solo gruppo per le entrate // if ( dEntrancesStdDev < dLenEps) { // // Caso di un solo gruppo per le uscite // if ( dExitsStdDev < dLenEps) { // if ( vExitsVec.back().first > vEntrancesVec[0].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // } // // Caso di due gruppi per le uscite // else { // // Cerco ultima uscita del primo gruppo // int n ; // for ( n = int( vExitsVec.size()) - 1 ; n >= 0 ; -- n) { // if ( vExitsVec[n].first < dExitsAvarage) // break ; // } // // Aggiungo ingressi e uscite filtrati. // if ( vExitsVec[n].first > vEntrancesVec[0].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec[n]) ; // } // else if ( vExitsVec.back().first > vEntrancesVec[0].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // } // } // // Caso di due gruppi per le entrate // else { // // Cerco prima entrata del secondo gruppo // int n ; // for ( n = 0 ; n < int( vEntrancesVec.size()) ; ++ n) { // if ( vEntrancesVec[n].first > dEntrancesAvarage) // break ; // } // // Caso di un solo gruppo per le uscite // if ( dExitsStdDev < dLenEps) { // // Aggiungo ingressi e uscite filtrati. // if ( vExitsVec.back().first > vEntrancesVec[n].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // else if ( vExitsVec.back().first > vEntrancesVec[0].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // } // // Caso di due gruppi per le uscite // else { // // Cerco ultima uscita del primo gruppo // int m ; // for ( m = int( vExitsVec.size()) - 1 ; m >= 0 ; -- m) { // if ( vExitsVec[m].first < dExitsAvarage) // break ; // } // // Aggiungo ingressi e uscite ai filtri. // if ( vExitsVec[m].first > vEntrancesVec[0].first) { // if ( vExitsVec[m].first > vEntrancesVec[n].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // else if ( vExitsVec.back().first > vEntrancesVec[n].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec[m]) ; // vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // else { // vFilteredIntersVec.emplace_back( vEntrancesVec[0]) ; // vFilteredIntersVec.emplace_back( vExitsVec[m]) ; // } // } // else { // if ( vExitsVec.back().first > vEntrancesVec[n].first) { // vFilteredIntersVec.emplace_back( vEntrancesVec[n]) ; // vFilteredIntersVec.emplace_back( vExitsVec.back()) ; // } // } // } // } //} return true ; } // Corona circolare //---------------------------------------------------------------------------- bool VolZmap::SurfCircCrown_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMaxRad, 1, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Se il movimento � in direzione opposta a quella ove la corona pu� tagliare, non devo fare nulla. if ( vtAx.z * ( ptE - ptS).z < EPS_ZERO) return true ; // Raggi di sicurezza per evitare di tagliare i dexel a filo del bordo dela regione interessata dal taglio. double dSqSafeMinRad = dMinRad * dMinRad + 2 * dMinRad * EPS_SMALL ; double dSqSafeMaxRad = dMaxRad * dMaxRad - 2 * dMaxRad * EPS_SMALL ; // Se la corona circolare defenera in un disco (dMinRad < EPS), forzo dSqSafeMinRad a - 1 // in modo da tagliare i dexel giacenti sul suo asse di simmetria. if ( dMinRad < EPS_SMALL) dSqSafeMinRad = - 1 ; Point3d ptSXY( ptS.x, ptS.y, 0) ; // Ciclo sui dexel. for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; Vector3d vtR = ptC - ptSXY ; double dSqLenR = vtR * vtR ; if ( dSqLenR > dSqSafeMinRad && dSqLenR < dSqSafeMaxRad) { double dMinZ = min( ptS.z, ptE.z) ; double dMaxZ = max( ptS.z, ptE.z) ; Vector3d vtMinN, vtMaxN ; if ( ptE.z < ptS.z) { vtMinN.z = 1 ; vtMaxN.z = -1 ; } else { vtMinN.z = 1 ; vtMaxN.z = - 1 ; } SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, vtMinN, vtMaxN) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::SurfCircCrown_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, 1, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Se il movimento � in direzione opposta a quella ove la corona pu� tagliare, non devo fare nulla. double dMotProjOnAx = vtAx * ( ptE - ptS) ; if ( dMotProjOnAx < EPS_ZERO) return true ; // Vettore di piani fittizio vector vEmptyPlaneVec ; // Ciclo sui dexel. for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con cilindro esterno int nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, dMotProjOnAx, false, vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro interno in caso di corona circolare propria (la funzione esegue // l'intersezione solo se il cilindro ha un raggio sensibilmente maggiore di zero) nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMinRad, dMotProjOnAx, true, vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con corona in posizione inziale nIntNum = IntersLineCircCrown( ptC, Z_AX, ptS, - vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Intersezione con corona in posizione inziale nIntNum = IntersLineCircCrown( ptC, Z_AX, ptE, vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::SurfCircCrown_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) { return SurfCircCrown_Milling( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad) ; } //---------------------------------------------------------------------------- bool VolZmap::SurfCircCrown_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMaxRad, 1, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Se il movimento � in direzione opposta a quella ove la corona pu� tagliare, non devo fare nulla. Vector3d vtDisp = ( ptE - ptS) ; double dMotProjOnAx = vtAx * vtDisp ; if ( dMotProjOnAx < EPS_ZERO) return true ; // Vettore di piani fittizio vector vEmptyPlaneVec ; // Ciclo sui dexel. for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con cilindro ellittico esterno int nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, vtDisp, false, vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro interno in caso di corona circolare propria (la funzione esegue // l'intersezione solo se il cilindro ha un raggio sensibilmente maggiore di zero) nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMinRad, vtDisp, true, vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con corona in posizione inziale nIntNum = IntersLineCircCrown( ptC, Z_AX, ptS, - vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Intersezione con corona in posizione inziale nIntNum = IntersLineCircCrown( ptC, Z_AX, ptE, vtAx, dMaxRad, dMinRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } return true ; } // Cilindro //---------------------------------------------------------------------------- //bool //VolZmap::SurfCyl_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, // double dHei, double dRad, bool bTapB, bool bTapT) //{ // return true ; //} // ////---------------------------------------------------------------------------- //bool //VolZmap::SurfCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, // double dHei, double dRad, bool bTapB, bool bTapT) //{ // return true ; //} //---------------------------------------------------------------------------- bool VolZmap::SurfCyl_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dRad, bool bOuterCutter) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore spostamento Vector3d vtDisp = ptE - ptS ; // Dimensioni del moto nella direzione utensile e ortogonale e quote iniziali e finali double dDispZ = vtDisp * vtAx ; double dDispXY = sqrt( max( vtDisp.SqLen() - dDispZ * dDispZ, 0.)) ; double dStartTopZ = ptS.z ; double dStartBotZ = ( ptS - dHei * vtAx).z ; // Sistema di riferimento del moto Vector3d vtV3 = vtAx ; Vector3d vtV1 = vtDisp - dDispZ * vtV3 ; vtV1.Normalize() ; Vector3d vtV2 = vtV3 ^ vtV1 ; Point3d ptSxy( ptS.x, ptS.y, 0) ; // Caso moto perpendicolare if ( abs( dDispZ) < EPS_SMALL) { // Ciclo sui dexel. for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; double dProj1 = ( ptC - ptSxy) * vtV1 ; double dProj2 = ( ptC - ptSxy) * vtV2 ; double dCirc1 = ( bOuterCutter ? 1 : - 1) * sqrt( max( dRad * dRad - dProj2 * dProj2, 0.)) ; if ( abs( dProj2) < dRad && dProj1 > dCirc1 && dProj1 < dDispXY + dCirc1) { // Quote minima e massima rispetto al sistema griglia e versori normali associati double dMin = vtAx.z > 0 ? dStartBotZ : dStartTopZ ; double dMax = vtAx.z > 0 ? dStartTopZ : dStartBotZ ; Vector3d vtMin = Z_AX ; Vector3d vtMax = - Z_AX ; // Taglio dei dexel SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } } } return true ; } // Ciclo sui dexel. for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; double dProj1 = ( ptC - ptSxy) * vtV1 ; double dProj2 = ( ptC - ptSxy) * vtV2 ; double dCirc1 = ( bOuterCutter ? 1 : - 1) * sqrt( max( dRad * dRad - dProj2 * dProj2, 0.)) ; if ( abs( dProj2) < dRad && dProj1 > dCirc1 && dProj1 < dDispXY + dCirc1) { // Quote inferiore e superiore rispetto alla direzione del versore utensile double dInfZ = dStartBotZ + ( dProj1 - dCirc1) * dDispZ * vtAx.z / dDispXY ; double dSupZ = dStartTopZ + ( dProj1 - dCirc1) * dDispZ * vtAx.z / dDispXY ; // Calcolo dei versori normali associati Vector3d vtRad = dCirc1 * vtV1 + dProj2 * vtV2 ; Vector3d vtTan( - vtRad.y, vtRad.x, 0) ; Vector3d vtCross = vtTan ^ vtDisp ; vtCross.Normalize() ; // Quote minima e massima rispetto al sistema griglia e versori normali associati double dMin = vtAx.z > 0 ? dInfZ : dSupZ ; double dMax = vtAx.z > 0 ? dSupZ : dInfZ ; Vector3d vtMin = bOuterCutter ? - vtCross : vtCross ; Vector3d vtMax = bOuterCutter ? vtCross : - vtCross ; // Taglio dei dexel SubtractIntervals( nGrid, i, j, dMin, dMax, vtMin, vtMax) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::SurfCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dRad, bool bOuterCutter, bool bTapB, bool bTapT) { // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore spostamento Vector3d vtDisp = ptE - ptS ; // Versore della componente del moto ortogonale all'asse dell'utensile double dDispZ = vtDisp * vtAx ; Vector3d vtOrtDisp = vtDisp - dDispZ * vtAx ; double dOrtDispLen = vtOrtDisp.Len() ; vtOrtDisp /= dOrtDispLen ; // Versore direzione del moto Vector3d vtDispDir = vtDisp ; vtDispDir.Normalize() ; // Versore laterale Vector3d vtLat = vtAx ^ vtOrtDisp ; // Deduzione dei punti per la definizione dei piani laterali Point3d ptPlanePlus = ptS - dHei * vtAx + dRad * vtLat ; Point3d ptPlaneMinus = ptS - dHei * vtAx - dRad * vtLat ; // Moto ortogonale all'asse del cilindro double dObCoef = dDispZ / dOrtDispLen ; double dMyLength = dObCoef * dRad / sqrt( 1 + dObCoef * dObCoef) ; if ( abs( dDispZ) < 2 * EPS_SMALL && dMyLength < 2 * EPS_SMALL) { Point3d ptMyE = ptS + dOrtDispLen * vtOrtDisp ; // Definisco i piani utilizzati per tagliare le superfici elementari. // Piano per cilindro in posizione iniziale vector vCutCylPlaneVecSt ; vCutCylPlaneVecSt.emplace_back() ; vCutCylPlaneVecSt.back().Set( ptS, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ; // Piano per cilindro in posizione finale vector vCutCylPlaneVecEn ; vCutCylPlaneVecEn.emplace_back() ; vCutCylPlaneVecEn.back().Set( ptMyE, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0.) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con cilindro in posizione iniziale int nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dRad, - dHei, bOuterCutter, vCutCylPlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro in posizione finale nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, vtAx, dRad, - dHei, ! bOuterCutter, vCutCylPlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con lingua di gatto superiore nIntNum = IntersLineCatTongue( ptC, Z_AX, bOuterCutter ? ptS : ptMyE, bOuterCutter ? ptMyE : ptS, vtAx, dRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Intersezione con lingua di gatto inferiore nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dHei * vtAx, ( bOuterCutter ? ptMyE : ptS) - dHei * vtAx, - vtAx, dRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Piano + (con normale + vtLat) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlus, dHei * vtAx, vtDisp, true, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Piano - (con normale - vtLat) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinus, dHei * vtAx, vtDisp, false, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } return true ; } // Definisco i piani utilizzati per tagliare le superfici elementari. // Piano per cilindro in posizione iniziale vector vCutCylPlaneVecSt ; vCutCylPlaneVecSt.emplace_back() ; vCutCylPlaneVecSt.back().Set( ptS, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ; // Piano per cilindro in posizione finale vector vCutCylPlaneVecEn ; vCutCylPlaneVecEn.emplace_back() ; vCutCylPlaneVecEn.back().Set( ptE, ( bOuterCutter ? - 1 : 1) * vtOrtDisp) ; // Piano per cilindro ellittico superiore vector vCutEllipCylPlaneVecUp ; if ( dDispZ > 0) { vCutEllipCylPlaneVecUp.emplace_back() ; vCutEllipCylPlaneVecUp.back().Set( ptS, ( bOuterCutter ? 1 : - 1) * vtDispDir ^ vtLat) ; } else { vCutEllipCylPlaneVecUp.emplace_back() ; vCutEllipCylPlaneVecUp.back().Set( ptS, ( bOuterCutter ? - 1 : 1) * vtDispDir ^ vtLat) ; } // Piani per cilindro ellittico inferiore vector vCutEllipCylPlaneVecDw ; if ( dDispZ > 0) { vCutEllipCylPlaneVecDw.emplace_back() ; vCutEllipCylPlaneVecDw.back().Set( ptS - dHei * vtAx, ( bOuterCutter ? 1 : - 1) * vtDispDir ^ vtLat) ; } else { vCutEllipCylPlaneVecDw.emplace_back() ; vCutEllipCylPlaneVecDw.back().Set( ptS - dHei * vtAx, ( bOuterCutter ? - 1 : 1) * vtDispDir ^ vtLat) ; } for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0.) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con cilindro in posizione iniziale int nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dRad, - dHei, bOuterCutter, vCutCylPlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro in posizione finale nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, vtAx, dRad, - dHei, ! bOuterCutter, vCutCylPlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico superiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dRad, vtDisp, bOuterCutter == dDispZ > 0, vCutEllipCylPlaneVecUp, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; if ( vCutEllipCylPlaneVecUp.size() == 1) { if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) { //double dLL1 = (ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN(); //double dLL2 = (ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN(); if ( ( ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ; else if ( ( ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ; } } } } // Intersezione con cilindro ellittico inferiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dRad, vtDisp, bOuterCutter != dDispZ > 0, vCutEllipCylPlaneVecDw, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; if ( vCutEllipCylPlaneVecDw.size() == 1) { if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) { //double dLL1 = (ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN(); //double dLL2 = (ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN(); if ( ( ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ; else if ( ( ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ; } } } } // Piano + (con normale + vtLat) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlus, dHei * vtAx, vtDisp, true, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Piano - (con normale - vtLat) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinus, dHei * vtAx, vtDisp, false, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } return true ; } // Cono //---------------------------------------------------------------------------- bool VolZmap::SurfConus_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { // Verifica sull'interferenza con lo Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Raggi di sicurezza per evitare di tagliare i dexel a filo del bordo dela regione interessata dal taglio. double dSqSafeMinRad = dMinRad * dMinRad + 2 * dMinRad * EPS_SMALL ; double dSqSafeMaxRad = dMaxRad * dMaxRad - 2 * dMaxRad * EPS_SMALL ; // Se il movimento � nella direzione ove il cono non taglia, ho finito. if ( vtAx.z * ( ptE.z - ptS.z) > 0 == bOuterCutter) return true ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { double dX = ( i + 0.5) * m_dStep ; double dY = ( j + 0.5) * m_dStep ; double dSqR = ( dX - ptS.x) * ( dX - ptS.x) + ( dY - ptS.y) * ( dY - ptS.y) ; if ( dSqR < dSqSafeMinRad || dSqR > dSqSafeMaxRad) continue ; if ( vtAx.z > 0) { double dr = sqrt( dSqR) ; // Quote Z double dMinZ = min( ptS.z, ptE.z) - dHei + ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ; double dMaxZ = max( ptS.z, ptE.z) - dHei + ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ; // Normali Vector3d vtMinN, vtMaxN ; if ( bOuterCutter) { double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ; Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ; Point3d ptIntMinP( dX, dY, dMinZ) ; Vector3d vtIntMinV = ptIntMinP - ptVertE ; double dCompLong = vtIntMinV * vtAx ; Vector3d vtIntMinLongV = dCompLong * vtAx ; Vector3d vtIntMinOrtV = vtIntMinV - vtIntMinLongV ; double dCompOrt = vtIntMinOrtV.Len() ; vtIntMinOrtV /= dCompOrt ; vtMinN = - dCompLong * vtIntMinOrtV + dCompOrt * vtAx ; vtMinN.Normalize() ; vtMaxN = - vtMinN ; } else { double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ; Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ; Point3d ptIntMaxP( dX, dY, dMaxZ) ; Vector3d vtIntMaxV = ptIntMaxP - ptVertE ; double dCompLong = vtIntMaxV * vtAx ; Vector3d vtIntMaxLongV = dCompLong * vtAx ; Vector3d vtIntMaxOrtV = vtIntMaxV - vtIntMaxLongV ; double dCompOrt = vtIntMaxOrtV.Len() ; vtIntMaxOrtV /= dCompOrt ; vtMaxN = dCompLong * vtIntMaxOrtV - dCompOrt * vtAx ; vtMaxN.Normalize() ; vtMinN = - vtMaxN ; } // Taglio dei dexel SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, vtMinN, vtMaxN) ; } else { double dr = sqrt( dSqR) ; // Quote Z double dMinZ = min( ptS.z, ptE.z) + dHei - ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ; double dMaxZ = max( ptS.z, ptE.z) + dHei - ( dr - dMinRad) * dHei / ( dMaxRad - dMinRad) ; // Normali Vector3d vtMinN, vtMaxN; if ( bOuterCutter) { double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ; Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ; Point3d ptIntMaxP( dX, dY, dMaxZ) ; Vector3d vtIntMaxV = ptIntMaxP - ptVertE ; double dCompLong = vtIntMaxV * vtAx ; Vector3d vtIntMaxLongV = dCompLong * vtAx ; Vector3d vtIntMaxOrtV = vtIntMaxV - vtIntMaxLongV ; double dCompOrt = vtIntMaxOrtV.Len() ; vtIntMaxOrtV /= dCompOrt ; vtMaxN = - dCompLong * vtIntMaxOrtV + dCompOrt * vtAx ; vtMaxN.Normalize() ; vtMinN = - vtMaxN ; } else { double dDeltaH = dMinRad * dHei / ( dMaxRad - dMinRad) ; Point3d ptVertE = ptE - ( dHei + dDeltaH) * vtAx ; Point3d ptIntMinP( dX, dY, dMinZ) ; Vector3d vtIntMinV = ptIntMinP - ptVertE ; double dCompLong = vtIntMinV * vtAx ; Vector3d vtIntMinLongV = dCompLong * vtAx ; Vector3d vtIntMinOrtV = vtIntMinV - vtIntMinLongV ; double dCompOrt = vtIntMinOrtV.Len() ; vtIntMinOrtV /= dCompOrt ; vtMinN = dCompLong * vtIntMinOrtV - dCompOrt * vtAx ; vtMinN.Normalize() ; vtMaxN = - vtMinN ; } // Taglio dei dexel SubtractIntervals( nGrid, i, j, dMinZ, dMaxZ, vtMinN, vtMaxN) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::SurfConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore spostamento e sua componente lungo l'asse del cono Vector3d vtDisp = ptE - ptS ; double dDispLong = vtAx * vtDisp ; // Se lo spostamento � in direzione opposta a quella ove il cono taglia, ho finito. bool bToolVecAndDispAreOpposite = dDispLong < 0 ; if ( bToolVecAndDispAreOpposite != bOuterCutter) return true ; // Vertici cono iniziale e finale double dDeltaHei = ( dMinRad * dHei) / ( dMaxRad - dMinRad) ; Point3d ptVs = ptS - ( dHei + dDeltaHei) * vtAx ; Point3d ptVe = ptE - ( dHei + dDeltaHei) * vtAx ; // Piani per tagliare le superfici elementari. vector vCutConePlaneVecSt ; vCutConePlaneVecSt.emplace_back() ; vCutConePlaneVecSt.back().Set( ptS - dHei * vtAx, - vtAx) ; vector vCutConePlaneVecEn ; vCutConePlaneVecEn.emplace_back() ; vCutConePlaneVecEn.back().Set( ptE - dHei * vtAx, - vtAx) ; vector vEmptyPlaneVec ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con il cono in posizione iniziale int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVs, vtAx, dMaxRad, dHei + dDeltaHei, /*!*/ bToolVecAndDispAreOpposite, vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con il cono in posizione finale nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVe, vtAx, dMaxRad, dHei + dDeltaHei, ! bToolVecAndDispAreOpposite, vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con il cilindro esterno nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, dDispLong, false, vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con il cilindro interno nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dMinRad, dDispLong, true, vEmptyPlaneVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::SurfConus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { return SurfConus_Milling( nGrid, ptS, ptE, vtAx, dHei, dMaxRad, dMinRad, bOuterCutter, true, true, vtArcNormMaxR, vtArcNormMinR) ; } //---------------------------------------------------------------------------- bool VolZmap::SurfConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) { // Verifico interferenza int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dMaxRad, dMinRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore spostamento Vector3d vtDisp = ptE - ptS ; // Spostamento nella direzione utensile e in quella ortogonale double dDispProjOnAxDir = vtDisp * vtAx ; Vector3d vtDispLong = dDispProjOnAxDir * vtAx ; Vector3d vtDispOrt = vtDisp - vtDispLong ; // Terna di riferimento del movimento Vector3d vtV1 = vtDispOrt ; vtV1.Normalize() ; Vector3d vtV2 = vtAx ^ vtV1 ; Vector3d vtV3 = vtAx ; // Parametri geometrici descriventi il cono e il moto double dDeltaHei = dMinRad * dHei / ( dMaxRad - dMinRad) ; double dTanAlpha = dMaxRad / ( dHei + dDeltaHei) ; double dCosTheta = Clamp( ( dTanAlpha * vtDisp * vtV3) / ( vtDisp * vtV1), -1., 1.) ; double dSinTheta = sqrt( max( 1 - dCosTheta * dCosTheta, 0.)) ; double dLim = abs( dCosTheta) ; // Se il movimento non � compatibile con il verso delle normali, ho finito. if ( dLim > 1 - EPS_ZERO && ( bOuterCutter == dDispProjOnAxDir > 0)) return true ; // Vertici del cono nelle posizioni iniziale e finale Point3d ptVertSt = ptS - ( dHei + dDeltaHei) * vtAx ; Point3d ptVertEn = ptE - ( dHei + dDeltaHei) * vtAx ; // Vettori radiali per definire i piani Vector3d vtRadPlus = dCosTheta * vtV1 + dSinTheta * vtV2 ; Vector3d vtRadMinus = dCosTheta * vtV1 - dSinTheta * vtV2 ; // Piani per tagliare le superfici elementari. // Piani per cono in posizione iniziale vector vCutConePlaneVecSt ; vCutConePlaneVecSt.emplace_back() ; vCutConePlaneVecSt.back().Set( ptS - dHei * vtAx, - vtAx) ; // Piani per cono in posizione finale vector vCutConePlaneVecEn ; vCutConePlaneVecEn.emplace_back() ; vCutConePlaneVecEn.back().Set( ptE - dHei * vtAx, - vtAx) ; // Piani per cilindro ellittico superiore vector vCutEllipCylPlaneVecUp ; // Piani per cilindro ellittico inferiore vector vCutEllipCylPlaneVecDw ; // Caso di limete oltrepassato if ( dLim > 1 - EPS_ZERO) { // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con il cono in posizione iniziale int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertSt, vtAx, dMaxRad, dHei + dDeltaHei, bOuterCutter, vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con il cono in posizione finale nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertEn, vtAx, dMaxRad, dHei + dDeltaHei, ! bOuterCutter, vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico esterno nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, vtDisp, false, vCutEllipCylPlaneVecUp, ptInt1, vtN1, ptInt2, vtN2); if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico interno nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dMinRad, vtDisp, true, vCutEllipCylPlaneVecDw, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } else { // Vettore normale ai piani per il nuovo taglio dei coni. Vector3d vtConePlaneNorm = ( ptS + dMaxRad * vtRadPlus - ptVertSt) ^ ( ptS + dMaxRad * vtRadMinus - ptVertSt) ; vtConePlaneNorm.Normalize() ; if ( bOuterCutter) vtConePlaneNorm *= - 1 ; // Aggiorno vettore di piani per tagliare il cono in posizione iniziale. vCutConePlaneVecSt.emplace_back() ; vCutConePlaneVecSt.back().Set( ptVertSt, vtConePlaneNorm) ; // Aggiorno vettore di piani per tagliare il cono in posizione finale. vCutConePlaneVecEn.emplace_back() ; vCutConePlaneVecEn.back().Set( ptVertEn, vtConePlaneNorm) ; // Punti e normali dei piani laterali Point3d ptPlanePlusP = ptS - dHei * vtAx + dMinRad * vtRadPlus ; Point3d ptPlaneMinusP = ptS - dHei * vtAx + dMinRad * vtRadMinus ; Vector3d vtPlanePlusN = ptS + dMaxRad * vtRadPlus - ptPlanePlusP ; Vector3d vtPlaneMinusN = ptS + dMaxRad * vtRadMinus - ptPlaneMinusP ; // Moto ortogonale all'asse del cono double dObCoef = dDispProjOnAxDir / vtDispOrt.Len() ; double dMyLengthMax = dObCoef * dMaxRad / sqrt( 1 + dObCoef * dObCoef) ; double dMyLengthMin = dObCoef * dMinRad / sqrt( 1 + dObCoef * dObCoef) ; if ( abs( dDispProjOnAxDir) < 2 * EPS_SMALL && min( dMyLengthMax, dMyLengthMin) < 2 * EPS_SMALL) { Point3d ptMyE = ptS + vtDispOrt ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con il cono in posizione iniziale int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertSt, vtAx, dMaxRad, dHei + dDeltaHei, bOuterCutter, vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con il cono in posizione finale nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertEn, vtAx, dMaxRad, dHei + dDeltaHei, ! bOuterCutter, vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con lingua di gatto superiore nIntNum = IntersLineCatTongue( ptC, Z_AX, bOuterCutter ? ptS : ptMyE, bOuterCutter ? ptMyE : ptS, vtAx, dMaxRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Intersezione con lingua di gatto inferiore nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dHei * vtAx, ( bOuterCutter ? ptMyE : ptS) - dHei * vtAx, - vtAx, dMinRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Piano + (con normale + vtAx ^ vtOrtDisp) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlusP, vtPlanePlusN, vtDisp, true, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Piano - (con normale - vtAx ^ vtOrtDisp) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinusP, vtPlaneMinusN, vtDisp, false, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } return true ; } // Aggiorno il vettore dei piani per tagliare il cilindro ellittico superiore. Vector3d vtEllipCylPlaneNormUp = vtDisp ^ vtV2 ; vtEllipCylPlaneNormUp.Normalize() ; if ( bOuterCutter != dDispProjOnAxDir > 0) vtEllipCylPlaneNormUp *= - 1 ; vCutEllipCylPlaneVecUp.emplace_back() ; vCutEllipCylPlaneVecUp.back().Set( ptS + dMaxRad * dCosTheta * vtV1, vtEllipCylPlaneNormUp) ; // Aggiorno il vettore dei piani per tagliare il cilindro ellittico inferiore. Vector3d vtEllipCylPlaneNormDw = vtEllipCylPlaneNormUp ; vCutEllipCylPlaneVecDw.emplace_back() ; vCutEllipCylPlaneVecDw.back().Set( ptS - dHei * vtAx + dMinRad * dCosTheta * vtV1, vtEllipCylPlaneNormDw) ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec; DexelSurfIntersVector vIntersConusStart, vIntersConusEnd, vIntersEllipSup, vIntersEllipInf, vIntersPlanePlus, vIntersPlaneMinus; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con il cono in posizione iniziale int nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertSt, vtAx, dMaxRad, dHei + dDeltaHei, bOuterCutter, vCutConePlaneVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con il cono in posizione finale nIntNum = IntersLineConeCuttedByPlanes( ptC, Z_AX, ptVertEn, vtAx, dMaxRad, dHei + dDeltaHei, ! bOuterCutter, vCutConePlaneVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico superiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS, vtAx, dMaxRad, vtDisp, bOuterCutter == dDispProjOnAxDir > 0, vCutEllipCylPlaneVecUp, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; if ( vCutEllipCylPlaneVecUp.size() == 1) { if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) { //double dLL1 = (ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN(); //double dLL2 = (ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN(); if ( ( ptInt1 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ; else if ( ( ptInt2 - vCutEllipCylPlaneVecUp[0].GetPoint()) * vCutEllipCylPlaneVecUp[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ; } } } } // Intersezione con cilindro ellittico inferiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dMinRad, vtDisp, bOuterCutter != dDispProjOnAxDir > 0, vCutEllipCylPlaneVecDw, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; if ( vCutEllipCylPlaneVecDw.size() == 1) { if ( SqDist( ptInt1, ptInt2) < EPS_SMALL) { //double dLL1 = (ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN(); //double dLL2 = (ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN(); if ( ( ptInt1 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 2) ; else if ( ( ptInt2 - vCutEllipCylPlaneVecDw[0].GetPoint()) * vCutEllipCylPlaneVecDw[0].GetVersN() > 0.) vParAndNormIntersVec.erase( vParAndNormIntersVec.begin() + int( vParAndNormIntersVec.size()) - 1) ; } } } } // Piano + (con normale + vtAx ^ vtOrtDisp) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlanePlusP, vtPlanePlusN, vtDisp, true, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Piano - (con normale - vtAx ^ vtOrtDisp) nIntNum = IntersLineParallelogram( ptC, Z_AX, ptPlaneMinusP, vtPlaneMinusN, vtDisp, false, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } return true ; } // Parte di calotta sferica //---------------------------------------------------------------------------- bool VolZmap::SurfSphericalShellPart_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dRad, double dInfH, double dSupH, bool bOuterCutter) { // Se la superficie � una calotta sferica, chiamo la routine apposita. if ( dInfH > dRad - EPS_SMALL) return SurfSphericalShell_Milling( nGrid, ptS, ptE, vtAx, dRad, dSupH, bOuterCutter) ; // Verifico interferisca int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore spostamento Vector3d vtDisp = ptE - ptS ; Vector3d vtDispVers = vtDisp ; double dDispLen = vtDispVers.Len() ; vtDispVers /= dDispLen ; // Prodotto scalare fra versore del movimento e asse della calotta sferica double dAxDispDot = vtDispVers * vtAx ; // Raggi dei cilindri ellittici double dInfRad = sqrt( max( dRad * dRad - dInfH * dInfH, 0.)) ; double dSupRad = sqrt( max( dRad * dRad - dSupH * dSupH, 0.)) ; // Coseni limite double dCosInf = dInfRad / dRad ; double dCosSup = dSupRad / dRad ; // Vettore dei piani di taglio della sfera in posizione iniziale vector vSphereCutPlanesVecSt ; vSphereCutPlanesVecSt.emplace_back() ; vSphereCutPlanesVecSt.back().Set( ptS - dSupH * vtAx, vtAx) ; vSphereCutPlanesVecSt.emplace_back() ; vSphereCutPlanesVecSt.back().Set( ptS - dInfH * vtAx, - vtAx) ; // Vettore dei piani di taglio della sfera in posizione finale vector vSphereCutPlanesVecEn ; vSphereCutPlanesVecEn.emplace_back() ; vSphereCutPlanesVecEn.back().Set( ptE - dSupH * vtAx, vtAx) ; vSphereCutPlanesVecEn.emplace_back() ; vSphereCutPlanesVecEn.back().Set( ptE - dInfH * vtAx, - vtAx) ; if ( abs( dAxDispDot) > dCosSup - EPS_ZERO) { if ( bOuterCutter == dAxDispDot > 0) return true ; // Vettori dei piani di taglio del cilindro ellittico superiore e inferiore vector vEllipCylCutPlanesVecSup ; vector vEllipCylCutPlanesVecInf ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con sfera in posizione iniziale int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con sfera in posizione finale nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico superiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, false, vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico inferiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, true, vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } else if ( abs( dAxDispDot) >= dCosInf) { // Aggiorno il vettore dei piani di taglio della sfera in posizione iniziale. vSphereCutPlanesVecSt.emplace_back() ; vSphereCutPlanesVecSt.back().Set( ptS, bOuterCutter ? - vtDispVers : vtDispVers) ; // Aggiorno il vettore dei piani di taglio della sfera in posizione finale. vSphereCutPlanesVecEn.emplace_back() ; vSphereCutPlanesVecEn.back().Set( ptE, bOuterCutter ? - vtDispVers : vtDispVers) ; // Versore della componente del moto perpendicolare all'asse Vector3d vtOrtDispVers = vtDisp - dDispLen * dAxDispDot * vtAx ; double dOrtDispLen = vtOrtDispVers.Len() ; vtOrtDispVers /= dOrtDispLen ; // Vettore dei piani di taglio del cilindro ellittico superiore Vector3d vtPlaneN = - dDispLen * dAxDispDot * vtOrtDispVers + dOrtDispLen * vtAx ; vtPlaneN.Normalize() ; if ( bOuterCutter != dAxDispDot > 0) vtPlaneN *= - 1 ; double dC = vtDispVers * vtAx ; double dS = sqrt( max( 1 - dC * dC, 0.)) ; Point3d ptPlaneP = ptS - dSupH * vtAx + ( dC * dSupH / dS) * vtOrtDispVers ; vector vEllipCylCutPlanesVecSup ; vEllipCylCutPlanesVecSup.emplace_back() ; vEllipCylCutPlanesVecSup.back().Set( ptPlaneP, vtPlaneN) ; // Vettore dei piani di taglio del cilindro ellittico inferiore vector vEllipCylCutPlanesVecInf ; // Vettore dei piani di taglio del cilindro vector vCylCutPlanesVec ; vCylCutPlanesVec.emplace_back() ; vCylCutPlanesVec.back().Set( ptPlaneP, bOuterCutter == dAxDispDot > 0 ? vtPlaneN : - vtPlaneN) ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con sfera in posizione iniziale int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con sfera in posizione finale nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico superiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, bOuterCutter == dAxDispDot > 0, vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico inferiore, se necessario if ( bOuterCutter != dAxDispDot > 0) { nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, true, vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } } // Intersezione con cilindro esterno nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, - vtDispVers, dRad, dDispLen, false, vCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } else { // Aggiorno il vettore dei piani di taglio della sfera in posizione iniziale. vSphereCutPlanesVecSt.emplace_back() ; vSphereCutPlanesVecSt.back().Set( ptS, bOuterCutter ? - vtDispVers : vtDispVers) ; // Aggiorno il vettore dei piani di taglio della sfera in posizione finale. vSphereCutPlanesVecEn.emplace_back() ; vSphereCutPlanesVecEn.back().Set( ptE, bOuterCutter ? - vtDispVers : vtDispVers) ; // Versore della componente del moto perpendicolare all'asse Vector3d vtOrtDispVers = vtDisp - dDispLen * dAxDispDot * vtAx ; double dOrtDispLen = vtOrtDispVers.Len() ; vtOrtDispVers /= dOrtDispLen ; // Determinazione dei piani di taglio dei cilindri ellittici Vector3d vtPlaneN = - dDispLen * dAxDispDot * vtOrtDispVers + dOrtDispLen * vtAx ; vtPlaneN.Normalize() ; if ( bOuterCutter != dAxDispDot > 0) vtPlaneN *= - 1 ; double dC = vtDispVers * vtAx ; double dS = sqrt( max( 1 - dC * dC, 0.)) ; Point3d ptPlaneSupP = ptS - dSupH * vtAx + ( dC * dSupH / dS) * vtOrtDispVers ; Point3d ptPlaneInfP = ptS - dInfH * vtAx + ( dC * dInfH / dS) * vtOrtDispVers ; // Vettore dei piani di taglio del cilindro ellittico superiore vector vEllipCylCutPlanesVecSup ; vEllipCylCutPlanesVecSup.emplace_back() ; vEllipCylCutPlanesVecSup.back().Set( ptPlaneSupP, vtPlaneN) ; // Vettore dei piani di taglio del cilindro ellittico inferiore vector vEllipCylCutPlanesVecInf ; vEllipCylCutPlanesVecInf.emplace_back() ; vEllipCylCutPlanesVecInf.back().Set( ptPlaneInfP, vtPlaneN) ; // Vettore dei piani di taglio del cilindro vector vCylCutPlanesVec ; vCylCutPlanesVec.emplace_back() ; vCylCutPlanesVec.back().Set( ptPlaneSupP, bOuterCutter == dAxDispDot > 0 ? vtPlaneN : - vtPlaneN) ; vCylCutPlanesVec.emplace_back() ; vCylCutPlanesVec.back().Set( ptPlaneInfP, bOuterCutter == dAxDispDot > 0 ? - vtPlaneN : vtPlaneN) ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con sfera in posizione iniziale int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con sfera in posizione finale nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } //// Se il movimento non � ortogonale all'asse interseco con i cilindri ellittici. //double dObCoef = dDispLen * dAxDispDot / dOrtDispLen ; //double dMyLengthSup = dObCoef * dSupRad / sqrt( 1 + dObCoef * dObCoef) ; //double dMyLengthInf = dObCoef * dInfRad / sqrt( 1 + dObCoef * dObCoef) ; //if ( abs( dDispLen * dAxDispDot) > EPS_SMALL && min( dMyLengthSup, dMyLengthInf) > 2 * EPS_SMALL) { // // Intersezione con cilindro ellittico superiore // nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, bOuterCutter == dAxDispDot > 0, // vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ; // if ( nIntNum >= 1) { // vParAndNormIntersVec.emplace_back() ; // vParAndNormIntersVec.back().first = ptInt1.z ; // vParAndNormIntersVec.back().second = vtN1 ; // if ( nIntNum == 2) { // vParAndNormIntersVec.emplace_back() ; // vParAndNormIntersVec.back().first = ptInt2.z ; // vParAndNormIntersVec.back().second = vtN2 ; // } // } // // // Intersezione con cilindro ellittico inferiore // nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, bOuterCutter != dAxDispDot > 0, // vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ; // if ( nIntNum >= 1) { // vParAndNormIntersVec.emplace_back() ; // vParAndNormIntersVec.back().first = ptInt1.z ; // vParAndNormIntersVec.back().second = vtN1 ; // if ( nIntNum == 2) { // vParAndNormIntersVec.emplace_back() ; // vParAndNormIntersVec.back().first = ptInt2.z ; // vParAndNormIntersVec.back().second = vtN2 ; // } // } //} //// Altrimenti interseco con le lingue di gatto. //else { // Point3d ptMyE = ptS + dOrtDispLen * vtOrtDispVers ; // // Intersezione con lingua la gatto superiore // nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dSupH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dSupH * vtAx, // vtAx, dSupRad, ptInt1, vtN1) ; // if ( nIntNum == 1) { // vParAndNormIntersVec.emplace_back() ; // vParAndNormIntersVec.back().first = ptInt1.z ; // vParAndNormIntersVec.back().second = vtN1 ; // } // // Intersezione con la lingua di gatto inferiore // nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dInfH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dInfH * vtAx, // - vtAx, dInfRad, ptInt1, vtN1) ; // if ( nIntNum == 1) { // vParAndNormIntersVec.emplace_back() ; // vParAndNormIntersVec.back().first = ptInt1.z ; // vParAndNormIntersVec.back().second = vtN1 ; // } //} // Se il movimento � ortogonale all'asse interseco con le lingue di gatto. double dObCoef = dDispLen * dAxDispDot / dOrtDispLen ; double dMyLengthSup = dObCoef * dSupRad / sqrt( 1 + dObCoef * dObCoef) ; double dMyLengthInf = dObCoef * dInfRad / sqrt( 1 + dObCoef * dObCoef) ; if ( abs( dDispLen * dAxDispDot) < 2 * EPS_SMALL && min( dMyLengthSup, dMyLengthInf) < 2 * EPS_SMALL) { Point3d ptMyE = ptS + dOrtDispLen * vtOrtDispVers ; // Intersezione con lingua la gatto superiore nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dSupH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dSupH * vtAx, vtAx, dSupRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } // Intersezione con la lingua di gatto inferiore nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dInfH * vtAx, ( bOuterCutter ? ptMyE : ptS) - dInfH * vtAx, - vtAx, dInfRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } } // Altrimenti interseco con i cilindri ellittici. else { // Intersezione con cilindro ellittico superiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dSupH * vtAx, vtAx, dSupRad, vtDisp, bOuterCutter == dAxDispDot > 0, vEllipCylCutPlanesVecSup, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico inferiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dInfH * vtAx, vtAx, dInfRad, vtDisp, bOuterCutter != dAxDispDot > 0, vEllipCylCutPlanesVecInf, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } } // Intersezione con cilindro esterno nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, - vtDispVers, dRad, dDispLen, false, vCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } return true ; } // Calotta sferica //---------------------------------------------------------------------------- bool VolZmap::SurfSphericalShell_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dRad, double dHei, bool bOuterCutter) { // Verifico interferisca int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, V_NULL, dRad, 0, 0, nStartI, nStartJ, nEndI, nEndJ)) return true ; // Vettore spostamento Vector3d vtDisp = ptE - ptS ; Vector3d vtDispVers = vtDisp ; double dDispLen = vtDispVers.Len() ; vtDispVers /= dDispLen ; // Prodotto scalare fra versore del movimento e asse della calotta sferica double dAxDispDot = vtDispVers * vtAx ; // Raggio del cilindro ellittico double dBaseRad = sqrt( max( dRad * dRad - dHei * dHei, 0.)) ; // Coseni limite double dCosLim = dBaseRad / dRad ; // Vettore dei piani di taglio della sfera in posizione iniziale vector vSphereCutPlanesVecSt ; vSphereCutPlanesVecSt.emplace_back() ; vSphereCutPlanesVecSt.back().Set( ptS - dHei * vtAx, vtAx) ; // Vettore dei piani di taglio della sfera in posizione finale vector vSphereCutPlanesVecEn ; vSphereCutPlanesVecEn.emplace_back() ; vSphereCutPlanesVecEn.back().Set( ptE - dHei * vtAx, vtAx) ; if ( abs( dAxDispDot) > dCosLim - EPS_ZERO) { if ( bOuterCutter == dAxDispDot > 0) return true ; // Vettore dei piani di taglio del cilindro ellittico vector vEllipCylCutPlanesVec ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con sfera in posizione iniziale int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con sfera in posizione finale nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con cilindro ellittico superiore nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dBaseRad, vtDisp, false, vEllipCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } else { // Aggiorno il vettore dei piani di taglio della sfera in posizione iniziale. vSphereCutPlanesVecSt.emplace_back() ; vSphereCutPlanesVecSt.back().Set( ptS, bOuterCutter ? - vtDispVers : vtDispVers) ; // Aggiorno il vettore dei piani di taglio della sfera in posizione finale. vSphereCutPlanesVecEn.emplace_back() ; vSphereCutPlanesVecEn.back().Set( ptE, bOuterCutter ? - vtDispVers : vtDispVers) ; // Versore della componente del moto perpendicolare all'asse Vector3d vtOrtDispVers = vtDisp - dDispLen * dAxDispDot * vtAx ; double dOrtDispLen = vtOrtDispVers.Len() ; vtOrtDispVers /= dOrtDispLen ; // Vettore dei piani di taglio del cilindro ellittico superiore Vector3d vtPlaneN = - dDispLen * dAxDispDot * vtOrtDispVers + dOrtDispLen * vtAx ; vtPlaneN.Normalize() ; if ( bOuterCutter != dAxDispDot > 0) vtPlaneN *= - 1 ; double dC = vtDispVers * vtAx ; double dS = sqrt( max( 1 - dC * dC, 0.)) ; Point3d ptPlaneP = ptS - dHei * vtAx + ( dC * dHei / dS) * vtOrtDispVers ; vector vEllipCylCutPlanesVec ; vEllipCylCutPlanesVec.emplace_back() ; vEllipCylCutPlanesVec.back().Set( ptPlaneP, vtPlaneN) ; // Vettore dei piani di taglio del cilindro vector vCylCutPlanesVec ; vCylCutPlanesVec.emplace_back() ; vCylCutPlanesVec.back().Set( ptPlaneP, bOuterCutter == dAxDispDot > 0 ? vtPlaneN : - vtPlaneN) ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ; DexelSurfIntersVector vParAndNormIntersVec ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; // Intersezione con sfera in posizione iniziale int nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptS, dRad, bOuterCutter, vSphereCutPlanesVecSt, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con sfera in posizione finale nIntNum = IntersLineSphereCuttedByPlanes( ptC, Z_AX, ptE, dRad, ! bOuterCutter, vSphereCutPlanesVecEn, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Intersezione con lingua di gatto se il movimento � perpendicolare all'asse di simmetria double dObCoef = dDispLen * dAxDispDot / dOrtDispLen ; double dMyLength = dObCoef * dRad / sqrt( 1 + dObCoef * dObCoef) ; if ( abs( dDispLen * dAxDispDot) < 2 * EPS_SMALL && dMyLength < 2 * EPS_SMALL) { Point3d ptMyE = ptS + dOrtDispLen * vtOrtDispVers ; nIntNum = IntersLineCatTongue( ptC, Z_AX, ( bOuterCutter ? ptS : ptMyE) - dHei * vtAx, ( bOuterCutter ? ptMyE : ptS) - dHei * vtAx, vtAx, dBaseRad, ptInt1, vtN1) ; if ( nIntNum == 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; } } // Intersezione con cilindro ellittico se il movimento � generico else { nIntNum = IntersLineCircSweptSurfCuttedByPlanes( ptC, Z_AX, ptS - dHei * vtAx, vtAx, dBaseRad, vtDisp, bOuterCutter == dAxDispDot > 0, vEllipCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } } // Intersezione con cilindro esterno nIntNum = IntersLineCylinderCuttedByPlanes( ptC, Z_AX, ptE, - vtDispVers, dRad, dDispLen, false, vCylCutPlanesVec, ptInt1, vtN1, ptInt2, vtN2) ; if ( nIntNum >= 1) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt1.z ; vParAndNormIntersVec.back().second = vtN1 ; if ( nIntNum == 2) { vParAndNormIntersVec.emplace_back() ; vParAndNormIntersVec.back().first = ptInt2.z ; vParAndNormIntersVec.back().second = vtN2 ; } } // Filtro le intersezioni trovate. DexelSurfIntersVector vFilteredIntersVec ; IntersectionsFilter( Z_AX, vParAndNormIntersVec, vFilteredIntersVec) ; // Sottraggo gli intervalli. for ( int n = 0 ; n < int( vFilteredIntersVec.size()) ; n += 2) { SubtractIntervals( nGrid, i, j, vFilteredIntersVec[n].first, vFilteredIntersVec[n+1].first, vFilteredIntersVec[n].second, vFilteredIntersVec[n+1].second) ; } } } } return true ; } // ------------------------- Utensili additivi --------------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool VolZmap::AddingMotion( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx/*, double dHei, double dRad, double dCornerRad*/) { // Dimensioni lineari dell'utensile double dHei = m_vTool[m_nCurrTool].GetHeigth() ; double dRad = m_vTool[m_nCurrTool].GetRadius() ; double dCornerRad = m_vTool[m_nCurrTool].GetCornRadius() ; // Verifica sull'interferenza utensile Zmap int nStartI, nStartJ, nEndI, nEndJ ; if ( ! TestCompoBBox( nGrid, ptS, ptE, vtAx, dRad, dRad, dHei, nStartI, nStartJ, nEndI, nEndJ)) return true ; Vector3d vtV1 = ptE - ptS ; double dLen1 = vtV1.Len() ; vtV1 / dLen1 ; Vector3d vtV2 = Z_AX ^ vtV1 ; if ( dCornerRad < EPS_SMALL) { if ( nGrid == 0) { for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Vector3d vtStC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ; Vector3d vtEnC = vtStC - dLen1 * vtV1 ; double dX1 = vtStC * vtV1 ; double dX2 = vtStC * vtV2 ; if ( ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dRad) || vtStC.SqLen() < dRad * dRad || vtEnC.SqLen() < dRad * dRad) { AddIntervals( nGrid, i, j, ptS.z - dHei, ptS.z, - Z_AX, Z_AX) ; } } } } else { Frame3d CylFrame, PolyFrame ; CylFrame.Set( ptS - dHei * vtAx, vtAx) ; PolyFrame.Set( ptS - dHei * vtAx, vtV1, vtAx ^ vtV1, vtAx) ; for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Point3d ptC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ; Point3d ptInt1, ptInt2 ; Vector3d vtN1, vtN2 ; if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true, ptInt1, vtN1, ptInt2, vtN2)) { AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2) ; } if ( IntersLineMyPolyhedron( ptC - dLen1 * vtV1, Z_AX, PolyFrame, dLen1, dRad, dHei, 0, ptInt1, vtN1, ptInt2, vtN2)) { AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2) ; } } } } } else { ; } return true ; /* if ( nGrid == 0) { Vector3d vtV1 = ptE - ptS ; double dLen1 = vtV1.Len() ; vtV1 / dLen1 ; Vector3d vtV2 = Z_AX ^ vtV1 ; double dSqareCornerRadProj = dCornerRad * dCornerRad - 0.25 * dHei * dHei ; if ( dSqareCornerRadProj > 0) { double dCylRad = dRad - dCornerRad + sqrt( dSquareCornerRadProj) ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Vector3d vtStC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ; Vector3d vtEnC = vtStC - dLen1 * vtV1 ; double dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; if ( ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dCylRad) || vtStC.SqLen() < dCylRad * dCylRad || vtEnC.SqLen() < dCylRad * dCylRad) { AddIntervals( nGrid, i, j, ptS.z - dHei, ptS.z, Z_AX, - Z_AX) ; } else if ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dRad) { double dr = dCornerRad - ( dRad - abs( dX2)) ; double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ; Vector3d vtMinN = ( dX2 > 0 ? - dr : dr) * vtV2 + Vector3d( 0, 0, dDeltaH) ; Vector3d vtMaxN = ( dX2 > 0 ? - dr : dr) * vtV2 - Vector3d( 0, 0, dDeltaH) ; vtMinN.Normalize() ; vtMaxN.Normalize() ; AddIntervals( nGrid, i, j, ptS.z - 0.5 * dHei - dDeltaH, ptS.z - 0.5 * dHei + dDeltaH, vtMinN, vtMaxN) ; } else if ( vtStC.SqLen() < dRad * dRad || vtEnC.SqLen() < dRad * dRad) { Vector3d vtR = dX1 > 0 ? vtEnC : vtStC ; double dLenR = vtR.Len() ; vtR /= dLenR ; double dr = dCornerRad - ( dRad - dLenR) ; double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ; Vector3d vtMinN = - dr * vtR + Vector3d( 0, 0, dDeltaH) ; Vector3d vtMaxN = - dr * vtR - Vector3d( 0, 0, dDeltaH) ; vtMinN.Normalize() ; vtMaxN.Normalize() ; AddIntervals( nGrid, i, j, ptS.z - 0.5 * dHei - dDeltaH, ptS.z - 0.5 * dHei + dDeltaH, vtMinN, vtMaxN) ; } } } } else { double dCylRad = dRad - dCornerRad ; // Ciclo sui punti for ( int i = nStartI ; i <= nEndI ; ++ i) { for ( int j = nStartJ ; j <= nEndJ ; ++ j) { Vector3d vtStC( ( i + 0.5) * m_dStep - ptS.x, ( j + 0.5) * m_dStep - ptS.y, 0) ; Vector3d vtEnC = vtStC - dLen1 * vtV1 ; double dX1 = vtC * vtV1 ; double dX2 = vtC * vtV2 ; if ( ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dCylRad) || vtStC.SqLen() < dCylRad * dCylRad || vtEnC.SqLen() < dCylRad * dCylRad) { AddIntervals( nGrid, i, j, ptS.z - dHei, ptS.z, Z_AX, - Z_AX) ; } else if ( dX1 > 0 && dX1 < dLen1 && abs( dX2) < dRad) { double dr = abs( dX2) - dCylRad ; double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ; Vector3d vtMinN = ( dX2 > 0 ? - dr : dr) * vtV2 + Vector3d( 0, 0, dDeltaH) ; Vector3d vtMaxN = ( dX2 > 0 ? - dr : dr) * vtV2 - Vector3d( 0, 0, dDeltaH) ; vtMinN.Normalize() ; vtMaxN.Normalize() ; AddIntervals( nGrid, i, j, ptS.z - dHei + dCornerRad - dDeltaH, ptS.z - dCornerRad + dDeltaH, vtMinN, vtMaxN) ; } else if ( vtStC.SqLen() < dRad * dRad || vtEnC.SqLen() < dRad * dRad) { Vector3d vtR = dX1 > 0 ? vtEnC : vtStC ; double dLenR = vtR.Len() ; vtR /= dLenR ; double dr = dLenR - dCylRad) ; double dDeltaH = sqrt( max( dCornerRad * dCornerRad - dr * dr, 0)) ; Vector3d vtMinN = - dr * vtR + Vector3d( 0, 0, dDeltaH) ; Vector3d vtMaxN = - dr * vtR - Vector3d( 0, 0, dDeltaH) ; vtMinN.Normalize() ; vtMaxN.Normalize() ; AddIntervals( nGrid, i, j, ptS.z - dHei + dCornerRad - dDeltaH, ptS.z - dCornerRad + dDeltaH, vtMinN, vtMaxN) ; } } } } } else { ; } */ } // ------------------------- BOUNDING BOX -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- inline BBox3d GetCylMoveBBox( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, double dRad, double dH) { // Determinazione delle posizioni della punta del componente nelle posizioni iniziale e finale Point3d ptP1T = ptP1 - dH * vtV ; Point3d ptP2T = ptP2 - dH * vtV ; // Calcolo del box del movimento dell'asse BBox3d b3Box ; b3Box.Add( ptP1) ; b3Box.Add( ptP1T) ; b3Box.Add( ptP2) ; b3Box.Add( ptP2T) ; // Aggiungo ingombro raggio if ( AreSameOrOppositeVectorApprox( vtV, X_AX)) b3Box.Expand( 0, dRad, dRad) ; else if ( AreSameOrOppositeVectorApprox( vtV, Y_AX)) b3Box.Expand( dRad, 0, dRad) ; else if ( AreSameOrOppositeVectorApprox( vtV, Z_AX)) b3Box.Expand( dRad, dRad, 0) ; else { double dExpandX = dRad * sqrt( 1 - vtV.x * vtV.x) ; double dExpandY = dRad * sqrt( 1 - vtV.y * vtV.y) ; double dExpandZ = dRad * sqrt( 1 - vtV.z * vtV.z) ; b3Box.Expand( dExpandX, dExpandY, dExpandZ) ; } // Restituisco il box calcolato return b3Box ; } //---------------------------------------------------------------------------- inline BBox3d GetSphereMoveBBox( const Point3d& ptP1, const Point3d& ptP2, double dRad) { // Calcolo del box del movimento del centro BBox3d b3Box ; b3Box.Add( ptP1) ; b3Box.Add( ptP2) ; // Aggiungo ingombro raggio b3Box.Expand( dRad) ; // Restituisco il box calcolato return b3Box ; } //---------------------------------------------------------------------------- inline bool VolZmap::TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, int& nStI, int& nStJ, int& nEnI, int& nEnJ) { return TestCompoBBox( nGrid, ptP1, ptP2, vtV, m_vTool[m_nCurrTool].GetRadius(), m_vTool[m_nCurrTool].GetTipRadius(), m_vTool[m_nCurrTool].GetHeigth(), nStI, nStJ, nEnI, nEnJ) ; } //---------------------------------------------------------------------------- inline bool VolZmap::TestCompoBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, double dRad, double dTipRad, double dHei, int& nStI, int& nStJ, int& nEnI, 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 ; // BBox dello Zmap BBox3d b3Zmap( 0, 0, m_dMinZ[nGrid], m_nNx[nGrid] * m_dStep, m_nNy[nGrid] * m_dStep, m_dMaxZ[nGrid]) ; // BBox dell'utensile nel suo movimento double dMaxRad = max( dRad, dTipRad) ; BBox3d b3Box = ( vtV.IsSmall() ? GetSphereMoveBBox( ptP1, ptP2, dRad) : GetCylMoveBBox( ptP1, ptP2, vtV, dMaxRad, dHei)) ; // Verifica dell'interferenza dell'utensile con lo Zmap if ( ! b3Zmap.FindIntersection( b3Box, b3Box)) return false ; // Limiti su indici nStI = max( 0, int( b3Box.GetMin().x / m_dStep)) ; nEnI = min( m_nNx[nGrid] - 1, int( b3Box.GetMax().x / m_dStep)) ; nStJ = max( 0, int( b3Box.GetMin().y / m_dStep)) ; nEnJ = min( m_nNy[nGrid] - 1, int( b3Box.GetMax().y / m_dStep)) ; return true ; } //---------------------------------------------------------------------------- inline bool VolZmap::TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA, double dLenX, double dLenY, double dLenZ, int& nStI, int& nStJ, int& nEnI, 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 dSemiDiag = sqrt( dLenX * dLenX + dLenY * dLenY) / 2 ; // Determinazione dei limiti del pi� piccolo parallelepipedo contenente il movimento double dMinX = min( min( ptS.x, ptSTip.x), min( ptE.x, ptETip.x)) - dSemiDiag ; double dMinY = min( min( ptS.y, ptSTip.y), min( ptE.y, ptETip.y)) - dSemiDiag ; double dMinZ = min( min( ptS.z, ptSTip.z), min( ptE.z, ptETip.z)) - dSemiDiag ; double dMaxX = max( max( ptS.x, ptSTip.x), max( ptE.x, ptETip.x)) + dSemiDiag ; double dMaxY = max( max( ptS.y, ptSTip.y), max( ptE.y, ptETip.y)) + dSemiDiag ; double dMaxZ = max( max( ptS.z, ptSTip.z), max( ptE.z, ptETip.z)) + dSemiDiag ; int nMaxNx = m_nNx[nGrid] ; 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 ; }