diff --git a/EgtGraphics.rc b/EgtGraphics.rc index ff7b49b..35d2ab6 100644 Binary files a/EgtGraphics.rc and b/EgtGraphics.rc differ diff --git a/EgtGraphics.vcxproj b/EgtGraphics.vcxproj index d3ef789..92fa550 100644 --- a/EgtGraphics.vcxproj +++ b/EgtGraphics.vcxproj @@ -233,6 +233,7 @@ copy $(TargetPath) \EgtProg\Dll64 + Create diff --git a/EgtGraphics.vcxproj.filters b/EgtGraphics.vcxproj.filters index 5f51ea5..0b0d70b 100644 --- a/EgtGraphics.vcxproj.filters +++ b/EgtGraphics.vcxproj.filters @@ -107,6 +107,9 @@ File di origine + + File di origine + diff --git a/ObjNewGraphics.cpp b/ObjNewGraphics.cpp index 2750169..d873418 100644 --- a/ObjNewGraphics.cpp +++ b/ObjNewGraphics.cpp @@ -290,19 +290,24 @@ ObjNewGraphics::Draw( int nStat, int nMark, bool bSurfSha, bool bShowAux) glLineWidth( 3) ; } - // colore speciale per superficie shading selezionata o marcata + // colori speciali per superficie shading selezionata o marcata bool bStdCol = true ; float fSelMarkCol[4] = { 1, 1, 1, 1} ; + float fSelMarkBackCol[4] = { 0.75, 0.75, 0.75, 1} ; if ( bSurfSha) { if ( nMark == GDB_MK_ON) { bStdCol = false ; Color colMark = ( ( GetScene() != nullptr) ? GetScene()->GetMark() : Color( 192, 192, 0)) ; colMark.GetFloat( fSelMarkCol) ; + Color colMarkBack = GetSurfBackColor( colMark) ; + colMarkBack.GetFloat( fSelMarkBackCol) ; } else if ( nStat == GDB_ST_SEL) { bStdCol = false ; Color colSelSurf = ( ( GetScene() != nullptr) ? GetScene()->GetSelSurf() : Color( 255, 255, 192)) ; colSelSurf.GetFloat( fSelMarkCol) ; + Color colSelSurfBack = GetSurfBackColor( colSelSurf) ; + colSelSurfBack.GetFloat( fSelMarkBackCol) ; } } @@ -340,7 +345,7 @@ ObjNewGraphics::Draw( int nStat, int nMark, bool bSurfSha, bool bShowAux) glMaterialf( GL_FRONT, GL_SHININESS, iIter->m_fCol[0]) ; break ; case NgAtom::MAT_B : - glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, iIter->m_fCol) ; + glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, ( bStdCol ? iIter->m_fCol : fSelMarkBackCol)) ; break ; } } diff --git a/ObjOldGraphics.cpp b/ObjOldGraphics.cpp index aba64f2..6d70150 100644 --- a/ObjOldGraphics.cpp +++ b/ObjOldGraphics.cpp @@ -195,16 +195,21 @@ ObjOldGraphics::Draw( int nStat, int nMark, bool bSurfSha, bool bShowAux) // colore speciale per superficie shading selezionata o marcata bool bStdCol = true ; float fSelMarkCol[4] = { 1, 1, 1, 1} ; + float fSelMarkBackCol[4] = { 0.75, 0.75, 0.75, 1} ; if ( bSurfSha) { if ( nMark == GDB_MK_ON) { bStdCol = false ; Color colMark = ( ( GetScene() != nullptr) ? GetScene()->GetMark() : Color( 255, 255, 0)) ; colMark.GetFloat( fSelMarkCol) ; + Color colMarkBack = GetSurfBackColor( colMark) ; + colMarkBack.GetFloat( fSelMarkBackCol) ; } else if ( nStat == GDB_ST_SEL) { bStdCol = false ; Color colSelSurf = ( ( GetScene() != nullptr) ? GetScene()->GetSelSurf() : Color( 255, 255, 192)) ; colSelSurf.GetFloat( fSelMarkCol) ; + Color colSelSurfBack = GetSurfBackColor( colSelSurf) ; + colSelSurfBack.GetFloat( fSelMarkBackCol) ; } } @@ -251,7 +256,7 @@ ObjOldGraphics::Draw( int nStat, int nMark, bool bSurfSha, bool bShowAux) glMaterialf( GL_FRONT, GL_SHININESS, iIter->m_fVal[0]) ; break ; case OgAtom::MAT_B : - glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, iIter->m_fVal) ; + glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, ( bStdCol ? iIter->m_fVal : fSelMarkBackCol)) ; break ; } } diff --git a/Scene.h b/Scene.h index 0096d45..bda716e 100644 --- a/Scene.h +++ b/Scene.h @@ -19,6 +19,7 @@ #include "OpenGL.h" class IGdbIterator ; +class ICurve ; //---------------------------------------------------------------------------- class MdStMk @@ -69,6 +70,7 @@ class Scene : public IEGrScene virtual int GetFirstSelectedObj( void) ; virtual int GetNextSelectedObj( void) ; virtual double GetSelectedObjWinZ( 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) ; virtual void Destroy( void) ; @@ -172,6 +174,8 @@ class Scene : public IEGrScene // 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 VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSqDist) ; bool GetSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH, Point3d& ptSel) ; diff --git a/SceneBasic.cpp b/SceneBasic.cpp index de16007..a7489c5 100644 --- a/SceneBasic.cpp +++ b/SceneBasic.cpp @@ -758,173 +758,6 @@ Scene::Draw( void) return true ; } -//---------------------------------------------------------------------------- -int -CompareSelRec( const void* pSr1, const void* pSr2) -{ - if ( ((SelRec*)pSr1)->nZmin > ((SelRec*)pSr2)->nZmin) - return 1 ; - else if ( ((SelRec*)pSr1)->nZmin < ((SelRec*)pSr2)->nZmin) - return - 1 ; - else { - if ( ((SelRec*)pSr1)->nId > ((SelRec*)pSr2)->nId) - return 1 ; - else if ( ((SelRec*)pSr1)->nId < ((SelRec*)pSr2)->nId) - return - 1 ; - else - return 0 ; - } -} - -//---------------------------------------------------------------------------- -bool -Scene::Select( const Point3d& ptSelCenter, int nW, int nH, int& nSel) -{ - // inizializzo selezione - m_bSelect = true ; - m_ptSelCent = ptSelCenter ; - m_nSelW = abs( nW) ; - m_nSelH = abs( nH) ; - m_nSelNbr = 0 ; - - // se una delle due dimensioni è nulla, non posso selezionare alcunché - if ( m_nSelW == 0 || m_nSelH == 0) { - m_bSelect = false ; - nSel = m_nSelNbr ; - return true ; - } - - // sfondo e Zbuffer non interessano - - // imposto la camera, riducendo la viewport all'area di selezione - if ( ! Prepare()) { - m_bSelect = false ; - nSel = m_nSelNbr ; - return false ; - } - - // imposto modalità di selezione - glSelectBuffer( DIM_SEL_BUF, (GLuint*)m_nSelBuff) ; - glRenderMode( GL_SELECT) ; - - // inizializzo stack dei nomi - glInitNames() ; - glPushName( 0) ; - - // eseguo disegno - // disabilito illuminazione - glDisable( GL_LIGHTING) ; - // non imposto glPolygonMode secondo il tipo di rendering perchè ignorato in selezione - // disegno le geometrie del DB in una sola passata - DrawGroup( GDB_ID_ROOT, 1, MdStMk( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF)) ; - - // pulisco stack nomi - glPopName() ; - - // chiudo modalità selezione, recupero buffer ripristino le matrici di OpenGL - m_nSelNbr = glRenderMode( GL_RENDER) ; - if ( m_nSelNbr < 0) - m_nSelNbr = DIM_SEL_BUF ; - m_bSelect = false ; - Prepare() ; - - // riordino il buffer di selezione secondo la Zdepth minima crescente - qsort( m_nSelBuff, m_nSelNbr, sizeof( SelRec), CompareSelRec) ; - - nSel = m_nSelNbr ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Scene::GetSelectedObjs( INTVECTOR& nIds) -{ - // inizializzo vettore Id - nIds.clear() ; - try { nIds.reserve( m_nSelNbr) ; } - catch(...) { return false ; } - // inserisco l'Id degli oggetti selezionati - for ( int i = 0 ; i < m_nSelNbr ; ++ i) - nIds.push_back( m_nSelBuff[i].nId) ; - return true ; -} - -//---------------------------------------------------------------------------- -int -Scene::GetFirstSelectedObj( void) -{ - m_nSelCurr = - 1 ; - return GetNextSelectedObj() ; -} - -//---------------------------------------------------------------------------- -int -Scene::GetNextSelectedObj( void) -{ - // fuori dal range - m_nSelCurr ++ ; - if ( m_nSelCurr < 0 || m_nSelCurr >= m_nSelNbr) - return GDB_ID_NULL ; - return m_nSelBuff[m_nSelCurr].nId ; -} - -//---------------------------------------------------------------------------- -double -Scene::GetSelectedObjWinZ( int nSel) -{ - if ( nSel < 0) - nSel = m_nSelCurr ; - if ( nSel < 0 || nSel >= m_nSelNbr) - return 0.5 ; - return 0.5 * ( double( m_nSelBuff[nSel].nZmin) + double( m_nSelBuff[nSel].nZmax)) / UINT_MAX ; -} - -/*------------------------------------------------------------------------------------------*/ -bool -Scene::UnselectableAdd( int nId) -{ - // non si ammettono radice e id negativi - if ( nId <= GDB_ID_ROOT) - return false ; - // inserisco l'elemento - m_Unsel.push_back( nId) ; - // ordino in senso crescente - stable_sort( m_Unsel.begin(), m_Unsel.end()) ; - return true ; -} - -/*------------------------------------------------------------------------------------------*/ -bool -Scene::UnselectableRemove( int nId) -{ - // non si ammettono radice e id negativi - if ( nId <= GDB_ID_ROOT) - return false ; - // cerco l'elemento - INTVECTOR::iterator Iter = find( m_Unsel.begin(), m_Unsel.end(), nId) ; - if ( Iter == m_Unsel.end()) - return true ; - m_Unsel.erase( Iter) ; - return true ; -} - -/*------------------------------------------------------------------------------------------*/ -bool -Scene::UnselectableClearAll( void) -{ - // cancello tutto - m_Unsel.clear() ; - return true ; -} - -/*------------------------------------------------------------------------------------------*/ -bool -Scene::UnselectableFind( int nId) -{ - // eseguo ricerca su vettore ordinato in senso crescente - return binary_search( m_Unsel.begin(), m_Unsel.end(), nId) ; -} - /*------------------------------------------------------------------------------------------*/ bool Scene::Project( const Point3d& ptWorld, Point3d& ptView) diff --git a/SceneSelect.cpp b/SceneSelect.cpp new file mode 100644 index 0000000..f5a6e78 --- /dev/null +++ b/SceneSelect.cpp @@ -0,0 +1,340 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : SceneSelect.cpp Data : 26.11.14 Versione : 1.5k5 +// Contenuto : Implementazione della selezione nella scena. +// +// +// +// Modifiche : 26.11.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "Scene.h" +#include "GraphObjs.h" +#include "DllMain.h" +#include "/EgtDev/Include/EgkGeoPoint3d.h" +#include "/EgtDev/Include/EgkGeoVector3d.h" +#include "/EgtDev/Include/EGkFrame3d.h" +#include "/EgtDev/Include/EGkCurve.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkExtText.h" +#include "/EgtDev/Include/EGkGdbConst.h" +#include "/EgtDev/Include/EGkGeomDB.h" +#include + +using namespace std ; + + +//---------------------------------------------------------------------------- +int +CompareSelRec( const void* pSr1, const void* pSr2) +{ + if ( ((SelRec*)pSr1)->nZmin > ((SelRec*)pSr2)->nZmin) + return 1 ; + else if ( ((SelRec*)pSr1)->nZmin < ((SelRec*)pSr2)->nZmin) + return - 1 ; + else { + if ( ((SelRec*)pSr1)->nId > ((SelRec*)pSr2)->nId) + return 1 ; + else if ( ((SelRec*)pSr1)->nId < ((SelRec*)pSr2)->nId) + return - 1 ; + else + return 0 ; + } +} + +//---------------------------------------------------------------------------- +bool +Scene::Select( const Point3d& ptSelCenter, int nW, int nH, int& nSel) +{ + // inizializzo selezione + m_bSelect = true ; + m_ptSelCent = ptSelCenter ; + m_nSelW = abs( nW) ; + m_nSelH = abs( nH) ; + m_nSelNbr = 0 ; + + // se una delle due dimensioni è nulla, non posso selezionare alcunché + if ( m_nSelW == 0 || m_nSelH == 0) { + m_bSelect = false ; + nSel = m_nSelNbr ; + return true ; + } + + // sfondo e Zbuffer non interessano + + // imposto la camera, riducendo la viewport all'area di selezione + if ( ! Prepare()) { + m_bSelect = false ; + nSel = m_nSelNbr ; + return false ; + } + + // imposto modalità di selezione + glSelectBuffer( DIM_SEL_BUF, (GLuint*)m_nSelBuff) ; + glRenderMode( GL_SELECT) ; + + // inizializzo stack dei nomi + glInitNames() ; + glPushName( 0) ; + + // eseguo disegno + // disabilito illuminazione + glDisable( GL_LIGHTING) ; + // non imposto glPolygonMode secondo il tipo di rendering perchè ignorato in selezione + // disegno le geometrie del DB in una sola passata + DrawGroup( GDB_ID_ROOT, 1, MdStMk( GDB_MD_STD, GDB_ST_ON, GDB_MK_OFF)) ; + + // pulisco stack nomi + glPopName() ; + + // chiudo modalità selezione, recupero buffer ripristino le matrici di OpenGL + m_nSelNbr = glRenderMode( GL_RENDER) ; + if ( m_nSelNbr < 0) + m_nSelNbr = DIM_SEL_BUF ; + m_bSelect = false ; + Prepare() ; + + // riordino il buffer di selezione secondo la Zdepth minima crescente + qsort( m_nSelBuff, m_nSelNbr, sizeof( SelRec), CompareSelRec) ; + + nSel = m_nSelNbr ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Scene::GetSelectedObjs( INTVECTOR& nIds) +{ + // inizializzo vettore Id + nIds.clear() ; + try { nIds.reserve( m_nSelNbr) ; } + catch(...) { return false ; } + // inserisco l'Id degli oggetti selezionati + for ( int i = 0 ; i < m_nSelNbr ; ++ i) + nIds.push_back( m_nSelBuff[i].nId) ; + return true ; +} + +//---------------------------------------------------------------------------- +int +Scene::GetFirstSelectedObj( void) +{ + m_nSelCurr = - 1 ; + return GetNextSelectedObj() ; +} + +//---------------------------------------------------------------------------- +int +Scene::GetNextSelectedObj( void) +{ + // fuori dal range + m_nSelCurr ++ ; + if ( m_nSelCurr < 0 || m_nSelCurr >= m_nSelNbr) + return GDB_ID_NULL ; + return m_nSelBuff[m_nSelCurr].nId ; +} + +//---------------------------------------------------------------------------- +double +Scene::GetSelectedObjWinZ( int nSel) +{ + if ( nSel < 0) + nSel = m_nSelCurr ; + if ( nSel < 0 || nSel >= m_nSelNbr) + return 0.5 ; + return 0.5 * ( double( m_nSelBuff[nSel].nZmin) + double( m_nSelBuff[nSel].nZmax)) / UINT_MAX ; +} + +/*------------------------------------------------------------------------------------------*/ +bool +Scene::UnselectableAdd( int nId) +{ + // non si ammettono radice e id negativi + if ( nId <= GDB_ID_ROOT) + return false ; + // inserisco l'elemento + m_Unsel.push_back( nId) ; + // ordino in senso crescente + stable_sort( m_Unsel.begin(), m_Unsel.end()) ; + return true ; +} + +/*------------------------------------------------------------------------------------------*/ +bool +Scene::UnselectableRemove( int nId) +{ + // non si ammettono radice e id negativi + if ( nId <= GDB_ID_ROOT) + return false ; + // cerco l'elemento + INTVECTOR::iterator Iter = find( m_Unsel.begin(), m_Unsel.end(), nId) ; + if ( Iter == m_Unsel.end()) + return true ; + m_Unsel.erase( Iter) ; + return true ; +} + +/*------------------------------------------------------------------------------------------*/ +bool +Scene::UnselectableClearAll( void) +{ + // cancello tutto + m_Unsel.clear() ; + return true ; +} + +/*------------------------------------------------------------------------------------------*/ +bool +Scene::UnselectableFind( int nId) +{ + // eseguo ricerca su vettore ordinato in senso crescente + return binary_search( m_Unsel.begin(), m_Unsel.end(), nId) ; +} + +/*------------------------------------------------------------------------------------------*/ +bool +Scene::GetPointFromSelect( int nSelId, const Point3d& ptView, Point3d& ptSel) +{ + // recupera il punto di mira proiettato sull'oggetto appena selezionato + // (va eseguito subito dopo la Select da cui si è derivato l'Id) + // è simile a GetSelectedSnapPoint + + // rendo corrente l'entità selezionata + bool bFound = false ; + for ( int nId = GetFirstSelectedObj() ; nId != GDB_ID_NULL ; nId = GetNextSelectedObj()) { + if ( nId == nSelId) { + bFound = true ; + break ; + } + } + if ( ! bFound) + return false ; + + // verifico sia entità geometrica + const IGeoObj* pGObj ; + if ( ( pGObj = m_pGeomDB->GetGeoObj( nSelId)) == nullptr) + return false ; + + // recupero riferimento dell'entità + Frame3d frEnt ; + if ( ! m_pGeomDB->GetGlobFrame( nSelId, frEnt)) + return false ; + + // se punto + if ( pGObj->GetType() == GEO_PNT3D) { + // recupero il geo-punto + const IGeoPoint3d* pGP = GetGeoPoint3d( pGObj) ; + // recupero il punto + ptSel = pGP->GetPoint() ; + ptSel.ToGlob( frEnt) ; + } + // se vettore + else if ( pGObj->GetType() == GEO_VECT3D) { + // recupero il geo-vettore + const IGeoVector3d* pGV = GetGeoVector3d( pGObj) ; + // recupero il punto + ptSel = pGV->GetBase() ; + ptSel.ToGlob( frEnt) ; + } + // se frame + else if ( pGObj->GetType() == GEO_FRAME3D) { + // recupero il geo-frame + const IGeoFrame3d* pGF = GetGeoFrame3d( pGObj) ; + // recupero il punto + ptSel = pGF->GetFrame().Orig() ; + ptSel.ToGlob( frEnt) ; + } + // se curva + 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( ptView.x, ptView.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 + double dMinSqDist = INFINITO * INFINITO ; + MinDistPCInfo mdInfo ; + DistPointCurve dstPtCurve( ptRef, *pCrv) ; + if ( dstPtCurve.GetMinDistInfo( 0, mdInfo)) { + Point3d ptP = mdInfo.ptQ ; + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + // eventuale verifica dell'estruso + double dTh ; + Vector3d vtExtr ; + if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall() && + pCrv->GetThickness( dTh) && fabs( dTh) > EPS_SMALL) { + vtExtr *= dTh ; + vtExtr.ToGlob( frEnt) ; + // correggo il punto di riferimento del contrario dell'estrusione + 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)) { + Point3d ptP = mdInfo.ptQ ; + ptP.ToGlob( frEnt) ; + ptP += vtExtr ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + } + } + // se testo + else if ( pGObj->GetType() == EXT_TEXT) { + // recupero il testo + const IExtText* pTxt = GetExtText( pGObj) ; + // cerco il punto + double dMinSqDist = INFINITO * INFINITO ; + Point3d ptP ; + // punto iniziale + if ( pTxt->GetStartPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + // punto sopra iniziale + if ( pTxt->GetOverStartPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + // punto finale + if ( pTxt->GetEndPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + // punto sopra finale + if ( pTxt->GetOverEndPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + // punto medio + if ( pTxt->GetMidPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + // centro + if ( pTxt->GetCenterPoint( ptP)) { + ptP.ToGlob( frEnt) ; + if ( VerifySnapPoint( ptP, ptView, dMinSqDist)) + ptSel = ptP ; + } + } + return true ; +} diff --git a/SceneSnap.cpp b/SceneSnap.cpp index b9e3326..52ed565 100644 --- a/SceneSnap.cpp +++ b/SceneSnap.cpp @@ -19,6 +19,7 @@ #include "/EgtDev/Include/EgkGeoVector3d.h" #include "/EgtDev/Include/EGkFrame3d.h" #include "/EgtDev/Include/EGkCurve.h" +#include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EgkIntersCurveCurve.h" @@ -117,20 +118,17 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po Select( ptWin, nW, nH, nSel) ; if ( nSel <= 0) return false ; - // recupero le entità selezionate - INTVECTOR nIds ; - GetSelectedObjs( nIds) ; - // cerco il punto notevole più vicino alla selezione + // cerco il punto notevole più vicino alla selezione tra le entità selezionate bool bFound = false ; double dMinSqDist = INFINITO * INFINITO ; - for ( size_t i = 0 ; i < nIds.size() ; ++ i) { + for ( int nId = GetFirstSelectedObj() ; nId != GDB_ID_NULL ; nId = GetNextSelectedObj()) { // se non è entità geometrica const IGeoObj* pGObj ; - if ( ( pGObj = m_pGeomDB->GetGeoObj( nIds[i])) == nullptr) + if ( ( pGObj = m_pGeomDB->GetGeoObj( nId)) == nullptr) continue ; // recupero riferimento dell'entità Frame3d frEnt ; - if ( ! m_pGeomDB->GetGlobFrame( nIds[i], frEnt)) + if ( ! m_pGeomDB->GetGlobFrame( nId, frEnt)) continue ; // se punto if ( pGObj->GetType() == GEO_PNT3D) { @@ -142,7 +140,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = false ; } } @@ -156,7 +154,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = pGV->GetVector() ; m_vtLastSnapDir.ToGlob( frEnt) ; @@ -172,174 +170,35 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = false ; } } - // se curva + // 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()) ; + // ciclo sulle curve elementari + const ICurve* pCrv = pCrvCompo->GetFirstCurve() ; + while ( pCrv != nullptr) { + // verifico i punti notevoli della curva + if ( TestCurveSnapPoints( nSnap, ptWinZ, nId, frEnt, pCrv, dMinSqDist, ptSel)) + bFound = true ; + // passo alla successiva + pCrv = pCrvCompo->GetNextCurve() ; + } + } + // se curva semplice else if ( ( pGObj->GetType() & GEO_CURVE) != 0) { // recupero la curva - const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nIds[i])) ; - // 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 - 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 = nIds[i] ; - 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 = nIds[i] ; - 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 = nIds[i] ; - 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 = nIds[i] ; - 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 = nIds[i] ; - 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 = nIds[i] ; - 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 = nIds[i] ; - m_bLastSnapDirOk = false ; - } - // eventuale verifica dell'estruso - if ( bExtr) { - ptP += vtExtr ; - if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { - bFound = true ; - ptSel = ptP ; - m_nLastSnapId = nIds[i] ; - m_bLastSnapDirOk = false ; - } - } - } - break ; - case SP_NEAR : - { // il punto di riferimento deriva da XY su viewport e Z da selezione - Point3d ptRefWin( ptWin.x, ptWin.y, GetSelectedObjWinZ( int( i))) ; - Point3d ptRef ; - // lo porto da spazio grafico a spazio geometrico globale - UnProject( ptRefWin, 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 = nIds[i] ; - 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, *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 = nIds[i] ; - m_bLastSnapDirOk = true ; - Point3d ptTmp ; - pCrv->GetPointTang( mdInfo.dPar, ICurve::FROM_MINUS, ptTmp, m_vtLastSnapDir) ; - m_vtLastSnapDir.ToGlob( frEnt) ; - } - } - } - } - break ; - } + 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) { @@ -355,7 +214,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = pTxt->GetDirVersor() ; m_vtLastSnapDir.ToGlob( frEnt) ; @@ -367,7 +226,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = pTxt->GetDirVersor() ; m_vtLastSnapDir.ToGlob( frEnt) ; @@ -379,7 +238,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = pTxt->GetDirVersor() ; m_vtLastSnapDir.ToGlob( frEnt) ; @@ -391,7 +250,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = pTxt->GetDirVersor() ; m_vtLastSnapDir.ToGlob( frEnt) ; @@ -405,7 +264,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = pTxt->GetDirVersor() ; m_vtLastSnapDir.ToGlob( frEnt) ; @@ -419,7 +278,7 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; ptSel = ptP ; - m_nLastSnapId = nIds[i] ; + m_nLastSnapId = nId ; m_bLastSnapDirOk = false ; } } @@ -430,6 +289,177 @@ Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Po return bFound ; } +//---------------------------------------------------------------------------- +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) @@ -450,6 +480,7 @@ Scene::VerifySnapPoint( const Point3d& ptP, const Point3d& ptWin, double& dMinSq bool Scene::GetSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH, Point3d& ptSel) { + // l'intersezione viene calcolata nel piano della griglia // verifico siano state selezionate delle entità int nSel ; Select( ptWin, nW, nH, nSel) ; @@ -481,25 +512,34 @@ Scene::GetSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH, Point return false ; if ( ! m_pGeomDB->GetGlobFrame( nId[1], frEnt[1])) return false ; - // se il riferimento della seconda curva è diverso da quello della prima entità, devo trasformarla - PtrOwner crvTrans( nullptr) ; - if ( ! AreSameFrame( frEnt[0], frEnt[1])) { - crvTrans.Set( pCrv[1]->Clone()) ; - if ( IsNull( crvTrans)) + // se il riferimento della seconda curva è diverso da quello della griglia, devo trasformarla + PtrOwner crvTrans0( nullptr) ; + if ( ! AreSameFrame( frEnt[0], m_frGrid)) { + crvTrans0.Set( pCrv[0]->Clone()) ; + if ( IsNull( crvTrans0)) return false ; - crvTrans->LocToLoc( frEnt[1], frEnt[0]) ; - pCrv[1] = ::Get( crvTrans) ; + crvTrans0->LocToLoc( frEnt[0],m_frGrid) ; + pCrv[0] = ::Get( crvTrans0) ; } - // uso il punto sketch come punto vicino e lo porto nel riferimento della prima curva + // se il riferimento della seconda curva è diverso da quello della griglia, devo trasformarla + PtrOwner crvTrans1( nullptr) ; + if ( ! AreSameFrame( frEnt[1], m_frGrid)) { + crvTrans1.Set( pCrv[1]->Clone()) ; + if ( IsNull( crvTrans1)) + return false ; + crvTrans1->LocToLoc( frEnt[1], m_frGrid) ; + pCrv[1] = ::Get( crvTrans1) ; + } + // uso il punto sketch come punto vicino e lo porto nel riferimento della griglia Point3d ptNear ; if ( ! GetGridSnapPoint( true, ptWin, ptNear) || ! UnProject( ptWin, ptNear)) ptNear = ORIG ; - ptNear.ToLoc( frEnt[0]) ; + ptNear.ToLoc( m_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)) return false ; - ptSel.ToGlob( frEnt[0]) ; + ptSel.ToGlob( m_frGrid) ; return true ; } \ No newline at end of file