Files
EgtConverter/EgtConverter.cpp
Daniele Bariletti 43655cedb6 EgtConverter :
- aggiunto controllo
- reso il log globale.
2026-04-10 10:32:09 +02:00

2206 lines
82 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2020-2024
//----------------------------------------------------------------------------
// File : EgtConverter.cpp Data : 09.04.24 Versione : 2.6d2
// Contenuto : Importatore da formati avanzati tramite C3d.
//
//
//
// Modifiche : 12.09.20 DS Creazione modulo.
// 20.11.20 SP Trasformazione diretta in nge.
// 09.04.24 DS Aggiunto ottavo parametro Flag.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkDllMain.h"
#include "/EgtDev/Include/EGkGeomDB.h"
#include "/EgtDev/Include/EGkColor.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Include/EGkCurveArc.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkCurveAux.h"
#include "/EgtDev/Include/EGkCurveBezier.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGnDllMain.h"
#include "/EgtDev/Include/EGnGetModuleVer.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGnFileUtils.h"
#include "/EgtDev/Include/EGnGetKeyData.h"
#include "/EgtDev/Include/EgtStringConverter.h"
#include "/EgtDev/Include/EgtLogger.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EgtKeyCodes.h"
#include "/EgtDev/Include/SELkLockId.h"
#include "/EgtDev/Include/SELkKeyProc.h"
#include "/EgtDev/Include/EGkSurfAux.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkCurve.h"
#include "/EgtDev/Extern/C3d/Include/tool_enabler.h"
#include "/EgtDev/Extern/C3d/Include/model.h"
#include "/EgtDev/Extern/C3d/Include/conv_model_exchange.h"
#include "/EgtDev/Extern/C3d/Include/conv_exchange_settings.h"
#include "/EgtDev/Extern/C3d/Include/mb_placement.h"
#include "/EgtDev/Extern/C3d/Include/solid.h"
#include "/EgtDev/Extern/C3d/Include/assembly.h"
#include "/EgtDev/Extern/C3d/Include/mesh.h"
#include "/EgtDev/Extern/C3d/Include/point_frame.h"
#include "/EgtDev/Extern/C3d/Include/wire_frame.h"
#include "/EgtDev/Extern/C3d/Include/space_instance.h"
#include "/EgtDev/Extern/C3d/Include/plane_instance.h"
#include "/EgtDev/Extern/C3d/Include/point3d.h"
#include "/EgtDev/Extern/C3d/Include/cur_polyline3d.h"
#include "/EgtDev/Extern/C3d/Include/cur_polyline.h"
#include "/EgtDev/Extern/C3d/Include/cur_line_segment3d.h"
#include "/EgtDev/Extern/C3d/Include/cur_line_segment.h"
#include "/EgtDev/Extern/C3d/Include/cur_arc3d.h"
#include "/EgtDev/Extern/C3d/Include/cur_arc.h"
#include "/EgtDev/Extern/C3d/Include/cur_nurbs3d.h"
#include "/EgtDev/Extern/C3d/Include/cur_nurbs.h"
#include "/EgtDev/Extern/C3d/Include/curve3d.h"
#include "/EgtDev/Extern/C3d/Include/attr_color.h"
#include "/EgtDev/Extern/C3d/Include/mb_property.h"
#include "/EgtDev/Extern/C3d/Include/attr_product.h"
#include "/EgtDev/Extern/C3d/Include/mip_solid_area_volume.h"
#include "/EgtDev/Extern/C3d/Include/surf_spline_surface.h"
#include "/EgtDev/Extern/C3d/Include/surf_curve_bounded_surface.h"
#include "/EgtDev/Extern/C3d/Include/cur_contour_on_surface.h"
#define SAVETRIMLOOPS 0
#define SAVECONTOUR 0
#if SAVETRIMLOOPS || SAVECONTOUR
std::vector<IGeoObj*> vGeo ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ;
using namespace c3d ;
using namespace egtlogger ;
//--------------------------- Costanti ----------------------------------------
#if defined( _WIN64)
#if defined( _DEBUG)
const string EXE_NAME = "EgtConverterD64.exe" ;
#else
const string EXE_NAME = "EgtConverterR64.exe" ;
#endif
#elif defined( _WIN32)
#if defined( _DEBUG)
const string EXE_NAME = "EgtConverterD32.exe" ;
#else
const string EXE_NAME = "EgtConverterR32.exe" ;
#endif
#endif
const double TOL_STD = 2 * EPS_SMALL ;
const double TOL_LIM_S = 0.101 ;
const double TOL_LIM_B = 1.001 ;
//------------------------- Prototipi locali ---------------------------------
bool PrepareExit( Logger* pLog = nullptr, const char* szOut = nullptr) ;
uint32 GetSolidColor( MbSolid* pSolid) ;
bool CreateMeshData( MbStepData& stepData, MbFormNote& note) ;
Point3d ConvertPoint( MbCartPoint3D& mbCPoint) ;
Point3d ConvertPoint( MbPoint3D& mbCPoint) ;
bool point_handler( const MbPoint3D* pPoint, int nLayId, IGeomDB* pGeomDB) ;
ICurveComposite* ConvertLoop( MbLoop* mbLoop) ;
ICurve* ConvertCurve( const MbCurve& pCurve, Point3d& ptDegen, double dScale = 1.) ;
ICurve* ConvertCurve3D( const MbCurve3D& pCurve, Point3d& ptDegen) ;
ICurveComposite* ConvertContour( const MbContour& mbContour) ;
bool curve_handler( const MbCurve3D* pCurve, int nLayId, IGeomDB* pGeomDB) ;
ISurfBezier* ConvertSurface( const MbSurface* mbSurface, DBLVECTOR& vU, DBLVECTOR& vV) ;
bool surface_handler( const MbSurface* pSurface, int nLayId, IGeomDB* pGeomDB, uint32 color, int nFlag = 0) ;
bool nurbs2D_handler( MbNurbs* pNurbs, int nLayId, IGeomDB* pGeomDB) ;
ICurve* ConvertNurbs( const MbNurbs* pNurbs, double dScale, bool bEraseSrc) ;
ICurve* ConvertNurbs3D( const MbNurbs3D* pNurbs, bool bEraseSrc) ;
bool nurbs3D_handler( const MbNurbs3D* pNurbs, int nLayId, IGeomDB* pGeomDB) ;
bool mesh_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, bool bColor = true) ;
ISurfBezier* ConvertFace( const MbFace* mbF) ;
bool solid_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, const int nFlag = 0) ;
bool pointframe_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB) ;
bool wireframe_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB) ;
bool spaceinstance_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag = 0) ;
bool planeinstance_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB) ;
bool assembly_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag = 0) ;
bool instance_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag = 0) ;
bool SimplifyCurve( ICurveComposite*& pCrv) ;
bool LimitLoop( double u0, double u1, double v0, double v1, ICurveComposite* pCrv, ICRVCOMPOPOVECTOR& vCC, bool bOpenOrClosed) ;
//------------------------- Variabili locali ---------------------------------
static double s_dLinToler = 0.1 ;
int nObject = 0 ;
PtrOwner<Logger> pGenLog ;
//----------------------------------------------------------------------------
int
wmain( int argc, wchar_t* argv[])
{
// Primo parametro della linea di comando : nome eseguibile
// Non interessa
// Secondo parametro della linea di comando : file di input
wstring swInpName = ( argc >= 2 ? argv[1] : L"") ;
if ( swInpName.empty()) {
cout << "Missing input file path" ;
return 1 ;
}
string sInpName = wstringtoA( swInpName) ;
// Terzo parametro della linea di comando : file di output
wstring swExpName = ( argc >= 3 ? argv[2] : L"") ;
if ( swExpName.empty()) {
cout << "Missing output file path" ;
return 2 ;
}
string sExpName = wstringtoA( swExpName) ;
// Quarto parametro della linea di comando : errore cordale massimo
wstring swToler = ( argc >= 4 ? argv[3] : L"0.1") ;
string sToler = wstringtoA( swToler) ;
FromString( sToler, s_dLinToler) ;
// Quinto parametro della linea di comando : livello di debug
wstring swDebugLev = ( argc >= 5 ? argv[4] : L"0") ;
string sDebugLev = wstringtoA( swDebugLev) ;
int nDebugLev = 0 ;
FromString( sDebugLev, nDebugLev) ;
// Sesto parametro della linea di comando : licenza
wstring swKeyCode = ( argc >= 6 ? argv[5] : L"") ;
if ( swKeyCode.empty()) {
cout << "Missing key code" ;
return 3 ;
}
string sKeyCode = wstringtoA( swKeyCode) ;
// Settimo parametro della linea di comando : LockId
wstring swLockId = ( argc >= 7 ? argv[6] : L"") ;
string sLockId = wstringtoA( swLockId) ;
// Ottavo parametro della linea di comando : Flag
wstring swFlag = ( argc >= 8 ? argv[7] : L"") ;
string sFlag = wstringtoA( swFlag) ;
int nFlag = 0 ;
FromString( sFlag, nFlag) ;
// Creo il logger
pGenLog.Set( new( nothrow) Logger( ( nDebugLev > 0 ? LL_DEBUG : LL_INFO), "EgtConverter")) ;
if ( IsNull( pGenLog)) {
cout << "Error creating logger" ;
return 4 ;
}
// assegno il file
string sLogFile = ChangeFileExtension( sExpName, "txt") ;
pGenLog->AddOutputStream( new( nothrow) ofstream( sLogFile), true) ;
// Imposto livello di debug alle librerie di base
SetEGkDebugLev( nDebugLev) ;
// Imposto logger
SetEGkLogger( pGenLog) ;
SetEGnLogger( pGenLog) ;
// Imposto il tipo di chiave
SetLockType( KEY_LOCK_TYPE_HW) ;
SetEGkKeyType( KEY_LOCK_TYPE_HW) ;
SetEGnKeyType( KEY_LOCK_TYPE_HW) ;
if ( ! sLockId.empty()) {
int nKeyType = KEY_LOCK_TYPE_HW ;
bool bNetHwKey = false ;
int nUserId = 0 ;
if ( GetLockIdStringInfo( sLockId, nKeyType, bNetHwKey, nUserId)) {
string sAddrPort = "" ;
if ( nKeyType == KEY_LOCK_TYPE_HW)
GetLockIdStringNetData( sLockId, sAddrPort) ;
SetNetHwKey( bNetHwKey, nUserId, sAddrPort) ;
SetEGkNetHwKey( bNetHwKey) ;
SetEGnNetHwKey( bNetHwKey) ;
}
}
// Verifico la chiave
int nKLev, nKeyExpDays ;
int nLevRet = GetKeyLevel( sKeyCode, KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nKLev, nKeyExpDays) ;
SetEGnKeyLevel( nLevRet, nKLev, nKeyExpDays) ;
unsigned int nOpt1, nOpt2 ;
int nKeyOptExpDays ;
int nOptRet = GetKeyOptions( sKeyCode, KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nOpt1, nOpt2, nKeyOptExpDays) ;
SetEGnKeyOptions( nOptRet, nOpt1, nOpt2, nKeyOptExpDays) ;
// Imposto la chiave di protezione alle librerie di base
SetEGkKey( sKeyCode) ;
SetEGnKey( sKeyCode) ;
// Dichiaro inizio programma
LOG_DATETIME( pGenLog, " Init")
// messaggio dall'applicazione
string sExeVer ; GetModuleVersion( NULL, sExeVer) ;
string sAppMsg = EXE_NAME + " ver." + sExeVer ;
LOG_INFO( pGenLog, sAppMsg.c_str())
// versione dei componenti
string sVer ;
sVer += GetEGkVersion() ;
LOG_INFO( pGenLog, sVer.c_str())
// tolleranza lineare
LOG_INFO( pGenLog, ( "Toler=" + sToler).c_str())
// livello di log
LOG_INFO( pGenLog, ( "DbgLev=" + sDebugLev).c_str())
// flag
LOG_INFO( pGenLog, ( "Flag=" + sFlag).c_str())
// Activation of the geometric kernel C3D.
// chiavi licenza dalla versione 117955 di c3d
string str0( "Egalware..[C3D][cnv][mdl]") ;
string str1( "1RM6ZehiyVYJeIbiHEWppkPKTE0Qfw+EGGDNQjAtvEFueEjOCSSvdx9dmZzoHTpu9ugDha+cR3qIAUYXcjvMfB6pHhvXX8f2DwIcbxzf9pMk/7umVH/1fUk485Z/7y+wj7TdscCmJ4sgooAc1CLn++0BXvukeXPhGXNFuS4YUSE=") ;
// chiavi licenza per vecchie versioni
// string str0( "Egaltech..[cnv][mdl]") ;
// string str1( "JW02HxzIKyBIMzDWswgytSRB98wcImMzPTohT44M5EbQK8BpmEHA54hEkogovfCbtMufHIT2HbjX6NSp1+gpEw==") ;
EnableMathModules( str0.c_str(), (int)str0.length(), str1.c_str(), (int)str1.length()) ;
// Verify module activation
bool bModOk = IsMathModelerEnable() ;
bool bConvOk = IsMathConverterEnable() ;
if ( ! bModOk || ! bConvOk) {
PrepareExit( pGenLog, "Error activating Modeler or Converter") ;
return 10 ;
}
// File import
LOG_INFO( pGenLog, ( "File to import : " + sInpName).c_str())
MbModel geomModel ;
int nReadRes = ImportFromFile( geomModel, C3DToPathstring(ToC3Dstring( swInpName))) ;
if ( nReadRes != cnv_Success) {
if ( nReadRes == cnv_FileOpenError)
PrepareExit( pGenLog, "Error opening input file") ;
else if ( nReadRes == cnv_UnknownExtension)
PrepareExit( pGenLog, "Unkwown input file type") ;
else if ( nReadRes == cnv_NotEnoughMemory)
PrepareExit( pGenLog, "Not enough memory") ;
else
PrepareExit( pGenLog, "Internal error during read") ;
return 11 ;
}
// Creo GeomDB
PtrOwner<IGeomDB> pGeomDB( CreateGeomDB()) ;
if ( IsNull( pGeomDB)){
PrepareExit( pGenLog, "Error creating GeomDB") ;
return 12 ;
}
// Inserisco gli oggetti nel GeomDB (sotto pezzo/layer)
pGeomDB->SetDefaultMaterial( Color( 176, 176, 176)) ;
int nPartId = pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, Frame3d()) ;
int nLayId = pGeomDB->AddGroup( GDB_ID_NULL, nPartId, Frame3d()) ;
nObject = 0 ;
// scorro il modello importato
for ( MbModel::ItemIterator it = geomModel.Begin() ; it != geomModel.End() ; it++ ) {
bool bSolOk = true ;
if ( ( *it)->IsA() == st_Assembly)
bSolOk = assembly_handler( *it, nLayId, pGeomDB, nFlag) ;
else if ( ( *it )->IsA() == st_Solid )
bSolOk = solid_handler( *it, nLayId, pGeomDB, nFlag) ;
else if ( ( *it)->IsA() == st_Instance)
bSolOk = instance_handler(*it, nLayId, pGeomDB, nFlag) ;
else if ( ( *it)->IsA() == st_PointFrame)
bSolOk = pointframe_handler(*it, nLayId, pGeomDB) ;
else if ( ( *it)->IsA() == st_WireFrame)
bSolOk = wireframe_handler(*it, nLayId, pGeomDB) ;
else if ( ( *it)->IsA() == st_SpaceInstance)
bSolOk = spaceinstance_handler(*it, nLayId, pGeomDB, nFlag) ;
else if ( ( *it)->IsA() == st_Mesh)
bSolOk = mesh_handler(*it, nLayId, pGeomDB) ;
else if ( ( *it)->IsA() == st_PlaneInstance)
bSolOk = planeinstance_handler(*it, nLayId, pGeomDB) ;
if ( ! bSolOk) {
PrepareExit( pGenLog, "Error on model") ;
return 14 ;
}
++nObject ;
}
// Salvo il progetto
bool bOk = pGeomDB->Save( GDB_ID_ROOT, sExpName, GDB_SV_BIN) ;
if ( ! bOk) {
PrepareExit( pGenLog, "Error saving GeomDB") ;
return 13 ;
}
else
LOG_INFO( pGenLog, "Conversion finished with success")
PrepareExit() ;
LOG_DATETIME( pGenLog, " Exit")
return 0 ;
}
//----------------------------------------------------------------------------
Point3d
ConvertPoint( MbCartPoint3D& mbCPoint)
{
Point3d pt( mbCPoint.x, mbCPoint.y ,mbCPoint.z) ;
return pt ;
}
//----------------------------------------------------------------------------
Point3d
ConvertPoint( MbPoint3D& mbPoint)
{
MbCartPoint3D mbCPoint3d = mbPoint.GetCartPoint() ;
return ConvertPoint( mbCPoint3d) ;
}
//----------------------------------------------------------------------------
ICurveComposite*
ConvertLoop( MbLoop* mbLoop)
{
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
if ( IsNull( pCC))
return nullptr ;
EdgesVector mbVEdges ;
EdgesSet mbSEdges ;
mbLoop->GetEdges( mbVEdges, mbSEdges) ;
for ( int i = 0 ; i < int( mbVEdges.size()) ; ++ i) {
Point3d ptDegen = P_INVALID ;
MbOrientedEdge* mbOEdge = mbLoop->GetOrientedEdge( i) ;
bool bDir = mbOEdge->GetOrientation() ;
PtrOwner<ICurve> pCrv( ConvertCurve3D( mbOEdge->GetCurve(), ptDegen)) ;
if ( IsNull( pCrv) || ! pCrv->IsValid())
return nullptr ;
if ( ! bDir)
pCrv->Invert() ;
pCC->AddCurve( Release( pCrv)) ;
}
return Release( pCC) ;
}
//----------------------------------------------------------------------------
ICurveComposite*
ConvertContour( const MbContour& mbContour)
{
Point3d ptDegen = P_INVALID ;
PtrOwner<ICurveComposite> pCC( ConvertCurveToComposite( ConvertCurve( mbContour.GetBasisCurve(), ptDegen, SBZ_TREG_COEFF))) ;
return Release( pCC) ;
}
//----------------------------------------------------------------------------
bool
PrepareExit( Logger* pLog, const char* szOut)
{
// Free of the geometric kernel C3D
FreeMathModulesChecker() ;
// Close NetKey if necessary
CloseNetHwKey() ;
// Log if requested
if ( pLog != nullptr && szOut != nullptr)
LOG_ERROR( pLog, szOut) ;
return true ;
}
//----------------------------------------------------------------------------
bool
mesh_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, bool bColor)
{
MbMesh * pMesh = static_cast<MbMesh*>( pIt) ;
if ( pMesh == nullptr) {
LOG_ERROR( pGenLog, "Error : Mesh pointer null") ;
return false ;
}
PtrOwner<ISurfTriMesh> pStm( CreateSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->Init( 3, 1))
return false ;
// scorro le grids
int nVertexNbr = 0 ;
for ( size_t i = 0 ; i < pMesh->GridsCount() ; i++) {
const MbGrid* pGrid = pMesh->GetGrid( i) ;
// scorro i punti
for ( size_t j = 0 ; j < pGrid->PointsCount() ; j ++) {
MbCartPoint3D pt ;
pGrid->GetPoint ( j, pt) ;
pStm->AddVertex( Point3d( pt.x, pt.y, pt.z)) ;
}
// scorro i triangoli
for ( size_t j = 0 ; j < pGrid->TrianglesCount() ; j++) {
uint idx0, idx1, idx2 ;
pGrid->GetTriangleIndex( j, idx0, idx1, idx2) ;
int nIdV[3] = { int( nVertexNbr + idx0), int( nVertexNbr + idx1), int( nVertexNbr + idx2)} ;
pStm->AddTriangle( nIdV) ;
}
// scorro i quadrilateri
for ( size_t j = 0 ; j < pGrid->QuadranglesCount() ; j++) {
uint idx0, idx1, idx2, idx3 ;
pGrid->GetQuadrangleIndex( j, idx0, idx1, idx2, idx3) ;
int nIdV[3] = { int( nVertexNbr + idx0), int( nVertexNbr + idx2), int( nVertexNbr + idx3)} ;
pStm->AddTriangle( nIdV) ;
int nIdV2[3] = { int( nVertexNbr + idx0), int( nVertexNbr + idx1), int( nVertexNbr + idx2)} ;
pStm->AddTriangle( nIdV2) ;
}
nVertexNbr += ( int)pGrid->PointsCount() ;
}
pStm->DoCompacting() ;
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, Release( pStm)) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object Stm to GeomDB") ;
return false ;
}
if ( bColor) {
uint32 MeshColor = pMesh->GetColor() ;
if ( MeshColor == 16744192) // colore "nullo"
return true ;
float r, g, b ;
uint322RGB( MeshColor, r, g, b) ;
pGeomDB->SetMaterial( nId, Color( r, g, b)) ;
}
return true ;
}
//----------------------------------------------------------------------------
uint32
GetSolidColor( MbSolid* pSolid)
{
unordered_map < uint32, double> color_map ;
uint32 color = 16744192 ; //colore "nullo" RGB (0,127,255)
double max_area = 0.0 ;
FacesVector faces ;
pSolid -> GetFaces( faces) ;
// cerco il colore che occupa l'area maggiore su tutte le facce del solido
for ( size_t i = 0 ; i < faces.size() ; i++){
uint32 colFace = faces[i]->GetColor() ;
if ( color_map.find( colFace) == color_map.end())
color_map.insert( make_pair( colFace, CalculateArea( *faces[i], 1))) ;
else
color_map[colFace]=color_map[colFace] + CalculateArea( *faces[i], 1) ;
if ( color_map[colFace] > max_area) {
color = colFace ;
max_area = color_map[colFace] ;
}
}
if ( color == 16744192)
return pSolid->GetColor() ;
return color ;
}
//----------------------------------------------------------------------------
struct Inters {
int nIn ;
int nOut ;
Point3d ptStart ;
Point3d ptEnd ;
PtrOwner<ICurveComposite> pCrv ;
// riordino le intersezioni per lato in senso antiorario dal top
// se ho pi intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool operator < ( Inters& b)
{
// trovo in che ordine stanno i due start, tenendo conto anche della possibilit che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
int nPos1 = std::distance( vEdges.begin(), iter1) ;
const auto iter2 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
int nPos2 = std::distance( vEdges.begin(), iter2) ;
// se sono loop interni li ordino in modo decrescente rispetto all'area
bool bEqIn = ( nIn == b.nIn) ;
// se nIn un vertice sistemo il valore
int nEdgeIn = nIn ;
if ( nIn > 3)
nEdgeIn = nIn - 4 ;
return ( nPos1 < nPos2 ||
( bEqIn && nEdgeIn == 0 && ptStart.x > b.ptStart.x) ||
( bEqIn && nEdgeIn == 1 && ptStart.y > b.ptStart.y) ||
( bEqIn && nEdgeIn == 2 && ptStart.x < b.ptStart.x) ||
( bEqIn && nEdgeIn == 3 && ptStart.y < b.ptStart.y)) ;
}
} ;
//----------------------------------------------------------------------------
bool
AreSameEdge( int nEdge1, int nEdge2)
{
if ( nEdge1 == 0)
return ( nEdge2 == 4 || nEdge2 == 0 || nEdge2 == 7) ;
else if ( nEdge1 == 1)
return ( nEdge2 == 4 || nEdge2 == 1 || nEdge2 == 5) ;
else if ( nEdge1 == 2)
return ( nEdge2 == 6 || nEdge2 == 2 || nEdge2 == 5) ;
else if ( nEdge1 == 3)
return ( nEdge2 == 6 || nEdge2 == 3 || nEdge2 == 7) ;
else if ( nEdge1 == 4)
return ( nEdge2 == 0 || nEdge2 == 1 || nEdge2 == 7 || nEdge2 == 5) ;
else if ( nEdge1 == 5)
return ( nEdge2 == 2 || nEdge2 == 1 || nEdge2 == 4 || nEdge2 == 6) ;
else if ( nEdge1 == 6)
return ( nEdge2 == 2 || nEdge2 == 3 || nEdge2 == 5 || nEdge2 == 7) ;
else if ( nEdge1 == 7)
return ( nEdge2 == 0 || nEdge2 == 3 || nEdge2 == 4 || nEdge2 == 6) ;
else
return false ;
}
//----------------------------------------------------------------------------
bool
SimplifyCurve( ICurveComposite*& pCrv)
{
if( pCrv == nullptr)
return false ;
PolyArc paApprox ;
if ( ! pCrv->ApproxWithArcs( 0.1, 15, paApprox)) {
PolyLine plApprox ;
if ( ! pCrv->ApproxWithLines( 0.1, 15, 0, plApprox))
return false ;
pCrv->Clear() ;
if ( ! pCrv->FromPolyLine( plApprox))
return false ;
}
else {
pCrv->Clear() ;
if ( ! pCrv->FromPolyArc( paApprox))
return false ;
}
if ( ! pCrv->RemoveSmallParts(0.1, 15) ||
! pCrv->MergeCurves( 0.1, 15) ||
! pCrv->RemoveSmallDefects( 0.1, 15, true))
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
LimitLoop( double u0, double u1, double v0, double v1, ICurveComposite* pCrv, ICRVCOMPOPOVECTOR& vCC, bool bOpenOrClosed) {
PtrOwner<ICurveComposite> pCCEdge( CreateCurveComposite()) ;
pCCEdge->AddPoint( Point3d( u1,v1)) ;
pCCEdge->AddLine( Point3d( u0,v1)) ;
pCCEdge->AddLine( Point3d( u0,v0)) ;
pCCEdge->AddLine( Point3d( u1,v0)) ;
pCCEdge->Close() ;
IntersCurveCurve icc( *pCrv, *pCCEdge) ;
CRVCVECTOR vCrvClass0 ;
CRVCVECTOR vCrvClass1 ;
#if SAVETRIMLOOPS
vGeo.clear() ;
vGeo.push_back( pCrv->Clone()) ;
vGeo.push_back( pCCEdge->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import\\trim_loops_during_limiting.nge") ;
#endif
if ( ! icc.GetCurveClassification( 0, EPS_SMALL, vCrvClass0) || ( ! bOpenOrClosed && ! icc.GetCurveClassification( 1, EPS_SMALL, vCrvClass1)))
return false ;
int nInters = icc.GetIntersCount() ;
ICCIVECTOR vICCI ;
for ( int i = 0 ; i < nInters ; ++i) {
IntCrvCrvInfo icci ; icc.GetIntCrvCrvInfo( i, icci) ;
vICCI.push_back( std::move( icci)) ;
}
double dLastParam0 = 0 ;
double dLastParam1 = 0 ;
double dStartA, dEndA ;
pCrv->GetDomain( dStartA, dEndA) ;
double dEndB = 4 ;
for ( int i = 0 ; i < ssize( vCrvClass0) ; ++i) {
if ( vCrvClass0[i].nClass == CRVC_IN || vCrvClass0[i].nClass == CRVC_ON_P) {
// se continua la curva precedente allora la giunta
if ( vCC.size() != 0 && abs( dLastParam0 - vCrvClass0[i].dParS) < EPS_PARAM)
vCC.back()->AddCurve( pCrv->CopyParamRange( vCrvClass0[i].dParS, vCrvClass0[i].dParE)) ;
// sennò creo una nuova curva
else
vCC.emplace_back( ConvertCurveToComposite( pCrv->CopyParamRange( vCrvClass0[i].dParS, vCrvClass0[i].dParE))) ;
dLastParam0 = vCrvClass0[i].dParE ;
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs( vICCI[j].IciA[k].dU - vCrvClass0[i].dParE) < EPS_PARAM) {
dLastParam1 = vICCI[j].IciB[k].dU ;
if ( dEndB - dLastParam1 < EPS_ZERO)
dLastParam1 = 0 ;
break ;
}
}
}
else if ( vCrvClass0[i].nClass == CRVC_OUT && ! bOpenOrClosed){
// aggiungo la parte di curva di edge al posto della parte di curva che esce dal parametrico
// se non ho ancora aggiunto un tratto parto dal primo punto di intersezione
if ( ssize( vCC) == 0) {
double dPar0 = vCrvClass0[i].dParS ;
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs(vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM ||
( ! bOpenOrClosed && abs( dEndA - vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM)) {
if ( abs( dEndB - vICCI[j].IciB[k].dU) < EPS_PARAM)
dLastParam1 = 0 ;
else
dLastParam1 = vICCI[j].IciB[k].dU ;
break ;
}
}
}
int c = 0 ;
while ( c < ssize( vCrvClass1) - 1 && abs( vCrvClass1[c].dParS - dLastParam1) > EPS_PARAM)
++c ;
if ( vCrvClass1[c].nClass == CRVC_IN && abs( vCrvClass1[c].dParS - dLastParam1) < EPS_PARAM) {
if ( ssize( vCC) == 0)
vCC.emplace_back( ConvertCurveToComposite( pCCEdge->CopyParamRange( vCrvClass1[c].dParS, vCrvClass1[c].dParE))) ;
else
vCC.back()->AddCurve( pCCEdge->CopyParamRange( vCrvClass1[c].dParS, vCrvClass1[c].dParE)) ;
dLastParam1 = vCrvClass1[c].dParE ;
// se sono alla fine curva verifico se devo aggiungere anche un pezzo di inizio
if ( dLastParam1 == dEndB && vCrvClass1[0].nClass == CRVC_IN) {
c = 0 ;
vCC.back()->AddCurve( pCCEdge->CopyParamRange( vCrvClass1[c].dParS, vCrvClass1[c].dParE)) ;
dLastParam1 = vCrvClass1[c].dParE ;
}
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
int k = vICCI[j].bOverlap ? 1 : 0 ;
if ( abs(vICCI[j].IciB[k].dU - dLastParam1) < EPS_PARAM) {
dLastParam0 = vICCI[j].IciA[k].dU ;
break ;
}
}
}
else
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
ISurfBezier*
ConvertFace( const MbFace* mbF) {
bool bSameSense = mbF->IsSameSense() ;
std::vector<SPtr<MbContour> > vMbContours ;
SurfaceSPtr mbSurf ( mbF->GetSurfaceCurvesData( vMbContours)) ;
//// controllo il tipo // qui devo poi fare tutti i casi con superfici che non richiedono di essere trasformate in bezier
MbeSpaceType mbSubType = mbF->GetSurface().IsA() ;
DBLVECTOR vU, vV ;
// N.B.: NON USARE direttamente mbSurf al posto di mbF->GetSurface(). Evidenza empirica mostra che restituiscono oggetti differenti
PtrOwner<ISurfBezier> pSurfBez(GetSurfBezier(ConvertSurface( &(mbF->GetSurface()), vU, vV))) ;
if ( IsNull( pSurfBez) || ! pSurfBez->IsValid()){
LOG_ERROR( pGenLog, "Error converting the face ( before trim) of a solid into a Bezier surface") ;
goto exit ; // porta alla fine per fare il delete dei puntatori a oggetti e un return nullptr
}
if ( mbSubType == st_CurveBoundedSurface) {
bool bPlanarSurf = pSurfBez->IsPlanar() ;
SurfFlatRegionByContours SfrCntr ;
// recupero i bordi dello spazio parametrico
// N.B.: NON USARE direttamente mbSurf al posto di mbF->GetSurface(). Evidenza empirica mostra che restituiscono oggetti differenti
double u0 = mbF->GetSurface().GetUMin() * SBZ_TREG_COEFF ;
double v0 = mbF->GetSurface().GetVMin() * SBZ_TREG_COEFF ;
double u1 = mbF->GetSurface().GetUMax() * SBZ_TREG_COEFF ;
double v1 = mbF->GetSurface().GetVMax() * SBZ_TREG_COEFF ;
Point3d ptTR( u1, v1) ;
Point3d ptTl( u0, v1) ;
Point3d ptBL( u0, v0) ;
Point3d ptBr( u1, v0) ;
int nLoops = vMbContours.size() ;
vector<Inters> vInters ;
// usando la MbCurveBoundedSurface
for ( int l = 0 ; l < nLoops ; ++l) {
ICurveComposite* pCrv( ConvertContour( *vMbContours[l])) ;
if ( pCrv == nullptr || ! pCrv->IsValid()) {
delete pCrv ;
LOG_ERROR( pGenLog, "Error converting the contour of a face of a Solid") ;
goto exit ;
}
#if SAVECONTOUR
vGeo.clear() ;
vGeo.push_back( pCrv->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import\\contour.nge") ;
#endif
if ( ! pCrv->IsClosed()){
// controllo se Start e End distano meno di 1 allora chiudo la curva a mano.
Point3d ptStart ; pCrv->GetStartPoint( ptStart) ;
Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ;
if ( AreSamePointEpsilon(ptStart, ptEnd, 1)) {
pCrv->Close() ;
if ( ! bPlanarSurf) {
if ( ! SimplifyCurve( pCrv)){
delete pCrv ;
LOG_ERROR( pGenLog, "Error simplifying open (but actually closed) curve") ;
goto exit ;
}
}
ICRVCOMPOPOVECTOR vCC ;
if ( ! LimitLoop( u0, u1, v0, v1, pCrv, vCC, false)) {
delete pCrv ;
LOG_ERROR( pGenLog, "Error limiting open (but actually closed) curve") ;
goto exit ;
}
delete pCrv ;
if ( IsNull(vCC[0]) || ! vCC[0]->IsValid() || ! SfrCntr.AddCurve( Release( vCC[0]))) {
LOG_ERROR( pGenLog, "Error adding open curve") ;
goto exit ;
}
}
else {
if ( ! bPlanarSurf) {
if ( ! SimplifyCurve( pCrv)) {
delete pCrv ;
LOG_ERROR( pGenLog, "Error simplifying open curve") ;
goto exit ;
}
}
vInters.emplace_back() ;
Point3d ptStart ; pCrv->GetStartPoint( ptStart) ;
Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ;
vInters.back().ptStart = ptStart ;
vInters.back().ptEnd = ptEnd ;
int nIn = -1, nOut = -1 ;
if ( ! OnWhichEdge( u0, u1, v0, v1, ptStart, nIn) || ! OnWhichEdge( u0, u1, v0, v1, ptEnd, nOut)) {
// visto che non sono riuscito ad identificare su quali edge inizia o finisce la curva allora la limito allo spazio parametrico
// prima di riprovare
ICRVCOMPOPOVECTOR vCC ;
if ( ! LimitLoop( u0, u1, v0, v1, pCrv, vCC, true)) {
delete pCrv ;
LOG_ERROR( pGenLog, "Error limiting an open trim") ;
goto exit ;
}
delete pCrv ;
// scorro su tutte le curve che si sono create
for ( int i = 0 ; i < int( vCC.size()) ; ++i) {
Point3d ptStart ; vCC[i]->GetStartPoint(ptStart) ;
Point3d ptEnd ; vCC[i]->GetEndPoint( ptEnd) ;
if ( ! OnWhichEdge( u0, u1, v0, v1, ptStart, nIn) || ! OnWhichEdge( u0, u1, v0, v1, ptEnd, nOut)) {
LOG_ERROR( pGenLog, "Error identifying edges touched by an open trim") ;
goto exit ;
}
vInters.back().nIn = nIn ;
vInters.back().nOut = nOut ;
vInters.back().pCrv.Set( Release(vCC[i])) ;
}
}
else {
vInters.back().nIn = nIn ;
vInters.back().nOut = nOut ;
vInters.back().pCrv.Set( pCrv) ;
}
}
}
else {
if ( ! bPlanarSurf) {
PtrOwner<ICurveComposite> pCrvCopy( pCrv->Clone()) ;
if ( ! SimplifyCurve( pCrv)) {
delete pCrv ;
LOG_ERROR( pGenLog, "Error simplifying closed curve") ;
goto exit ;
}
double dArea = -1 ; pCrv->GetAreaXY( dArea) ;
if ( dArea < EPS_ZERO ) {
pCrv->Clear() ;
pCrv = Release( pCrvCopy) ;
}
}
#if SAVETRIMLOOPS
SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\import\\trim_loops_before_limiting.nge") ;
#endif
// se il box ha dimensioni che sforano il dominio limito il loop
BBox3d bbCrv ;
pCrv->GetBBox( GLOB_FRM, bbCrv) ;
const Point3d& ptMin = bbCrv.GetMin() ;
const Point3d& ptMax = bbCrv.GetMax() ;
if ( ptMin.x < u0 - EPS_ZERO || ptMin.y < v0 - EPS_ZERO || ptMax.x > u1 + EPS_ZERO || ptMax.y > v1 + EPS_ZERO) {
ICRVCOMPOPOVECTOR vCC ;
if ( ! LimitLoop( u0, u1, v0, v1, pCrv, vCC, false)) {
LOG_ERROR( pGenLog, "Error 1 limiting closed curve") ;
goto exit ;
}
delete pCrv ;
if ( ssize( vCC) == 0) {
LOG_ERROR( pGenLog, "Error 2 limiting closed curve") ;
goto exit ;
}
#if SAVETRIMLOOPS
vector<IGeoObj*> vGeo ;
for ( int j = 0 ; j < ssize( vCC) ; ++j)
vGeo.push_back( vCC[j]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import\\trim_loops_after_limiting.nge") ;
#endif
//devo fare la chain di queste curve prima di metterele nella SFR
GetChainedCurves( vCC) ;
#if SAVETRIMLOOPS
vGeo.clear() ;
vGeo.push_back( vCC[0]) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import\\trim_loops_after_chain.nge") ;
#endif
for( int i = 0 ; i < ssize(vCC) ; ++i){
vCC[i]->Close() ;
SfrCntr.AddCurve( Release(vCC[i])) ;
}
}
else {
// queste curve dovrebbero essere gi nel parametrico
SfrCntr.AddCurve( pCrv) ;
}
}
}
// aggiungo anche le curve aperte tutte insieme
if ( vInters.size() != 0) {
ICurveComposite* pCCOpen ( Release( vInters[0].pCrv)) ;
sort( vInters.begin(), vInters.end()) ;
bool bNotCameBack = true ;
int nEdge = vInters[0].nOut ;
// se ero in un vertice passo all'edge successivo
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge == 7)
nEdge = 0 ;
int nInters = 0 ;
while ( bNotCameBack) {
bool bAtNextStart = false ;
PolyLine plEdge ;
int nCount = 0 ;
plEdge.AddUPoint( nCount, vInters[nInters].ptEnd) ;
++ nCount ;
++ nInters ;
if ( nInters == vInters.size())
nInters = 0 ;
// scorro tutti i lati finch non torno allo start del loop
while( ! bAtNextStart) {
Point3d ptToAdd ;
if ( nEdge == 0)
ptToAdd = ptTl ;
else if ( nEdge == 1)
ptToAdd = ptBL ;
else if ( nEdge == 2)
ptToAdd = ptBr ;
else if ( nEdge == 3)
ptToAdd = ptTR ;
if ( plEdge.AddUPoint( nCount, ptToAdd))
++ nCount ;
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge < 3)
++ nEdge ;
else
nEdge = 0 ;
if ( AreSameEdge(nEdge,vInters[nInters].nIn))
bAtNextStart = true ;
}
ICurveComposite* pCC( CreateCurveComposite()) ;
pCC->FromPolyLine( plEdge) ;
// aggiungo il tratto di edge
pCCOpen->AddCurve( pCC) ;
// agggiungo il prossio taglio
if ( nInters != 0)
pCCOpen->AddCurve( Release( vInters[nInters].pCrv)) ;
if ( AreSameEdge(nEdge, vInters[0].nIn)) {
pCCOpen->Close() ;
bNotCameBack = false ;
}
}
if ( ! pCCOpen->IsClosed()) {
delete pCCOpen ;
LOG_ERROR( pGenLog, "Error creating the contour from open trims") ;
goto exit ;
}
if ( ! bPlanarSurf) {
if ( ! SimplifyCurve( pCCOpen)) {
delete pCCOpen ;
LOG_ERROR( pGenLog, "Error simplifying the contour recreated from the open trims") ;
goto exit ;
}
}
SfrCntr.AddCurve( pCCOpen) ;
}
double dScaleU = u1 - u0 ;
double dScaleV = v1 - v0 ;
ISurfFlatRegion* pTrimReg( SfrCntr.GetSurf()) ;
if ( pTrimReg == nullptr || ! pTrimReg->IsValid()) {
delete pTrimReg ;
LOG_ERROR( pGenLog, "Error creating the trim surface") ;
goto exit ;
}
#if SAVETRIMLOOPS
SaveGeoObj( pTrimReg->Clone(), "D:\\Temp\\bezier\\import\\trim_loops.nge") ;
#endif
Vector3d vToOrig( -u0, -v0, 0) ;
pTrimReg->Translate( vToOrig) ;
#if SAVETRIMLOOPS
SaveGeoObj( pTrimReg->Clone(), "D:\\Temp\\bezier\\import\\trim_loops_moved.nge") ;
#endif
bool bRescaled = false ;
int nDegU, nDegV , nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBez->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
if ( ! MakeUniform( pTrimReg, bRescaled, vU, vV, nDegU, nDegV, dScaleU, dScaleV, false)) {
LOG_ERROR( pGenLog, "Error making uniform the trim surface") ;
goto exit ;
}
if ( ! pSurfBez->SetTrimRegion(*pTrimReg)) {
// se l'intersezione è fallita allora provo a semplificare i loop della trim region
SurfFlatRegionByContours sfrTrim ;
for ( int c = 0 ; c < pTrimReg->GetChunkCount() ; ++c) {
for ( int l = 0 ; l < pTrimReg->GetLoopCount( c) ; ++l) {
ICurveComposite* pCC( GetCurveComposite(pTrimReg->GetLoop( c, l))) ;
if ( ! SimplifyCurve( pCC)) {
LOG_ERROR( pGenLog, "Error simplifying a curve of a trim region ( surface was not trimmed)") ;
delete pCC ;
delete pTrimReg ;
goto exit ;
}
if ( ! sfrTrim.AddCurve( pCC)) {
LOG_ERROR( pGenLog, "Error adding a curve to the trim region ( surface was not trimmed)") ;
delete pCC ;
delete pTrimReg ;
goto exit ;
}
}
}
PtrOwner<ISurfFlatRegion> pSfrTrimNew ( sfrTrim.GetSurf()) ;
if ( IsNull( pSfrTrimNew) || ! pSfrTrimNew->IsValid()) {
delete pTrimReg ;
LOG_DBG_ERR( pGenLog, "Error recreating trim region, in attempt to retry an intersection with the parameter space") ;
goto exit ;
}
if ( ! pSurfBez->SetTrimRegion(*pSfrTrimNew)) {
delete pTrimReg ;
LOG_DBG_ERR( pGenLog, "Error intersecating parameter space and trim surface") ;
goto exit ;
}
}
delete pTrimReg ;
pSurfBez->RemoveCollapsedSpans() ;
}
exit :
if ( IsNull( pSurfBez) || ! pSurfBez->IsValid())
return nullptr ;
if ( ! bSameSense)
pSurfBez->Invert() ;
return Release( pSurfBez) ;
}
int nAssObj = 0 ;
//----------------------------------------------------------------------------
bool
solid_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag)
{
MbSolid* pSolid = static_cast<MbSolid*>( pIt) ;
if ( pSolid == nullptr) {
LOG_ERROR( pGenLog, "Error : Solid pointer null") ;
return false ;
}
INTVECTOR vIds ;
// conversione diretta in trimesh
if ( nFlag == 0) {
// Creazione mesh
MbStepData stepdata ;
MbFormNote note ;
CreateMeshData( stepdata, note) ;
// conversione in mesh
MbMesh mesh ;
pSolid->CalculateMesh( stepdata, note, mesh) ;
if ( ! mesh_handler( & mesh, nLayId, pGeomDB, false))
return false ;
int nId = pGeomDB->GetLastInGroup( nLayId) ; // recupero id dell'oggetto appena aggiunto
vIds.push_back( nId) ;
}
// conversione in superfici di Bezier ( una per ogni faccia)
else if ( nFlag == 1) {
// reucpero le facce e le converto in NURBS prima di importarle
const MbFaceShell* FaceShell = pSolid->GetShell() ;
int nFaces = int( FaceShell->GetFacesCount()) ;
for ( int f = 0 ; f < nFaces ; ++ f) {
MbFace* mbF = FaceShell->GetFace(f) ;
PtrOwner<ISurf> pSurf( ConvertFace( mbF)) ;
if ( IsNull(pSurf) || ! pSurf->IsValid()) {
LOG_ERROR( pGenLog, "Error converting a face of a solid") ;
continue ;
}
// qui potrei inserire un controllo per evitare di aggiungere superfici di Bezier che sono collassate in punti
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, Release( pSurf)) ;
vIds.push_back( nId) ;
}
}
// Gestione colori
uint32 col=GetSolidColor( pSolid) ;
for ( int nId : vIds) {
// Aggiungo attributes
AttrVector attributes ;
pSolid->GetAttributes( attributes, at_Undefined, at_Undefined) ;
for ( unsigned int i = 0 ; i < attributes.size() ; i++) {
MbAttribute* pAttr = attributes[i] ;
if ( pAttr == nullptr)
continue ;
if ( pAttr->AttributeType() == at_ProductInfo) {
MbProductInfo* pInfo = static_cast<MbProductInfo*>( pAttr) ;
if ( ! pInfo->GetName().empty()) {
pGeomDB->SetName( nId, ToSTDstring( pInfo->GetName())) ;
if ( ! pInfo->GetId().empty())
pGeomDB->SetInfo( nId, "Id", ToSTDstring( pInfo->GetId())) ;
}
else if ( ! pInfo->GetId().empty())
pGeomDB->SetName( nId, ToSTDstring( pInfo->GetName())) ;
if ( ! pInfo->GetDescription().empty())
pGeomDB->SetInfo( nId, "Description", ToSTDstring( pInfo->GetDescription())) ;
}
}
// verifico non sia il colore "nullo"
if ( col != 16744192) {
float r, g, b = 0 ;
uint322RGB( col, r, g, b) ;
pGeomDB->SetMaterial( nId, Color( r, g, b)) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
pointframe_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB)
{
MbPointFrame* pPointFr = static_cast<MbPointFrame*>( pIt) ;
if ( pPointFr == nullptr) {
LOG_ERROR( pGenLog, "Error : Point Frame pointer null") ;
return false ;
}
// scorro i punti del PointFrame
for ( size_t i = 0 ; i < pPointFr->GetVerticesCount() ; i++) {
MbCartPoint3D pt ;
pPointFr->GetCartPoint( i, pt) ;
MbPoint3D ptP( pt) ;
bool bPointOk = point_handler( &ptP, nLayId, pGeomDB) ;
if ( ! bPointOk)
return false ;
}
return true;
}
//----------------------------------------------------------------------------
bool
wireframe_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB)
{
MbWireFrame* pWireFr = static_cast<MbWireFrame*>( pIt) ;
if ( pWireFr == nullptr) {
LOG_ERROR( pGenLog, "Error : Point Frame pointer null") ;
return false ;
}
vector<MbCurve3D*> curves ;
pWireFr->GetCurves(curves) ;
for ( size_t i =0 ; i < curves.size() ; i++) { // scorro tutte le curve del WireFrame
bool bCurveOk = curve_handler( curves[i], nLayId, pGeomDB) ;
if ( ! bCurveOk)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
assembly_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag)
{
MbAssembly* pAss = static_cast<MbAssembly*>( pIt) ;
if ( pAss == nullptr)
return false ;
// analizzo gl elementi dell'assembly
RPArray <MbItem> assItems ;
pAss->GetItems( assItems) ;
nAssObj = 0 ;
for ( MbItem** it = assItems.begin() ; it != assItems.end() ; it ++) {
bool bSolOk = true ;
if ( (*it)->IsA() == st_Assembly)
bSolOk = assembly_handler( *it, nLayId, pGeomDB, nFlag) ;
else if ( (*it)->IsA() == st_Solid)
bSolOk = solid_handler( *it, nLayId, pGeomDB, nFlag) ;
else if ( (*it)->IsA() == st_Instance)
bSolOk = instance_handler( *it, nLayId, pGeomDB, nFlag) ;
else if ( (*it)->IsA() == st_PointFrame)
bSolOk = pointframe_handler( *it, nLayId, pGeomDB) ;
else if ( (*it)->IsA() == st_WireFrame)
bSolOk = wireframe_handler( *it, nLayId, pGeomDB) ;
else if ( (*it)->IsA() == st_SpaceInstance)
bSolOk = spaceinstance_handler( *it, nLayId, pGeomDB, nFlag) ;
else if ( (*it)->IsA() == st_Mesh)
bSolOk = mesh_handler( *it, nLayId, pGeomDB) ;
else if ( (*it)->IsA() == st_PlaneInstance)
bSolOk = planeinstance_handler( *it, nLayId, pGeomDB) ;
++ nAssObj ;
if ( ! bSolOk)
return false ;
}
return true;
}
//----------------------------------------------------------------------------
bool
instance_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag)
{
MbInstance* pInst = static_cast<MbInstance*>( pIt) ;
if ( pInst == nullptr)
return false ;
const MbItem* pInstItem = pInst->GetItem() ;
if ( pInstItem == nullptr)
return false ;
MbItem* pItem = static_cast<MbItem*>( &pInstItem->Duplicate()) ;
if ( pItem == nullptr)
return false ;
MbPlacement3D InstPlacement = pInst->GetPlacement() ;
// Matrice di trasformazione dalle coord locali a quelle assolute
MbMatrix3D matrix( InstPlacement) ;
pItem->Transform( matrix) ;
// Analizzo l'item dell'instance
if ( pInstItem->IsA() == st_Solid)
return solid_handler( pItem, nLayId, pGeomDB, nFlag) ;
else if ( pInstItem->IsA() == st_Assembly)
return assembly_handler( pItem, nLayId, pGeomDB, nFlag) ;
else if ( (pInstItem)->IsA() == st_PointFrame)
return pointframe_handler( pItem, nLayId, pGeomDB) ;
else if ( (pInstItem)->IsA() == st_WireFrame)
return wireframe_handler( pItem, nLayId, pGeomDB) ;
else if ( (pInstItem)->IsA() == st_SpaceInstance)
return spaceinstance_handler( pItem, nLayId, pGeomDB, nFlag) ;
else if ( (pInstItem)->IsA() == st_Mesh)
return mesh_handler( pItem, nLayId, pGeomDB) ;
else if ( (pInstItem)->IsA() == st_PlaneInstance)
return planeinstance_handler( pItem, nLayId, pGeomDB) ;
return false ;
}
//----------------------------------------------------------------------------
bool
planeinstance_handler( MbItem* pIt, int nLayId, IGeomDB* pGeomDB)
{
MbPlaneInstance * pPlaneInstance = static_cast<MbPlaneInstance*> (pIt) ;
if ( pPlaneInstance == nullptr) {
LOG_ERROR( pGenLog, "Error : Plane Instance pointer null") ;
return false ;
}
vector<const MbPlaneItem *> pConstPlaneItems ;
pPlaneInstance->GetItems ( pConstPlaneItems) ;
const MbPlacement3D placement = pPlaneInstance->GetPlacement() ;
// matrice di trasformazione dalle coord locali a quelle assolute
MbCartPoint placement2D_origin( placement.GetOrigin().x, placement.GetOrigin().y) ;
MbVector placement2D_xaxis( placement.GetAxisX().x, placement.GetAxisX().y) ;
MbVector placement2D_yaxis( placement.GetAxisY().x, placement.GetAxisY().y) ;
MbPlacement placement2D( placement2D_origin, placement2D_xaxis, placement2D_yaxis) ;
MbMatrix matrix( placement2D) ;
// scorro tutti i PlaneItems contenuti in PlaneInstance
for ( size_t i = 0 ; i < pConstPlaneItems.size() ; i++) {
MbPlaneItem * pPlaneIt = &pConstPlaneItems[i]->Duplicate() ;
if ( pPlaneIt == nullptr)
return false ;
// trasformo in coordinate assolute
pPlaneIt->Transform( matrix) ;
// Plane Polyline
if ( pPlaneIt->IsA() == pt_Polyline) {
MbPolyline * pPolyline = static_cast<MbPolyline*> ( pPlaneIt) ;
if ( pPlaneInstance == nullptr) {
LOG_ERROR( pGenLog, "Error : Polyline pointer null") ;
return false ;
}
vector<MbCartPoint> points ;
pPolyline->GetPoints( points) ;
// elimino punti coincidenti rispetto alla tol fissata
for ( vector<MbCartPoint>::iterator it = points.begin() + 1 ; it != points.end() ; it++)
if ( abs( it->x - ( it-1)->x) < TOL_STD && abs( it->y - ( it-1)->y) < TOL_STD) {
points.erase( it) ;
it-- ;
}
// se dopo la rimozione è rimasto un solo punto, la curva è degenerata in un GeoPoint
if ( points.size() == 1) {
LOG_ERROR( pGenLog, "Warining : curve degenerated in one point") ;
const MbPoint3D point( MbCartPoint3D( points[0].x, points[0].y, 0)) ;
return point_handler( &point, nLayId, pGeomDB) ;
}
ICurveComposite* pCurveCompo = CreateCurveComposite() ;
if ( pCurveCompo == nullptr){
LOG_ERROR( pGenLog, "Error : creating CurveComposite") ;
return false ;
}
bool bStartPointOk = pCurveCompo->AddPoint( Point3d( points[0].x, points[0].y)) ; //starting point
if ( ! bStartPointOk) {
LOG_ERROR( pGenLog, "Error : creating CurveComposite") ;
return false ;
}
for ( size_t i = 1 ; i < points.size() - 1 ; i++){ //mid points
bool bAddLineOk = pCurveCompo->AddLine( Point3d( points[i].x, points[i].y), false) ;
if ( ! bAddLineOk) {
LOG_ERROR( pGenLog, "Error : creating CurveComposite") ;
return false ;
}
}
bool bAddLineOk = pCurveCompo->AddLine( Point3d( points.back().x, points.back().y), false) ; //end point
if ( ! bAddLineOk) {
LOG_ERROR( pGenLog, "Error : creating CurveComposite") ;
return false ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pCurveCompo) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CurveComposite 2D to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
}
// Plane LineSegment
else if ( pPlaneIt->IsA() == pt_LineSegment) {
MbLineSegment * pSegment = static_cast<MbLineSegment*>( pPlaneIt) ;
if ( pSegment == nullptr) {
LOG_ERROR( pGenLog, "Error : Segment pointer null") ;
return false ;
}
MbCartPoint start = pSegment->GetLimitPoint( 1) ;
MbCartPoint end = pSegment->GetLimitPoint( 2) ;
// se i due punti sono coincidenti per la toll fissata, la curva è degenerata in un GeoPoint
if ( abs( start.x - end.x) < TOL_STD && abs( start.y - end.y) < TOL_STD) {
LOG_ERROR( pGenLog, "Warining : CurveLine 2D degenerated in one point") ;
const MbPoint3D point( MbCartPoint3D( start.x, start.y, 0)) ;
return point_handler( &point, nLayId, pGeomDB) ;
}
ICurveLine* pLine = CreateCurveLine() ;
if ( pLine == nullptr) {
LOG_ERROR( pGenLog, "Error : creating CurveLine 2D") ;
return false ;
}
bool bLineOk = pLine->Set( Point3d( start.x, start.y), Point3d( end.x, end.y)) ;
if ( ! bLineOk) {
LOG_ERROR( pGenLog, "Error : creating CurveLine 2D") ;
return false ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pLine) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CurveLine 2D to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
}
// Plane Nurbs
else if ( pPlaneIt->IsA() == pt_Nurbs) {
MbNurbs * pNurbs= static_cast<MbNurbs*>( pPlaneIt) ;
if ( pNurbs == nullptr) {
LOG_ERROR( pGenLog, "Error : Curve Nurbs 2D pointer null") ;
return false ;
}
bool bNurbsOk = nurbs2D_handler( pNurbs, nLayId, pGeomDB) ;
if ( ! bNurbsOk)
return false ;
}
// Plane Generic Curve
else if ( pPlaneIt->Family() == pt_Curve) {
MbCurve * pCurve= static_cast<MbCurve*>( pPlaneIt) ;
if ( pCurve == nullptr) {
LOG_ERROR( pGenLog, "Error : Curve 2D pointer null") ;
return false ;
}
// Approssimo la curva con Nurbs
MbNurbs* pNurbs = pCurve->NurbsCurve() ;
if ( pNurbs == nullptr) {
LOG_ERROR( pGenLog, "Error : converting the curve 2D to a NURBS") ;
return false ;
}
bool bNurbsOk = nurbs2D_handler( pNurbs, nLayId, pGeomDB) ;
if ( ! bNurbsOk)
return false ;
}
} // ciclo sui planeitems
return true ;
}
//----------------------------------------------------------------------------
bool
nurbs2D_handler( MbNurbs* pNurbs, int nLayId, IGeomDB* pGeomDB)
{
// se la Nurbs è periodica non la considero e passo all'item successivo
if ( pNurbs->IsPeriodic()) {
LOG_ERROR( pGenLog, "Warning : periodic NURBS is ignored") ;
return true ;
}
vector<MbCartPoint> ctrlPoints ;
DBLVECTOR knots, weights ;
pNurbs->GetPoints( ctrlPoints) ;
pNurbs->GetKnots( knots) ;
pNurbs->GetWeights( weights) ;
PNTVECTOR ctrlPoints_vector( ctrlPoints.size()) ;
for ( size_t i = 0 ; i < ctrlPoints.size() ; i++)
ctrlPoints_vector[i] = Point3d( ctrlPoints[i].x, ctrlPoints[i].y) ;
// creo la struct NurbsData
CNurbsData NurbsData;
NurbsData.nDeg = int( pNurbs->GetDegree()) - 1 ; // la funzione GetDegree di c3d restituisce l'ordine
NurbsData.bRat = pNurbs->IsRational() ;
NurbsData.bClosed = pNurbs->IsClosed() ;
NurbsData.bPeriodic = pNurbs->IsPeriodic() ;
NurbsData.bExtraKnotes = false ;
if ( knots.size() == ctrlPoints.size() + NurbsData.nDeg + 1) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
NurbsData.vU = vector<double>( knots.begin() + 1, knots.end() - 1) ;
else
NurbsData.vU = knots ;
NurbsData.vCP = ctrlPoints_vector ;
NurbsData.vW = weights ;
ICurve* pBezierCurve = NurbsToBezierCurve( NurbsData) ;
if ( pBezierCurve == nullptr) {
LOG_ERROR( pGenLog, "Error : cannot create CrvBezier 2D from given Nurbs") ;
return false ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pBezierCurve) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CrvBezier 2D to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
return true ;
}
//----------------------------------------------------------------------------
bool
spaceinstance_handler ( MbItem* pIt, int nLayId, IGeomDB* pGeomDB, int nFlag)
{
MbSpaceInstance* pSpaceInst = static_cast<MbSpaceInstance*>( pIt) ;
if ( pSpaceInst == nullptr) {
LOG_ERROR( pGenLog, "Error : Space Instance pointer null") ;
return false ;
}
uint32 color = pSpaceInst->GetColor() ;
// ricavo l'oggetto contenuto nello space instance
const MbSpaceItem * pSpaceIt = pSpaceInst->GetSpaceItem() ;
if ( pSpaceIt == nullptr) {
LOG_ERROR( pGenLog, "Error : null space item") ;
return false ;
}
// point
if ( pSpaceIt->IsA() == st_Point3D) {
const MbPoint3D* pPoint = static_cast<const MbPoint3D*>( pSpaceIt) ;
if ( pPoint == nullptr) {
LOG_ERROR( pGenLog, "Error : Point pointer null") ;
return false ;
}
return point_handler( pPoint, nLayId, pGeomDB) ;
}
// curve
else if ( pSpaceIt->Family() == st_Curve3D) {
const MbCurve3D* pCurve = static_cast<const MbCurve3D*>( pSpaceIt) ;
if ( pCurve == nullptr) {
LOG_ERROR( pGenLog, "Error : Curve pointer null") ;
return false ;
}
return curve_handler( pCurve, nLayId, pGeomDB) ;
}
// surface
else if ( pSpaceIt->Family() == st_Surface) {
const MbSurface* pSurface = static_cast<const MbSurface*>( pSpaceIt) ;
if ( pSurface == nullptr) {
LOG_ERROR( pGenLog, "Error : Surface pointer null") ;
return false ;
}
return surface_handler( pSurface, nLayId, pGeomDB, color, nFlag) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
point_handler( const MbPoint3D* pPoint, int nLayId, IGeomDB* pGeomDB)
{
MbCartPoint3D pt = pPoint->GetCartPoint() ;
IGeoPoint3d* pGeoPoint = CreateGeoPoint3d() ;
if ( pGeoPoint == nullptr) {
LOG_ERROR( pGenLog, "Error : creating GeoPoint") ;
return false ;
}
bool bPointOk = pGeoPoint->Set( Point3d( pt.x, pt.y, pt.z)) ;
if ( ! bPointOk) {
LOG_ERROR( pGenLog, "Error : creating GeoPoint") ;
return false ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pGeoPoint) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object GeoPoint to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
return true ;
}
//----------------------------------------------------------------------------
ICurve*
ConvertCurve3D( const MbCurve3D& pCurve, Point3d& ptDegen)
{
PtrOwner<ICurve> pCrv ;
// Polyline
if ( pCurve.IsA() == st_Polyline3D) {
const MbPolyline3D* pPolyline = static_cast<const MbPolyline3D*>( &pCurve) ;
if ( pPolyline == nullptr)
return nullptr ;
vector< MbCartPoint3D > points ;
pPolyline->GetPoints( points) ;
// elimino punti coincidenti rispetto alla tol fissata
for ( vector<MbCartPoint3D>::iterator it = points.begin() + 1 ; it != points.end() ; it++)
if ( abs( it->x - ( it-1)->x) < TOL_STD && abs( it->y - ( it-1)->y) < TOL_STD && abs( it->z - ( it-1)->z) < TOL_STD) {
points.erase( it) ;
it-- ;
}
// se dopo la rimozione è rimasto un solo punto, la curva è degenerata in un GeoPoint
if ( points.size() == 1) {
MbPoint3D ptP( points[0]) ;
ptDegen = ConvertPoint( ptP) ;
return nullptr ;
}
ICurveComposite* pCurveCompo = CreateCurveComposite() ;
if ( pCurveCompo == nullptr)
return nullptr ;
bool bStartPointOk = pCurveCompo->AddPoint( Point3d( points[0].x, points[0].y, points[0].z)) ; // starting point
if ( ! bStartPointOk)
return nullptr ;
for ( size_t i = 1 ; i < points.size() - 1 ; i++) { // mid points
bool bAddLineOk = pCurveCompo->AddLine( Point3d( points[i].x, points[i].y, points[i].z), false) ;
if ( ! bAddLineOk)
return nullptr ;
}
bool bAddLineOk = pCurveCompo->AddLine( Point3d( points.back().x, points.back().y, points.back().z), false) ; // end point
if ( ! bAddLineOk)
return nullptr ;
return pCurveCompo ;
}
// LineSegment
else if ( pCurve.IsA() == st_LineSegment3D ){
const MbLineSegment3D * pSegment = static_cast<const MbLineSegment3D*>( &pCurve) ;
if ( pSegment == nullptr)
return nullptr ;
MbCartPoint3D start = pSegment->GetLimitPoint( 1) ;
MbCartPoint3D end = pSegment->GetLimitPoint( 2) ;
// Se i due punti sono coincidenti per la toll fissata, la curva è degenerata in un GeoPoint
if ( abs( start.x - end.x) < TOL_STD && abs( start.y - end.y) < TOL_STD && abs( start.z - end.z) < TOL_STD) {
MbPoint3D ptP( start) ;
ptDegen = ConvertPoint( ptP) ;
return nullptr ;
}
ICurveLine* pLine = CreateCurveLine() ;
if ( pLine == nullptr)
return nullptr ;
bool bLineOk = pLine->Set( Point3d( start.x, start.y, start.z), Point3d( end.x, end.y, end.z)) ;
if ( ! bLineOk)
return nullptr ;
return pLine ;
}
// Arc
else if ( pCurve.IsA() == st_Arc3D ) {
const MbArc3D * pArc = static_cast<const MbArc3D*>( &pCurve) ;
if ( pArc == nullptr)
return nullptr ;
MbCartPoint3D start = pArc->GetLimitPoint( 1) ;
MbCartPoint3D end = pArc->GetLimitPoint( 2) ;
double dRad = pArc->GetRadius() ;
ICurveArc* pCurveArc = CreateCurveArc() ;
if ( pCurveArc == nullptr)
return nullptr ;
bool bArcOk = false ;
// circonferenza
if ( abs( start.x - end.x) < TOL_STD && abs( start.y - end.y) < TOL_STD && abs( start.z - end.z) < TOL_STD) {
MbAxis3D axis ;
bool bAxisOk = pArc->GetCircleAxis( axis) ;
if ( ! bAxisOk )
return nullptr ;
if ( dRad < TOL_STD) {
MbPoint3D ptP( start) ;
ptDegen = ConvertPoint( ptP) ;
return nullptr ;
}
bArcOk = pCurveArc->Set( Point3d( axis.GetOrigin().x, axis.GetOrigin().y, axis.GetOrigin().z),
Vector3d( axis.GetAxisZ().x, axis.GetAxisZ().y, axis.GetAxisZ().z), dRad) ;
}
// arco generico
else {
MbCartPoint3D mid ;
double t = pArc->GetTMid() ;
pArc->PointOn( t, mid) ;
bArcOk = pCurveArc->Set3P( Point3d( start.x, start.y, start.z),
Point3d( mid.x, mid.y, mid.z),
Point3d( end.x, end.y, end.z)) ;
}
if ( ! bArcOk)
return nullptr ;
return pCurveArc ;
}
// Nurbs
else if ( pCurve.IsA() == st_Nurbs3D) {
const MbNurbs3D * pNurbs= static_cast<const MbNurbs3D*>( &pCurve) ;
return ConvertNurbs3D( pNurbs, false) ;
}
// Generic curve
else {
// Approssimo la curva con Nurbs
const MbNurbs3D* pNurbs = pCurve.NurbsCurve() ;
return ConvertNurbs3D( pNurbs, true) ;
}
return nullptr ;
}
//----------------------------------------------------------------------------
ICurve*
ConvertCurve( const MbCurve& pCurve, Point3d& ptDegen, double dScale)
{
MbePlaneType mbCrvType = pCurve.IsA() ;
// Polyline
if ( mbCrvType == pt_Polyline) {
const MbPolyline* pPolyline = static_cast<const MbPolyline*>( &pCurve) ;
if ( pPolyline == nullptr)
return nullptr ;
vector< MbCartPoint> points ;
pPolyline->GetPoints( points) ;
// elimino punti coincidenti rispetto alla tol fissata
for ( vector<MbCartPoint>::iterator it = points.begin() + 1 ; it != points.end() ; it++)
if ( abs( it->x - ( it-1)->x) < TOL_STD && abs( it->y - ( it-1)->y) < TOL_STD) {
points.erase( it) ;
it-- ;
}
// se dopo la rimozione è rimasto un solo punto, la curva è degenerata in un GeoPoint
if ( points.size() == 1) {
MbPoint3D ptP( points[0].x, points[0].y, 0) ;
ptDegen = ConvertPoint( ptP) ;
ptDegen.Scale( GLOB_FRM, dScale, dScale, 1.) ;
return nullptr ;
}
ICurveComposite* pCurveCompo = CreateCurveComposite() ;
if ( pCurveCompo == nullptr)
return nullptr ;
bool bStartPointOk = pCurveCompo->AddPoint( Point3d( points[0].x * dScale, points[0].y * dScale, 0)) ; // starting point
if ( ! bStartPointOk)
return nullptr ;
for ( size_t i = 1 ; i < points.size() - 1 ; i++){ // mid points
bool bAddLineOk = pCurveCompo->AddLine( Point3d( points[i].x * dScale, points[i].y, 0) * dScale, false) ;
if ( ! bAddLineOk)
return nullptr ;
}
bool bAddLineOk = pCurveCompo->AddLine( Point3d( points.back().x * dScale, points.back().y * dScale, 0), false) ; // end point
if ( ! bAddLineOk)
return nullptr ;
return pCurveCompo ;
}
// LineSegment
else if ( mbCrvType == pt_LineSegment ){
const MbLineSegment * pSegment = static_cast<const MbLineSegment*>( &pCurve) ;
if ( pSegment == nullptr)
return nullptr ;
MbCartPoint start = pSegment->GetLimitPoint( 1) ;
MbCartPoint end = pSegment->GetLimitPoint( 2) ;
// Se i due punti sono coincidenti per la toll fissata, la curva è degenerata in un GeoPoint
if ( abs( start.x - end.x) * dScale < TOL_STD && abs( start.y - end.y) * dScale < TOL_STD) {
MbCartPoint3D mbCPt3D ; mbCPt3D.Init( start) ;
MbPoint3D ptP( mbCPt3D) ;
ptDegen = ConvertPoint( ptP) ;
ptDegen.Scale( GLOB_FRM, dScale, dScale, 1.) ;
return nullptr ;
}
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( pLine == nullptr)
return nullptr ;
bool bLineOk = pLine->Set( Point3d( start.x * dScale, start.y * dScale, 0), Point3d( end.x * dScale, end.y * dScale, 0)) ;
if ( ! bLineOk)
return nullptr ;
return Release( pLine) ;
}
// Arc
else if ( mbCrvType == pt_Arc) {
const MbArc * pArc = static_cast<const MbArc*>( &pCurve) ;
if ( pArc == nullptr)
return nullptr ;
MbCartPoint start = pArc->GetLimitPoint( 1) ;
MbCartPoint end = pArc->GetLimitPoint( 2) ;
double dRad = pArc->GetRadius() ;
PtrOwner<ICurveArc> pCurveArc( CreateCurveArc()) ;
if ( pCurveArc == nullptr)
return nullptr ;
bool bArcOk = false ;
// circonferenza
if ( abs( start.x - end.x) * dScale < TOL_STD && abs( start.y - end.y) * dScale < TOL_STD) {
MbPlacement mbPlacement = pArc->GetPlacement() ;
MbVector mvVtX = mbPlacement.GetAxisX() ;
MbVector mvVtY = mbPlacement.GetAxisY() ;
if ( dRad * dScale < TOL_STD) {
ptDegen = Point3d( mbPlacement.GetOrigin().x, mbPlacement.GetOrigin().y, 0) * dScale ;
return nullptr ;
}
bArcOk = pCurveArc->Set( Point3d( mbPlacement.GetOrigin().x, mbPlacement.GetOrigin().y, 0) * dScale, Z_AX, dRad * dScale) ;
double dUStart ;
if ( pCurveArc->GetParamAtPoint( Point3d( start.x * dScale, start.y * dScale), dUStart, EPS_SMALL * dScale)) {
pCurveArc->ChangeStartPoint( dUStart) ;
Vector3d vtStartDir ; pCurveArc->GetStartDir( vtStartDir) ;
double dStart = 0 ;
MbDirection mbStartDir = pArc->Tangent( dStart) ;
Vector3d vtStartOrig( mbStartDir.ax, mbStartDir.ay) ;
bool bSameDir = vtStartDir * vtStartOrig > 0 ;
if ( ! bSameDir)
pCurveArc->Invert() ;
}
}
// arco generico
else {
MbCartPoint mid ;
double t = pArc->GetTMid() ;
pArc->PointOn( t, mid) ;
bArcOk = pCurveArc->Set3P( Point3d( start.x * dScale, start.y * dScale, 0),
Point3d( mid.x * dScale, mid.y * dScale, 0),
Point3d( end.x * dScale, end.y * dScale, 0)) ;
}
if ( ! bArcOk)
return nullptr ;
return Release( pCurveArc) ;
}
// Nurbs
else if ( mbCrvType == pt_Nurbs) {
const MbNurbs * pNurbs = static_cast<const MbNurbs*>( &pCurve) ;
return ConvertNurbs( pNurbs, dScale, false) ;
}
// curve di contorno
else if ( mbCrvType == pt_Contour) {
double dJoinTol = 20 * EPS_SMALL * dScale ;
const MbContour* pContour = static_cast<const MbContour*>( &pCurve) ;
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
for( int nS = 0 ; nS < int( pContour->GetSegmentsCount()) ; ++nS) {
const MbCurve* pSubCrv = pContour->GetSegment( nS) ;
Point3d ptDegen = P_INVALID ;
PtrOwner<ICurve> pCrvConv( ConvertCurve( *pSubCrv, ptDegen, dScale)) ;
#if SAVECONTOUR
vGeo.clear() ;
if ( pCC->IsValid())
vGeo.push_back( pCC->Clone()) ;
if ( pCrvConv->IsValid())
vGeo.push_back( pCrvConv->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import\\contour.nge") ;
#endif
if ( ptDegen.IsValid())
continue ;
Point3d ptEndCurr, ptStartNext ;
if ( pCC->IsValid()) {
if ( pCrvConv == nullptr) {
LOG_ERROR( pGenLog, "Error : failed conversion of contour") ;
return nullptr ;
}
pCC->GetEndPoint( ptEndCurr) ;
pCrvConv->GetStartPoint( ptStartNext) ;
if ( Dist( ptEndCurr, ptStartNext) < dJoinTol) {
if ( ! pCC->AddCurve( Release( pCrvConv), true, dJoinTol))
return nullptr ;
}
else {
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
pCL->Set( ptEndCurr, ptStartNext) ;
if ( ! pCC->AddCurve( Release( pCL), true, dJoinTol) || ! pCC->AddCurve( Release( pCrvConv), true, dJoinTol))
return nullptr ;
}
}
else {
if ( ! pCC->AddCurve( Release( pCrvConv), true, dJoinTol))
return nullptr ;
}
}
return Release( pCC) ;
////////// conversione in NURBS
// MbNurbs* pNurbs = pCurve.NurbsCurve() ;
// PtrOwner<ICurve> pCrv( ConvertNurbs( pNurbs, dScale, true)) ;
//#if SAVECONTOUR
// vGeo.clear() ;
// vGeo.push_back( pCrv->Clone()) ;
// SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import\\contour.nge") ;
//#endif
// return Release(pCrv) ;
}
// Generic curve
else {
// Approssimo la curva con Nurbs
MbNurbs* pNurbs = pCurve.NurbsCurve() ;
return ConvertNurbs( pNurbs, dScale, true) ;
}
return nullptr ;
}
//----------------------------------------------------------------------------
bool
curve_handler( const MbCurve3D* pCurve, int nLayId, IGeomDB* pGeomDB)
{
// Polyline
if ( pCurve->IsA() == st_Polyline3D) {
Point3d ptDegen = P_INVALID ;
ICurve* pCurveCompo = ConvertCurveToComposite( ConvertCurve3D( *pCurve, ptDegen)) ;
if ( pCurveCompo == nullptr) {
if ( ! ptDegen.IsValid()) {
LOG_ERROR( pGenLog, "Error : creating CurveComposite") ;
return false ;
}
LOG_ERROR( pGenLog, "Warning : curve degenerated in one point") ;
MbPoint3D mbCPt( ptDegen.x, ptDegen.y, ptDegen.z) ;
return point_handler( &mbCPt, nLayId, pGeomDB) ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pCurveCompo) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CurveComposite to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
}
// LineSegment
else if ( pCurve->IsA() == st_LineSegment3D) {
Point3d ptDegen = P_INVALID ;
ICurve* pLine = ConvertCurve3D( *pCurve, ptDegen) ;
if ( pLine == nullptr) {
if ( ! ptDegen.IsValid()) {
LOG_ERROR( pGenLog, "Error : creating CurveLine") ;
return false ;
}
LOG_ERROR( pGenLog, "Warning : CurveLine degenerated in one point") ;
MbPoint3D mbCPt( ptDegen.x, ptDegen.y, ptDegen.z) ;
return point_handler( &mbCPt, nLayId, pGeomDB) ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pLine) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CurveLine to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
}
// Arc
else if ( pCurve->IsA() == st_Arc3D ) {
const MbArc3D * pArc = static_cast<const MbArc3D*>( pCurve) ;
if ( pArc == nullptr) {
LOG_ERROR( pGenLog, "Error : Arc pointer null") ;
return false ;
}
Point3d ptDegen = P_INVALID ;
ICurve* pCurveArc = ConvertCurve3D( *pCurve, ptDegen) ;
if ( pCurveArc == nullptr) {
if ( ! ptDegen.IsValid()) {
LOG_ERROR( pGenLog, "Error : creating CurveArc") ;
return false ;
}
LOG_ERROR( pGenLog, "Warning : CurveArc degenerated in one point") ;
MbPoint3D mbCPt( ptDegen.x, ptDegen.y, ptDegen.z) ;
return point_handler( &mbCPt, nLayId, pGeomDB) ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pCurveArc) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CurveArc to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
}
// Nurbs
else if ( pCurve->IsA() == st_Nurbs3D) {
const MbNurbs3D * pNurbs= static_cast<const MbNurbs3D*>( pCurve) ;
if ( pNurbs == nullptr) {
LOG_ERROR( pGenLog, "Error : Nurbs pointer null") ;
return false ;
}
return nurbs3D_handler( pNurbs, nLayId, pGeomDB) ;
}
// Generic curve
else {
// Approssimo la curva con Nurbs
const MbNurbs3D* pNurbs = pCurve->NurbsCurve() ;
if ( pNurbs == nullptr) {
LOG_ERROR( pGenLog, "Error : converting the curve to a NURBS") ;
return false ;
}
return nurbs3D_handler( pNurbs, nLayId, pGeomDB) ;
}
return true ;
}
//----------------------------------------------------------------------------
ICurve*
ConvertNurbs( const MbNurbs* pNurbs, double dScale, bool bEraseSrc)
{
vector<MbCartPoint> ctrlPoints ;
DBLVECTOR knots, weights ;
pNurbs->GetPoints( ctrlPoints) ;
pNurbs->GetKnots( knots) ;
pNurbs->GetWeights( weights) ;
PNTVECTOR ctrlPoints_vector( ctrlPoints.size()) ;
// salvo i punti di controllo e li scalo con il fattore richiesto
for ( size_t i = 0 ; i < ctrlPoints.size() ; i++)
ctrlPoints_vector[i] = Point3d( ctrlPoints[i].x * dScale, ctrlPoints[i].y * dScale, 0) ;
// creo la struct NurbsData
CNurbsData NurbsData;
NurbsData.nDeg = int( pNurbs->GetDegree()) - 1 ; // la funzione GetDegree di c3d restituisce l'ordine
NurbsData.bRat = pNurbs->IsRational() ;
NurbsData.bClosed = pNurbs->IsClosed() ;
NurbsData.bPeriodic = pNurbs->IsPeriodic() ;
NurbsData.bExtraKnotes = false ;
if ( knots.size() == ctrlPoints.size() + NurbsData.nDeg + 1) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
NurbsData.vU = vector<double>( knots.begin() + 1, knots.end() - 1) ;
else
NurbsData.vU = knots ;
NurbsData.vCP = ctrlPoints_vector ;
NurbsData.vW = weights ;
if ( NurbsData.bPeriodic || ! NurbsData.bClamped ) {
NurbsCurveCanonicalize( NurbsData) ;
}
if ( bEraseSrc)
// cancello l'oggetto del puntatore
delete pNurbs ;
PtrOwner<ICurve> pCrv( NurbsToBezierCurve( NurbsData)) ;
return Release(pCrv) ;
}
//----------------------------------------------------------------------------
ICurve*
ConvertNurbs3D( const MbNurbs3D* pNurbs, bool bEraseSrc)
{
vector<MbCartPoint3D> ctrlPoints ;
DBLVECTOR knots, weights ;
pNurbs->GetPoints( ctrlPoints) ;
pNurbs->GetKnots( knots) ;
pNurbs->GetWeights( weights) ;
PNTVECTOR ctrlPoints_vector( ctrlPoints.size()) ;
for ( size_t i = 0 ; i < ctrlPoints.size() ; i++)
ctrlPoints_vector[i] = Point3d( ctrlPoints[i].x, ctrlPoints[i].y, ctrlPoints[i].z) ;
// creo la struct NurbsData
CNurbsData NurbsData;
NurbsData.nDeg = int( pNurbs->GetDegree()) - 1 ; // la funzione GetDegree di c3d restituisce l'ordine
NurbsData.bRat = pNurbs->IsRational() ;
NurbsData.bClosed = pNurbs->IsClosed() ;
NurbsData.bPeriodic = pNurbs->IsPeriodic() ;
NurbsData.bExtraKnotes = false ;
if ( knots.size() == ctrlPoints.size() + NurbsData.nDeg + 1) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
NurbsData.vU = vector<double>( knots.begin() + 1, knots.end() - 1) ;
else
NurbsData.vU = knots ;
NurbsData.vCP = ctrlPoints_vector ;
NurbsData.vW = weights ;
if ( NurbsData.bPeriodic || ! NurbsData.bClamped)
NurbsCurveCanonicalize( NurbsData) ;
if ( bEraseSrc)
delete pNurbs ;
PtrOwner<ICurve> pCrv( NurbsToBezierCurve( NurbsData)) ;
if ( ! IsNull( pCrv))
return Release( pCrv) ;
// Non è riuscita la conversione, creo la composita dei punti di controllo
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
PolyLine PL ;
if ( PL.FromPointVector( ctrlPoints_vector) && pCrvCompo->FromPolyLine( PL))
return Release( pCrvCompo) ;
return nullptr ;
}
//----------------------------------------------------------------------------
bool
nurbs3D_handler( const MbNurbs3D* pNurbs, int nLayId, IGeomDB* pGeomDB)
{
ICurve* pBezierCurve = ConvertNurbs3D( pNurbs, false) ;
if ( pBezierCurve == nullptr) {
LOG_ERROR( pGenLog, "Error : cannot create Bezier Curve from given Nurbs") ;
return false ;
}
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, pBezierCurve) ;
if ( nId == GDB_ID_NULL) {
LOG_ERROR( pGenLog, "Error : adding object CrvBezier to GeomDB") ;
return false ;
}
pGeomDB->SetMaterial( nId, Color( 0, 0, 0)) ;
return true ;
}
//----------------------------------------------------------------------------
ISurfBezier*
ConvertSurface(const MbSurface* pSurface, DBLVECTOR& vU, DBLVECTOR& vV) {
SNurbsSurfData sNurbsSurf ;
sNurbsSurf.bClosedU = pSurface->IsUClosed() ;
sNurbsSurf.bClosedV = pSurface->IsVClosed() ;
sNurbsSurf.bPeriodicU = pSurface->IsUPeriodic() ;
sNurbsSurf.bPeriodicV = pSurface->IsVPeriodic() ;
sNurbsSurf.bClampedU = true ; // di questi non ho trovato il membro da copiare, quindi li setto a true, senn viene chiamata la canonicalize
sNurbsSurf.bClampedV = true ;
// superficie che deve essere trasformata in NURBS e poi in Bezier
MbSplineSurface* mbNurbs = pSurface->NurbsSurface( true) ;
sNurbsSurf.bRat = mbNurbs->IsRational() ;
sNurbsSurf.nDegU = mbNurbs->GetUDegree() - 1 ; // la funzione degree restituisce l'ordine in realt, quindi devo ridurre il valore di 1
sNurbsSurf.nDegV = mbNurbs->GetVDegree() - 1 ;
//MbControlData3D mbCtrlPt ; mbNurbs->GetBasisPoints( mbCtrlPt) ;
int nUKnots = int( mbNurbs->GetKnotsCount( true)) ;
int nVKnots = int( mbNurbs->GetKnotsCount( false)) ;
sNurbsSurf.nCPU = mbNurbs->GetPointsUCount() ; // numero di colonne
sNurbsSurf.nCPV = mbNurbs->GetPointsVCount() ; // numero di righe
PNTVECTOR vCPV( sNurbsSurf.nCPV) ;
sNurbsSurf.mCP.resize( sNurbsSurf.nCPU, vCPV) ;
DBLVECTOR vWV( sNurbsSurf.nCPV) ;
sNurbsSurf.mW.resize( sNurbsSurf.nCPU, vWV) ;
for ( int i = 0 ; i < sNurbsSurf.nCPU ; ++i) {
for ( int j = 0 ; j < sNurbsSurf.nCPV ; ++j) {
MbCartPoint3D mbPt ; mbNurbs->GetPoint(j, i, mbPt) ;
Point3d ptCP = ConvertPoint( mbPt) ;
sNurbsSurf.mCP[i][j] = ptCP ;
if ( sNurbsSurf.bRat){
double dW = mbNurbs->GetWeight( j, i) ;
//sNurbsSurf.mCP[i][j] = ptCP/* / dW */;
sNurbsSurf.mW[i][j] = dW ;
}
//else
// sNurbsSurf.mCP[i][j] = ptCP ;
}
}
for ( int i = 0 ; i < nUKnots ; ++i)
sNurbsSurf.vU.push_back( mbNurbs->GetKnot( true, i)) ;
if ( sNurbsSurf.vU.size() == sNurbsSurf.nCPU + sNurbsSurf.nDegU + 1) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
sNurbsSurf.vU = vector<double>( sNurbsSurf.vU.begin() + 1, sNurbsSurf.vU.end() - 1) ;
for ( int j = 0 ; j < nVKnots ; ++j)
sNurbsSurf.vV.push_back( mbNurbs->GetKnot( false, j)) ;
if ( sNurbsSurf.vV.size() == sNurbsSurf.nCPV + sNurbsSurf.nDegV + 1) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
sNurbsSurf.vV = vector<double>( sNurbsSurf.vV.begin() + 1, sNurbsSurf.vV.end() - 1) ;
if ( sNurbsSurf.bPeriodicU || sNurbsSurf.bPeriodicV || ! sNurbsSurf.bClampedU || ! sNurbsSurf.bClampedV)
NurbsSurfaceCanonicalize( sNurbsSurf) ;
// salvo i vettori dei nodi
vU = sNurbsSurf.vU ;
vV = sNurbsSurf.vV ;
delete mbNurbs ;
PtrOwner<ISurfBezier> pSurfBez( GetSurfBezier(NurbsToBezierSurface( sNurbsSurf))) ;
if ( IsNull( pSurfBez) || ! pSurfBez->IsValid())
return nullptr ;
return Release( pSurfBez) ;
}
//----------------------------------------------------------------------------
bool
surface_handler( const MbSurface* pSurface, int nLayId, IGeomDB* pGeomDB, uint32 color, int nFlag)
{
// conversione diretta in trimesh
if ( nFlag == 0) {
// Creazione mesh
MbStepData stepdata ;
MbFormNote note ;
CreateMeshData( stepdata, note) ;
MbMesh mesh ;
pSurface->CalculateMesh( stepdata, note, mesh) ;
bool bMeshOk = mesh_handler( & mesh, nLayId, pGeomDB, false) ;
if ( ! bMeshOk)
return false ;
}
// conversione in superficie di Bezier
else if ( nFlag == 1) {
DBLVECTOR vU, vV ;
PtrOwner<ISurfBezier> pSurf( ConvertSurface( pSurface, vU, vV)) ;
if ( IsNull( pSurf) || ! pSurf->IsValid())
return false ;
pSurf->RemoveCollapsedSpans() ;
pGeomDB->AddGeoObj( GDB_ID_NULL, nLayId, Release(pSurf)) ;
}
int nId = pGeomDB->GetLastInGroup( nLayId) ; // recupero id dell'oggetto appena aggiunto dal mesh_handler
if ( color != 16744192) {
float r, g, b ;
uint322RGB( color, r, g, b) ;
pGeomDB->SetMaterial( nId, Color( r, g, b)) ;
}
return true ;
}
//---------------------------------------------------
bool
CreateMeshData( MbStepData& stepData, MbFormNote& note)
{
stepData.Init( ist_SpaceStep, s_dLinToler, M_PI / 12, ( s_dLinToler > TOL_LIM_S ? 1000 : 100)) ;
stepData.SetStepType( ist_DeviationStep) ;
if ( s_dLinToler < TOL_LIM_B)
stepData.SetStepType( ist_MetricStep) ;
note.SetWire( true) ;
note.SetGrid( true) ;
note.SetSeam( true) ;
note.SetExact( true) ;
note.SetQuad( false) ;
note.SetFair( true) ;
note.SetMere( true) ;
return true ;
}