EgtExecutor 1.9j3 :

- aggiunta funzione Exe e Lua CreateSurfTmConvexHullInBBox.
This commit is contained in:
Dario Sassi
2018-10-12 07:34:13 +00:00
parent 71c9e31c83
commit dbd7a96277
5 changed files with 279 additions and 44 deletions
+196 -42
View File
@@ -24,6 +24,7 @@
#include "/EgtDev/Include/EGkStmStandard.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkPolygon3d.h"
#include "/EgtDev/Include/EGkVolZmap.h"
#include "/EgtDev/Include/EgkStringUtils3d.h"
#include "/EgtDev/Include/EgkGeoPoint3d.h"
@@ -348,56 +349,23 @@ MyCreateSurfTmPlaneInBBox( int nParentId, const Point3d& ptP, const Vector3d& vt
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
nParentId = AdjustId( nParentId) ;
// definisco contorno del piano nel suo riferimento intrinseco
double dRad ;
if ( ! b3Box.GetRadius( dRad))
// costruisco il piano nel box
Plane3d plPlane ;
plPlane.Set( ptP, vtN) ;
PtrOwner<ISurfTriMesh> pStm( GetSurfTriMeshPlaneInBox( plPlane, b3Box)) ;
if ( IsNull( pStm))
return GDB_ID_NULL ;
double dDiam = 2 * dRad ;
PolyLine PL ;
PL.AddUPoint( 0, Point3d( - dDiam, -dDiam, 0)) ;
PL.AddUPoint( 1, Point3d( dDiam, -dDiam, 0)) ;
PL.AddUPoint( 2, Point3d( dDiam, dDiam, 0)) ;
PL.AddUPoint( 3, Point3d( -dDiam, dDiam, 0)) ;
PL.AddUPoint( 4, Point3d( -dDiam, -dDiam, 0)) ;
// lo porto nel riferimento di definizione
Frame3d frPlane ;
if ( ! frPlane.Set( ptP, vtN))
return GDB_ID_NULL ;
PL.ToGlob( frPlane) ;
// creo la superficie piano
PtrOwner<ISurfTriMesh> pSTM( CreateSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByFlatContour( PL))
return GDB_ID_NULL ;
// la taglio con le pareti del box
Plane3d plBottom ; plBottom.Set( b3Box.GetMin(), -Z_AX) ;
if ( ! pSTM->Cut( plBottom, true))
return GDB_ID_NULL ;
Plane3d plTop ; plTop.Set( b3Box.GetMax(), Z_AX) ;
if ( ! pSTM->Cut( plTop, true))
return GDB_ID_NULL ;
Plane3d plLeft ; plLeft.Set( b3Box.GetMin(), -X_AX) ;
if ( ! pSTM->Cut( plLeft, true))
return GDB_ID_NULL ;
Plane3d plRight ; plRight.Set( b3Box.GetMax(), X_AX) ;
if ( ! pSTM->Cut( plRight, true))
return GDB_ID_NULL ;
Plane3d plFront ; plFront.Set( b3Box.GetMin(), -Y_AX) ;
if ( ! pSTM->Cut( plFront, true))
return GDB_ID_NULL ;
Plane3d plBack ; plBack.Set( b3Box.GetMax(), Y_AX) ;
if ( ! pSTM->Cut( plBack, true))
return GDB_ID_NULL ;
// recupero il riferimento locale
// recupero il riferimento locale del gruppo destinazione
Frame3d frLoc ;
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
return GDB_ID_NULL ;
// se necessario, porto la superficie piano trimmato nel riferimento locale
if ( nRefType == RTY_GLOB)
pSTM->ToLoc( frLoc) ;
pStm->ToLoc( frLoc) ;
else if ( nRefType == RTY_GRID)
pSTM->LocToLoc( pGeomDB->GetGridFrame(), frLoc) ;
pStm->LocToLoc( pGeomDB->GetGridFrame(), frLoc) ;
// inserisco la superficie nel DB
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pSTM)) ;
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pStm)) ;
return nNewId ;
}
@@ -423,6 +391,192 @@ ExeCreateSurfTmPlaneInBBox( int nParentId, const Point3d& ptP, const Vector3d& v
return nNewId ;
}
//-------------------------------------------------------------------------------
static Triangle3d
MyCreateSidePlaneHull( const PNTVECTOR& vVert, bool bNXp, const BBox3d& b3Box, int nFace)
{
// determino i vertici della superficie sui bordi della faccia Z+ del BBox
Triangle3d Tria ;
for ( int i = 0 ; i < int( vVert.size()) ; ++ i) {
if ( ( nFace == +2 && abs( vVert[i].y - b3Box.GetMax().y) > 100 * EPS_SMALL) ||
( nFace == -2 && abs( vVert[i].y - b3Box.GetMin().y) > 100 * EPS_SMALL) ||
( nFace == +3 && abs( vVert[i].z - b3Box.GetMax().z) > 100 * EPS_SMALL) ||
( nFace == -3 && abs( vVert[i].z - b3Box.GetMin().z) > 100 * EPS_SMALL))
continue ;
if ( ( nFace == +2 && abs( vVert[i].z - b3Box.GetMin().z) < 10 * EPS_SMALL) ||
( nFace == -2 && abs( vVert[i].z - b3Box.GetMax().z) < 10 * EPS_SMALL) ||
( nFace == +3 && abs( vVert[i].y - b3Box.GetMax().y) < 10 * EPS_SMALL) ||
( nFace == -3 && abs( vVert[i].y - b3Box.GetMin().y) < 10 * EPS_SMALL)) {
int nI = ( bNXp ? 0 : 1) ;
Tria.SetP( nI, vVert[i]) ;
Tria.SetAttrib( nI, i) ;
Tria.SetGrade( Tria.GetGrade() + 2) ;
continue ;
}
if ( ( nFace == +2 && abs( vVert[i].z - b3Box.GetMax().z) < 10 * EPS_SMALL) ||
( nFace == -2 && abs( vVert[i].z - b3Box.GetMin().z) < 10 * EPS_SMALL) ||
( nFace == +3 && abs( vVert[i].y - b3Box.GetMin().y) < 10 * EPS_SMALL) ||
( nFace == -3 && abs( vVert[i].y - b3Box.GetMax().y) < 10 * EPS_SMALL)) {
int nI = ( bNXp ? 1 : 0) ;
Tria.SetP( nI, vVert[i]) ;
Tria.SetAttrib( nI, i) ;
Tria.SetGrade( Tria.GetGrade() + 1) ;
continue ;
}
}
Tria.SetAttrib( 2, -1) ;
if ( Tria.GetGrade() != 3)
return Tria ;
// determino il piano passante per questa linea che racchiude tutti i punti
for ( int i = 0 ; i < int( vVert.size()) ; ++ i) {
if ( i != Tria.GetAttrib( 0) && i != Tria.GetAttrib( 1)) {
if ( Tria.GetAttrib( 2) == -1 ||
( ( vVert[i] - Tria.GetP( 0)) * Tria.GetN() > EPS_ZERO)) {
Tria.SetP( 2, vVert[i]) ;
Tria.Validate( true) ;
Tria.SetAttrib( 2, i) ;
}
}
}
return Tria ;
}
//----------------------------------------------------------------------------
bool
MyDoSewing( ISurfTriMesh* pStm, const Polygon3d& Polyg)
{
// verifico esistenza superficie
if ( pStm == nullptr)
return false ;
// se poligono vuoto, non devo fare alcunché
if ( Polyg.GetSideCount() == 0)
return true ;
// creo la superficie trimesh del poligono
PtrOwner<ISurfTriMesh> pStm2( CreateSurfTriMesh()) ;
if ( IsNull( pStm2) || ! pStm2->CreateByFlatContour( Polyg.GetPolyLine()))
return false ;
// le unisco
return pStm->DoSewing( *pStm2) ;
}
//-------------------------------------------------------------------------------
static int
MyCreateSurfTmConvexHullInBBox( int nParentId, int nId, const BBox3d& b3Box, int nRefType)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// recupero la superficie TriMesh
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nId)) ;
if ( pStm == nullptr)
return GDB_ID_NULL ;
// recupero il suo riferimento e lo porto in quello indicato
Frame3d frStm ;
if ( ! pGeomDB->GetGlobFrame( nId, frStm))
return GDB_ID_NULL ;
frStm = GetFrameInRef( pGeomDB, frStm, GLOB_FRM, nRefType) ;
// ne calcolo la normale media
Vector3d vtN ;
Triangle3d Tria ;
int nT = pStm->GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) {
// sommo la normale moltiplicata per l'area del triangolo
vtN += Tria.GetArea() * Tria.GetN() ;
// passo al triangolo successivo
nT = pStm->GetNextTriangle( nT, Tria) ;
}
if ( ! vtN.Normalize())
return GDB_ID_NULL ;
vtN.ToGlob( frStm) ;
bool bNXp = ( vtN.x >= 0) ;
// recupero i vertici e li porto nel riferimento indicato
PNTVECTOR vVert ;
for ( int i = 0 ; i < pStm->GetVertexSize() ; ++ i) {
Point3d ptP ;
if ( pStm->GetVertex( i, ptP)) {
ptP.ToGlob( frStm) ;
vVert.emplace_back( ptP) ;
}
}
// determino i piani che racchiudono tutta la superficie dalle tracce sulla facce laterali della stessa
Triangle3d vTria[4] ;
vTria[0] = MyCreateSidePlaneHull( vVert, bNXp, b3Box, +3) ;
vTria[1] = MyCreateSidePlaneHull( vVert, bNXp, b3Box, -3) ;
vTria[2] = MyCreateSidePlaneHull( vVert, bNXp, b3Box, +2) ;
vTria[3] = MyCreateSidePlaneHull( vVert, bNXp, b3Box, -2) ;
// cerco uno o due piani validi
int nPlane1 = -1 ;
int nPlane2 = -1 ;
for ( int i = 0 ; i < 4 ; ++ i) {
if ( ! vTria[i].IsValid())
continue ;
nPlane1 = i ;
for ( int j = i + 1 ; j < 4 ; ++ j) {
if ( vTria[j].IsValid() &&
abs( vTria[i].GetN() * vTria[j].GetN()) < 0.94) {
nPlane2 = j ;
break ;
}
}
break ;
}
// se nessun piano valido
if ( nPlane1 == -1)
return GDB_ID_NULL ;
// se un solo piano valido
if ( nPlane2 == -1)
return MyCreateSurfTmPlaneInBBox( nParentId, vTria[nPlane1].GetP( 0), vTria[nPlane1].GetN(), b3Box, nRefType) ;
// altrimenti due piani validi
Polygon3d Polyg1 ;
if ( ! Polyg1.FromPlaneTrimmedWithBox( vTria[nPlane1].GetPlane(), b3Box.GetMin(), b3Box.GetMax()))
return GDB_ID_NULL ;
Polygon3d Polyg2 ;
if ( ! Polyg2.FromPlaneTrimmedWithBox( vTria[nPlane2].GetPlane(), b3Box.GetMin(), b3Box.GetMax()))
return GDB_ID_NULL ;
if ( ! Polyg1.Trim( Polyg2, true, true) || ! Polyg2.Trim( Polyg1, true, false))
return GDB_ID_NULL ;
// creo la trimesh dalle due facce
PtrOwner<ISurfTriMesh> pChStm( CreateSurfTriMesh()) ;
if ( IsNull( pChStm))
return GDB_ID_NULL ;
if ( ! MyDoSewing( pChStm, Polyg1) ||
! MyDoSewing( pChStm, Polyg2))
return GDB_ID_NULL ;
pChStm->DoCompacting() ;
// recupero il riferimento locale del gruppo destinazione
Frame3d frLoc ;
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
return GDB_ID_NULL ;
// se necessario, porto la superficie piano trimmato nel riferimento locale
if ( nRefType == RTY_GLOB)
pChStm->ToLoc( frLoc) ;
else if ( nRefType == RTY_GRID)
pChStm->LocToLoc( pGeomDB->GetGridFrame(), frLoc) ;
// inserisco la superficie nel DB
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pChStm)) ;
return nNewId ;
}
//-------------------------------------------------------------------------------
int
ExeCreateSurfTmConvexHullInBBox( int nParentId, int nId, const BBox3d& b3Box, int nRefType)
{
// creo il piano
int nNewId = MyCreateSurfTmConvexHullInBBox( nParentId, nId, b3Box, nRefType) ;
ExeSetModified() ;
// se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtSurfTmConvexHullInBBox(" + IdToString( nParentId) + "," +
IdToString( nId) + ",{" +
ToString( b3Box.GetMin()) + "},{" +
ToString( b3Box.GetMax()) + "}}," +
RefTypeToString( nRefType) + ")" +
" -- Id=" + ToString( nNewId) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// restituisco l'identificativo della nuova entità
return nNewId ;
}
//-------------------------------------------------------------------------------
int
ExeCreateSurfTmBBox( int nParentId, const BBox3d& b3Box, int nRefType)