2e688ef9aa
- ricompilazione con cambio codifica file a UTF-8.
1077 lines
42 KiB
C++
1077 lines
42 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2021
|
|
//----------------------------------------------------------------------------
|
|
// File : SceneGeom.cpp Data : 11.03.21 Versione : 2.3c1
|
|
// Contenuto : Implementazione della gestione geometria della classe scena.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 10.02.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "Scene.h"
|
|
#include "ObjOldGraphics.h"
|
|
#include "ObjNewGraphics.h"
|
|
#include "ObjMultiGraphics.h"
|
|
#include "EGrUtils.h"
|
|
#include "DllMain.h"
|
|
#include "/EgtDev/Include/EGkFrame3d.h"
|
|
#include "/EgtDev/Include/EGkGdbIterator.h"
|
|
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
|
#include "/EgtDev/Include/EGkCurve.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.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/EGkGdbFunct.h"
|
|
#include "/EgtDev/Include/EGnStringUtils.h"
|
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
#include "/EgtDev/Include/EgtILogger.h"
|
|
|
|
using namespace std ;
|
|
|
|
//------------------------------ Local functions -----------------------------
|
|
static ObjEGrGraphics* CreateObjEGrGraphics( int nCount, bool bNewWay) ;
|
|
static bool CalcCurveTailMark( const Vector3d& vtRef, const PolyLine& plCrv, PolyLine& plMark) ;
|
|
static bool CalcCurveTipArrow( const Vector3d& vtRef, const PolyLine& plCrv, PolyLine& plArr) ;
|
|
static bool CalcCurveConnectingLines( const PolyLine& plCrv, const Vector3d& vtTh, bool bDense, PNTVECTOR& vPnt) ;
|
|
static bool CalcCurveJoints( const ICurve* pCurve, PNTVECTOR& vPnt) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::UpdateExtension( void)
|
|
{
|
|
BBox3d b3Ext ;
|
|
if ( m_pGeomDB == nullptr || ! m_pGeomDB->GetLocalBBox( GDB_ID_ROOT, b3Ext, BBF_ONLY_VISIBLE))
|
|
return false ;
|
|
return SetExtension( b3Ext) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetMark( Color colMark)
|
|
{
|
|
m_colMark = colMark ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetMark2( Color colMark)
|
|
{
|
|
m_colMark2 = colMark ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetSelSurf( Color colSelSurf)
|
|
{
|
|
m_colSelSurf = colSelSurf ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::SetLineWidth( int nW)
|
|
{
|
|
nW = Clamp( nW, 1, 3) ;
|
|
switch ( nW) {
|
|
case 1 :
|
|
m_dLineWidth = 1 ;
|
|
m_dSelLineWidth = 2 ;
|
|
m_dMarkLineWidth = 5 ;
|
|
m_dPointSize = 3 ;
|
|
m_dSelPointSize = 5 ;
|
|
m_dMarkPointSize = 7 ;
|
|
break ;
|
|
case 2 :
|
|
m_dLineWidth = 2 ;
|
|
m_dSelLineWidth = 4 ;
|
|
m_dMarkLineWidth = 7 ;
|
|
m_dPointSize = 4 ;
|
|
m_dSelPointSize = 7 ;
|
|
m_dMarkPointSize = 9 ;
|
|
break ;
|
|
case 3 :
|
|
m_dLineWidth = 3 ;
|
|
m_dSelLineWidth = 6 ;
|
|
m_dMarkLineWidth = 9 ;
|
|
m_dPointSize = 5 ;
|
|
m_dSelPointSize = 9 ;
|
|
m_dMarkPointSize = 11 ;
|
|
break ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::DrawGroup( int nId, int nPass, const MdStMkCol& cParent)
|
|
{
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGeomDB)) ;
|
|
if ( IsNull( pIter))
|
|
return false ;
|
|
|
|
// recupero il gruppo
|
|
if ( ! pIter->GoTo( nId))
|
|
return false ;
|
|
|
|
// eseguo il disegno
|
|
return DrawGroup( *pIter, nPass, cParent) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::DrawGroup( const IGdbIterator& iIter, int nPass, const MdStMkCol& cParent)
|
|
{
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGeomDB)) ;
|
|
if ( IsNull( pIter))
|
|
return false ;
|
|
// recupero il riferimento del gruppo
|
|
Frame3d frFrame ;
|
|
if ( ! iIter.GetGroupFrame( frFrame))
|
|
return false ;
|
|
// se non è identità, lo aggiungo sullo stack delle matrici MODELVIEW di OpenGL
|
|
bool bMatrix = ( frFrame.GetType() != Frame3d::TOP || ! frFrame.Orig().IsSmall()) ;
|
|
if ( bMatrix) {
|
|
glPushMatrix() ;
|
|
double Matrix[OGLMAT_DIM] ;
|
|
if ( FrameToOpenGlMatrix( frFrame, Matrix))
|
|
glMultMatrixd( Matrix) ;
|
|
}
|
|
// scandisco il gruppo
|
|
bool bOk = true ;
|
|
for ( bool bNext = pIter->GoToFirstInGroup( iIter) ;
|
|
bNext ;
|
|
bNext = pIter->GoToNext()) {
|
|
// leggo il tipo di oggetto
|
|
int nGdbType = pIter->GetGdbType() ;
|
|
// recupero e aggiorno il modo dell'oggetto
|
|
int nMode = GDB_MD_STD ;
|
|
pIter->GetMode( nMode) ;
|
|
nMode = ::CalcMode( nMode, cParent.nMode) ;
|
|
// recupero e aggiorno lo stato dell'oggetto
|
|
int nStat = GDB_ST_ON ;
|
|
pIter->GetStatus( nStat) ;
|
|
nStat = ::CalcStatus( nStat, cParent.nStat) ;
|
|
nStat = ::AdjustStatusWithMode( nStat, nMode) ;
|
|
// recupero e aggiorno la marcatura dell'oggetto
|
|
int nMark = GDB_MK_OFF ;
|
|
pIter->GetMark( nMark) ;
|
|
nMark = ::CalcMark( nMark, cParent.nMark) ;
|
|
// recupero e aggiorno il colore dell'oggetto
|
|
Color colObj = cParent.colObj ;
|
|
pIter->GetMaterial( colObj) ;
|
|
// se in modalità selezione, verifico sia selezionabile
|
|
bool bSel = true ;
|
|
if ( m_bSelect && UnselectableFind( pIter->GetId()))
|
|
bSel = false ;
|
|
// se oggetto geometrico
|
|
if ( nGdbType == GDB_TY_GEO) {
|
|
// se non nascosto e selezionabile, lo disegno
|
|
if ( nStat != GDB_ST_OFF && bSel) {
|
|
if ( ! DrawGeoObj( *pIter, nPass, MdStMkCol( nMode, nStat, nMark, colObj)))
|
|
bOk = false ;
|
|
}
|
|
}
|
|
// se gruppo
|
|
else if ( nGdbType == GDB_TY_GROUP) {
|
|
// se non nascosto e selezionabile, lo disegno
|
|
if ( nStat != GDB_ST_OFF && bSel) {
|
|
if ( ! DrawGroup( *pIter, nPass, MdStMkCol( nMode, nStat, nMark, colObj)))
|
|
bOk = false ;
|
|
}
|
|
}
|
|
}
|
|
// se necessario, ripristino lo stack delle matrici
|
|
if ( bMatrix)
|
|
glPopMatrix() ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static const ISurfTriMesh*
|
|
GetSurfTriMeshAux( const IGeoObj* pGeoObj)
|
|
{
|
|
int nGeoType = pGeoObj->GetType() ;
|
|
switch ( nGeoType) {
|
|
case SRF_TRIMESH : return GetSurfTriMesh( pGeoObj) ;
|
|
case SRF_FLATRGN : return GetSurfFlatRegion( pGeoObj)->GetAuxSurf() ;
|
|
case SRF_BEZIER : return GetSurfBezier( pGeoObj)->GetAuxSurf() ;
|
|
default : return nullptr ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::DrawGeoObj( const IGdbIterator& iIter, int nPass, const MdStMkCol& siObj)
|
|
{
|
|
// recupero l'oggetto geometrico e il suo tipo
|
|
IGeoObj* pGeoObj = (const_cast<IGdbIterator*>(&iIter))->GetGeoObj() ;
|
|
if ( pGeoObj == nullptr)
|
|
return false ;
|
|
int nGeoType = pGeoObj->GetType() ;
|
|
|
|
// recupero eventuale parte custom
|
|
const IUserObj* pUserObj = iIter.GetUserObj() ;
|
|
|
|
// numero di colori per TriMesh e Zmap
|
|
const int STM_COL = 2 ;
|
|
const int ZMAP_COL = 2 ;
|
|
|
|
// se non esiste grafica associata, la creo
|
|
if ( pGeoObj->GetObjGraphics() == nullptr) {
|
|
// oggetto grafico molteplice solo per Zmap o superfici che lo richiedono
|
|
int nCount = 0 ;
|
|
if ( nGeoType == VOL_ZMAP) {
|
|
const IVolZmap* pZmap = GetVolZmap( pGeoObj) ;
|
|
if ( pZmap != nullptr) {
|
|
if ( ( m_nShowZmap & ZSM_SURF) != 0)
|
|
nCount += ZMAP_COL * pZmap->GetBlockCount() ;
|
|
if ( ( m_nShowZmap & ZSM_LINES) != 0 || ( m_nShowZmap & ZSM_NORMALS) != 0)
|
|
nCount += 1 ;
|
|
if ( pZmap->GetShowEdges())
|
|
nCount += 1 ;
|
|
}
|
|
}
|
|
else if (( nGeoType & GEO_SURF) != 0) {
|
|
const ISurfTriMesh* pSTM = GetSurfTriMeshAux( pGeoObj) ;
|
|
if ( pSTM != nullptr) {
|
|
if ( pSTM->GetMaxTFlag() > 0)
|
|
nCount = STM_COL ;
|
|
else
|
|
nCount = 1 ;
|
|
if ( pSTM->GetShowEdges())
|
|
nCount += 1 ;
|
|
}
|
|
}
|
|
// nuova modalità grafica solo per superfici e testi con molti triangoli o solidi Zmap
|
|
const int N_MIN_TRIA_NEWWAY = 100 ;
|
|
bool bNewWay = false ;
|
|
if ( m_bNewWay) {
|
|
if ( ( nGeoType & GEO_SURF) != 0) {
|
|
const ISurfTriMesh* pSTM = GetSurfTriMeshAux( pGeoObj) ;
|
|
if ( pSTM != nullptr && pSTM->GetTriangleCount() > N_MIN_TRIA_NEWWAY)
|
|
bNewWay = true ;
|
|
}
|
|
else if ( ( nGeoType & GEO_VOLUME) != 0) {
|
|
bNewWay = true ;
|
|
}
|
|
else if ( nGeoType == EXT_TEXT) {
|
|
const ISurfTriMesh* pSTM = ( m_nShowText == TXT_FILL ? GetExtText( pGeoObj)->GetAuxSurf() : nullptr) ;
|
|
if ( pSTM != nullptr && pSTM->GetTriangleCount() > N_MIN_TRIA_NEWWAY)
|
|
bNewWay = true ;
|
|
}
|
|
}
|
|
ObjEGrGraphics* pGraphics = CreateObjEGrGraphics( nCount, bNewWay) ;
|
|
if ( pGraphics == nullptr)
|
|
return false ;
|
|
pGraphics->SetScene( this) ;
|
|
pGeoObj->SetObjGraphics( pGraphics) ;
|
|
}
|
|
|
|
// se la grafica associata non è valida la ricalcolo
|
|
ObjEGrGraphics* pGraphics = GetObjEGrGraphics( pGeoObj) ;
|
|
if ( ! pGraphics->IsValid()) {
|
|
const double ANG_TOL_GRAPH_DEG = 15 ;
|
|
// se vettore
|
|
if ( nGeoType == GEO_VECT3D) {
|
|
// recupero il vettore
|
|
const IGeoVector3d* pVector = GetGeoVector3d( pGeoObj) ;
|
|
if ( pVector == nullptr)
|
|
return false ;
|
|
// calcolo la grafica
|
|
pGraphics->Clear() ;
|
|
pGraphics->AddColor( siObj.colObj) ;
|
|
int nFactor, nPattern ;
|
|
if ( iIter.GetStipple( nFactor, nPattern) && nFactor != 0)
|
|
pGraphics->AddLineStipple( nFactor, nPattern) ;
|
|
PolyLine PL ;
|
|
if ( pVector->GetDrawWithArrowHead( 0.1, 10, PL))
|
|
pGraphics->AddPolyLine(PL) ;
|
|
else
|
|
pGraphics->AddPoint( pVector->GetBase()) ;
|
|
}
|
|
// se punto
|
|
else if ( nGeoType == GEO_PNT3D) {
|
|
// recupero il punto
|
|
const IGeoPoint3d* pPoint = GetGeoPoint3d( pGeoObj) ;
|
|
if ( pPoint == nullptr)
|
|
return false ;
|
|
// calcolo la grafica
|
|
pGraphics->Clear() ;
|
|
pGraphics->AddColor( siObj.colObj) ;
|
|
int nFactor, nPattern ;
|
|
if ( iIter.GetStipple( nFactor, nPattern) && nFactor != 0)
|
|
pGraphics->AddLineStipple( nFactor, nPattern) ;
|
|
pGraphics->AddPoint( pPoint->GetPoint()) ;
|
|
}
|
|
// se riferimento
|
|
else if ( nGeoType == GEO_FRAME3D) {
|
|
// recupero il riferimento
|
|
const IGeoFrame3d* pFrame = GetGeoFrame3d( pGeoObj) ;
|
|
if ( pFrame == nullptr)
|
|
return false ;
|
|
// aggiorno la grafica (colori speciali)
|
|
PolyLine plX, plY, plZ ;
|
|
pFrame->GetDrawWithArrowHeads( 40, 0.1, plX, plY, plZ) ;
|
|
pGraphics->Clear() ;
|
|
pGraphics->AddColor( RED) ;
|
|
pGraphics->AddPolyLine( plX) ;
|
|
pGraphics->AddColor( LIME) ;
|
|
pGraphics->AddPolyLine( plY) ;
|
|
pGraphics->AddColor( BLUE) ;
|
|
pGraphics->AddPolyLine( plZ) ;
|
|
}
|
|
// se curva
|
|
else if ( ( nGeoType & GEO_CURVE) != 0) {
|
|
// recupero la curva
|
|
const ICurve* pCurve = GetCurve( pGeoObj) ;
|
|
if ( pCurve == nullptr)
|
|
return false ;
|
|
// calcolo la grafica
|
|
PolyLine PL ;
|
|
pCurve->ApproxWithLines( EPS_SMALL, ANG_TOL_GRAPH_DEG, ICurve::APL_SPECIAL, PL) ;
|
|
pGraphics->Clear() ;
|
|
pGraphics->AddColor( siObj.colObj) ;
|
|
int nFactor, nPattern ;
|
|
if ( iIter.GetStipple( nFactor, nPattern) && nFactor != 0)
|
|
pGraphics->AddLineStipple( nFactor, nPattern) ;
|
|
pGraphics->AddPolyLine( PL) ;
|
|
// eventuali segni ausiliari (mark, frecce, ...)
|
|
Vector3d vtRef ;
|
|
if ( ! pCurve->GetExtrusion( vtRef) || vtRef.IsSmall())
|
|
vtRef = Z_AX ;
|
|
PolyLine PLM ;
|
|
if ( CalcCurveTailMark( vtRef, PL, PLM))
|
|
pGraphics->AddPolyLine( PLM, true) ;
|
|
PolyLine PLA ;
|
|
if ( CalcCurveTipArrow( vtRef, PL, PLA))
|
|
pGraphics->AddPolyLine( PLA, true) ;
|
|
PNTVECTOR vPnt ;
|
|
if ( CalcCurveJoints( pCurve, vPnt))
|
|
pGraphics->AddPoints( vPnt, true) ;
|
|
// eventuale spessore
|
|
double dTh ;
|
|
Vector3d vtExtr ;
|
|
if ( pCurve->GetExtrusion( vtExtr) && ! vtExtr.IsSmall() &&
|
|
pCurve->GetThickness( dTh) && abs( dTh) > EPS_SMALL) {
|
|
// segmenti di raccordo
|
|
PNTVECTOR vPnt ;
|
|
bool bDense = ( nGeoType == CRV_ARC || nGeoType == CRV_BEZIER) ;
|
|
if ( CalcCurveConnectingLines( PL, dTh * vtExtr, bDense, vPnt))
|
|
pGraphics->AddLines( vPnt) ;
|
|
// percorso traslato
|
|
PL.Translate( dTh * vtExtr) ;
|
|
pGraphics->AddPolyLine( PL) ;
|
|
}
|
|
}
|
|
// se superficie
|
|
else if ( ( nGeoType & GEO_SURF) != 0) {
|
|
// recupero la trimesh da visualizzare
|
|
const ISurfTriMesh* pSTM = GetSurfTriMeshAux( pGeoObj) ;
|
|
if ( pSTM == nullptr)
|
|
return false ;
|
|
// superficie con visualizzazione standard
|
|
bool bTwoColors = ( pSTM->GetMaxTFlag() > 0) ;
|
|
if ( ! bTwoColors) {
|
|
// recupero il materiale
|
|
Material mMat ;
|
|
if ( ! iIter.GetCalcMaterial( mMat))
|
|
mMat.Set( m_colDef) ;
|
|
// Imposto indice blocco corrente
|
|
pGraphics->SetCurrent( 0) ;
|
|
// pulisco
|
|
pGraphics->Clear() ;
|
|
// se ci sono triangoli
|
|
int nTria = pSTM->GetTriangleCount() ;
|
|
if ( nTria > 0) {
|
|
// assegno i materiali
|
|
pGraphics->AddColor( siObj.colObj) ; // per wireframe
|
|
pGraphics->AddMaterial( mMat.GetAmbient(), mMat.GetDiffuse(),
|
|
mMat.GetSpecular(), mMat.GetShininess()) ;
|
|
pGraphics->AddBackMaterial( GetSurfBackColor( mMat.GetDiffuse())) ;
|
|
// ciclo sui triangoli della superficie
|
|
pGraphics->StartTriangles( nTria) ;
|
|
Triangle3dEx Tria ;
|
|
int nId = pSTM->GetFirstTriangle( Tria) ;
|
|
while ( nId != SVT_NULL) {
|
|
// se visualizzazione avanzata : edge solo se boundary e normali ai vertici smussate
|
|
if ( m_bShowTriaAdvanced)
|
|
pGraphics->AddTriangle( Tria, Tria.GetTriFlags(), Tria.GetTriNormals()) ;
|
|
// altrimenti : tutti gli edge e normali ai vertici prendono quella del triangolo
|
|
else
|
|
pGraphics->AddTriangle( Tria, TriFlags3d(), TriNormals3d( Tria.GetN())) ;
|
|
nId = pSTM->GetNextTriangle( nId, Tria) ;
|
|
}
|
|
pGraphics->EndTriangles() ;
|
|
}
|
|
else
|
|
pGraphics->Validate() ;
|
|
}
|
|
// altrimenti superficie con due colori
|
|
else {
|
|
// definizione materiali
|
|
Material mMat[STM_COL] ;
|
|
Color cCol[STM_COL] ;
|
|
// recupero il materiale principale
|
|
cCol[0] = siObj.colObj ;
|
|
if ( ! iIter.GetCalcMaterial( mMat[0]))
|
|
mMat[0].Set( m_colDef) ;
|
|
// secondo materiale per parti modificate (tonalità spostata di +22.5 deg)
|
|
cCol[1] = cCol[0] ;
|
|
mMat[1] = mMat[0] ;
|
|
HSV hsv = GetHSVFromColor( siObj.colObj) ;
|
|
if ( hsv.dSat > EPS_ZERO)
|
|
hsv.dHue += ANG_RIGHT / 4 ;
|
|
else
|
|
hsv.dVal = 1 - hsv.dVal ;
|
|
cCol[1] = GetColorFromHSV( hsv) ;
|
|
mMat[1].Set( cCol[1]) ;
|
|
// conto i triangoli per tipo (TFlag == 0 e altri)
|
|
int nTri[STM_COL] = { 0, 0} ;
|
|
nTri[0] = pSTM->GetTriangleCount( 0) ;
|
|
nTri[1] = pSTM->GetTriangleCount() - nTri[0] ;
|
|
// Ciclo sui colori
|
|
for ( int j = 0 ; j < STM_COL ; ++ j) {
|
|
// Imposto indice blocco corrente
|
|
if ( pGraphics->SetCurrent( j))
|
|
pGraphics->Clear() ;
|
|
// se non ci sono triangoli, passo oltre
|
|
if ( nTri[j] == 0) {
|
|
pGraphics->Validate() ;
|
|
continue ;
|
|
}
|
|
// assegno materiali
|
|
pGraphics->AddColor( cCol[j]) ; // per wireframe
|
|
pGraphics->AddMaterial( mMat[j].GetAmbient(), mMat[j].GetDiffuse(),
|
|
mMat[j].GetSpecular(), mMat[j].GetShininess()) ;
|
|
pGraphics->AddBackMaterial( GetSurfBackColor( mMat[j].GetDiffuse())) ;
|
|
// ciclo sui triangoli della superficie
|
|
pGraphics->StartTriangles( nTri[j]) ;
|
|
Triangle3dEx Tria ;
|
|
int nId = pSTM->GetFirstTriangle( Tria) ;
|
|
while ( nId != SVT_NULL) {
|
|
if ( ( j == 0 && Tria.GetGrade() == 0) || ( j == 1 && Tria.GetGrade() != 0)) {
|
|
// se visualizzazione avanzata : edge solo se boundary e normali ai vertici smussate
|
|
if ( m_bShowTriaAdvanced)
|
|
pGraphics->AddTriangle( Tria, Tria.GetTriFlags(), Tria.GetTriNormals()) ;
|
|
// altrimenti : tutti gli edge e normali ai vertici prendono quella del triangolo
|
|
else
|
|
pGraphics->AddTriangle( Tria, TriFlags3d(), TriNormals3d( Tria.GetN())) ;
|
|
}
|
|
nId = pSTM->GetNextTriangle( nId, Tria) ;
|
|
}
|
|
pGraphics->EndTriangles() ;
|
|
}
|
|
}
|
|
// eventuali spigoli vivi
|
|
if ( pSTM->GetShowEdges()) {
|
|
if ( pGraphics->SetCurrent( bTwoColors ? 2 : 1))
|
|
pGraphics->Clear() ;
|
|
int nEdgCnt = pSTM->GetEdgeCount() ;
|
|
if ( nEdgCnt > 0) {
|
|
pGraphics->AddColor( DGRAY) ;
|
|
pGraphics->AddMaterial( DGRAY, DGRAY, DGRAY, 10) ;
|
|
pGraphics->AddBackMaterial( DGRAY) ;
|
|
PNTVECTOR vPnt ; vPnt.reserve( 2 * nEdgCnt) ;
|
|
for ( int i = 0 ; i < nEdgCnt ; ++i) {
|
|
Point3d ptP1, ptP2 ;
|
|
double dAng ;
|
|
if ( pSTM->GetEdge( i, ptP1, ptP2, dAng) &&
|
|
abs( dAng) > pSTM->GetSmoothAngle()) {
|
|
vPnt.emplace_back( ptP1) ;
|
|
vPnt.emplace_back( ptP2) ;
|
|
}
|
|
}
|
|
pGraphics->AddLines( vPnt, false, true) ;
|
|
}
|
|
}
|
|
}
|
|
// se Zmap
|
|
else if ( nGeoType == VOL_ZMAP) {
|
|
// recupero il solido Zmap
|
|
const IVolZmap* pZmap = GetVolZmap( pGeoObj) ;
|
|
if ( pZmap == nullptr)
|
|
return false ;
|
|
// numero di blocchi
|
|
int nCount = 0 ;
|
|
// indicazione se tridexel
|
|
bool bIsTriDexel = pZmap->IsTriDexel() ;
|
|
// se triangoli da disegnare
|
|
if ( ( m_nShowZmap & ZSM_SURF) != 0) {
|
|
// definizione materiali
|
|
Material mMat[ZMAP_COL] ;
|
|
Color cCol[ZMAP_COL] ;
|
|
// recupero il materiale principale
|
|
cCol[0] = siObj.colObj ;
|
|
if ( ! iIter.GetCalcMaterial( mMat[0]))
|
|
mMat[0].Set( m_colDef) ;
|
|
// secondo materiale per parti lavorate (tonalità spostata di +22.5 deg)
|
|
cCol[1] = cCol[0] ;
|
|
mMat[1] = mMat[0] ;
|
|
// se richiesto diverso
|
|
if ( ( m_nShowZmap & ZSM_COLORS) != 0) {
|
|
HSV hsv = GetHSVFromColor( siObj.colObj) ;
|
|
if ( hsv.dSat > EPS_ZERO)
|
|
hsv.dHue += ANG_RIGHT / 4 ;
|
|
else
|
|
hsv.dVal = 1 - hsv.dVal ;
|
|
cCol[1] = GetColorFromHSV( hsv) ;
|
|
mMat[1].Set( cCol[1]) ;
|
|
}
|
|
// Ciclo sui blocchi
|
|
nCount = pZmap->GetBlockCount() ;
|
|
for ( int i = 0 ; i < nCount ; ++ i) {
|
|
// Se blocco non esistente o già aggiornato, vado oltre
|
|
if ( ! pGraphics->SetCurrent( ZMAP_COL * i) ||
|
|
pZmap->GetBlockUpdatingCounter( i) <= pGraphics->GetCounter())
|
|
continue ;
|
|
// Recupero i triangoli del blocco
|
|
TRIA3DEXVECTOR vTria ;
|
|
pZmap->GetBlockTriangles( i, vTria) ;
|
|
// conto i triangoli per tipo (Flag == 0 e altri)
|
|
int nTri[ZMAP_COL] = { 0, 0} ;
|
|
for ( const auto& Tria : vTria) {
|
|
if ( Tria.GetGrade() == 0)
|
|
++ nTri[0] ;
|
|
else
|
|
++ nTri[1] ;
|
|
}
|
|
// Ciclo sui colori
|
|
for ( int j = 0 ; j < ZMAP_COL ; ++ j) {
|
|
// Imposto indice blocco corrente, se non esiste passo oltre
|
|
if ( ! pGraphics->SetCurrent( ZMAP_COL * i + j))
|
|
continue ;
|
|
// lo pulisco
|
|
pGraphics->Clear() ;
|
|
// se non ci sono triangoli, passo oltre
|
|
if ( nTri[j] == 0)
|
|
continue ;
|
|
// assegno materiali
|
|
pGraphics->AddColor( cCol[j]) ; // per wireframe
|
|
pGraphics->AddMaterial( mMat[j].GetAmbient(), mMat[j].GetDiffuse(),
|
|
mMat[j].GetSpecular(), mMat[j].GetShininess()) ;
|
|
pGraphics->AddBackMaterial( GetSurfBackColor( mMat[j].GetDiffuse())) ;
|
|
// passo i triangoli alla grafica
|
|
pGraphics->StartTriangles( nTri[j]) ;
|
|
for ( const auto& Tria : vTria) {
|
|
if ( ( j == 0 && Tria.GetGrade() != 0) || ( j == 1 && Tria.GetGrade() == 0))
|
|
continue ;
|
|
if ( m_bShowTriaAdvanced && bIsTriDexel)
|
|
pGraphics->AddTriangle( Tria, Tria.GetTriFlags(), Tria.GetTriNormals()) ;
|
|
else
|
|
pGraphics->AddTriangle( Tria, TriFlags3d(), TriNormals3d( Tria.GetN())) ;
|
|
}
|
|
pGraphics->EndTriangles() ;
|
|
// assegno contatore di aggiornamenti
|
|
pGraphics->SetCounter( pZmap->GetBlockUpdatingCounter( i)) ;
|
|
}
|
|
}
|
|
}
|
|
// visualizzazione spilloni e normali (sempre nell'ultimo blocco)
|
|
bool bLinNrmShow = ( ( m_nShowZmap & ZSM_LINES) != 0 || ( m_nShowZmap & ZSM_NORMALS) != 0) ;
|
|
if ( bLinNrmShow) {
|
|
// imposto indice blocco corrente
|
|
if ( pGraphics->SetCurrent( ZMAP_COL * nCount)) {
|
|
// lo pulisco
|
|
pGraphics->Clear() ;
|
|
// ciclo sui tre gruppi di spilloni
|
|
int nKmin = ( m_nShowZmap & ZSM_LINES) != 0 ? 0 : 3 ;
|
|
int nKmax = ( m_nShowZmap & ZSM_NORMALS) != 0 ? 6 : 3 ;
|
|
Color vCol[6] = {BLUE, RED, GREEN, BLUE, RED, GREEN} ;
|
|
for ( int k = nKmin ; k < nKmax ; ++ k) {
|
|
pGraphics->AddColor( vCol[k]) ;
|
|
pGraphics->AddMaterial( vCol[k], vCol[k], vCol[k], 10) ;
|
|
pGraphics->AddBackMaterial( vCol[k]) ;
|
|
PNTVECTOR vPnt ;
|
|
for ( int i = 0 ; ; ++ i) {
|
|
bool bOutBreak = false ;
|
|
for ( int j = 0 ; ; ++ j) {
|
|
POLYLINELIST lstPL ;
|
|
if ( pZmap->GetDexelLines( k, j, i, lstPL)) {
|
|
for ( const auto& PL : lstPL) {
|
|
Point3d ptS, ptE ;
|
|
bool Found = PL.GetFirstLine( ptS, ptE) ;
|
|
while ( Found) {
|
|
vPnt.emplace_back( ptS) ;
|
|
vPnt.emplace_back( ptE) ;
|
|
Found = PL.GetNextLine( ptS, ptE) ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if ( j == 0)
|
|
bOutBreak = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( bOutBreak)
|
|
break ;
|
|
}
|
|
if ( vPnt.size() > 0)
|
|
pGraphics->AddLines( vPnt) ;
|
|
}
|
|
}
|
|
}
|
|
// eventuali spigoli vivi
|
|
if ( pZmap->GetShowEdges()) {
|
|
// imposto indice blocco corrente
|
|
if ( pGraphics->SetCurrent( ZMAP_COL * nCount + ( bLinNrmShow ? 1 : 0))) {
|
|
// lo pulisco
|
|
pGraphics->Clear() ;
|
|
// inserisco le curve
|
|
ICURVEPOVECTOR vpCurve ;
|
|
if ( pZmap->GetEdges( vpCurve) && ! vpCurve.empty()) {
|
|
pGraphics->AddColor( DGRAY) ;
|
|
pGraphics->AddMaterial( DGRAY, DGRAY, DGRAY, 10) ;
|
|
pGraphics->AddBackMaterial( DGRAY) ;
|
|
for ( const auto& pCrv : vpCurve) {
|
|
PolyLine PL ;
|
|
if ( pCrv->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_GRAPH_DEG, ICurve::APL_SPECIAL, PL))
|
|
pGraphics->AddPolyLine( PL, false, true) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// se testo
|
|
else if ( nGeoType == EXT_TEXT) {
|
|
// recupero il testo
|
|
const IExtText* pTXT = GetExtText( pGeoObj) ;
|
|
if ( pTXT == nullptr)
|
|
return false ;
|
|
// calcolo la grafica
|
|
const ISurfTriMesh* pSTM = ( m_nShowText == TXT_FILL ? pTXT->GetAuxSurf() : nullptr) ;
|
|
if ( pSTM != nullptr) {
|
|
// recupero il materiale
|
|
Material mMat ;
|
|
if ( ! iIter.GetCalcMaterial( mMat))
|
|
mMat.Set( m_colDef) ;
|
|
// lo pulisco
|
|
pGraphics->Clear() ;
|
|
// se ci sono triangoli
|
|
int nTria = pSTM->GetTriangleCount() ;
|
|
if ( nTria > 0) {
|
|
// assegno materiali
|
|
pGraphics->AddColor( siObj.colObj) ; // per wireframe
|
|
pGraphics->AddMaterial( mMat.GetAmbient(), mMat.GetDiffuse(),
|
|
mMat.GetSpecular(), mMat.GetShininess()) ;
|
|
pGraphics->AddBackMaterial( GetSurfBackColor( mMat.GetDiffuse())) ;
|
|
// ciclo sui triangoli della superficie
|
|
pGraphics->StartTriangles( nTria) ;
|
|
Triangle3dEx Tria ;
|
|
int nId = pSTM->GetFirstTriangle( Tria) ;
|
|
while ( nId != SVT_NULL) {
|
|
// se visualizzazione avanzata : edge solo se boundary e normali ai vertici smussate
|
|
if ( m_bShowTriaAdvanced)
|
|
pGraphics->AddTriangle( Tria, Tria.GetTriFlags(), Tria.GetTriNormals()) ;
|
|
// altrimenti : tutti gli edge e normali ai vertici prendono quella del triangolo
|
|
else
|
|
pGraphics->AddTriangle( Tria, TriFlags3d(), TriNormals3d( Tria.GetN())) ;
|
|
nId = pSTM->GetNextTriangle( nId, Tria) ;
|
|
}
|
|
pGraphics->EndTriangles() ;
|
|
}
|
|
}
|
|
else {
|
|
POLYLINELIST lstPL ;
|
|
pTXT->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_GRAPH_DEG, lstPL) ;
|
|
pGraphics->Clear() ;
|
|
pGraphics->AddColor( siObj.colObj) ;
|
|
for ( const auto& PL : lstPL)
|
|
pGraphics->AddPolyLine( PL) ;
|
|
}
|
|
}
|
|
// se quota
|
|
else if ( nGeoType == EXT_DIMENSION) {
|
|
// recupero la quota
|
|
const IExtDimension* pDim = GetExtDimension( pGeoObj) ;
|
|
if ( pDim == nullptr)
|
|
return false ;
|
|
// calcolo la grafica
|
|
POLYLINELIST lstPL ;
|
|
pDim->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_GRAPH_DEG, lstPL) ;
|
|
pGraphics->Clear() ;
|
|
pGraphics->AddColor( siObj.colObj) ;
|
|
for ( const auto& PL : lstPL)
|
|
pGraphics->AddPolyLine( PL) ;
|
|
}
|
|
// se esiste parte custom
|
|
if ( pUserObj != nullptr) {
|
|
POLYLINELIST lstPL ;
|
|
if ( pUserObj->GetDrawPolyLines( lstPL)) {
|
|
for ( const auto& PL : lstPL)
|
|
pGraphics->AddPolyLine( PL, ( PL.GetTempProp() == 0)) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// se richiesto, visualizzo la grafica associata
|
|
bool bShowAux = false ;
|
|
if ( (( nGeoType & GEO_CURVE) != 0 || pUserObj != nullptr) && m_bShowCurveDirection)
|
|
bShowAux = true ;
|
|
|
|
// verifico se oggetto con superficie
|
|
bool bSurf = (( nGeoType & ( GEO_SURF | GEO_VOLUME)) != 0) ;
|
|
bool bGenSurf = ( bSurf || ( nGeoType == EXT_TEXT && m_nShowText == TXT_FILL && GetExtText( pGeoObj)->GetAuxSurf() != nullptr)) ;
|
|
|
|
// recupero il valore di opacità (solo per le superfici e i solidi può esserci trasparenza)
|
|
int nAlpha = siObj.colObj.GetIntAlpha() ;
|
|
|
|
// salto in ogni caso le superfici e i solidi completamente trasparenti
|
|
if ( nAlpha == 0 && bGenSurf)
|
|
return true ;
|
|
|
|
// se hiddenline e non selezione
|
|
if ( m_nShowMode == SM_HIDDENLINE && ! m_bSelect) {
|
|
// in prima passata disegno solo le superfici opache
|
|
if ( nPass == 1 && ( ! bGenSurf || nAlpha <= ALPHA_LIM))
|
|
return true ;
|
|
}
|
|
|
|
// se shading e non modalità selezione
|
|
bool bSurfSha = false ;
|
|
if ( m_nShowMode == SM_SHADING && ! m_bSelect) {
|
|
// in prima passata disegno solo le superfici opache e metto in un vettore quelle semitrasparenti
|
|
if ( nPass == 1) {
|
|
if ( ! bGenSurf)
|
|
return true ;
|
|
else {
|
|
if ( nAlpha > ALPHA_LIM)
|
|
bSurfSha = true ;
|
|
else {
|
|
// recupero matrice MODELVIEW corrente
|
|
GLdouble ModelView[ OGLMAT_DIM] ;
|
|
glGetDoublev( GL_MODELVIEW_MATRIX, ModelView) ;
|
|
Frame3d frModView ;
|
|
OpenGlMatrixToFrame( ModelView, frModView) ;
|
|
// recupero il box dell'oggetto e lo porto nel riferimento MODELVIEW
|
|
BBox3d b3Box ;
|
|
pGraphics->GetLocalBBox( b3Box) ;
|
|
b3Box.ToGlob( frModView) ;
|
|
// inserisco i dati nel vettore
|
|
m_vAlphaSurf.emplace_back( frModView, pGraphics, siObj.nStat, siObj.nMark,
|
|
bSurf, nAlpha, bShowAux, b3Box.GetMin().z, b3Box.GetMax().z) ;
|
|
return true ;
|
|
}
|
|
}
|
|
}
|
|
// in seconda passata disegno solo dimensioni 0 e curve
|
|
if ( nPass == 2 && bGenSurf)
|
|
return true ;
|
|
}
|
|
|
|
// se in selezione
|
|
if ( m_bSelect) {
|
|
// vaglio per il filtro di tipo
|
|
if ( ( nGeoType & m_nObjFilterForSelect) == 0)
|
|
return true ;
|
|
// carico il nome
|
|
glLoadName( iIter.GetId()) ;
|
|
}
|
|
|
|
// eventuale texture
|
|
string sTxrName ;
|
|
if ( iIter.GetTextureName( sTxrName)) {
|
|
// rendo corrente la texture
|
|
GLuint texName ;
|
|
double dTextDimS ;
|
|
double dTextDimT ;
|
|
if ( m_TextMgr.GetTextureData( sTxrName, texName, dTextDimS, dTextDimT)) {
|
|
glEnable( GL_TEXTURE_2D) ;
|
|
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ;
|
|
glBindTexture( GL_TEXTURE_2D, texName) ;
|
|
}
|
|
// se esiste parte custom, eventuale recupero dimensioni aggiornate
|
|
if ( pUserObj != nullptr)
|
|
pUserObj->GetDimensions( dTextDimS, dTextDimT) ;
|
|
// recupero il riferimento della texture
|
|
Frame3d frTxr ;
|
|
iIter.GetTextureFrame( frTxr) ;
|
|
// creo piano per la S
|
|
GLfloat PlaneS[4] { GLfloat( frTxr.VersX().x / dTextDimS),
|
|
GLfloat( frTxr.VersX().y / dTextDimS),
|
|
GLfloat( frTxr.VersX().z / dTextDimS),
|
|
GLfloat( -frTxr.VersX() * ( frTxr.Orig() - ORIG) / dTextDimS)} ;
|
|
// creo piano per la T
|
|
GLfloat PlaneT[4] { GLfloat( frTxr.VersY().x / dTextDimT),
|
|
GLfloat( frTxr.VersY().y / dTextDimT),
|
|
GLfloat( frTxr.VersY().z / dTextDimT),
|
|
GLfloat( -frTxr.VersY() * ( frTxr.Orig() - ORIG) / dTextDimT)} ;
|
|
// setto generazione automatica coordinate S e T per texture
|
|
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) ;
|
|
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) ;
|
|
glTexGenfv( GL_S, GL_OBJECT_PLANE, PlaneS) ;
|
|
glTexGenfv( GL_T, GL_OBJECT_PLANE, PlaneT) ;
|
|
glEnable( GL_TEXTURE_GEN_S) ;
|
|
glEnable( GL_TEXTURE_GEN_T) ;
|
|
}
|
|
|
|
// eseguo visualizzazione
|
|
bool bOk = pGraphics->Draw( siObj.nStat, siObj.nMark, bSurfSha, bSurf, nAlpha, bShowAux) ;
|
|
|
|
// disabilito textures
|
|
glDisable( GL_TEXTURE_GEN_S) ;
|
|
glDisable( GL_TEXTURE_GEN_T) ;
|
|
glDisable( GL_TEXTURE_2D) ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::DrawAlphaSurfVector( void)
|
|
{
|
|
// ordino vettore in senso crescente secondo Zmax (asse Z punta verso osservatore)
|
|
sort( m_vAlphaSurf.begin(), m_vAlphaSurf.end(),
|
|
[]( const AlphaSurf& a, const AlphaSurf&b) { return a.dZmax < b.dZmax ; }) ;
|
|
|
|
// eseguo visualizzazione
|
|
bool bOk = true ;
|
|
for ( const auto& AlphaSurf : m_vAlphaSurf) {
|
|
// imposto matrice MODELVIEW
|
|
double Matrix[OGLMAT_DIM] ;
|
|
FrameToOpenGlMatrix( AlphaSurf.frModView, Matrix) ;
|
|
glPushMatrix() ;
|
|
glLoadMatrixd( Matrix) ;
|
|
// eseguo visualizzazione
|
|
if ( ! AlphaSurf.pGraph->Draw( AlphaSurf.nStat, AlphaSurf.nMark, true,
|
|
AlphaSurf.bSurf, AlphaSurf.nAlpha, AlphaSurf.bShowAux))
|
|
bOk = false ;
|
|
// ripristino matrice
|
|
glPopMatrix() ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Scene::DeleteObjGraphicsGroup( int nId)
|
|
{
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( m_pGeomDB)) ;
|
|
if ( IsNull( pIter))
|
|
return false ;
|
|
// scandisco il gruppo
|
|
bool bNext = pIter->GoToFirstInGroup( nId) ;
|
|
while ( bNext) {
|
|
// leggo il tipo di nodo
|
|
int nGdbType = pIter->GetGdbType() ;
|
|
// se oggetto geometrico
|
|
if ( nGdbType == GDB_TY_GEO) {
|
|
// lo recupero
|
|
IGeoObj* pGeoObj = pIter->GetGeoObj() ;
|
|
if ( pGeoObj == nullptr)
|
|
return false ;
|
|
// ne cancello l'eventuale parte grafica
|
|
ObjEGrGraphics* pGraph = GetObjEGrGraphics( pGeoObj) ;
|
|
if ( pGraph != nullptr && pGraph->GetScene() == this)
|
|
pGeoObj->SetObjGraphics( nullptr) ;
|
|
}
|
|
// se gruppo
|
|
else if ( nGdbType == GDB_TY_GROUP) {
|
|
// ripeto sugli oggetti dello stesso
|
|
if ( ! DeleteObjGraphicsGroup( pIter->GetId()))
|
|
return false ;
|
|
}
|
|
// passo al successivo
|
|
bNext = pIter->GoToNext() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//------------------------------ Local functions -----------------------------
|
|
//----------------------------------------------------------------------------
|
|
static ObjEGrGraphics*
|
|
CreateObjEGrGraphics( int nCount, bool bNewWay)
|
|
{
|
|
if ( nCount > 1)
|
|
return ( new( nothrow) ObjMultiGraphics( nCount, bNewWay)) ;
|
|
else if ( bNewWay)
|
|
return ( new( nothrow) ObjNewGraphics) ;
|
|
else
|
|
return ( new( nothrow) ObjOldGraphics) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
CalcCurveTailMark( const Vector3d& vtRef, const PolyLine& plCrv, PolyLine& plMark)
|
|
{
|
|
// pulisco la polilinea per il segno
|
|
plMark.Clear() ;
|
|
// verifico effettiva esistenza della polilinea approssimante la curva
|
|
if ( plCrv.GetLineNbr() < 1)
|
|
return false ;
|
|
// dimensioni limite traverso
|
|
const double MAX_LEN_TR = 6 ;
|
|
const double MIN_LEN_TR = 0.1 ;
|
|
// recupero dati primo tratto della curva
|
|
Point3d ptTail, ptP ;
|
|
if ( ! plCrv.GetFirstLine( ptTail, ptP))
|
|
return false ;
|
|
Vector3d vtDir = ptP - ptTail ;
|
|
double dLen = vtDir.Len() ;
|
|
if ( dLen < EPS_SMALL)
|
|
return false ;
|
|
vtDir /= dLen ;
|
|
// se molto piccolo, cerco di allungarmi senza deviare troppo
|
|
while ( dLen < MAX_LEN_TR) {
|
|
Point3d ptP1, ptP2 ;
|
|
if ( ! plCrv.GetNextLine( ptP1, ptP2))
|
|
break ;
|
|
Vector3d vtNxDir = ptP2 - ptP1 ;
|
|
vtNxDir.Normalize() ;
|
|
if ( ( vtDir * vtNxDir) > cos( 30 * DEGTORAD))
|
|
dLen = (ptP1 - ptTail).Len() ;
|
|
else
|
|
break ;
|
|
}
|
|
// recupero lunghezza del percorso
|
|
double dLenRef = 0 ;
|
|
plCrv.GetApproxLength( dLenRef) ;
|
|
// lunghezza della freccia
|
|
// calcolo dimensioni traverso
|
|
const double TR_COEFF = 0.6 ;
|
|
const double LEN_COEFF = 0.15 ;
|
|
double dLenTr = TR_COEFF * min( LEN_COEFF * dLenRef, dLen) ;
|
|
if ( dLenTr > MAX_LEN_TR)
|
|
dLenTr = MAX_LEN_TR ;
|
|
else if ( dLenTr < MIN_LEN_TR)
|
|
dLenTr = MIN_LEN_TR ;
|
|
// disegno traverso
|
|
Frame3d frF ;
|
|
if ( frF.Set( ptTail, vtDir, vtRef)) {
|
|
Point3d ptP0 = GetToGlob( ORIG + Vector3d( 0, 0.5 * dLenTr, 0), frF) ;
|
|
plMark.AddUPoint( 0, ptP0) ;
|
|
Point3d ptP1 = GetToGlob( ORIG + Vector3d( 0, - 0.5 * dLenTr, 0), frF) ;
|
|
plMark.AddUPoint( 1, ptP1) ;
|
|
}
|
|
else {
|
|
frF.Set( ptTail, vtDir) ;
|
|
Point3d ptP0 = GetToGlob( ORIG + Vector3d( - 0.5 * dLenTr, - 0.5 * dLenTr, 0), frF) ;
|
|
plMark.AddUPoint( 0, ptP0) ;
|
|
Point3d ptP1 = GetToGlob( ORIG + Vector3d( 0.5 * dLenTr, - 0.5 * dLenTr, 0), frF) ;
|
|
plMark.AddUPoint( 1, ptP1) ;
|
|
Point3d ptP2 = GetToGlob( ORIG + Vector3d( 0.5 * dLenTr, 0.5 * dLenTr, 0), frF) ;
|
|
plMark.AddUPoint( 2, ptP2) ;
|
|
Point3d ptP3 = GetToGlob( ORIG + Vector3d( - 0.5 * dLenTr, 0.5 * dLenTr, 0), frF) ;
|
|
plMark.AddUPoint( 3, ptP3) ;
|
|
// punto di chiusura coincidente con il primo
|
|
plMark.AddUPoint( 4, ptP0) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
CalcCurveTipArrow( const Vector3d& vtRef, const PolyLine& plCrv, PolyLine& plArr)
|
|
{
|
|
// pulisco la polilinea per la freccia
|
|
plArr.Clear() ;
|
|
// verifico effettiva esistenza della polilinea approssimante la curva
|
|
if ( plCrv.GetLineNbr() < 1)
|
|
return false ;
|
|
// dimensioni freccia limite
|
|
const double MAX_LEN_ARR = 10.0 ;
|
|
const double MIN_LEN_ARR = 0.1 ;
|
|
// recupero dati ultimo tratto della curva
|
|
Point3d ptTip, ptP ;
|
|
if ( ! plCrv.GetLastLine( ptP, ptTip))
|
|
return false ;
|
|
Vector3d vtDir = ptTip - ptP ;
|
|
double dLen = vtDir.Len() ;
|
|
if ( dLen < EPS_SMALL)
|
|
return false ;
|
|
vtDir /= dLen ;
|
|
// se molto piccolo, cerco di allungarmi senza deviare troppo
|
|
while ( dLen < MAX_LEN_ARR) {
|
|
Point3d ptP1, ptP2 ;
|
|
if ( ! plCrv.GetPrevLine( ptP1, ptP2))
|
|
break ;
|
|
Vector3d vtPrDir = ptP2 - ptP1 ;
|
|
vtPrDir.Normalize() ;
|
|
if ( ( vtDir * vtPrDir) > cos( 30 * DEGTORAD))
|
|
dLen = (ptTip - ptP1).Len() ;
|
|
else
|
|
break ;
|
|
}
|
|
// recupero lunghezza del percorso
|
|
double dLenRef = 0 ;
|
|
plCrv.GetApproxLength( dLenRef) ;
|
|
// lunghezza della freccia
|
|
const double LEN_COEFF = 0.15 ;
|
|
double dLenArr = min( LEN_COEFF * dLenRef, dLen) ;
|
|
if ( dLenArr > MAX_LEN_ARR)
|
|
dLenArr = MAX_LEN_ARR ;
|
|
else if ( dLenArr < MIN_LEN_ARR)
|
|
dLenArr = MIN_LEN_ARR ;
|
|
// disegno freccia
|
|
const double A_WIDTH_COEFF = 0.3 ;
|
|
Frame3d frF ;
|
|
if ( ! frF.Set( ptTip, vtDir, vtRef))
|
|
frF.Set( ptTip, vtDir) ;
|
|
plArr.AddUPoint( 0, ptTip) ;
|
|
Point3d ptP1 = GetToGlob( ORIG + Vector3d( 0, A_WIDTH_COEFF, -1) * dLenArr, frF) ;
|
|
plArr.AddUPoint( 1, ptP1) ;
|
|
Point3d ptP2 = GetToGlob( ORIG + Vector3d( 0, - A_WIDTH_COEFF, -1) * dLenArr, frF) ;
|
|
plArr.AddUPoint( 2, ptP2) ;
|
|
plArr.AddUPoint( 3, ptTip) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
CalcCurveConnectingLines( const PolyLine& plCrv, const Vector3d& vtTh, bool bDense, PNTVECTOR& vPnt)
|
|
{
|
|
// assegno coefficiente
|
|
double dDelta = ( bDense ? 0.25 : 0.5) ;
|
|
// ciclo per creare i segmenti di raccordo
|
|
double dU, dUprev = - dDelta ;
|
|
vPnt.reserve( 5) ;
|
|
for ( bool bFound = plCrv.GetFirstU( dU) ; bFound ; bFound = plCrv.GetNextU( dU)) {
|
|
if ( ( dU - dUprev) > dDelta - EPS_PARAM || fmod( dU, 1.) < EPS_PARAM) {
|
|
Point3d ptP ;
|
|
plCrv.GetCurrPoint( ptP) ;
|
|
vPnt.push_back( ptP) ;
|
|
ptP += vtTh ;
|
|
vPnt.push_back( ptP) ;
|
|
dUprev = dU ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
CalcCurveJoints( const ICurve* pCurve, PNTVECTOR& vPnt)
|
|
{
|
|
// pulisco il vettore dei punti
|
|
vPnt.clear() ;
|
|
// recupero il dominio della curva
|
|
double dParS = 0, dParE = 1 ;
|
|
pCurve->GetDomain( dParS, dParE) ;
|
|
// recupero i punti intermedi
|
|
for ( double dPar = dParS + 1 ; dPar < dParE - EPS_PARAM ; dPar += 1) {
|
|
Point3d ptP ;
|
|
if ( pCurve->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP))
|
|
vPnt.push_back( ptP) ;
|
|
}
|
|
return true ;
|
|
}
|