//---------------------------------------------------------------------------- // 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 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 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 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 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 pSTM( GetSurfTriMeshRuled( ptTip, &cArc, dLinTol)) ; if ( IsNull( pSTM)) return nullptr ; // creo la superficie di base e la inverto PtrOwner 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 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 pSTM( GetSurfTriMeshRuled( &cArc1, &cArc2, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ; if ( IsNull( pSTM)) return nullptr ; // creo la superficie sotto e la inverto PtrOwner 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 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 pStm( CreateBasicSurfTriMesh()) ; if ( IsNull( pStm) || ! pStm->CreateByFlatContour( Polyg.GetPolyLine())) return nullptr ; // restituisco la superficie return Release( pStm) ; }