Files
EgtGraphics/SceneSnap.cpp
T
Dario Sassi ff8c9fa37c EgtGraphics 1.6c3 :
- possibilità di filtrare selezione per tipologia di entità
- filtro per snap punto ricondotto al caso precedente.
2015-03-18 13:54:57 +00:00

821 lines
30 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 "ObjEGrGraphics.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/EGkCurveArc.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/EGkIntersLineSurfTm.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 ;
// verifico validità GDB
if ( m_pGeomDB == nullptr)
return false ;
// se Snap Sketch o Grid, devo trovare il punto sulla griglia
if ( nSnap == SP_SKETCH || nSnap == SP_GRID) {
if ( FindGridSnapPoint( ( nSnap == SP_SKETCH), ptWin)) {
ptSel = m_ptLastSnapPnt ;
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 ;
}
//----------------------------------------------------------------------------
bool
Scene::GetGridSnapPointZ( bool bSketch, const Point3d& ptWin, const Point3d& ptGrid, 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 ;
// 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 * frGrid.VersZ()) * 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) * frGrid.VersZ() ;
if ( ! bSketch)
dDeltaZ = floor( dDeltaZ / m_dSnapStep + 0.5) * m_dSnapStep ;
ptSel = ptGrid + dDeltaZ * frGrid.VersZ() ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::FindGridSnapPoint( bool bSketch, const Point3d& ptWin)
{
// 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 ;
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 ;
}
// il punto deve stare sulla griglia
m_ptLastSnapPnt.z = 0 ;
// lo riporto in globale
m_ptLastSnapPnt.ToGlob( frGrid) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::FindSelectedIntersectionPoint( const Point3d& ptWin, int nW, int nH)
{
// --- l'intersezione viene calcolata nel piano della griglia ---
// verifico siano state selezionate delle entità
int nSel ;
Select( ptWin, nW, nH, nSel) ;
if ( nSel <= 0)
return false ;
// cerco le prime due curve inquadrate con i loro riferimenti
const ICurve* pCrv[2] ;
Frame3d frEnt[2] ;
double dWinZ = 0 ;
int nCrvNum = 0 ;
for ( int i = GetFirstSelectedObj() ; i != GDB_ID_NULL && nCrvNum < 2 ; i = GetNextSelectedObj()) {
// se non è entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGeomDB->GetGeoObj( i)) == nullptr)
continue ;
if ( ( pGObj->GetType() & GEO_CURVE) != 0) {
pCrv[nCrvNum] = GetCurve( pGObj) ;
if ( ! m_pGeomDB->GetGlobFrame( i, frEnt[nCrvNum]))
return false ;
dWinZ += 0.5 * GetSelectedObjWinZ() ;
++ nCrvNum ;
}
}
if ( nCrvNum != 2)
return false ;
// recupero il riferimento di griglia
Frame3d frGrid = GetGridFrame() ;
// se il riferimento della seconda curva è diverso da quello della griglia, devo trasformarla
PtrOwner<ICurve> crvTrans0( nullptr) ;
if ( ! AreSameFrame( frEnt[0], frGrid)) {
crvTrans0.Set( pCrv[0]->Clone()) ;
if ( IsNull( crvTrans0))
return false ;
crvTrans0->LocToLoc( frEnt[0], frGrid) ;
pCrv[0] = ::Get( crvTrans0) ;
}
// se il riferimento della seconda curva è diverso da quello della griglia, devo trasformarla
PtrOwner<ICurve> crvTrans1( nullptr) ;
if ( ! AreSameFrame( frEnt[1], frGrid)) {
crvTrans1.Set( pCrv[1]->Clone()) ;
if ( IsNull( crvTrans1))
return false ;
crvTrans1->LocToLoc( frEnt[1], frGrid) ;
pCrv[1] = ::Get( crvTrans1) ;
}
// uso il punto sketch come punto vicino e lo porto nel riferimento della griglia
Point3d ptWinZ( ptWin.x, ptWin.y, dWinZ) ;
Point3d ptNear ;
if ( ! UnProject( ptWinZ, ptNear))
ptNear = ORIG ;
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, m_ptLastSnapPnt))
return false ;
m_ptLastSnapPnt.ToGlob( frGrid) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Scene::FindSelectedSnapPoint( int nSnap, const Point3d& ptWin, int nW, int nH)
{
// seleziono e 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 ;
if ( pCrv->GetType() == CRV_ARC) {
m_bLastSnapDirOk = true ;
m_vtLastSnapDir = GetCurveArc( pCrv)->GetNormVersor() ;
m_vtLastSnapDir.ToGlob( frEnt) ;
}
else
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)
{
// 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 ;
// recupero la direzione di mira
Vector3d vtDir = - m_vtDirCamera ;
// il punto di confronto è quello sulla linea di mira a minima distanza dal punto dato
Point3d ptCfr = ptRef + (( ptP - ptRef) * vtDir) * vtDir ;
// determino la distanza e la confronto con il minimo
double dSqDist = SqDist( ptP, ptCfr) ;
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<int>( 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<ICurve*>(pCrv))->SetExtrusion( vtExtr) ;
(const_cast<ICurve*>(pCrv))->SetThickness( dThick) ;
// verifico i punti notevoli della curva
if ( FindCurveSnapPoint( nSnap, ptWin, nId, frEnt, pCrv, dMinSqDist))
bFound = true ;
// ripristino valori originali
(const_cast<ICurve*>(pCrv))->SetExtrusion( V_NULL) ;
(const_cast<ICurve*>(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) ;
// recupero il raggio del box di ingombro
double dBlRad = 1000 ;
const ObjEGrGraphics* pGraphics = GetObjEGrGraphics( pStm) ;
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 ;
if ( pStm->GetCentroid( 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
ILSIVECTOR vInfo ;
if ( ! IntersLineSurfTm( ptMir, vtDir, dLenMir, *pStm, vInfo) || 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 ;
// punto finale più vicino
int nF = pStm->GetFacetFromTria( vInfo[i].nT) ;
Point3d ptEnd ;
Vector3d vtN ;
if ( pStm->GetFacetNearestEndPoint( nF, ptInt, ptEnd, vtN)) {
// 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 ;
// punto medio più vicino
int nF = pStm->GetFacetFromTria( vInfo[i].nT) ;
Point3d ptMid ;
Vector3d vtN ;
if ( pStm->GetFacetNearestMidPoint( nF, ptInt, ptMid, vtN)) {
// 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) {
// centro più vicino
int nF = pStm->GetFacetFromTria( vInfo[i].nT) ;
Point3d ptCen ;
Vector3d vtN ;
if ( pStm->GetFacetCenter( nF, ptCen, vtN)) {
// 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
Triangle3d Tria ;
TriNormals3d Tnorms ;
Vector3d vtNorm ;
if ( pStm->GetTriangle( vInfo[0].nT, Tria) &&
pStm->GetTriangleSmoothNormals( vInfo[0].nT, Tnorms) &&
CalcNormal( ptInt, Tria, Tnorms, vtNorm)) {
m_bLastSnapDirOk = true ;
m_vtLastSnapDir = vtNorm ;
m_vtLastSnapDir.ToGlob( frEnt) ;
}
else
m_bLastSnapDirOk = false ;
}
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,
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->GetNormVersor() ;
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->GetNormVersor() ;
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->GetNormVersor() ;
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->GetNormVersor() ;
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->GetNormVersor() ;
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 = true ;
m_vtLastSnapDir = pTxt->GetNormVersor() ;
m_vtLastSnapDir.ToGlob( frEnt) ;
}
}
break ;
}
return bFound ;
}