f0716e2727
- aggiunte funzioni GetSurfTriMeshPyramidFrustum e GetSurfTriMeshConeFrustum - modificata funzione GetSurfTriMeshPyramid per origine ora in centro alla base.
383 lines
15 KiB
C++
383 lines
15 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2015
|
|
//----------------------------------------------------------------------------
|
|
// File : StmStandard.cpp Data : 31.03.15 Versione : 1.6c7
|
|
// Contenuto : Implementazione di funzioni per creazione di superfici Stm
|
|
// standard : Box, Pyramid, Cylinder, Sphere, Cone.
|
|
//
|
|
//
|
|
// Modifiche : 31.03.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "CurveArc.h"
|
|
#include "SurfTriMesh.h"
|
|
#include "/EgtDev/Include/EGkStmStandard.h"
|
|
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
|
#include "/EgtDev/Include/EGkPolygon3d.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshEmpty( void)
|
|
{
|
|
// creo oggetto con superficie vuota
|
|
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pStm) || ! pStm->AdjustTopology())
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pStm) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
static SurfTriMesh*
|
|
GetStandardSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
|
{
|
|
// creo oggetto vuoto
|
|
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pSTM))
|
|
return nullptr ;
|
|
// assegno i vertici
|
|
double dBotZ = 0, dTopZ = dHeight ;
|
|
if ( dBotZ > dTopZ)
|
|
swap( dBotZ, dTopZ) ;
|
|
if ( pSTM->AddVertex( Point3d( 0, 0, dBotZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( 0, 0, dTopZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( dDimX, 0, dBotZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( dDimX, 0, dTopZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( dDimX, dDimY, dBotZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( dDimX, dDimY, dTopZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( 0, dDimY, dBotZ)) == SVT_NULL ||
|
|
pSTM->AddVertex( Point3d( 0, dDimY, dTopZ)) == SVT_NULL)
|
|
return nullptr ;
|
|
// definisco i triangoli
|
|
int aVertId[12][3]{{ 1, 0, 2}, { 1, 2, 3},
|
|
{ 3, 2, 4}, { 3, 4, 5},
|
|
{ 5, 4, 6}, { 5, 6, 7},
|
|
{ 7, 6, 0}, { 7, 0, 1},
|
|
{ 0, 4, 2}, { 6, 4, 0},
|
|
{ 1, 3, 5}, { 7, 1, 5}} ;
|
|
for ( int i = 0 ; i < 12 ; ++ i) {
|
|
if ( pSTM->AddTriangle( aVertId[i]) == SVT_NULL)
|
|
return nullptr ;
|
|
}
|
|
// sistemo la topologia
|
|
if ( ! pSTM->AdjustTopology())
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pSTM) ;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
static SurfTriMesh*
|
|
GetRegularSurfTriMeshBox( double dDimX, double dDimY, double dHeight)
|
|
{
|
|
// i triangoli devono essere quasi equilateri pertanto calcolo come dividere le varie parti
|
|
double dMaxStep = INFINITO ;
|
|
double dMin1 = min( dDimX, dDimY) ;
|
|
double dMin2 = min( max( dDimX, dDimY), abs( dHeight)) ;
|
|
dMaxStep = min( max( dMin1, dMin2), 2 * min( dMin1, dMin2)) ;
|
|
dMaxStep = max( dMaxStep, 1.) ;
|
|
int nStepX = max( int( dDimX / dMaxStep + 0.9), 1) ;
|
|
double dStepX = dDimX / nStepX ;
|
|
int nStepY = max( int( dDimY / dMaxStep + 0.9), 1) ;
|
|
double dStepY = dDimY / nStepY ;
|
|
int nStepZ = max( int( abs( dHeight) / dMaxStep + 0.9), 1) ;
|
|
double dStepZ = dHeight / nStepZ ;
|
|
// creo la polilinea del contorno della base
|
|
PolyLine PL1 ;
|
|
int nU1 = 0 ;
|
|
PL1.AddUPoint( nU1, ORIG) ;
|
|
for ( int i = 1 ; i <= nStepX ; ++i)
|
|
PL1.AddUPoint( ++ nU1, Point3d( i * dStepX, 0, 0)) ;
|
|
for ( int j = 1 ; j <= nStepY ; ++j)
|
|
PL1.AddUPoint( ++ nU1, Point3d( dDimX, j * dStepY, 0)) ;
|
|
for ( int i = 1 ; i <= nStepX ; ++i)
|
|
PL1.AddUPoint( ++ nU1, Point3d( dDimX - i * dStepX, dDimY, 0)) ;
|
|
for ( int j = 1 ; j <= nStepY ; ++j)
|
|
PL1.AddUPoint( ++ nU1, Point3d( 0, dDimY - j * dStepY, 0)) ;
|
|
if ( dHeight < 0)
|
|
PL1.Invert() ;
|
|
// vettore altezza (estrusione)
|
|
Vector3d vtExtr1( 0, 0, dStepZ) ;
|
|
// creo e unisco le superfici trimesh laterali
|
|
PtrOwner<SurfTriMesh> pSTM1 ;
|
|
for ( int k = 0 ; k < nStepZ ; ++ k) {
|
|
SurfTriMesh STMz ;
|
|
if ( ! STMz.CreateByExtrusion( PL1, vtExtr1))
|
|
return nullptr ;
|
|
STMz.Translate( Vector3d( 0, 0, k * dStepZ)) ;
|
|
if ( IsNull( pSTM1))
|
|
pSTM1.Set( STMz.Clone()) ;
|
|
else if ( ! pSTM1->DoSewing( STMz))
|
|
return nullptr ;
|
|
}
|
|
// creo la polilinea del lato sinistro della superficie inferiore
|
|
PolyLine PL2 ;
|
|
int nU2 = 0 ;
|
|
PL2.AddUPoint( nU2, ORIG) ;
|
|
for ( int j = 1 ; j <= nStepY ; ++j)
|
|
PL2.AddUPoint( ++ nU2, Point3d( 0, j * dStepY, 0)) ;
|
|
// vettore estrusione
|
|
Vector3d vtExtr2( dStepX, 0, 0) ;
|
|
// creo e unisco le superfici trimesh inferiori
|
|
SurfTriMesh STM2 ;
|
|
for ( int i = 0 ; i < nStepX ; ++ i) {
|
|
SurfTriMesh STMx ;
|
|
if ( ! STMx.CreateByExtrusion( PL2, vtExtr2))
|
|
return nullptr ;
|
|
STMx.Translate( Vector3d( i * dStepX, 0, 0)) ;
|
|
if ( STM2.IsEmpty())
|
|
STM2 = STMx ;
|
|
else if ( ! STM2.DoSewing( STMx))
|
|
return nullptr ;
|
|
}
|
|
// la copio
|
|
SurfTriMesh STM3 = STM2 ;
|
|
// inverto e traslo la superficie superiore
|
|
STM3.Invert() ;
|
|
STM3.Translate( Vector3d( 0, 0, dHeight)) ;
|
|
// le unisco alla superficie del fianco
|
|
if ( ! pSTM1->DoSewing( STM2) || ! pSTM1->DoSewing( STM3))
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pSTM1) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshBox( double dDimX, double dDimY, double dHeight, bool bRegular)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( dDimX < EPS_SMALL || dDimY < EPS_SMALL || abs( dHeight) < EPS_SMALL)
|
|
return nullptr ;
|
|
// se trimesh standard
|
|
if ( ! bRegular)
|
|
return GetStandardSurfTriMeshBox( dDimX, dDimY, dHeight) ;
|
|
// altrimenti regolarizzata
|
|
else
|
|
return GetRegularSurfTriMeshBox( dDimX, dDimY, dHeight) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshPyramid( double dDimX, double dDimY, double dHeight)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( dDimX < EPS_SMALL || dDimY < EPS_SMALL || abs( dHeight) < EPS_SMALL)
|
|
return nullptr ;
|
|
// creo la polilinea del contorno della base
|
|
PolyLine PL ;
|
|
PL.AddUPoint( 0, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
|
PL.AddUPoint( 1, Point3d( dDimX / 2, -dDimY / 2, 0)) ;
|
|
PL.AddUPoint( 2, Point3d( dDimX / 2, dDimY / 2, 0)) ;
|
|
PL.AddUPoint( 3, Point3d( -dDimX / 2, dDimY / 2, 0)) ;
|
|
PL.AddUPoint( 4, Point3d( -dDimX / 2, -dDimY / 2, 0)) ;
|
|
if ( dHeight < 0)
|
|
PL.Invert() ;
|
|
// punto di vertice
|
|
Point3d ptTip( 0, 0, dHeight) ;
|
|
// creo e setto la superficie trimesh laterale
|
|
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pSTM) || ! pSTM->CreateByPointCurve( ptTip, PL))
|
|
return nullptr ;
|
|
// creo la superficie di base e ne inverto la normale
|
|
SurfTriMesh STM1 ;
|
|
if ( ! STM1.CreateByFlatContour( PL))
|
|
return nullptr ;
|
|
STM1.Invert() ;
|
|
// la unisco alla superficie del fianco
|
|
if ( ! pSTM->DoSewing( STM1))
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pSTM) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshCylinder( double dRadius, double dHeight, double dLinTol)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL)
|
|
return nullptr ;
|
|
// creo la circonferenza di base
|
|
CurveArc cArc ;
|
|
cArc.Set( ORIG, Z_AX, dRadius) ;
|
|
// vettore altezza (estrusione)
|
|
Vector3d vtExtr( 0, 0, dHeight) ;
|
|
// creo il cilindro
|
|
return GetSurfTriMeshByExtrusion( &cArc, vtExtr, true, dLinTol) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshCone( double dRadius, double dHeight, double dLinTol)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL)
|
|
return nullptr ;
|
|
// creo la circonferenza di base
|
|
CurveArc cArc ;
|
|
cArc.Set( ORIG, Z_AX, dRadius) ;
|
|
if ( dHeight < 0)
|
|
cArc.Invert() ;
|
|
// punto di vertice
|
|
Point3d ptTip( 0, 0, dHeight) ;
|
|
// creo la superficie laterale del cono
|
|
PtrOwner<ISurfTriMesh> pSTM( GetSurfTriMeshRuled( ptTip, &cArc, dLinTol)) ;
|
|
if ( IsNull( pSTM))
|
|
return nullptr ;
|
|
// creo la superficie di base e la inverto
|
|
PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc, dLinTol)) ;
|
|
if ( IsNull( pSTM1))
|
|
return nullptr ;
|
|
pSTM1->Invert() ;
|
|
// la unisco alla superficie del fianco
|
|
if ( ! pSTM->DoSewing( *pSTM1))
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pSTM) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshSphere( double dRadius, double dLinTol)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( dRadius < EPS_SMALL)
|
|
return nullptr ;
|
|
// creo la semicirconferenza di riferimento
|
|
CurveArc cArc ;
|
|
cArc.Set( ORIG, Y_AX, dRadius, Z_AX, ANG_STRAIGHT, 0) ;
|
|
// creo la sfera
|
|
return GetSurfTriMeshByRevolve( &cArc, ORIG, Z_AX, true, dLinTol) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshPyramidFrustum( double dBaseDimX, double dBaseDimY, double dTopDimX, double dTopDimY, double dHeight)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( ( min( dBaseDimX, dBaseDimY) < EPS_SMALL && min( dTopDimX, dTopDimY) < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
|
|
return nullptr ;
|
|
// se piramide
|
|
if ( min( dTopDimX, dTopDimY) < EPS_SMALL)
|
|
return GetSurfTriMeshPyramid( dBaseDimX, dBaseDimY, dHeight) ;
|
|
// se piramide inversa
|
|
if ( min( dBaseDimX, dBaseDimY) < EPS_SMALL)
|
|
return GetSurfTriMeshPyramid( dTopDimX, dTopDimY, -dHeight) ;
|
|
// se parallelepipedo
|
|
// continuo qui per avere l'origine in centro e non sullo spigolo in basso a sinistra
|
|
// creo la polilinea del contorno della base
|
|
PolyLine PL1 ;
|
|
PL1.AddUPoint( 0, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
|
PL1.AddUPoint( 1, Point3d( dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
|
PL1.AddUPoint( 2, Point3d( dBaseDimX / 2 , dBaseDimY / 2, 0)) ;
|
|
PL1.AddUPoint( 3, Point3d( -dBaseDimX / 2, dBaseDimY / 2, 0)) ;
|
|
PL1.AddUPoint( 4, Point3d( -dBaseDimX / 2, -dBaseDimY / 2, 0)) ;
|
|
if ( dHeight < 0)
|
|
PL1.Invert() ;
|
|
// creo la polilinea del contorno di sopra
|
|
PolyLine PL2 ;
|
|
PL2.AddUPoint( 0, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
|
PL2.AddUPoint( 1, Point3d( dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
|
PL2.AddUPoint( 2, Point3d( dTopDimX / 2, dTopDimY / 2, dHeight)) ;
|
|
PL2.AddUPoint( 3, Point3d( -dTopDimX / 2, dTopDimY / 2, dHeight)) ;
|
|
PL2.AddUPoint( 4, Point3d( -dTopDimX / 2, -dTopDimY / 2, dHeight)) ;
|
|
if ( dHeight < 0)
|
|
PL2.Invert() ;
|
|
// creo e setto la superficie trimesh laterale
|
|
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pSTM) || ! pSTM->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR_SMOOTH))
|
|
return nullptr ;
|
|
// creo la superficie di base e ne inverto la normale
|
|
SurfTriMesh STM1 ;
|
|
if ( ! STM1.CreateByFlatContour( PL1))
|
|
return nullptr ;
|
|
STM1.Invert() ;
|
|
// la unisco alla superficie del fianco
|
|
if ( ! pSTM->DoSewing( STM1))
|
|
return nullptr ;
|
|
// creo la superficie sopra
|
|
SurfTriMesh STM2 ;
|
|
if ( ! STM2.CreateByFlatContour( PL2))
|
|
return nullptr ;
|
|
// la unisco alla superficie del fianco
|
|
if ( ! pSTM->DoSewing( STM2))
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pSTM) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshConeFrustum( double dBaseRad, double dTopRad, double dHeight, double dLinTol)
|
|
{
|
|
// le dimensioni devono essere significative
|
|
if ( ( dBaseRad < EPS_SMALL && dTopRad < EPS_SMALL) || abs( dHeight) < EPS_SMALL)
|
|
return nullptr ;
|
|
// se cono
|
|
if ( dTopRad < EPS_SMALL)
|
|
return GetSurfTriMeshCone( dBaseRad, dHeight, dLinTol) ;
|
|
// se cono rovescio
|
|
if ( dBaseRad < EPS_SMALL)
|
|
return GetSurfTriMeshCone( dTopRad, -dHeight, dLinTol) ;
|
|
// se cilindro
|
|
if ( abs( dTopRad - dBaseRad) < EPS_SMALL)
|
|
return GetSurfTriMeshCylinder( dBaseRad, dHeight, dLinTol) ;
|
|
// creo la circonferenza sotto
|
|
CurveArc cArc1 ;
|
|
cArc1.Set( ORIG, Z_AX, dBaseRad) ;
|
|
if ( dHeight < 0)
|
|
cArc1.Invert() ;
|
|
// creo la circonferenza sopra
|
|
CurveArc cArc2 ;
|
|
cArc2.Set( Point3d( 0, 0, dHeight), Z_AX, dTopRad) ;
|
|
if ( dHeight < 0)
|
|
cArc2.Invert() ;
|
|
// creo la superficie laterale del cono
|
|
PtrOwner<ISurfTriMesh> pSTM( GetSurfTriMeshRuled( &cArc1, &cArc2, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
|
|
if ( IsNull( pSTM))
|
|
return nullptr ;
|
|
// creo la superficie sotto e la inverto
|
|
PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc1, dLinTol)) ;
|
|
if ( IsNull( pSTM1))
|
|
return nullptr ;
|
|
pSTM1->Invert() ;
|
|
// la unisco alla superficie del fianco
|
|
if ( ! pSTM->DoSewing( *pSTM1))
|
|
return nullptr ;
|
|
// creo la superficie sopra
|
|
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMeshByFlatContour( &cArc2, dLinTol)) ;
|
|
if ( IsNull( pSTM2))
|
|
return nullptr ;
|
|
// la unisco alla superficie del fianco
|
|
if ( ! pSTM->DoSewing( *pSTM2))
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pSTM) ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
GetSurfTriMeshPlaneInBox( const Plane3d& plPlane, const BBox3d& b3Box, bool bOnEq, bool bOnCt)
|
|
{
|
|
// verifico la definizione del piano
|
|
if ( ! plPlane.IsValid())
|
|
return nullptr ;
|
|
// creo il poligono corrispondente alla parte di piano limitata dal box
|
|
Polygon3d Polyg ;
|
|
if ( ! Polyg.FromPlaneTrimmedWithBox( plPlane, b3Box.GetMin(), b3Box.GetMax(), bOnEq, bOnCt))
|
|
return nullptr ;
|
|
// creo la trimesh con questo contorno
|
|
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pStm) || ! pStm->CreateByFlatContour( Polyg.GetPolyLine()))
|
|
return nullptr ;
|
|
// restituisco la superficie
|
|
return Release( pStm) ;
|
|
}
|