diff --git a/EgtGraphics.rc b/EgtGraphics.rc index 0402cb5..13186c9 100644 Binary files a/EgtGraphics.rc and b/EgtGraphics.rc differ diff --git a/Scene.h b/Scene.h index 583ede9..3a748e8 100644 --- a/Scene.h +++ b/Scene.h @@ -20,6 +20,9 @@ class IGdbIterator ; class ICurve ; +class ICurveComposite ; +class ISurfTriMesh ; +class IExtText ; class ObjEGrGraphics ; //---------------------------------------------------------------------------- @@ -83,6 +86,7 @@ class Scene : public IEGrScene virtual int GetFirstSelectedObj( void) ; virtual int GetNextSelectedObj( void) ; virtual double GetSelectedObjWinZ( int nSel = - 1) ; + virtual double GetSelectedObjMinWinZ( int nSel = - 1) ; virtual bool GetPointFromSelect( int nSelId, const Point3d& ptView, Point3d& ptSel) ; virtual bool Project( const Point3d& ptWorld, Point3d& ptView) ; virtual bool UnProject( const Point3d& ptView, Point3d& ptWorld) ; @@ -200,12 +204,19 @@ class Scene : public IEGrScene bool DrawGeoTria( void) ; bool DrawWinRect( void) ; // Snap - bool GetGridSnapPoint( bool bSketch, const Point3d& ptWin, Point3d& ptSel) ; - bool GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Point3d& ptSel) ; - bool TestCurveSnapPoints( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, - const ICurve* pCrv, double& dMinSqDist, Point3d& ptSel) ; + bool FindGridSnapPoint( bool bSketch, const Point3d& ptWin) ; + bool FindSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH) ; + bool FindSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH) ; + bool FindCurveSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const ICurve* pCrv, double& dMinSqDist) ; bool VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSqDist) ; - bool GetSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH, Point3d& ptSel) ; + bool AdjustForCurveExtr( const Point3d& ptWin, const Frame3d& frEnt, const ICurve* pCrv, Point3d& ptP) ; + bool FindCurveCompoSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const ICurveComposite* pCrvCompo, double& dMinSqDist) ; + bool FindSurfTMSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const ISurfTriMesh* pStm, double& dMinSqDist) ; + bool FindTextSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const IExtText* pTxt, double& dMinSqDist) ; private : // Basic @@ -241,6 +252,7 @@ class Scene : public IEGrScene SelRec m_nSelBuff[DIM_SEL_BUF] ; // buffer per selezione con OpenGL // Snap int m_nLastSnapId ; // Id dell'entità generatrice dell'ultimo punto snap + Point3d m_ptLastSnapPnt ; // ultimo punto di snap bool m_bLastSnapDirOk ; // flag validità direzione associata a ultimo punto snap Vector3d m_vtLastSnapDir ; // direzione associata a ultimo punto snap // Geometry diff --git a/SceneGeom.cpp b/SceneGeom.cpp index 8266747..89ffc70 100644 --- a/SceneGeom.cpp +++ b/SceneGeom.cpp @@ -158,9 +158,6 @@ Scene::DrawGroup( const IGdbIterator& iIter, int nPass, const MdStMkCol& cParent bool Scene::DrawGeoObj( const IGdbIterator& iIter, int nPass, const MdStMkCol& siObj) { - // valore limite di opacità oltre il quale è considerata completa - const int ALPHA_LIM = 90 ; - // recupero l'oggetto geometrico e il suo tipo IGeoObj* pGeoObj = (const_cast(&iIter))->GetGeoObj() ; if ( pGeoObj == nullptr) diff --git a/SceneSelect.cpp b/SceneSelect.cpp index 91a3205..a65e21a 100644 --- a/SceneSelect.cpp +++ b/SceneSelect.cpp @@ -150,6 +150,17 @@ Scene::GetSelectedObjWinZ( int nSel) return 0.5 * ( double( m_nSelBuff[nSel].nZmin) + double( m_nSelBuff[nSel].nZmax)) / UINT_MAX ; } +//---------------------------------------------------------------------------- +double +Scene::GetSelectedObjMinWinZ( int nSel) +{ + if ( nSel < 0) + nSel = m_nSelCurr ; + if ( nSel < 0 || nSel >= m_nSelNbr) + return 0.5 ; + return ( double( m_nSelBuff[nSel].nZmin)) / UINT_MAX ; +} + /*------------------------------------------------------------------------------------------*/ bool Scene::UnselectableAdd( int nId) diff --git a/SceneSnap.cpp b/SceneSnap.cpp index e49a913..b4d543a 100644 --- a/SceneSnap.cpp +++ b/SceneSnap.cpp @@ -21,8 +21,10 @@ #include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EgkIntersCurveCurve.h" +#include "/EgtDev/Include/EgkIntersLineTria.h" #include "/EgtDev/Include/EgtPointerOwner.h" @@ -39,48 +41,28 @@ Scene::GetGraphicSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Poi if ( m_pGeomDB == nullptr) return false ; // se Snap Sketch o Grid, devo trovare il punto sulla griglia - if ( nSnap == SP_SKETCH || nSnap == SP_GRID) - return GetGridSnapPoint( ( nSnap == SP_SKETCH), ptWin, ptSel) ; - // se Snap Intersection, devo trovare l'intersezione tra due entità inquadrate - else if ( nSnap == SP_INTERS) - return GetSelectedIntersectionPoint( ptWin, nW, nH, ptSel) ; - // altrimenti devo trovare il punto dall'entità inquadrata - else - return GetSelectedSnapPoint( nSnap, ptWin, nW, nH, ptSel) ; -} - -//---------------------------------------------------------------------------- -bool -Scene::GetGridSnapPoint( bool bSketch, const Point3d& ptWin, Point3d& ptSel) -{ - // recupero il riferimento di griglia - Frame3d frGrid = GetGridFrame() ; - - // calcolo un punto e la direzione della linea di mira - Point3d ptLine ; - if ( ! UnProject( ptWin, ptLine)) - return false ; - Vector3d vtLine = - m_vtDirCamera ; - - // determino l'intersezione di questa linea con il piano della griglia - double dDenom = vtLine * frGrid.VersZ() ; - if ( fabs( dDenom) < COS_ORTO_ANG_SMALL) - return false ; - double dU = ( ( frGrid.Orig() - ptLine) * frGrid.VersZ()) / dDenom ; - ptSel = ptLine + dU * vtLine ; - - // porto il punto sul piano di griglia - ptSel.ToLoc( frGrid) ; - // se punto grid, devo arrotondare al nodo di griglia più vicino - if ( ! bSketch) { - ptSel.x = floor( ptSel.x / m_dSnapStep + 0.5) * m_dSnapStep ; - ptSel.y = floor( ptSel.y / m_dSnapStep + 0.5) * m_dSnapStep ; + if ( nSnap == SP_SKETCH || nSnap == SP_GRID) { + if ( FindGridSnapPoint( ( nSnap == SP_SKETCH), ptWin)) { + ptSel = m_ptLastSnapPnt ; + return true ; + } } - // il punto deve stare sulla griglia - ptSel.z = 0 ; - // lo riporto in globale - ptSel.ToGlob( frGrid) ; - return true ; + // se Snap Intersection, devo trovare l'intersezione tra due entità inquadrate + else if ( nSnap == SP_INTERS) { + if ( FindSelectedIntersectionPoint( ptWin, nW, nH)) { + ptSel = m_ptLastSnapPnt ; + return true ; + } + } + // altrimenti devo trovare il punto dall'entità inquadrata + else { + if ( FindSelectedSnapPoint( nSnap, ptWin, nW, nH)) { + ptSel = m_ptLastSnapPnt ; + return true ; + } + } + // non trovato + return false ; } //---------------------------------------------------------------------------- @@ -120,401 +102,41 @@ Scene::GetGridSnapPointZ( bool bSketch, const Point3d& ptWin, const Point3d& ptG //---------------------------------------------------------------------------- bool -Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Point3d& ptSel) +Scene::FindGridSnapPoint( bool bSketch, const Point3d& ptWin) { - // verifico siano state selezionate delle entità - int nSel ; - Select( ptWin, nW, nH, nSel) ; - if ( nSel <= 0) + // recupero il riferimento di griglia + Frame3d frGrid = GetGridFrame() ; + + // calcolo un punto e la direzione della linea di mira + Point3d ptLine ; + if ( ! UnProject( ptWin, ptLine)) return false ; - // cerco il punto notevole più vicino alla selezione tra le entità selezionate - bool bFound = false ; - double dMinSqDist = INFINITO * INFINITO ; - for ( int nId = GetFirstSelectedObj() ; nId != GDB_ID_NULL ; nId = GetNextSelectedObj()) { - // se non è entità geometrica - const IGeoObj* pGObj ; - if ( ( pGObj = m_pGeomDB->GetGeoObj( nId)) == nullptr) - continue ; - // recupero riferimento dell'entità - Frame3d frEnt ; - if ( ! m_pGeomDB->GetGlobFrame( nId, frEnt)) - continue ; - // se punto - if ( pGObj->GetType() == GEO_PNT3D) { - // recupero il geo-punto - const IGeoPoint3d* pGP = GetGeoPoint3d( pGObj) ; - // recupero il punto - Point3d ptP = pGP->GetPoint() ; - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = false ; - } - } - // se vettore - else if ( pGObj->GetType() == GEO_VECT3D) { - // recupero il geo-vettore - const IGeoVector3d* pGV = GetGeoVector3d( pGObj) ; - // recupero il punto - Point3d ptP = pGV->GetBase() ; - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - m_vtLastSnapDir = pGV->GetVector() ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - // se frame - else if ( pGObj->GetType() == GEO_FRAME3D) { - // recupero il geo-frame - const IGeoFrame3d* pGF = GetGeoFrame3d( pGObj) ; - // recupero il punto - Point3d ptP = pGF->GetFrame().Orig() ; - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = false ; - } - } - // se curva composita - else if ( pGObj->GetType() == CRV_COMPO) { - // recupero la curva composita - const ICurveComposite* pCrvCompo = GetCurveComposite( pGObj) ; - // il punto di riferimento deriva da XY su viewport e Z da selezione - Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjWinZ()) ; - // determino la curva elementare più vicina al punto di riferimento - int nCrv = - 1 ; - Point3d ptRef ; - if ( UnProject( ptWinZ, ptRef)) { - double dPar ; - int nFlag ; - // porto il punto nel riferimento della curva - ptRef.ToLoc( frEnt) ; - // cerco il punto della curva più vicino, dal suo parametro deduco la curva elementare - if ( DistPointCurve( ptRef, *pCrvCompo).GetParamAtMinDistPoint( 0, dPar, nFlag)) - nCrv = static_cast( dPar) ; - } - // vettore estrusione e spessore della curva composita - Vector3d vtExtr = V_NULL ; - pCrvCompo->GetExtrusion( vtExtr) ; - double dThick = 0 ; - pCrvCompo->GetThickness( dThick) ; - // ciclo sulle curve elementari - int nCont = 0 ; - const ICurve* pCrv = pCrvCompo->GetFirstCurve() ; - while ( pCrv != nullptr) { - if ( nCont == nCrv) { - // imposto estrusione e spessore della curva composita - (const_cast(pCrv))->SetExtrusion( vtExtr) ; - (const_cast(pCrv))->SetThickness( dThick) ; - // verifico i punti notevoli della curva - if ( TestCurveSnapPoints( nSnap, ptWinZ, nId, frEnt, pCrv, dMinSqDist, ptSel)) - bFound = true ; - // ripristino valori originali - (const_cast(pCrv))->SetExtrusion( V_NULL) ; - (const_cast(pCrv))->SetThickness( 0) ; - } - // passo alla successiva - ++ nCont ; - pCrv = pCrvCompo->GetNextCurve() ; - } - } - // se curva semplice - else if ( ( pGObj->GetType() & GEO_CURVE) != 0) { - // recupero la curva - const ICurve* pCrv = GetCurve( pGObj) ; - // il punto di riferimento deriva da XY su viewport e Z da selezione - Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjWinZ()) ; - // verifico i punti notevoli della curva - if ( TestCurveSnapPoints( nSnap, ptWinZ, nId, frEnt, pCrv, dMinSqDist, ptSel)) - bFound = true ; - } - // se testo - else if ( pGObj->GetType() == EXT_TEXT) { - // recupero il testo - const IExtText* pTxt = GetExtText( pGObj) ; - // recupero il punto - Point3d ptP ; - switch ( nSnap) { - case SP_END : - // punto iniziale - if ( pTxt->GetStartPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - m_vtLastSnapDir = pTxt->GetDirVersor() ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - // punto sopra iniziale - if ( pTxt->GetOverStartPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - m_vtLastSnapDir = pTxt->GetDirVersor() ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - // punto finale - if ( pTxt->GetEndPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - m_vtLastSnapDir = pTxt->GetDirVersor() ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - // punto sopra finale - if ( pTxt->GetOverEndPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - m_vtLastSnapDir = pTxt->GetDirVersor() ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - break ; - case SP_MID : - // punto medio - if ( pTxt->GetMidPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - m_vtLastSnapDir = pTxt->GetDirVersor() ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - break ; - case SP_CENTER : - // centro - if ( pTxt->GetCenterPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = false ; - } - } - break ; - } - } + Vector3d vtLine = - m_vtDirCamera ; + + // determino l'intersezione di questa linea con il piano della griglia + double dDenom = vtLine * frGrid.VersZ() ; + if ( fabs( dDenom) < COS_ORTO_ANG_SMALL) + return false ; + double dU = ( ( frGrid.Orig() - ptLine) * frGrid.VersZ()) / dDenom ; + m_ptLastSnapPnt = ptLine + dU * vtLine ; + + // porto il punto sul piano di griglia + m_ptLastSnapPnt.ToLoc( frGrid) ; + // se punto grid, devo arrotondare al nodo di griglia più vicino + if ( ! bSketch) { + m_ptLastSnapPnt.x = floor( m_ptLastSnapPnt.x / m_dSnapStep + 0.5) * m_dSnapStep ; + m_ptLastSnapPnt.y = floor( m_ptLastSnapPnt.y / m_dSnapStep + 0.5) * m_dSnapStep ; } - return bFound ; + // il punto deve stare sulla griglia + m_ptLastSnapPnt.z = 0 ; + // lo riporto in globale + m_ptLastSnapPnt.ToGlob( frGrid) ; + return true ; } //---------------------------------------------------------------------------- bool -Scene::TestCurveSnapPoints( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, const ICurve* pCrv, - double& dMinSqDist, Point3d& ptSel) -{ - // recupero eventuale spessore di estrusione - bool bExtr = false ; - double dTh ; - Vector3d vtExtr ; - if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall() && - pCrv->GetThickness( dTh) && fabs( dTh) > EPS_SMALL) { - vtExtr *= dTh ; - vtExtr.ToGlob( frEnt) ; - bExtr = true ; - } - // recupero il punto - bool bFound = false ; - Point3d ptP ; - switch ( nSnap) { - case SP_END : - // punto iniziale - if ( pCrv->GetStartPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - pCrv->GetStartDir( m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - m_vtLastSnapDir.Invert() ; - } - // eventuale verifica dell'estruso - if ( bExtr) { - ptP += vtExtr ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - pCrv->GetStartDir( m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - m_vtLastSnapDir.Invert() ; - } - } - } - // punto finale - if ( pCrv->GetEndPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - pCrv->GetEndDir( m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - // eventuale verifica dell'estruso - if ( bExtr) { - ptP += vtExtr ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - pCrv->GetEndDir( m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - } - break ; - case SP_MID : - if ( pCrv->GetMidPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - pCrv->GetMidDir( m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - // eventuale verifica dell'estruso - if ( bExtr) { - ptP += vtExtr ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - pCrv->GetMidDir( m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - } - break ; - case SP_CENTER : - if ( pCrv->GetCenterPoint( ptP)) { - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = false ; - } - // eventuale verifica dell'estruso - if ( bExtr) { - ptP += vtExtr ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = false ; - } - } - } - break ; - case SP_NEAR : - case SP_TANG : - case SP_PERP : - case SP_MINDIST : - { - Point3d ptRef ; - // lo porto da spazio grafico a spazio geometrico globale - UnProject( ptWin, ptRef) ; - // lo porto nel frame della curva - ptRef.ToLoc( frEnt) ; - // determino il punto più vicino della curva a questo - MinDistPCInfo mdInfo ; - DistPointCurve dstPtCurve( ptRef, *pCrv) ; - if ( dstPtCurve.GetMinDistInfo( 0, mdInfo)) { - ptP = mdInfo.ptQ ; - ptP.ToGlob( frEnt) ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - Point3d ptTmp ; - pCrv->GetPointTang( mdInfo.dPar, ICurve::FROM_MINUS, ptTmp, m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - // eventuale verifica dell'estruso - if ( bExtr) { - Vector3d vtTemp = vtExtr ; - vtTemp.ToLoc( frEnt) ; - // determino il punto più vicino della curva a questo - MinDistPCInfo mdInfo ; - DistPointCurve dstPtCurve( ptRef - vtTemp, *pCrv) ; - if ( dstPtCurve.GetMinDistInfo( 0, mdInfo)) { - ptP = mdInfo.ptQ ; - ptP.ToGlob( frEnt) ; - ptP += vtExtr ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nId ; - m_bLastSnapDirOk = true ; - Point3d ptTmp ; - pCrv->GetPointTang( mdInfo.dPar, ICurve::FROM_MINUS, ptTmp, m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - } - } - break ; - } - return bFound ; -} - -//---------------------------------------------------------------------------- -bool -Scene::VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSqDist) -{ - // proietto il punto sulla viewport - Point3d ptWinP ; - Project( ptP, ptWinP) ; - // confronto le distanze - double dSqDist = SqDistXY( ptWin, ptWinP) ; - if ( dSqDist < dMinSqDist) { - dMinSqDist = dSqDist ; - return true ; - } - return false ; -} - -//---------------------------------------------------------------------------- -bool -Scene::GetSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH, Point3d& ptSel) +Scene::FindSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH) { // --- l'intersezione viene calcolata nel piano della griglia --- // verifico siano state selezionate delle entità @@ -570,8 +192,498 @@ Scene::GetSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH, Point ptNear.ToLoc( frGrid) ; // calcolo il punto di intersezione sulla prima curva più vicino al punto di riferimento IntersCurveCurve intCC( *pCrv[0], *pCrv[1], true) ; - if ( ! intCC.GetIntersPointNearTo( 0, ptNear, ptSel)) + if ( ! intCC.GetIntersPointNearTo( 0, ptNear, m_ptLastSnapPnt)) return false ; - ptSel.ToGlob( frGrid) ; + m_ptLastSnapPnt.ToGlob( frGrid) ; return true ; +} + +//---------------------------------------------------------------------------- +bool +Scene::FindSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH) +{ + // verifico siano state selezionate delle entità + int nSel ; + Select( ptWin, nW, nH, nSel) ; + if ( nSel <= 0) + return false ; + // cerco il punto notevole più vicino alla selezione tra le entità selezionate + bool bFound = false ; + double dMinSqDist = INFINITO * INFINITO ; + for ( int nId = GetFirstSelectedObj() ; nId != GDB_ID_NULL ; nId = GetNextSelectedObj()) { + // se non è entità geometrica + const IGeoObj* pGObj ; + if ( ( pGObj = m_pGeomDB->GetGeoObj( nId)) == nullptr) + continue ; + // recupero riferimento dell'entità + Frame3d frEnt ; + if ( ! m_pGeomDB->GetGlobFrame( nId, frEnt)) + continue ; + // se punto + if ( pGObj->GetType() == GEO_PNT3D) { + // recupero il geo-punto + const IGeoPoint3d* pGP = GetGeoPoint3d( pGObj) ; + // recupero il punto + Point3d ptP = pGP->GetPoint() ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + } + // se vettore + else if ( pGObj->GetType() == GEO_VECT3D) { + // recupero il geo-vettore + const IGeoVector3d* pGV = GetGeoVector3d( pGObj) ; + // recupero il punto base + Point3d ptP = pGV->GetBase() ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = pGV->GetVector() ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + // se frame + else if ( pGObj->GetType() == GEO_FRAME3D) { + // recupero il geo-frame + const IGeoFrame3d* pGF = GetGeoFrame3d( pGObj) ; + // recupero l'origine del riferimento + Point3d ptP = pGF->GetFrame().Orig() ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + } + // se curva composita + else if ( pGObj->GetType() == CRV_COMPO) { + // recupero la curva composita + const ICurveComposite* pCrvCompo = GetCurveComposite( pGObj) ; + // verifico i punti notevoli della curva composita + if ( FindCurveCompoSnapPoint( nSnap, ptWin, nId, frEnt, pCrvCompo, dMinSqDist)) + bFound = true ; + } + // se curva semplice + else if ( ( pGObj->GetType() & GEO_CURVE) != 0) { + // recupero la curva + const ICurve* pCrv = GetCurve( pGObj) ; + // verifico i punti notevoli della curva + if ( FindCurveSnapPoint( nSnap, ptWin, nId, frEnt, pCrv, dMinSqDist)) + bFound = true ; + } + // se superficie trimesh + else if ( pGObj->GetType() == SRF_TRIMESH) { + // recupero la superficie + const ISurfTriMesh* pStm = GetSurfTriMesh( pGObj) ; + // verifico i punti notevoli della superficie + if ( FindSurfTMSnapPoint( nSnap, ptWin, nId, frEnt, pStm, dMinSqDist)) + bFound = true ; + } + // se testo + else if ( pGObj->GetType() == EXT_TEXT) { + // recupero il testo + const IExtText* pTxt = GetExtText( pGObj) ; + // verifico i punti notevoli del testo + if ( FindTextSnapPoint( nSnap, ptWin, nId, frEnt, pTxt, dMinSqDist)) + bFound = true ; + } + } + return bFound ; +} + +//---------------------------------------------------------------------------- +bool +Scene::FindCurveSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const ICurve* pCrv, double& dMinSqDist) +{ + // recupero il punto + bool bFound = false ; + Point3d ptP ; + switch ( nSnap) { + case SP_END : + // punto iniziale + if ( pCrv->GetStartPoint( ptP)) { + AdjustForCurveExtr( ptWin, frEnt, pCrv, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + pCrv->GetStartDir( m_vtLastSnapDir) ; + m_vtLastSnapDir.ToGlob( frEnt) ; + m_vtLastSnapDir.Invert() ; + } + } + // punto finale + if ( pCrv->GetEndPoint( ptP)) { + AdjustForCurveExtr( ptWin, frEnt, pCrv, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + pCrv->GetEndDir( m_vtLastSnapDir) ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + break ; + case SP_MID : + if ( pCrv->GetMidPoint( ptP)) { + AdjustForCurveExtr( ptWin, frEnt, pCrv, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + pCrv->GetMidDir( m_vtLastSnapDir) ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + break ; + case SP_CENTER : + if ( pCrv->GetCenterPoint( ptP)) { + AdjustForCurveExtr( ptWin, frEnt, pCrv, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + } + break ; + case SP_CENTROID : + if ( pCrv->GetCentroid( ptP)) { + AdjustForCurveExtr( ptWin, frEnt, pCrv, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + } + break ; + case SP_NEAR : + case SP_TANG : + case SP_PERP : + case SP_MINDIST : + { + // il punto di riferimento deriva da XY su viewport e Z media da selezione + Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjWinZ()) ; + // lo porto da spazio grafico a spazio geometrico globale + Point3d ptRef ; + UnProject( ptWinZ, ptRef) ; + // lo porto nel frame della curva + ptRef.ToLoc( frEnt) ; + // determino il punto più vicino della curva a questo + MinDistPCInfo mdInfo ; + DistPointCurve dstPtCurve( ptRef, *pCrv) ; + if ( dstPtCurve.GetMinDistInfo( 0, mdInfo)) { + ptP = mdInfo.ptQ ; + AdjustForCurveExtr( ptWin, frEnt, pCrv, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWinZ, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + Point3d ptTmp ; + pCrv->GetPointTang( mdInfo.dPar, ICurve::FROM_MINUS, ptTmp, m_vtLastSnapDir) ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + } + break ; + } + return bFound ; +} + +//---------------------------------------------------------------------------- +bool +Scene::VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSqDist) +{ + // proietto il punto sulla viewport + Point3d ptWinP ; + Project( ptP, ptWinP) ; + // confronto le distanze + double dSqDist = SqDistXY( ptWin, ptWinP) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +Scene::AdjustForCurveExtr( const Point3d& ptWin, const Frame3d& frEnt, const ICurve* pCrv, + Point3d& ptP) +{ + // recupero l'eventuale estrusione della curva + double dTh ; + Vector3d vtExtr ; + if ( ! pCrv->GetExtrusion( vtExtr) || vtExtr.IsSmall() || + ! pCrv->GetThickness( dTh) || fabs( dTh) < EPS_SMALL) + return false ; + vtExtr *= dTh ; + + // il punto di riferimento deriva da XY su viewport e Z media da selezione + Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjWinZ()) ; + // lo porto da spazio grafico a spazio geometrico globale + Point3d ptRef ; + UnProject( ptWinZ, ptRef) ; + // lo porto nel frame della curva + ptRef.ToLoc( frEnt) ; + + // determino la minima distanza dalla curva base + double dBaseSqDist = INFINITO ; + DistPointCurve dstPtBCurve( ptRef, *pCrv) ; + dstPtBCurve.GetSqDist( dBaseSqDist) ; + // determino la minima distanza dalla curva estrusa (sposto il punto del contrario dell'estrusione) + double dExtrSqDist = INFINITO ; + DistPointCurve dstPtECurve( ptRef - vtExtr, *pCrv) ; + dstPtECurve.GetSqDist( dExtrSqDist) ; + // se più vicino a base non devo modificare il punto + if ( dBaseSqDist <= dExtrSqDist) + return false ; + // più vicino ad estrusione, quindi la aggiungo + ptP += vtExtr ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Scene::FindCurveCompoSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const ICurveComposite* pCrvCompo, double& dMinSqDist) +{ + // il punto di riferimento deriva da XY su viewport e Z media da selezione + Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjWinZ()) ; + // punto di riferimento nello spazio geometrico 3d + Point3d ptRef ; + if ( ! UnProject( ptWinZ, ptRef)) + return false ; + // porto il punto nel riferimento della curva + ptRef.ToLoc( frEnt) ; + // se richiesto il centro di gravità (baricentro, centroide) + if ( nSnap == SP_CENTROID) { + Point3d ptP ; + bool bFound = false ; + if ( pCrvCompo->GetCentroid( ptP)) { + AdjustForCurveExtr( ptWin, frEnt, pCrvCompo, ptP) ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + } + return bFound ; + } + // altrimenti opero sulle curve componenti elementari + // determino la curva elementare più vicina al punto di riferimento + int nCrv = - 1 ; + double dPar ; + int nFlag ; + // cerco il punto della curva più vicino, dal suo parametro deduco la curva elementare + if ( DistPointCurve( ptRef, *pCrvCompo).GetParamAtMinDistPoint( 0, dPar, nFlag)) + nCrv = static_cast( dPar) ; + // lavoro sulla curva elementare + bool bFound = false ; + const ICurve* pCrv = pCrvCompo->GetCurve( nCrv) ; + if ( pCrv != nullptr) { + // vettore estrusione e spessore della curva composita + Vector3d vtExtr = V_NULL ; + pCrvCompo->GetExtrusion( vtExtr) ; + double dThick = 0 ; + pCrvCompo->GetThickness( dThick) ; + // imposto estrusione e spessore della curva composita + (const_cast(pCrv))->SetExtrusion( vtExtr) ; + (const_cast(pCrv))->SetThickness( dThick) ; + // verifico i punti notevoli della curva + if ( FindCurveSnapPoint( nSnap, ptWin, nId, frEnt, pCrv, dMinSqDist)) + bFound = true ; + // ripristino valori originali + (const_cast(pCrv))->SetExtrusion( V_NULL) ; + (const_cast(pCrv))->SetThickness( 0) ; + } + return bFound ; +} + +//---------------------------------------------------------------------------- +bool +Scene::FindSurfTMSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const ISurfTriMesh* pStm, 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) ; + // salvo stato precedente di snap + bool bPrevFound = ( m_nLastSnapId != GDB_ID_NULL) ; + // cerco il vertice a minor distanza dalla linea + bool bFound = false ; + int nVert ; + Point3d ptMin ; + Point3d ptP ; + int nIv = pStm->GetFirstVertex( ptP) ; + while ( nIv != SVT_NULL) { + // in generale (shading e hiddenline) il punto di confronto è quello di riferimento + Point3d ptCfr = ptRef ; + // se wireframe, il punto di confronto è quello della linea di mira a minima distanza dal vertice + if ( m_nShowMode == SM_WIREFRAME) + 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 ; + nVert = nIv ; + ptMin = ptCfr ; + dMinSqDist = dSqDist ; + ptP.ToGlob( frEnt) ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + // passo al successivo + nIv = pStm->GetNextVertex( nIv, ptP) ; + } + // se è la prima selezione e non è modalità wireframe, la favorisco perchè davanti + if ( bFound && ! bPrevFound && m_nShowMode != SM_WIREFRAME) + dMinSqDist = 0 ; + // se trovato punto, cerco la faccia + if ( bFound) { + // cerco i triangoli intorno al vertice + INTVECTOR vTria ; + bool bCirc ; + int nTtot = pStm->GetAllTriaAroundVertex( nVert, vTria, bCirc) ; + // tra quelli che intersecano la linea di mira prendo il più vicino al punto Minimo + double dMinSqDistFace = INFINITO * INFINITO ; + for ( int i = 0 ; i < int( vTria.size()) ; ++ i) { + Triangle3d Tria ; + if ( ! pStm->GetTriangle( vTria[i], Tria)) + continue ; + Point3d ptInt ; + int nRes = IntersLineTria( ptRef - vtDir * 1000, vtDir, 2000, Tria, ptInt) ; + if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) { + double dSqDist = SqDist( ptInt, ptMin) ; + if ( dSqDist < dMinSqDistFace) { + dMinSqDistFace = dSqDist ; + m_bLastSnapDirOk = true ; + pStm->GetVertexSmoothNormal( nVert, vTria[i], m_vtLastSnapDir) ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + } + } + // risultato dello snap su questo oggetto + return bFound ; +} + +//---------------------------------------------------------------------------- +bool +Scene::FindTextSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, + const IExtText* pTxt, double& dMinSqDist) +{ + // cerco il punto + bool bFound = false ; + Point3d ptP ; + switch ( nSnap) { + case SP_END : + // punto iniziale + if ( pTxt->GetStartPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = pTxt->GetDirVersor() ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + // punto sopra iniziale + if ( pTxt->GetOverStartPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = pTxt->GetDirVersor() ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + // punto finale + if ( pTxt->GetEndPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = pTxt->GetDirVersor() ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + // punto sopra finale + if ( pTxt->GetOverEndPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = pTxt->GetDirVersor() ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + break ; + case SP_MID : + // punto medio + if ( pTxt->GetMidPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = true ; + m_vtLastSnapDir = pTxt->GetDirVersor() ; + m_vtLastSnapDir.ToGlob( frEnt) ; + } + } + break ; + case SP_CENTER : + // centro + if ( pTxt->GetCenterPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { + bFound = true ; + m_nLastSnapId = nId ; + m_ptLastSnapPnt = ptP ; + m_bLastSnapDirOk = false ; + } + } + break ; + } + return bFound ; } \ No newline at end of file