Files
EgtGraphics/SceneSnap.cpp
T
Dario Sassi d5fff587aa EgtGraphics 1.5k3 :
- insieme con punto snap si prende la direzione e l'id dell'oggetto generatore
- si marca anche l'inizio delle curve, quando richiesto.
2014-11-21 17:45:13 +00:00

505 lines
19 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : SceneSnap.cpp Data : 09.10.14 Versione : 1.5j1
// Contenuto : Implementazione snap di punti trmite selezione.
//
//
//
// Modifiche : 09.10.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Scene.h"
#include "/EgtDev/Include/EGkGeomDB.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/EgkIntersCurveCurve.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
Scene::GetGraphicSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Point3d& ptSel)
{
// reset dati associati a ultimo punto snap
m_nLastSnapId = GDB_ID_NULL ;
m_bLastSnapDirOk = 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)
{
// 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 * m_frGrid.VersZ() ;
if ( fabs( dDenom) < COS_ORTO_ANG_SMALL)
return false ;
double dU = ( ( m_frGrid.Orig() - ptLine) * m_frGrid.VersZ()) / dDenom ;
ptSel = ptLine + dU * vtLine ;
// porto il punto sul piano di griglia
ptSel.ToLoc( m_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 ;
}
// il punto deve stare sulla griglia
ptSel.z = 0 ;
// lo riporto in globale
ptSel.ToGlob( m_frGrid) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::GetGridSnapPointZ( bool bSketch, const Point3d& ptWin, const Point3d& ptGrid, Point3d& ptSel)
{
// calcolo un punto e la direzione della linea di mira
Point3d ptLine ;
if ( ! UnProject( ptWin, ptLine))
return false ;
Vector3d vtLine = - m_vtDirCamera ;
// piano di elevazione :
// per il punto di griglia, contenente la perp. alla griglia e più perp. possibile alla direzione di mira
Vector3d vtNorm = vtLine - ( vtLine * m_frGrid.VersZ()) * m_frGrid.VersZ() ;
if ( ! vtNorm.Normalize())
return false ;
// determino l'intersezione della linea di mira con il piano di elevazione
double dDenom = vtLine * vtNorm ;
if ( fabs( dDenom) < COS_ORTO_ANG_SMALL)
return false ;
double dU = ( ( ptGrid - ptLine) * vtNorm) / dDenom ;
Point3d ptNear = ptLine + dU * vtLine ;
// proietto il punto sulla linea di elevazione
double dDeltaZ = ( ptNear - ptGrid) * m_frGrid.VersZ() ;
if ( ! bSketch)
dDeltaZ = floor( dDeltaZ / m_dSnapStep + 0.5) * m_dSnapStep ;
ptSel = ptGrid + dDeltaZ * m_frGrid.VersZ() ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::GetSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH, Point3d& ptSel)
{
// verifico siano state selezionate delle entità
int nSel ;
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
bool bFound = false ;
double dMinSqDist = INFINITO * INFINITO ;
for ( size_t i = 0 ; i < nIds.size() ; ++ i) {
// se non è entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGeomDB->GetGeoObj( nIds[i])) == nullptr)
continue ;
// recupero riferimento dell'entità
Frame3d frEnt ;
if ( ! m_pGeomDB->GetGlobFrame( nIds[i], 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 = nIds[i] ;
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 = nIds[i] ;
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 = nIds[i] ;
m_bLastSnapDirOk = false ;
}
}
// se curva
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 ;
}
}
// 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 = nIds[i] ;
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 = nIds[i] ;
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 = nIds[i] ;
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 = nIds[i] ;
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 = nIds[i] ;
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 = nIds[i] ;
m_bLastSnapDirOk = false ;
}
}
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)
{
// verifico siano state selezionate delle entità
int nSel ;
Select( ptWin, nW, nH, nSel) ;
if ( nSel <= 0)
return false ;
// recupero le entità selezionate
INTVECTOR nIds ;
GetSelectedObjs( nIds) ;
// cerco le prime due curve inquadrate
int nCrvNum = 0 ;
int nId[2] = { GDB_ID_NULL, GDB_ID_NULL} ;
const ICurve* pCrv[2] = { nullptr, nullptr} ;
for ( size_t i = 0 ; i < nIds.size() && nCrvNum < 2 ; ++ i) {
// se non è entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGeomDB->GetGeoObj( nIds[i])) == nullptr)
continue ;
if ( ( pGObj->GetType() & GEO_CURVE) != 0) {
nId[nCrvNum] = nIds[i] ;
pCrv[nCrvNum] = GetCurve( pGObj) ;
++ nCrvNum ;
}
}
if ( nCrvNum < 2)
return false ;
// recupero i riferimenti in cui sono immerse
Frame3d frEnt[2] ;
if ( ! m_pGeomDB->GetGlobFrame( nId[0], frEnt[0]))
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<ICurve> crvTrans( nullptr) ;
if ( ! AreSameFrame( frEnt[0], frEnt[1])) {
crvTrans.Set( pCrv[1]->Clone()) ;
if ( IsNull( crvTrans))
return false ;
crvTrans->LocToLoc( frEnt[1], frEnt[0]) ;
pCrv[1] = ::Get( crvTrans) ;
}
// uso il punto sketch come punto vicino e lo porto nel riferimento della prima curva
Point3d ptNear ;
if ( ! GetGridSnapPoint( true, ptWin, ptNear) ||
! UnProject( ptWin, ptNear))
ptNear = ORIG ;
ptNear.ToLoc( frEnt[0]) ;
// 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]) ;
return true ;
}