EgtExecutor 1.9j3 :
- aggiunta funzione Exe e Lua CreateSurfTmConvexHullInBBox.
This commit is contained in:
+196
-42
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user