//---------------------------------------------------------------------------- // 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/EGkSurfFlatRegion.h" #include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkVolZmap.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkExtDimension.h" #include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; //---------------------------------------------------------------------------- const double SRF_SMALL_SQDIST = 100 ; //---------------------------------------------------------------------------- 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) const { // 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 ( abs( 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 ( abs( 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 ; } } // se nessuna curva, esco if ( nCrvNum == 0) return false ; // se una sola curva, può essere auto intersezione if ( nCrvNum == 1) { // recupero il riferimento di griglia Frame3d frGrid = GetGridFrame() ; // se il riferimento della curva è diverso da quello della griglia, devo trasformarla PtrOwner pcrvTrans0 ; if ( ! AreSameFrame( frEnt[0], frGrid)) { pcrvTrans0.Set( pCrv[0]->Clone()) ; if ( IsNull( pcrvTrans0)) return false ; pcrvTrans0->LocToLoc( frEnt[0], frGrid) ; pCrv[0] = pcrvTrans0 ; } // 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 SelfIntersCurve sintC( *pCrv[0]) ; if ( ! sintC.GetIntersPointNearTo( ptNear, m_ptLastSnapPnt)) return false ; m_ptLastSnapPnt.ToGlob( frGrid) ; return true ; } // altrimenti due curve, procedo normalmente // recupero il riferimento di griglia Frame3d frGrid = GetGridFrame() ; // se il riferimento della prima curva è diverso da quello della griglia, devo trasformarla PtrOwner pcrvTrans0 ; if ( ! AreSameFrame( frEnt[0], frGrid)) { pcrvTrans0.Set( pCrv[0]->Clone()) ; if ( IsNull( pcrvTrans0)) return false ; pcrvTrans0->LocToLoc( frEnt[0], frGrid) ; pCrv[0] = pcrvTrans0 ; } // se il riferimento della seconda curva è diverso da quello della griglia, devo trasformarla PtrOwner pcrvTrans1 ; if ( ! AreSameFrame( frEnt[1], frGrid)) { pcrvTrans1.Set( pCrv[1]->Clone()) ; if ( IsNull( pcrvTrans1)) return false ; pcrvTrans1->LocToLoc( frEnt[1], frGrid) ; pCrv[1] = pcrvTrans1 ; } // 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 = GetToGlob( pGP->GetPoint(), 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 = GetToGlob( pGV->GetBase(), frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pGV->GetVector(), frEnt) ; } // recupero il punto tip Point3d ptTip = GetToGlob( pGV->GetBase() + pGV->GetVector(), frEnt) ; if ( VerifySnapPoint( ptTip, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptTip ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pGV->GetVector(), 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 = GetToGlob( pGF->GetFrame().Orig(), 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 regione else if ( pGObj->GetType() == SRF_FLATRGN) { // recupero la regione const ISurfFlatRegion* pReg = GetSurfFlatRegion( pGObj) ; // verifico i punti notevoli della regione if ( FindSurfFRSnapPoint( nSnap, ptWin, nId, frEnt, pReg, dMinSqDist)) bFound = true ; } // se superficie di Bezier else if ( pGObj->GetType() == SRF_BEZIER) { // recupero la superficie const ISurfBezier* pSbz = GetSurfBezier( pGObj) ; const ISurfTriMesh* pStm = pSbz->GetAuxSurf() ; // verifico i punti notevoli della superficie ausiliaria associata if ( FindSurfTMSnapPoint( nSnap, ptWin, nId, frEnt, pStm, dMinSqDist)) bFound = true ; } // se solido Zmap else if ( pGObj->GetType() == VOL_ZMAP) { // recupero il solido const IVolZmap* pVzm = GetVolZmap( pGObj) ; // verifico i punti notevoli del solido if ( FindVolZmapSnapPoint( nSnap, ptWin, nId, frEnt, pVzm, dMinSqDist)) bFound = true ; } // se testo else if ( pGObj->GetType() == EXT_TEXT) { // recupero il testo const IExtText* pTxt = GetExtText( pGObj) ; // verifico i punti notevoli del testo if ( FindTextSnapPoint( nSnap, ptWin, nId, frEnt, pTxt, dMinSqDist)) bFound = true ; } // se quotatura else if ( pGObj->GetType() == EXT_DIMENSION) { // recupero la quotatura const IExtDimension* pDim = GetExtDimension( pGObj) ; // verifico i punti notevoli della quotatura if ( FindDimensionSnapPoint( nSnap, ptWin, nId, frEnt, pDim, 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) const { // 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) || abs( 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 = GetToLoc( -m_vtDirCamera, 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 = GetToGlob( ptP, 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)) return false ; // se non trovato alcunchè, cerco le linee che partono dagli angoli del rettangolo di mira Vector3d vtWinD( -1, -1, 0) ; for ( int i = 0 ; i < 4 && vInfo.size() == 0 ; ++ i) { // determino punto su vertice del rettangolo di selezione Point3d ptWinZ2 = ptWinZ + vtWinD.x * m_nSelH * X_AX + vtWinD.y * m_nSelW * Y_AX ; vtWinD.Rotate( Z_AX, 0, 1) ; // ne ricavo punto di mira Point3d ptMir2 ; if ( ! UnProject( ptWinZ2, ptMir2)) return false ; ptMir2.ToLoc( frEnt) ; ptMir2 -= vtDir * 2 * dBlRad ; // interseco con la superficie if ( ! IntersLineSurfTm( ptMir2, vtDir, dLenMir, *pStm, vInfo)) return false ; } if ( vInfo.size() == 0) return false ; // elaborazione a seconda del tipo di snap bool bFound = false ; switch ( nSnap) { case SP_END : { // con wireframe devo provare tutti i triangoli intersecati, con shading e hiddenline solo il primo int nTtot = (( bAlpha || m_nShowMode == SM_WIREFRAME) ? int( vInfo.size()) : 1) ; for ( int i = 0 ; i < nTtot ; ++ i) { // punto di intersezione Point3d ptInt = vInfo[i].ptI ; // 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 = GetToGlob( ptEnd, frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( vtN, 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 = GetToGlob( ptMid, frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( vtN, 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 = GetToGlob( ptCen, frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( vtN, 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 = GetToGlob( ptInt, 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 = GetToGlob( vtNorm, 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 < SRF_SMALL_SQDIST) dMinSqDist = 0 ; return bFound ; } //---------------------------------------------------------------------------- bool Scene::FindSurfFRSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, const ISurfFlatRegion* pSfr, 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 = GetToLoc( -m_vtDirCamera, frEnt) ; // determino se oggetto trasparente Color cCol ; bool bAlpha = ( m_pGeomDB->GetCalcMaterial( nId, cCol) && cCol.GetIntAlpha() <= ALPHA_LIM) ; // elaborazione a seconda del tipo di snap bool bFound = false ; // se richiesto il centro di gravità (baricentro, centroide) if ( nSnap == SP_CENTROID) { Point3d ptP ; if ( pSfr->GetCentroid( ptP)) { // il punto di confronto è quello sulla linea di mira a minima distanza dal centro 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 = GetToGlob( ptP, frEnt) ; m_bLastSnapDirOk = false ; } } } // se richiesto il centro (è il centroide del chunk più vicino) else if ( nSnap == SP_CENTER) { Point3d ptP ; for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) { if ( pSfr->GetChunkCentroid( i, ptP)) { // il punto di confronto è quello sulla linea di mira a minima distanza dal centro 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 = GetToGlob( ptP, frEnt) ; m_bLastSnapDirOk = false ; } } } } // se richiesto punto vicino o assimilabile else if ( nSnap == SP_NEAR || nSnap == SP_TANG || nSnap == SP_PERP || nSnap == SP_MINDIST) { // recupero il piano della regione Plane3d plReg ; plReg.Set( pSfr->GetPlanePoint(), pSfr->GetNormVersor()) ; // interseco la linea di mira con il piano della regione Point3d ptInt ; if ( IntersLinePlane( ptRef, vtDir, INFINITO, plReg, ptInt, false) != ILPT_YES) return false ; // assegno il risultato bFound = true ; dMinSqDist = 0 ; m_nLastSnapId = nId ; m_ptLastSnapPnt = GetToGlob( ptInt, frEnt) ; m_bLastSnapDirOk = false ; } // in tutti gli altri casi else { // cerco sui contorni della regione for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) { for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) { PtrOwner pCrv( pSfr->GetLoop( i, j)) ; if ( IsNull( pCrv)) return false ; if ( pCrv->GetType() == CRV_COMPO) { ICurveComposite* pCrvCompo = GetCurveComposite( pCrv) ; if ( FindCurveCompoSnapPoint( nSnap, ptWin, nId, frEnt, pCrvCompo, dMinSqDist)) bFound = true ; } else { if ( FindCurveSnapPoint( nSnap, ptWin, nId, frEnt, pCrv, dMinSqDist)) bFound = true ; } } } } // se trovato e modalità shading o hiddenline, la favorisco perchè davanti alle possibili successive if ( bFound && ! ( bAlpha || m_nShowMode == SM_WIREFRAME) && dMinSqDist < SRF_SMALL_SQDIST) dMinSqDist = 0 ; return bFound ; } //---------------------------------------------------------------------------- bool Scene::FindVolZmapSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, const IVolZmap* pVzm, double& dMinSqDist) { // il punto di riferimento deriva da XY su viewport e Z minima (più vicina a osservatore) da selezione Point3d ptWinZ( ptWin.x, ptWin.y, GetSelectedObjMinWinZ()) ; // punto di riferimento nello spazio geometrico 3d Point3d ptRef ; if ( ! UnProject( ptWinZ, ptRef)) return false ; // porto il punto nel riferimento della superficie ptRef.ToLoc( frEnt) ; // recupero la direzione di mira e la porto nel riferimento della superficie Vector3d vtDir = GetToLoc( -m_vtDirCamera, frEnt) ; // recupero il raggio del box di ingombro double dBlRad = 1000 ; const ObjEGrGraphics* pGraphics = GetObjEGrGraphics( pVzm) ; if ( pGraphics != nullptr) { BBox3d b3Loc ; if ( pGraphics->GetLocalBBox( b3Loc)) b3Loc.GetRadius( dBlRad) ; } // punto davanti all'oggetto lungo il raggio di mira Point3d ptMir = ptRef - vtDir * 2 * dBlRad ; // determino se oggetto trasparente Color cCol ; bool bAlpha = ( m_pGeomDB->GetCalcMaterial( nId, cCol) && cCol.GetIntAlpha() <= ALPHA_LIM) ; // se richiesto il centro di gravità (baricentro, centroide) if ( nSnap == SP_CENTROID) { Point3d ptP ; bool bFound = false ; BBox3d b3Loc ; if ( pVzm->GetLocalBBox( b3Loc) && b3Loc.GetCenter( ptP)) { // il punto di confronto è quello sulla linea di mira a minima distanza dal vertice Point3d ptCfr = ptRef + (( ptP - ptRef) * vtDir) * vtDir ; // determino la distanza e la confronto con il minimo double dSqDist = SqDist( ptP, ptCfr) ; if ( dSqDist < dMinSqDist) { bFound = true ; dMinSqDist = dSqDist ; m_nLastSnapId = nId ; m_ptLastSnapPnt = GetToGlob( ptP, frEnt) ; m_bLastSnapDirOk = false ; } } // se trovato e modalità shading o hiddenline, la favorisco perchè davanti alle possibili successive if ( bFound && ! ( bAlpha || m_nShowMode == SM_WIREFRAME)) dMinSqDist = 0 ; return bFound ; } // cerco i triangoli intersecati dalla linea di mira ILZIVECTOR vInfo ; if ( ! pVzm->GetLineIntersection( ptMir, vtDir, vInfo)) return false ; // se non trovato alcunchè, cerco le linee che partono dagli angoli del rettangolo di mira Vector3d vtWinD( -1, -1, 0) ; for ( int i = 0 ; i < 4 && vInfo.size() == 0 ; ++ i) { // determino punto su vertice del rettangolo di selezione Point3d ptWinZ2 = ptWinZ + vtWinD.x * m_nSelH * X_AX + vtWinD.y * m_nSelW * Y_AX ; vtWinD.Rotate( Z_AX, 0, 1) ; // ne ricavo punto di mira Point3d ptMir2 ; if ( ! UnProject( ptWinZ2, ptMir2)) return false ; ptMir2.ToLoc( frEnt) ; ptMir2 -= vtDir * 2 * dBlRad ; // interseco con la superficie if ( ! pVzm->GetLineIntersection( ptMir2, vtDir, vInfo)) return false ; } if ( vInfo.size() == 0) return false ; // elaborazione a seconda del tipo di snap bool bFound = false ; switch ( nSnap) { case SP_END : { // con wireframe devo provare tutti i triangoli intersecati, con shading e hiddenline solo il primo int nTtot = (( bAlpha || m_nShowMode == SM_WIREFRAME) ? int( vInfo.size()) : 1) ; for ( int i = 0 ; i < nTtot ; ++ i) { // triangolo Triangle3d& trTria = vInfo[i].trTria ; // recupero il vertice del triangolo più vicino alla linea di mira int nVert ; double dSqDist ; if ( GetTriaVertexNearestToLine( trTria, ptRef, vtDir, nVert, dSqDist) && dSqDist < dMinSqDist) { bFound = true ; dMinSqDist = dSqDist ; m_nLastSnapId = nId ; m_ptLastSnapPnt = GetToGlob( trTria.GetP( nVert), frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( trTria.GetN(), 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) { // triangolo Triangle3d& trTria = vInfo[i].trTria ; // recupero il punto medio del lato del triangolo più vicino alla linea di mira Point3d ptMid ; double dSqDist ; if ( GetTriaMidEdgeNearestToLine( trTria, ptRef, vtDir, ptMid, dSqDist) && dSqDist < dMinSqDist) { bFound = true ; dMinSqDist = dSqDist ; m_nLastSnapId = nId ; m_ptLastSnapPnt = GetToGlob( ptMid, frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( trTria.GetN(), frEnt) ; } } } break ; case SP_CENTER : { // con wireframe devo provare tutti i triangoli intersecati, con shading e hiddenline solo il primo int nTtot = (( bAlpha || m_nShowMode == SM_WIREFRAME) ? int( vInfo.size()) : 1) ; for ( int i = 0 ; i < nTtot ; ++ i) { // triangolo Triangle3d& trTria = vInfo[i].trTria ; // centro più vicino Point3d ptCen = trTria.GetCentroid() ; // 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 = GetToGlob( ptCen, frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( trTria.GetN(), 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 ; m_ptLastSnapPnt = GetToGlob( vInfo[0].ptI, frEnt) ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( vInfo[0].trTria.GetN(), frEnt) ; } break ; default : break ; } // se trovato e modalità shading o hiddenline, la favorisco perchè davanti alle possibili successive if ( bFound && ! ( bAlpha || m_nShowMode == SM_WIREFRAME) && dMinSqDist < SRF_SMALL_SQDIST) 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 = GetToGlob( pTxt->GetNormVersor(), 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 = GetToGlob( pTxt->GetNormVersor(), 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 = GetToGlob( pTxt->GetNormVersor(), 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 = GetToGlob( pTxt->GetNormVersor(), 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 = GetToGlob( pTxt->GetNormVersor(), frEnt) ; } } break ; case SP_CENTER : case SP_CENTROID : // 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 = GetToGlob( pTxt->GetNormVersor(), frEnt) ; } } break ; } return bFound ; } //---------------------------------------------------------------------------- bool Scene::FindDimensionSnapPoint( int nSnap, const Point3d& ptWin, int nId, const Frame3d& frEnt, const IExtDimension* pDim, double& dMinSqDist) { // cerco il punto bool bFound = false ; Point3d ptP ; switch ( nSnap) { case SP_END : // punto iniziale if ( pDim->IsValid()) { ptP = GetToGlob( pDim->GetStart(), frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pDim->GetNormVersor(), frEnt) ; } } // punto sopra iniziale if ( pDim->IsValid()) { ptP = GetToGlob( pDim->GetOverStart(), frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pDim->GetNormVersor(), frEnt) ; } } // punto finale if ( pDim->IsValid()) { ptP = GetToGlob( pDim->GetEnd(), frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pDim->GetNormVersor(), frEnt) ; } } // punto sopra finale if ( pDim->IsValid()) { ptP = GetToGlob( pDim->GetOverEnd(), frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pDim->GetNormVersor(), frEnt) ; } } break ; case SP_MID : // punto medio if ( pDim->GetMidPoint( ptP)) { ptP.ToGlob( frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pDim->GetNormVersor(), frEnt) ; } } break ; case SP_CENTER : case SP_CENTROID : // centro if ( pDim->GetCenterPoint( ptP)) { ptP.ToGlob( frEnt) ; if ( VerifySnapPoint( ptP, ptWin, dMinSqDist)) { bFound = true ; m_nLastSnapId = nId ; m_ptLastSnapPnt = ptP ; m_bLastSnapDirOk = true ; m_vtLastSnapDir = GetToGlob( pDim->GetNormVersor(), frEnt) ; } } break ; } return bFound ; } //---------------------------------------------------------------------------- bool Scene::GetPlaneSnapPoint( const Point3d& ptWin, const Plane3d& plPlane, Point3d& ptSel) const { // 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 double dDenom = vtLine * plPlane.GetVersN() ; if ( abs( dDenom) < COS_ORTO_ANG_ZERO) return false ; double dU = ( plPlane.GetDist() - ( ptLine - ORIG) * plPlane.GetVersN()) / dDenom ; ptSel = ptLine + dU * vtLine ; return true ; }