diff --git a/EgtGraphics.rc b/EgtGraphics.rc index 1daed6c..ee67fa7 100644 Binary files a/EgtGraphics.rc and b/EgtGraphics.rc differ diff --git a/Scene.h b/Scene.h index 34ec7d6..d56a89b 100644 --- a/Scene.h +++ b/Scene.h @@ -24,6 +24,7 @@ class ICurve ; class ICurveComposite ; class ISurfTriMesh ; class ISurfFlatRegion ; +class IVolZmap ; class IExtText ; class ObjEGrGraphics ; @@ -245,6 +246,8 @@ class Scene : public IEGrScene const ISurfTriMesh* pStm, double& dMinSqDist) ; bool FindSurfFRSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, const ISurfFlatRegion* pSfr, double& dMinSqDist) ; + bool FindVolZmapSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const IVolZmap* pVzm, double& dMinSqDist) ; bool FindTextSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, const IExtText* pTxt, double& dMinSqDist) ; diff --git a/SceneSnap.cpp b/SceneSnap.cpp index f71a72a..55310e3 100644 --- a/SceneSnap.cpp +++ b/SceneSnap.cpp @@ -25,6 +25,7 @@ #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkSurfFlatRegion.h" +#include "/EgtDev/Include/EGkVolZmap.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EgkIntersCurves.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" @@ -338,6 +339,14 @@ Scene::FindSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH) if ( FindSurfFRSnapPoint( nSnap, ptWin, nId, frEnt, pReg, dMinSqDist)) bFound = true ; } + // se solido Zmap + else if ( pGObj->GetType() == VOL_ZMAP) { + // recupero il solido + const IVolZmap* pVzm = GetVolZmap( pGObj) ; + // verifico i punti notevoli del solido + if ( FindVolZmapSnapPoint( nSnap, ptWin, nId, frEnt, pVzm, dMinSqDist)) + bFound = true ; + } // se testo else if ( pGObj->GetType() == EXT_TEXT) { // recupero il testo @@ -902,6 +911,216 @@ Scene::FindSurfFRSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Fram return bFound ; } +//---------------------------------------------------------------------------- +bool +Scene::FindVolZmapSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const IVolZmap* pVzm, double& dMinSqDist) +{ + // il punto di riferimento deriva da XY su viewport e Z minima (più vicina a osservatore) da selezione + Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjMinWinZ()) ; + // punto di riferimento nello spazio geometrico 3d + Point3d ptRef ; + if ( ! UnProject( ptWinZ, ptRef)) + return false ; + // porto il punto nel riferimento della superficie + ptRef.ToLoc( frEnt) ; + // recupero la direzione di mira e la porto nel riferimento della superficie + Vector3d vtDir = - m_vtDirCamera ; + vtDir.ToLoc( frEnt) ; + // recupero il raggio del box di ingombro + double dBlRad = 1000 ; + const ObjEGrGraphics* pGraphics = GetObjEGrGraphics( pVzm) ; + if ( pGraphics != nullptr) { + BBox3d b3Loc ; + if ( pGraphics->GetLocalBBox( b3Loc)) + b3Loc.GetRadius( dBlRad) ; + } + // punto davanti all'oggetto lungo il raggio di mira + Point3d ptMir = ptRef - vtDir * 2 * dBlRad ; + double dLenMir = 4 * dBlRad ; + + // determino se oggetto trasparente + Color cCol ; + bool bAlpha = ( m_pGeomDB->GetCalcMaterial( nId, cCol) && cCol.GetIntAlpha() <= ALPHA_LIM) ; + + // se richiesto il centro di gravità (baricentro, centroide) + if ( nSnap == SP_CENTROID) { + Point3d ptP ; + bool bFound = false ; + BBox3d b3Loc ; + if ( pVzm->GetLocalBBox( b3Loc) && b3Loc.GetCenter( ptP)) { + // il punto di confronto è quello sulla linea di mira a minima distanza dal vertice + Point3d ptCfr = ptRef + (( ptP - ptRef) * vtDir) * vtDir ; + // determino la distanza e la confronto con il minimo + double dSqDist = SqDist( ptP, ptCfr) ; + if ( dSqDist < dMinSqDist) { + bFound = true ; + dMinSqDist = dSqDist ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_ptLastSnapPnt.ToGlob( frEnt) ; + m_bLastSnapDirOk = false ; + } + } + // se trovato e modalità shading o hiddenline, la favorisco perchè davanti alle possibili successive + if ( bFound && ! ( bAlpha || m_nShowMode == SM_WIREFRAME)) + dMinSqDist = 0 ; + return bFound ; + } + + // cerco i triangoli intersecati dalla linea di mira + ILZIVECTOR vInfo ; + if ( ! pVzm->GetLineIntersection( ptMir, vtDir, vInfo)) + return false ; + // se non trovato alcunchè, cerco le linee che partono dagli angoli del rettangolo di mira + Vector3d vtWinD( -1, -1, 0) ; + for ( int i = 0 ; i < 4 && vInfo.size() == 0 ; ++ i) { + // determino punto su vertice del rettangolo di selezione + Point3d ptWinZ2 = ptWinZ + vtWinD.x * m_nSelH * X_AX + vtWinD.y * m_nSelW * Y_AX ; + vtWinD.Rotate( Z_AX, 0, 1) ; + // ne ricavo punto di mira + Point3d ptMir2 ; + if ( ! UnProject( ptWinZ2, ptMir2)) + return false ; + ptMir2.ToLoc( frEnt) ; + ptMir2 -= vtDir * 2 * dBlRad ; + // interseco con la superficie + if ( ! pVzm->GetLineIntersection( ptMir2, vtDir, vInfo)) + return false ; + } + if ( vInfo.size() == 0) + return false ; + + // elaborazione a seconda del tipo di snap + bool bFound = false ; + switch ( nSnap) { + case SP_END : + { + // con wireframe devo provare tutti i triangoli intersecati, con shading e hiddenline solo il primo + int nTtot = (( bAlpha || m_nShowMode == SM_WIREFRAME) ? int( vInfo.size()) : 1) ; + for ( int i = 0 ; i < nTtot ; ++ i) { + // punto di intersezione + Point3d ptInt = vInfo[i].ptI ; + // triangolo + Triangle3d& trTria = vInfo[i].trTria ; + // punto finale più vicino + Point3d ptEnd = trTria.GetP( 0) ; + if ( SqDist( trTria.GetP( 1), ptInt) < SqDist( ptEnd, ptInt)) + ptEnd = trTria.GetP( 1) ; + if ( SqDist( trTria.GetP( 2), ptInt) < SqDist( ptEnd, ptInt)) + ptEnd = trTria.GetP( 2) ; + Vector3d vtN = trTria.GetN() ; + // il punto di confronto è quello sulla linea di mira a minima distanza dal vertice + Point3d ptCfr = ptRef + (( ptEnd - ptRef) * vtDir) * vtDir ; + // determino la distanza e la confronto con il minimo + double dSqDist = SqDist( ptEnd, ptCfr) ; + if ( dSqDist < dMinSqDist) { + bFound = true ; + dMinSqDist = dSqDist ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptEnd ; + m_ptLastSnapPnt.ToGlob( frEnt) ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = vtN ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + } + break ; + case SP_MID : + { + // con wireframe devo provare tutti i triangoli intersecati, con shading e hiddenline solo il primo + int nTtot = (( bAlpha || m_nShowMode == SM_WIREFRAME) ? int( vInfo.size()) : 1) ; + for ( int i = 0 ; i < nTtot ; ++ i) { + // punto di intersezione + Point3d ptInt = vInfo[i].ptI ; + // triangolo + Triangle3d& trTria = vInfo[i].trTria ; + // punto medio più vicino + Point3d ptMid = Media( trTria.GetP( 0), trTria.GetP( 1)) ; + Point3d ptMid2 = Media( trTria.GetP( 1), trTria.GetP( 2)) ; + if ( SqDist( ptMid2, ptInt) < SqDist( ptMid, ptInt)) + ptMid = ptMid2 ; + Point3d ptMid3 = Media( trTria.GetP( 2), trTria.GetP( 0)) ; + if ( SqDist( ptMid3, ptInt) < SqDist( ptMid, ptInt)) + ptMid = ptMid3 ; + Vector3d vtN = trTria.GetN() ; + // il punto di confronto è quello sulla linea di mira a minima distanza dal punto medio + Point3d ptCfr = ptRef + (( ptMid - ptRef) * vtDir) * vtDir ; + // determino la distanza e la confronto con il minimo + double dSqDist = SqDist( ptMid, ptCfr) ; + if ( dSqDist < dMinSqDist) { + bFound = true ; + dMinSqDist = dSqDist ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptMid ; + m_ptLastSnapPnt.ToGlob( frEnt) ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = vtN ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + } + break ; + case SP_CENTER : + { + // con wireframe devo provare tutti i triangoli intersecati, con shading e hiddenline solo il primo + int nTtot = (( bAlpha || m_nShowMode == SM_WIREFRAME) ? int( vInfo.size()) : 1) ; + for ( int i = 0 ; i < nTtot ; ++ i) { + // triangolo + Triangle3d& trTria = vInfo[i].trTria ; + // centro più vicino + Point3d ptCen = trTria.GetCentroid() ; + Vector3d vtN = trTria.GetN() ; + // il punto di confronto è quello sulla linea di mira a minima distanza dal centro + Point3d ptCfr = ptRef + (( ptCen - ptRef) * vtDir) * vtDir ; + // determino la distanza e la confronto con il minimo + double dSqDist = SqDist( ptCen, ptCfr) ; + if ( dSqDist < dMinSqDist) { + bFound = true ; + dMinSqDist = dSqDist ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptCen ; + m_ptLastSnapPnt.ToGlob( frEnt) ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = vtN ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + } + break ; + case SP_NEAR : + case SP_TANG : + case SP_PERP : + case SP_MINDIST : + // considero solo il primo triangolo intersecato + // la distanza è nulla e la confronto con il minimo + if ( 0 < dMinSqDist) { + bFound = true ; + dMinSqDist = 0 ; + m_nLastSnapId = nId ; + // punto + Point3d ptInt = vInfo[0].ptI ; + m_ptLastSnapPnt = ptInt ; + m_ptLastSnapPnt.ToGlob( frEnt) ; + // direzione + Vector3d vtNorm = vInfo[0].trTria.GetN() ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = vtNorm ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + break ; + default : + break ; + } + + // se trovato e modalità shading o hiddenline, la favorisco perchè davanti alle possibili successive + if ( bFound && ! ( bAlpha || m_nShowMode == SM_WIREFRAME)) + dMinSqDist = 0 ; + + return bFound ; +} + //---------------------------------------------------------------------------- bool Scene::FindTextSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt,