//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 // Contenuto : Implementazione della classe Volume Zmap (tre griglie) // // // // Modifiche : 22.01.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" #include "VolZmap.h" #include "GeoConst.h" #include "IntersLineSurfTm.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkIntersLineTria.h" using namespace std ; //---------------------------------------------------------------------------- bool VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax) const { // Il box è allineato agli assi double dU1, dU2 ; return IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) const { // Il box è allineato agli assi dU1 = - INFINITO ; dU2 = INFINITO ; // confronto con piani YZ (perpendicolari ad asse X) if ( vtV.x > EPS_ZERO) { dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ; dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ; } else if ( vtV.x < - EPS_ZERO) { dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ; dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ; } else if ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL) return false ; // confronto con piani ZX (perpendicolari ad asse Y) if ( vtV.y > EPS_ZERO) { dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ; dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ; } else if ( vtV.y < - EPS_ZERO) { dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ; dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ; } else if ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL) return false ; // confronto con piani XY (perpendicolari ad asse Z) if ( vtV.z > EPS_ZERO) { dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ; dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ; } else if ( vtV.z < - EPS_ZERO) { dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ; dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ; } else if ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL) return false ; return ( dU2 >= dU1) ; } //---------------------------------------------------------------------------- // La retta è rappresentata da un punto e dal versore espressi nel riferimento dello Zmap. // Se non vi è intersezione, viene restituito falso bool VolZmap::IntersLineZMapLattice( const Point3d& ptP, const Vector3d& vtV, double& dU1, double& dU2) const { // Punti estremi della diagonale del box del reticolo Point3d ptMin( - 0.5 * m_dStep, - 0.5 * m_dStep, - 0.5 * m_dStep) ; Point3d ptMax( ( m_nNx[0] + 0.5) * m_dStep, ( m_nNy[0] + 0.5) * m_dStep, ( m_nNy[1] + 0.5) * m_dStep) ; return IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineZMapBBox( const Point3d& ptP, const Vector3d& vtV, unsigned int nGrid, double& dU1, double& dU2) const { // Punti estremi del box dello Zmap Point3d ptMin = ORIG ; Point3d ptMax = ptMin + Vector3d( m_nNx[nGrid] * m_dStep, m_nNy[nGrid] * m_dStep, m_dMaxZ[nGrid]) ; return IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineDexel( const Point3d& ptP, const Vector3d& vtV, unsigned int nGrid, unsigned int nI, unsigned int nJ, double& dU1, double& dU2) const { // Determino l'indice del dexel e il numero di suoi intervalli unsigned int nDexelPos = nJ * m_nNx[nGrid] + nI ; unsigned int nDexelSize = unsigned int( m_Values[nGrid][nDexelPos].size()) ; // Se non c'è materiale non devo fare alcunché if ( nDexelSize == 0) return false ; // Determino estremi nel piano XY intrinseco del dexel double dXmin = nI * m_dStep ; double dYmin = nJ * m_dStep ; double dXmax = ( nI + 1) * m_dStep ; double dYmax = ( nJ + 1) * m_dStep ; // ciclo sugli intervalli dU1 = INFINITO ; dU2 = - INFINITO ; bool bInters = false ; for ( unsigned int nIndex = 0 ; nIndex < nDexelSize ; nIndex += 1) { // estremi del box del singolo intervallo Point3d ptE1( dXmin, dYmin, m_Values[nGrid][nDexelPos][nIndex].dMin) ; Point3d ptE2( dXmax, dYmax, m_Values[nGrid][nDexelPos][nIndex].dMax) ; double dP1, dP2 ; if ( IntersLineBox( ptP, vtV, ptE1, ptE2, dP1, dP2)) { bInters = true ; dU1 = min( dU1, dP1) ; dU2 = max( dU2, dP2) ; } } return bInters ; } //---------------------------------------------------------------------------- bool VolZmap::IntersRayDexel( const Point3d& ptP, const Vector3d& vtV, unsigned int nGrid, unsigned int nI, unsigned int nJ, double& dU1, double& dU2) const { // Determino l'indice del dexel e il numero di suoi intervalli unsigned int nDexelPos = nJ * m_nNx[nGrid] + nI ; unsigned int nDexelSize = unsigned int( m_Values[nGrid][nDexelPos].size()) ; // Se non c'è materiale non devo fare alcunché if ( nDexelSize == 0) return false ; // Determino estremi nel piano XY intrinseco del dexel double dXmin = nI * m_dStep ; double dYmin = nJ * m_dStep ; double dXmax = ( nI + 1) * m_dStep ; double dYmax = ( nJ + 1) * m_dStep ; // ciclo sugli intervalli dU1 = INFINITO ; dU2 = - INFINITO ; bool bInters = false ; for ( unsigned int nIndex = 0 ; nIndex < nDexelSize ; nIndex += 1) { // estremi del box del singolo intervallo Point3d ptE1( dXmin, dYmin, m_Values[nGrid][nDexelPos][nIndex].dMin) ; Point3d ptE2( dXmax, dYmax, m_Values[nGrid][nDexelPos][nIndex].dMax) ; double dP1, dP2 ; if ( IntersLineBox( ptP, vtV, ptE1, ptE2, dP1, dP2)) { if ( dP2 >= 0) { bInters = true ; if ( dP1 >= 0) dU1 = min( dU1, dP1) ; else dU1 = - 1 ; dU2 = max( dU2, dP2) ; } } } return bInters ; } //---------------------------------------------------------------------------- // Calcola la profondità del materiale lungo un raggio, identificato da un punto e un versoreore. // Punto e versore devono essere espressi nel sistema di riferimento locale, in cui è immerso quello dello Zmap. // InLength = distanza di ingresso (se -1 il punto è interno, se -2 il punto è esterno e il raggio non interseca lo Zmap) // OutLength = distanza di uscita bool VolZmap::GetDepth( const Point3d& ptPLoc, const Vector3d& vtDLoc, double& dInLength, double& dOutLength, bool bExact) const { Point3d ptP = ptPLoc ; Vector3d vtD = vtDLoc ; ptP.ToLoc( m_MapFrame[0]) ; vtD.ToLoc( m_MapFrame[0]) ; if ( bExact) return GetDepthWithVoxel( ptP, vtD, dInLength, dOutLength, true) ; else return GetDepthWithDexel( ptP, vtD, dInLength, dOutLength) ; } //---------------------------------------------------------------------------- // Calcola la profondità del materiale usando i parallelepipedi corrispondenti ai segmenti di dexel di una griglia. // Punto e versore devono essere espressi nel sistema di riferimento Zmap. Il vettore deve essere normalizzato. // InLength = distanza di ingresso (se -1 il punto è interno, se -2 il punto è esterno e il raggio non interseca lo Zmap) // OutLength = distanza di uscita bool VolZmap::GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtV, double& dInLength, double& dOutLength) const { int nGrid = 0 ; // Intersezione fra semiretta e BBox dello Zmap double dU1, dU2 ; bool bTest = IntersLineZMapBBox( ptP, vtV, nGrid, dU1, dU2) && ( dU1 > 0 || dU2 > 0) ; // Semiretta esterna al box dello Zmap quindi esterna anche allo Zmap if ( ! bTest) { dInLength = - 2 ; dOutLength = - 2 ; return true ; } Point3d ptI, ptF ; // Una sola intersezione valida ( punto interno, intersezione valida 2) if ( dU1 < 0 && dU2 > 0) { ptI = ptP ; ptF = ptP + dU2 * vtV ; } // due soluzioni valide ( punto esterno) else { ptI = ptP + dU1 * vtV ; ptF = ptP + dU2 * vtV ; } // Inizializzo distanze dInLength = INFINITO ; dOutLength = - INFINITO ; // Determino asse di spostamento maggiore bool bOnX = ( abs( ptF.y - ptI.y) <= abs( ptF.x - ptI.x)) ; // Movimento crescente su asse di movimento principale if ( ( bOnX && ptF.x < ptI.x) || ( ! bOnX && ptF.y < ptI.y) ) swap( ptI, ptF) ; // Pendenza double dDeltaX = ( ptF.x - ptI.x) ; double dDeltaY = ( ptF.y - ptI.y) ; double dM = 0 ; if ( bOnX && abs( dDeltaX) > EPS_SMALL) dM = dDeltaY / dDeltaX ; else if ( ! bOnX && abs( dDeltaY) > EPS_SMALL) dM = dDeltaX / dDeltaY ; // Determinazione degli indici i j dei punti ptI e ptF int nIi = Clamp( int( floor( ptI.x / m_dStep)), 0, m_nNx[nGrid] - 1) ; int nIj = Clamp( int( floor( ptI.y / m_dStep)), 0, m_nNy[nGrid] - 1) ; int nFi = Clamp( int( floor( ptF.x / m_dStep)), 0, m_nNx[nGrid] - 1) ; int nFj = Clamp( int( floor( ptF.y / m_dStep)), 0, m_nNy[nGrid] - 1) ; // mi muovo int i = nIi ; int j = nIj ; while ( ( bOnX && i <= nFi) || ( ! bOnX && j <= nFj)) { // Eseguo controllo double dU1, dU2 ; if ( IntersRayDexel( ptP, vtV, nGrid, i, j, dU1, dU2)) { dInLength = min( dInLength, dU1) ; dOutLength = max( dOutLength, dU2) ; } // Calcolo spostamento (a destra o sopra) if ( bOnX) { double dMoveX = ( ( i + 1) * m_dStep - ptI.x) ; double dMoveY = dMoveX * dM ; double dY = ptI.y + dMoveY ; int nNewJ = Clamp( int( floor( dY / m_dStep)), 0, m_nNy[nGrid] - 1) ; if ( nNewJ != j) j = nNewJ ; else ++ i ; } else { double dMoveY = ( ( j + 1) * m_dStep - ptI.y) ; double dMoveX = dMoveY * dM ; double dX = ptI.x + dMoveX ; int nNewI = Clamp( int( floor( dX / m_dStep)), 0, m_nNx[nGrid] - 1) ; if ( nNewI != i) i = nNewI ; else ++ j ; } } // Se non abbiamo incontrato materiale if ( dInLength > dOutLength - EPS_SMALL) { dInLength = - 2 ; dOutLength = - 2 ; return true ; } // Se parto dall'interno if ( dInLength < - EPS_SMALL) dInLength = - 1 ; return true ; } //---------------------------------------------------------------------------- // Calcola la profondità del materiale usando i triangoli della rappresentazione grafica. // Punto e versore devono essere espressi nel sistema di riferimento Zmap. // Se si vuole che vengano utilizzati i triangoli con sharp-featue bEnh deve valere true, false altrimenti. // InLength = distanza di ingresso (se -1 il punto è interno, se -2 il punto è esterno e il raggio non interseca lo Zmap) // OutLength = distanza di uscita. bool VolZmap::GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bEnh) const { // Parametri di intersezione retta BBox dello Zmap double dU1, dU2 ; // Intersezione fra semiretta e BBox dello Zmap bool bLineBBoxInters = IntersLineZMapBBox( ptP, vtD, 0, dU1, dU2) && ( dU1 > 0 || dU2 > 0) ; // Semiretta esterna al box dello Zmap quindi esterna anche allo Zmap if ( ! bLineBBoxInters) { dInLength = - 2 ; dOutLength = - 2 ; return true ; } // Indici del voxel corrente int nVoxI, nVoxJ, nVoxK ; // Determino il voxel di partenza if ( ! GetPointVoxel( ptP, nVoxI, nVoxJ, nVoxK)) { if ( ! GetPointVoxel( ptP + dU1 * vtD, nVoxI, nVoxJ, nVoxK)) return false ; } // Vettore di voxel vector vVox ; // Incrementi degli indici per sguire la retta int nDeltaI = ( vtD.x > 0 ? 1 : ( vtD.x < 0 ? - 1 : 0)) ; int nDeltaJ = ( vtD.y > 0 ? 1 : ( vtD.y < 0 ? - 1 : 0)) ; int nDeltaK = ( vtD.z > 0 ? 1 : ( vtD.z < 0 ? - 1 : 0)) ; // Scelgo i piani del voxel con cui intersecare la retta, // per determinare il voxel successivo int nPlaneI = ( vtD.x >= 0 ? 1 : 0) ; int nPlaneJ = ( vtD.y >= 0 ? 1 : 0) ; int nPlaneK = ( vtD.z >= 0 ? 1 : 0) ; // Ciclo sui voxel while ( IsValidVoxel( nVoxI, nVoxJ, nVoxK)) { // Estremi della diagonale del voxel corrente Point3d ptMin( ( nVoxI * N_DEXVOXRATIO + 0.5) * m_dStep, ( nVoxJ * N_DEXVOXRATIO + 0.5) * m_dStep, ( nVoxK * N_DEXVOXRATIO + 0.5) * m_dStep) ; Point3d ptMax( ( ( nVoxI + 1) * N_DEXVOXRATIO + 0.5) * m_dStep, ( ( nVoxJ + 1) * N_DEXVOXRATIO + 0.5) * m_dStep, ( ( nVoxK + 1) * N_DEXVOXRATIO + 0.5) * m_dStep) ; // Studio il voxel corrente if ( IntersLineBox( ptP, vtD, ptMin, ptMax)) { Voxel NewVox ; NewVox.nI = nVoxI ; NewVox.nJ = nVoxJ ; NewVox.nK = nVoxK ; vVox.emplace_back( NewVox) ; } // Interseco la retta con i piani frontiera del voxel double dMaxTX = ( abs( vtD.x) > EPS_ZERO ? abs( ( ( ( nVoxI + nPlaneI) * N_DEXVOXRATIO + 0.5) * m_dStep - ptP.x) / vtD.x) : INFINITO) ; double dMaxTY = ( abs( vtD.y) > EPS_ZERO ? abs( ( ( ( nVoxJ + nPlaneJ) * N_DEXVOXRATIO + 0.5) * m_dStep - ptP.y) / vtD.y) : INFINITO) ; double dMaxTZ = ( abs( vtD.z) > EPS_ZERO ? abs( ( ( ( nVoxK + nPlaneK) * N_DEXVOXRATIO + 0.5) * m_dStep - ptP.z) / vtD.z) : INFINITO) ; if ( dMaxTX < dMaxTY) { if ( dMaxTX < dMaxTZ) nVoxI += nDeltaI ; else nVoxK += nDeltaK ; } else { if ( dMaxTY < dMaxTZ) nVoxJ += nDeltaJ ; else nVoxK += nDeltaK ; } } TRIA3DLIST lstTria ; ExtMarchingCubes( vVox, lstTria, bEnh) ; // Struttura studio dell'intersezione struct LineTriaInt { double dPar ; double dDot ; } ; vector> IntMatrix ; // Ciclo sui triangoli del voxel for ( auto it = lstTria.begin() ; it != lstTria.end() ; ++it ) { // Triangolo corrente e suoi punti di intersezione con la retta Triangle3d CurrTria = *it ; Point3d ptLineTria1, ptLineTria2 ; // Studio dell'intersezione della retta con il triangolo corrente int nIntType = IntersLineTria( ptP, vtD, 1.5 * dU2, CurrTria, ptLineTria1, ptLineTria2) ; // Se non ci sono intersezioni passo al prossimo triangolo if ( nIntType == ILTT_NO) continue ; // se altrimenti c'è una sola intersezione else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) { LineTriaInt NewInt ; NewInt.dPar = ( ptLineTria1 - ptP) * vtD ; NewInt.dDot = vtD * CurrTria.GetN() ; vector vSing ; vSing.emplace_back( NewInt) ; IntMatrix.emplace_back( vSing) ; } // altrimenti ci sono due intersezioni else { LineTriaInt NewInt1, NewInt2 ; vector vCouple ; double dP1 = ( ptLineTria1 - ptP) * vtD ; double dP2 = ( ptLineTria2 - ptP) * vtD ; NewInt1.dPar = ( dP1 < dP2 ? dP1 : dP2) ; NewInt2.dPar = ( dP1 < dP2 ? dP2 : dP1) ; NewInt1.dDot = vtD * CurrTria.GetN() ; NewInt2.dDot = NewInt1.dDot ; vCouple.emplace_back( NewInt1) ; vCouple.emplace_back( NewInt2) ; IntMatrix.emplace_back( vCouple) ; } } // Ordino le intersezioni in base al parametro distanza con segno da ptP for ( int nN = 0 ; nN < int( IntMatrix.size()) - 1 ; ++ nN) { for ( int nM = nN + 1 ; nM < int( IntMatrix.size()) ; ++ nM) { double dFP = ( IntMatrix[nN].size() == 2 ? 0.5 * ( IntMatrix[nN][0].dPar + IntMatrix[nN][1].dPar) : IntMatrix[nN][0].dPar) ; double dLP = ( IntMatrix[nM].size() == 2 ? 0.5 * ( IntMatrix[nM][0].dPar + IntMatrix[nM][1].dPar) : IntMatrix[nM][0].dPar) ; if ( dFP > dLP) swap( IntMatrix[nN], IntMatrix[nM]) ; } } vector vInt ; for ( int nN = 0 ; nN < int( IntMatrix.size()) ; ++ nN) { vInt.emplace_back( IntMatrix[nN][0]) ; if ( IntMatrix[nN].size() == 2) vInt.emplace_back( IntMatrix[nN][1]) ; } // Inizializzo le distanze di ingresso e uscita: // dInLength diminuisce, dOutLength aumenta. dInLength = INFINITO ; dOutLength = - INFINITO ; int nFirstPosN ; int nN = 0 ; for ( ; nN < int( vInt.size()) ; ++ nN) { if ( /*vInt[nN].dPar >= 0*/vInt[nN].dPar > - EPS_SMALL) { // SCEGLIERE FRA LE DUE OPZIONI nFirstPosN = nN ; break ; } } if ( nN == int( vInt.size())) { dInLength = - 2 ; dOutLength = - 2 ; return true ; } if ( nFirstPosN > 0) { if ( vInt[nFirstPosN - 1].dDot < EPS_ZERO) dInLength = -1 ; } else if ( nFirstPosN == 0) { if ( vInt[nFirstPosN].dDot > EPS_ZERO) // dInLength = -1 ; else if ( GetPointVoxel( ptP, nVoxI, nVoxJ, nVoxK)) { int nCubeType = CalcIndex( nVoxI, nVoxJ, nVoxK) ; if ( nCubeType == 255) dInLength = -1 ; } } for ( int nN = nFirstPosN ; nN < int( vInt.size()) ; ++ nN) { if ( vInt[nN].dDot > - EPS_ZERO && dOutLength < vInt[nN].dPar) dOutLength = vInt[nN].dPar ; if ( vInt[nN].dDot < EPS_ZERO && dInLength > vInt[nN].dPar) dInLength = vInt[nN].dPar ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag) const { // BBox BBox3d b3Box( ORIG, ORIG + vtDiag) ; // lo porto nel riferimento intrinseco dello Zmap b3Box.LocToLoc( frBox, m_MapFrame[0]) ; // BBox dello Zmap nel suo riferimento intrinseco BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ; // Se non interferiscono, posso uscire BBox3d b3Int ; if ( ! b3Zmap.FindIntersection( b3Box, b3Int)) return true ; // Limiti su indici int nStI = Clamp( int( b3Int.GetMin().x / m_dStep), 0, m_nNx[0] -1) ; int nEnI = Clamp( int( b3Int.GetMax().x / m_dStep), 0, m_nNx[0] -1) ; int nStJ = Clamp( int( b3Int.GetMin().y / m_dStep), 0, m_nNy[0] -1) ; int nEnJ = Clamp( int( b3Int.GetMax().y / m_dStep), 0, m_nNy[0] -1) ; // Vettore direzione dei dexel nel riferimento del Box Vector3d vtK = Z_AX ; vtK.LocToLoc( m_MapFrame[0], frBox) ; // Riferimento intrinseco dei dexel nel riferimento del box Point3d ptO = ORIG ; ptO.LocToLoc( m_MapFrame[0], frBox) ; Vector3d vtX = X_AX ; vtX.LocToLoc( m_MapFrame[0], frBox) ; Vector3d vtY = Y_AX ; vtY.LocToLoc( m_MapFrame[0], frBox) ; // Ciclo di intersezione dei dexel con il BBox for ( int i = nStI ; i <= nEnI ; ++ i) { for ( int j = nStJ ; j <= nEnJ ; ++ j) { int nPos = j * m_nNx[0] + i ; int nSize = int( m_Values[0][nPos].size()) ; if ( nSize == 0) continue ; Point3d ptC = ptO + ( i + 0.5) * m_dStep * vtX + ( j + 0.5) * m_dStep * vtY ; double dZmin, dZmax ; if ( IntersLineBox( ptC, vtK, ORIG, ORIG + vtDiag, dZmin, dZmax)) { for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) { if ( ! ( dZmax < m_Values[0][nPos][nIndex].dMin - EPS_SMALL || dZmin > m_Values[0][nPos][nIndex].dMax + EPS_SMALL)) return false ; } } } } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir, const Frame3d& CylFrame, double dL, double dR, Point3d& ptInt1, Point3d& ptInt2, Vector3d& vtN1, Vector3d& vtN2, bool bTapO, bool bTapL) { // NB: L'origine del sistema di riferimento deve essere // nel centro della circonferenza di base e l'asse di simmetria // deve coincidere con l'asse x. // La funzione restituisce true in caso di intersezione, // false altrimenti. Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Trasformazione delle coordinate: // l'asse del cilindro corrisponde con // l'asse x del sistema di riferimento ptP.ToLoc( CylFrame) ; vtV.ToLoc( CylFrame) ; DBLVECTOR vdCoef(3) ; DBLVECTOR vdRoots ; double dSqRad = dR * dR - 2 * dR * EPS_SMALL ; vdCoef[0] = ptP.y * ptP.y + ptP.z * ptP.z - dSqRad ; vdCoef[1] = 2 * ( ptP.y * vtV.y + ptP.z * vtV.z) ; vdCoef[2] = vtV.y * vtV.y + vtV.z * vtV.z ; // Computo radici int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Nessuna soluzione if ( nRoot == 0 || nRoot == 1) { if ( abs( vtV.x) > EPS_ZERO) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN1 = X_AX ; vtN2 = - X_AX ; if ( ptInt1.y * ptInt1.y + ptInt1.z * ptInt1.z <= dSqRad && ptInt2.y * ptInt2.y + ptInt2.z * ptInt2.z <= dSqRad) { ptInt1.ToGlob( CylFrame) ; ptInt2.ToGlob( CylFrame) ; vtN1.ToGlob( CylFrame) ; vtN2.ToGlob( CylFrame) ; return true ; } // Nessuna intersezione else return false ; } // Nessuna intersezione else return false ; } // L'equazione ammette o due soluzioni (eventualmente // coincidenti) oppure nessuna o infinite se la la retta // appartiene alla superficie if ( nRoot == 2) { double dEpsO = ( bTapO ? - EPS_SMALL : EPS_SMALL) ; double dEpsL = ( bTapL ? EPS_SMALL : - EPS_SMALL) ; ptInt1 = ptP + vdRoots[0] * vtV ; ptInt2 = ptP + vdRoots[1] * vtV ; if ( ptInt1.x > ptInt2.x) swap( ptInt1, ptInt2) ; vtN1.Set( 0, ( ORIG - ptInt1).y, ( ORIG - ptInt1).z) ; vtN2.Set( 0, ( ORIG - ptInt2).y, ( ORIG - ptInt2).z) ; if ( ptInt1.x < dL + dEpsL) { if ( ptInt1.x > dEpsO) { if ( ptInt2.x > dL + dEpsL) { ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN2.Set( -1, 0, 0) ; } } else { if ( ptInt2.x > dL + dEpsL) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN1.Set( 1, 0, 0) ; vtN2.Set( -1, 0, 0) ; } else if ( ptInt2.x > dEpsO) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; vtN1.Set( 1, 0, 0) ; } else return false ; } } else return false ; // Riporto le coordinate nel sistema di riferimento griglia ptInt1.ToGlob( CylFrame) ; ptInt2.ToGlob( CylFrame) ; vtN1.ToGlob( CylFrame) ; vtN2.ToGlob( CylFrame) ; vtN1.Normalize() ; vtN2.Normalize() ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IntersZLineCylinder( const Point3d& ptLine, const Point3d& ptBase, const Point3d& ptTop, double dCylR, double& dInfZ, double& dSupZ) { // NB: Le coordinate sono espresse nel sistema griglia // La funzione restituisce true in caso di intersezione, // false altrimenti. double dSqRad = dCylR * dCylR ; // Cilindro verticale if ( AreSamePointXYApprox( ptBase, ptTop)) { // Intersezione if ( SqDistXY( ptLine, ptBase) < dSqRad) { dInfZ = min( ptBase.z, ptTop.z) ; dSupZ = max( ptBase.z, ptTop.z) ; return true ; } // Non vi è intersezione else return false ; } // Cilindro non verticale else { // Studio delle simmetrie Point3d ptS = ( ptBase.z < ptTop.z ? ptBase : ptTop) ; Point3d ptE = ( ptBase.z < ptTop.z ? ptTop : ptBase) ; Vector3d vtAx = ptE - ptS ; Vector3d vtV1( vtAx.x, vtAx.y, 0) ; double dLenXY = vtV1.LenXY() ; double dSZ = ptS.z ; double dEZ = ptE.z ; double dDeltaZ = dEZ - dSZ ; Vector3d vtL( ptLine.x - ptS.x, ptLine.y - ptS.y, 0) ; // vtV1 e vtV2 formano un sistema ortonormale // sul piano e insieme a ptSxy formano un sistema // di riferimento bidimensionale vtV1.Normalize() ; Vector3d vtV2 = vtV1 ; vtV2.Rotate( Z_AX, 90) ; double dLen = vtAx.Len() ; // Sono seno e coseno dell'angolo complementare // rispetto a quello formato dal vettore movimento // con il piano, per questo motivo si ha dCos con // dDeltaZ e dSin con dLenXY double dCos = dDeltaZ / dLen ; double dSin = dLenXY / dLen ; // Nuove coordinate piane del punto double dLocX1 = vtL * vtV1 ; double dLocX2 = vtL * vtV2 ; double dSqRoot = sqrt( dSqRad - dLocX2 * dLocX2) ; double dX1_0 = dCos * dSqRoot ; if ( dLocX1 >= - dX1_0 && dLocX1 <= dLenXY + dX1_0 && abs( dLocX2) < dCylR) { // Minimi if ( dLocX1 < dX1_0) { double dDotS = vtAx * ( ptS - ORIG) ; // Qui usiamo ptLine perché servono coordinate griglia dInfZ = ( dDotS - vtAx.x * ptLine.x - vtAx.y * ptLine.y) / vtAx.z ; } else { double dZ0 = - dSin * dSqRoot ; dInfZ = dSZ + dZ0 + ( dLocX1 - dX1_0) * dDeltaZ / dLenXY ; } // Massimi if ( dLocX1 <= dLenXY - dX1_0) { double dZ0 = dSin * dSqRoot ; dSupZ = dSZ + dZ0 + ( dLocX1 + dX1_0) * dDeltaZ / dLenXY ; } else { double dDotE = vtAx * ( ptE - ORIG) ; // Qui usiamo ptLine perché servono coordinate griglia dSupZ = ( dDotE - vtAx.x * ptLine.x - vtAx.y * ptLine.y) / vtAx.z ; } return true ; } return false ; } } //---------------------------------------------------------------------------- bool VolZmap::IntersLineConus( const Point3d& ptLineSt, const Vector3d& vtLineDir, const Frame3d& ConusFrame, double dTan, double dl, double dL, Point3d& ptInt1, Point3d& ptInt2, Vector3d& vtN1, Vector3d& vtN2, bool bTapLow, bool bTapUp) { // NB: L'origine del sistema di riferimento deve essere // nel vertice del cono e l'asse di simmetria deve coincidere // con l'asse x. // La funzione restituisce true in caso di intersezione, // false altrimenti. Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Trasformazione delle coordinate ptP.ToLoc( ConusFrame) ; vtV.ToLoc( ConusFrame) ; DBLVECTOR vdCoef(3) ; DBLVECTOR vdRoots ; double dSqTan = dTan * dTan ; double dMinRad = dTan * dl ; double dMaxRad = dTan * dL ; double dDeltaR = dMaxRad - dMinRad ; double dHei = dL - dl ; vdCoef[0] = dSqTan * ptP.x * ptP.x - ptP.y * ptP.y - ptP.z * ptP.z ; vdCoef[1] = 2 * ( dSqTan * ptP.x * vtV.x - ptP.y * vtV.y - ptP.z * vtV.z) ; vdCoef[2] = dSqTan * vtV.x * vtV.x - vtV.y * vtV.y - vtV.z * vtV.z ; // Computo radici int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Nessuna soluzione if ( nRoot == 0) return false ; double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ; double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ; // Una soluzione: la retta iterseca superficie // laterale e un piano if ( nRoot == 1) { ptInt1 = ptP + vdRoots[0] * vtV ; Vector3d vtU = ( ptInt1 - ORIG) - ( ptInt1 - ORIG).x * X_AX ; vtU.Normalize() ; vtN1 = dDeltaR * X_AX - dHei * vtU ; vtN1.Normalize() ; if ( ptInt1.x < dL + dEpsUp) { if ( ptInt1.x > dl + dEpsLow) { ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN2 = - X_AX ; } else if ( ptInt1.x > - EPS_SMALL) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN1 = X_AX ; vtN2 = - X_AX ; if ( ptInt2.y * ptInt2.y + ptInt2.z * ptInt2.z > dMaxRad * dMaxRad) return false ; } else return false ; ptInt1.ToGlob( ConusFrame) ; ptInt2.ToGlob( ConusFrame) ; vtN1.ToGlob( ConusFrame) ; vtN2.ToGlob( ConusFrame) ; return true ; } else return false ; } // Due soluzioni: la retta interseca due volte la // superficie laterale else if ( nRoot == 2) { ptInt1 = ptP + vdRoots[0] * vtV ; ptInt2 = ptP + vdRoots[1] * vtV ; if ( ptInt1.x > ptInt2.x) swap( ptInt1, ptInt2) ; Vector3d vtU1 = ( ptInt1 - ORIG) - ( ptInt1 - ORIG).x * X_AX ; Vector3d vtU2 = ( ptInt2 - ORIG) - ( ptInt2 - ORIG).x * X_AX ; vtU1.Normalize() ; vtU2.Normalize() ; vtN1 = dDeltaR * X_AX - dHei * vtU1 ; vtN2 = dDeltaR * X_AX - dHei * vtU2 ; vtN1.Normalize() ; vtN2.Normalize() ; if ( abs( vtV.x) < EPS_ZERO) { if ( ptInt1.x > dl + dEpsLow && ptInt1.x < dL + dEpsUp) { ptInt1.ToGlob( ConusFrame) ; ptInt2.ToGlob( ConusFrame) ; vtN1.ToGlob( ConusFrame) ; vtN2.ToGlob( ConusFrame) ; vtN1.Normalize() ; vtN2.Normalize() ; return true ; } else return false ; } if ( ptInt1.x < dL + dEpsUp) { if ( ptInt1.x > dl + dEpsLow) { if ( ptInt2.x > dL + dEpsUp) { ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN2 = - X_AX ; } } else if ( ptInt1.x > - EPS_SMALL) { if ( ptInt2.x > dL + dEpsUp) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN1 = X_AX ; vtN2 = - X_AX ; } else if ( ptInt2.x > dl + dEpsLow) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; vtN1 = X_AX ; } else return false ; } else { if ( ptInt2.x < 0) return false ; else if ( ptInt2.x < dl + dEpsLow) { ptInt1 = ptP + ( ( dl - ptP.x) / vtV.x) * vtV ; ptInt2 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN1 = X_AX ; vtN2 = - X_AX ; } else if ( ptInt2.x < dL + dEpsUp) { ptInt1 = ptP + ( ( dL - ptP.x) / vtV.x) * vtV ; vtN1 = - X_AX ; } else return false ; } ptInt1.ToGlob( ConusFrame) ; ptInt2.ToGlob( ConusFrame) ; vtN1.ToGlob( ConusFrame) ; vtN2.ToGlob( ConusFrame) ; vtN1.Normalize() ; vtN2.Normalize() ; return true ; } else return false ; } return false ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineEllipticalCylinder( const Vector3d& vtLineDir, const Point3d& ptLineSt, const Frame3d& CircFrame, double dSqRad, double dLongMvLen, double dOrtMvLen, Point3d& ptInt1, Point3d& ptInt2, Vector3d& vtN1, Vector3d& vtN2, bool bTapLow, bool bTapUp) { // NB: L'origine del sistema di riferimento deve essere // nel centro della circonferenza di base, la cui tralsazione obliqua // genera il cilindro ellittico, e l'asse x deve essere l'asse // di simmetria di tale circonferenza. // La funzione restituisce true in caso di intersezione, // false altrimenti. // NB: dSqRad è il quadrato del raggio della circonferenza la cui // traslazione obliqua genera il cilindro ellittico, dLongMvLen e // dOrtMvLen sono rispettivamente le lunghezze delle proiezioni del // movimento su x e y del sistema di riferimento CircFrame. double dObCoef = dOrtMvLen / dLongMvLen ; double dSqCoef = dObCoef * dObCoef ; Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Asse cilindro ellittico Vector3d vtAx( dLongMvLen, dOrtMvLen, 0) ; vtAx.Normalize() ; // Trasformazione delle coordinate ptP.ToLoc( CircFrame) ; vtV.ToLoc( CircFrame) ; vector vdCoef(3) ; vector vdRoots ; vdCoef[0] = dSqCoef * ptP.x * ptP.x + ptP.y * ptP.y + ptP.z * ptP.z - 2 * dObCoef * ptP.x * ptP.y - dSqRad ; vdCoef[1] = 2 * ( dSqCoef * vtV.x * ptP.x + vtV.y * ptP.y + vtV.z * ptP.z - dObCoef * ( vtV.x * ptP.y + vtV.y * ptP.x)) ; vdCoef[2] = dSqCoef * vtV.x * vtV.x + vtV.y * vtV.y + vtV.z * vtV.z - 2 * dObCoef * vtV.x * vtV.y ; int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; // Nessuna soluzione if ( nRoot == 0 || nRoot == 1) { if ( abs( vtV.x) > EPS_ZERO) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; ptInt2 = ptP + ( ( dLongMvLen - ptP.x) / vtV.x) * vtV ; if ( ptInt1.y * ptInt1.y + ptInt1.z * ptInt1.z < dSqRad && ( ptInt2.y - dOrtMvLen) * ( ptInt2.y - dOrtMvLen) + ptInt2.z * ptInt2.z < dSqRad) { ptInt1.ToGlob( CircFrame) ; ptInt2.ToGlob( CircFrame) ; vtN1 = X_AX ; vtN2 = - X_AX ; vtN1.ToGlob( CircFrame) ; vtN2.ToGlob( CircFrame) ; return true ; } // Nessuna intersezione else return false ; } // Nessuna intersezione else return false ; } double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ; double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ; // L'equazione ammette o due soluzioni (eventualmente // coincidenti) oppure nessuna o infinite se la la retta // appartiene alla superficie Vector3d vtMv( dLongMvLen, dOrtMvLen, 0) ; if ( nRoot == 2) { ptInt1 = ptP + vdRoots[0] * vtV ; ptInt2 = ptP + vdRoots[1] * vtV ; if ( ptInt1.x > ptInt2.x) swap( ptInt1, ptInt2) ; Vector3d vtTest1 = ( ptInt1 - ORIG) - ( ptInt1 - ORIG) * vtAx * vtAx ; Vector3d vtTest2 = ( ptInt2 - ORIG) - ( ptInt2 - ORIG) * vtAx * vtAx ; double dY0_1, dY0_2 ; if ( vtTest1.y > 0) { dY0_1 = ( dSqRad - ptInt1.z * ptInt1.z > 0 ? sqrt( dSqRad - ptInt1.z * ptInt1.z) : 0) ; } else { dY0_1 = ( dSqRad - ptInt1.z * ptInt1.z > 0 ? - sqrt( dSqRad - ptInt1.z * ptInt1.z) : 0) ; } Vector3d vtCirc1( 0, - dY0_1, - ptInt1.z) ; Vector3d vtTan1( 0, - vtCirc1.z, vtCirc1.y) ; Vector3d vtCross1 = vtTan1 ^ vtMv ; vtN1 = ( vtCross1 * vtCirc1 > - EPS_ZERO ? vtCross1 : - vtCross1) ; if ( vtTest2.y > 0) { dY0_2 = ( dSqRad - ptInt2.z * ptInt2.z > 0 ? sqrt( dSqRad - ptInt2.z * ptInt2.z) : 0) ; } else { dY0_2 = ( dSqRad - ptInt2.z * ptInt2.z > 0 ? - sqrt( dSqRad - ptInt2.z * ptInt2.z) : 0) ; } Vector3d vtCirc2( 0, - dY0_2, - ptInt2.z) ; Vector3d vtTan2( 0, - vtCirc2.z, vtCirc2.y) ; Vector3d vtCross2 = vtTan2 ^ vtMv ; vtN2 = ( vtCross2 * vtCirc2 > - EPS_ZERO ? vtCross2 : - vtCross2) ; if ( ptInt1.x < dLongMvLen + dEpsUp) { if ( ptInt1.x > + dEpsLow) { if ( ptInt2.x > dLongMvLen + dEpsUp) { ptInt2 = ptP + ( ( dLongMvLen - ptP.x) / vtV.x) * vtV ; vtN2 = - X_AX ; } } else { if ( ptInt2.x > dLongMvLen + dEpsUp) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; ptInt2 = ptP + ( ( dLongMvLen - ptP.x) / vtV.x) * vtV ; vtN1.Set( 1, 0, 0) ; vtN2.Set( -1, 0, 0) ; if ( ptInt1.y * ptInt1.y + ptInt1.z * ptInt1.z > dSqRad && ptInt2.y * ptInt2.y + ptInt2.z * ptInt2.z > dSqRad) return false ; } else if ( ptInt2.x > dEpsLow) { ptInt1 = ptP - ( ptP.x / vtV.x) * vtV ; vtN1.Set( 1, 0, 0) ; } else return false ; } } else return false ; // Riporto le coordinate nel sistema di riferimento // griglia ptInt1.ToGlob( CircFrame) ; ptInt2.ToGlob( CircFrame) ; vtN1.ToGlob( CircFrame) ; vtN2.ToGlob( CircFrame) ; vtN1.Normalize() ; vtN2.Normalize() ; } return true ; } //---------------------------------------------------------------------------- bool VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLineDir, const Frame3d& PolyFrame, double dLenX, double dLenY, double dLenZ, double dDeltaX, Point3d& ptInt1, Point3d& ptInt2, Vector3d& vtN1, Vector3d& vtN2) { Point3d ptP = ptLineSt ; Vector3d vtV = vtLineDir ; // Trasformazione delle coordinate ptP.ToLoc( PolyFrame) ; vtV.ToLoc( PolyFrame) ; // Facce 1 e 2 parallele a XY // Facce 3 e 4 parallele a XZ // Facce 5 e 6 oblique Point3d ptFacet135( 0, 0, dLenZ /2) ; Point3d ptFacet246( dLenX + dDeltaX, dLenY, - dLenZ / 2) ; // Servono per descrivere i piani obliqui Vector3d vtFacet5 = ptFacet135 - ptP ; Vector3d vtFacet6 = ptFacet246 - ptP ; Vector3d vtOb( dLenY, - dDeltaX, 0) ; vtOb.Normalize() ; Point3d ptI1 = ptP + ( ( ptFacet135.z - ptP.z) / vtV.z) * vtV ; Point3d ptI2 = ptP + ( ( ptFacet246.z - ptP.z) / vtV.z) * vtV ; Point3d ptI3 = ptP + ( ( ptFacet135.y - ptP.y) / vtV.y) * vtV ; Point3d ptI4 = ptP + ( ( ptFacet246.y - ptP.y) / vtV.y) * vtV ; Point3d ptI5 = ptP + ( ( vtFacet5 * vtOb) / ( vtV * vtOb)) * vtV ; Point3d ptI6 = ptP + ( ( vtFacet6 * vtOb) / ( vtV * vtOb)) * vtV ; // Controlli affinché non vengano tagliati dexel a filo // con il passaggio dell'utensile: // Controllo sulle facce 1 e 2 if ( abs( vtV.z) < EPS_ZERO && abs( ptP.z) > dLenZ / 2 - EPS_SMALL) return false ; // Controllo sulle facce 3 e 4 if ( abs( vtV.y) < EPS_ZERO && ( ptP.y < EPS_SMALL || ptP.y > dLenY - EPS_SMALL)) return false ; // Controllo sulle facce 5 e 6 Vector3d vtW( dDeltaX, dLenY, 0) ; vtW.Normalize() ; Vector3d vtU = vtV - vtV.z * Z_AX - vtV * vtW * vtW ; if ( vtU.Len() < EPS_ZERO && ( ptP.x * dLenY < dDeltaX * ptP.y + dLenY * EPS_SMALL || ptP.x * dLenY > dDeltaX * ptP.y + dLenY * ( dLenX - EPS_SMALL))) return false ; // Ricerca intersezioni con le facce int nIntNum = 0 ; // Intersezione con la prima faccia if ( ptI1.y >= 0 && ptI1.y <= dLenY && ptI1.x * dLenY >= dDeltaX * ptI1.y && ( ptI1.x - dLenX) * dLenY <= dDeltaX * ptI1.y) { ptInt1 = ptI1 ; vtN1 = - Z_AX ; ++ nIntNum ; } // Intersezione con la seconda faccia if ( ptI2.y >= 0 && ptI2.y <= dLenY && ptI2.x * dLenY >= dDeltaX * ptI2.y && ( ptI2.x - dLenX) * dLenY <= dDeltaX * ptI2.y) { if ( nIntNum == 0) { ptInt1 = ptI2 ; vtN1 = Z_AX ; ++ nIntNum ; } else if ( ( ptInt1 - ptI2).SqLen() > SQ_EPS_SMALL) { ptInt2 = ptI2 ; vtN2 = Z_AX ; ++ nIntNum ; } } // Intersezione con la terza faccia if ( nIntNum < 2 && ptI3.x >= 0 && ptI3.x <= dLenX && ptI3.z >= - ptFacet135.z && ptI3.z <= ptFacet135.z) { if ( nIntNum == 0) { ptInt1 = ptI3 ; vtN1 = Y_AX ; ++ nIntNum ; } else if ( ( ptInt1 - ptI3).SqLen() > SQ_EPS_SMALL) { ptInt2 = ptI3 ; vtN2 = Y_AX ; ++ nIntNum ; } } // Intersezione con la quarta faccia if ( nIntNum < 2 && ptI4.x >= dDeltaX && ptI4.x <= dLenX + dDeltaX && ptI4.z >= - ptFacet135.z && ptI4.z <= ptFacet135.z) { if ( nIntNum == 0) { ptInt1 = ptI4 ; vtN1 = - Y_AX ; ++ nIntNum ; } else if ( ( ptInt1 - ptI4).SqLen() > SQ_EPS_SMALL) { ptInt2 = ptI4 ; vtN2 = - Y_AX ; ++ nIntNum ; } } // Intersezione con la quinta faccia if ( nIntNum < 2 && ptI5.y >= 0 && ptI5.y <= dLenY && ptI5.z >= - ptFacet135.z && ptI5.z <= ptFacet135.z) { if ( nIntNum == 0) { ptInt1 = ptI5 ; vtN1 = vtOb ; ++ nIntNum ; } else if ( ( ptInt1 - ptI5).SqLen() > SQ_EPS_SMALL) { ptInt2 = ptI5 ; vtN2 = vtOb ; ++ nIntNum ; } } // Intersezione con la sesta faccia if ( nIntNum < 2 && ptI6.y >= 0 && ptI6.y <= dLenY && ptI6.z >= - ptFacet135.z && ptI6.z <= ptFacet135.z) { if ( nIntNum == 0) { ptInt1 = ptI6; vtN1 = - vtOb ; ++ nIntNum ; } else if ( ( ptInt1 - ptI6).SqLen() > SQ_EPS_SMALL) { ptInt2 = ptI6; vtN2 = - vtOb ; ++ nIntNum ; } } if ( nIntNum == 2) { ptInt1.ToGlob( PolyFrame) ; ptInt2.ToGlob( PolyFrame) ; vtN1.ToGlob( PolyFrame) ; vtN2.ToGlob( PolyFrame) ; return true ; } else return false ; } //---------------------------------------------------------------------------- bool VolZmap::GetVolume( double& dVol) const { // verifico lo stato if ( m_nStatus != OK) return false ; // Eseguo il calcolo della lunghezza totale degli spilloni double dLen = 0 ; for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) { for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) { dLen += m_Values[nMap][nDex][nInt].dMax - m_Values[nMap][nDex][nInt].dMin ; } } } // Il volume si trova moltiplicando per l'area di ogni spillone e dividendo per il numero di mappe dVol = dLen * ( m_dStep * m_dStep) / m_nMapNum ; return true ; } //---------------------------------------------------------------------------- bool VolZmap::GetPartVolume( int nPart, double& dVol) const { // verifico lo stato if ( m_nStatus != OK) return false ; // Se una sola mappa o il numero di componenti è indefinito, errore if ( m_nMapNum == 1 || m_nConnectedCompoCount == -1) return false ; // Se la componente richiesta non esiste, errore if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1) return false ; // Eseguo il calcolo della lunghezza totale degli spilloni double dLen = 0 ; for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) { for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) { // se il pezzo di spillone appartiene alla parte, ne aggiungo la lunghezza if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) { dLen += m_Values[nMap][nDex][nInt].dMax - m_Values[nMap][nDex][nInt].dMin ; } } } } // Il volume si trova moltiplicando per l'area di ogni spillone e dividendo per il numero di mappe dVol = dLen * ( m_dStep * m_dStep) / 3 ; return true ; }