Files
EgtExchange/Import3dm.cpp
T
Daniele Bariletti 549f3d47bd EgtExchange:
- aggiunto l'import per file 3dm.
2023-08-03 10:18:12 +02:00

468 lines
18 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2023
//----------------------------------------------------------------------------
// File : Import3dm.cpp Data : 23.06.23 Versione : 2.5f1
// Contenuto : Implementazione della classe per l'importazione di 3dm.
//
//
//
// Modifiche : 23.06.23 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Import3dm.h"
#include "DllMain.h"
#include "/EgtDev/Include/EExDllMain.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/SELkKeyProc.h"
#include "/EgtDev/Include/EgtKeyCodes.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Include/EGkArcSpecial.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkCurveBezier.h"
#include "/EgtDev/Include/EGkCurveAux.h"
#include "/EgtDev/Include/EGkSurf.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "C:/EgtDev/opennurbs/opennurbs.h"
using namespace std ;
class ON_ClassId ;
//----------------------------------------------------------------------------
IImport3dm*
CreateImport3dm( void)
{
// verifico la chiave e le opzioni
if ( ! VerifyKey( KEYOPT_EEX_INPBASE))
return nullptr ;
// creo l'oggetto
return static_cast<IImport3dm*> ( new(nothrow) Import3dm) ;
}
//----------------------------------------------------------------------------
bool
Import3dm::Import( const string& sFile__, IGeomDB* pGDB, int nIdGroup, double dScaleFactor)
{
// verifico il DB geometrico
if ( pGDB == nullptr) {
LOG_ERROR( GetEExLogger(), "Import3dm : Error on GeomDB")
return false ;
}
m_pGDB = pGDB ;
// verifico l'Id di gruppo
if ( ! m_pGDB->ExistsObj( nIdGroup)) {
LOG_ERROR( GetEExLogger(), "Import3dm : Error on IdGroup")
return false ;
}
m_nIdGroup = nIdGroup ;
// verifico il fattore di scala
if ( dScaleFactor < EPS_SMALL) {
LOG_ERROR( GetEExLogger(), "Import3dm : Error on ScaleFactor too small (minimum 0.001).")
return false ;
}
m_dScaleFactor = dScaleFactor ;
// scorro l'archivio fino ad arrivare agli elementi geometrici
std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V6\\my_points.3dm" ;
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V6\\my_curves.3dm" ;
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V5\\v5_rhino_logo.3dm" ;
ONX_Model model;
std::wstring widestr = std::wstring(sFile.begin(), sFile.end()) ;
const wchar_t* sFileName = widestr.c_str() ;
FILE* archive_fp = ON::OpenFile( sFileName, L"rb") ;
if ( !archive_fp )
{
LOG_ERROR( GetEExLogger(), "Unable to open file." ) ;
return false;
}
// create achive object from file pointer
ON_BinaryFile archive( ON::archive_mode::read3dm, archive_fp ) ;
// read the contents of the file into "model"
ON_TextLog dump ;
bool rc = model.Read( archive, &dump ) ;
if ( ! rc)
LOG_ERROR( GetEExLogger(), "Unable to read file." ) ;
// close the file
ON::CloseFile( archive_fp ) ;
ON_ModelComponent::Type component_type = ON_ModelComponent::Type::ModelGeometry ;
//const ON_wString type_name_string = ON_ModelComponent::ComponentTypeToString(component_type) ;
//////// aggiungo gli elementi geometrici al GeomDB
//for (
// const ONX_ModelComponentReferenceLink* link = model.Internal_ComponentListConst(component_type).m_first_mcr_link;
// nullptr != link;
// link = link->m_next
// )
//{
//int a=0 ;
//}
// devo trovare il numero di oggetti geometrici
//int nCount = model.Internal_ComponentListConst(ON_ModelComponent::Type::ModelGeometry).m_count ;
//int component_model_index = 10 ;
//ON_ModelComponentReference mcr = model.ComponentFromIndex( component_type, component_model_index) ;
//while ( ! mcr.IsEmpty()) {
//int component_model_index = 114 ;
//ON_ModelComponentReference mcr = model.ComponentFromIndex( component_type, component_model_index) ;
//unsigned int limit = model.ComponentIndexLimit( ON_ModelComponent::Type::ModelGeometry) ;
//const ON_ComponentManifest& manifest = model.Manifest() ;
//const ON_ManifestMap map = model.ModelToOriginalMap() ;
//int count = manifest.TotalComponentCount( ON_ModelComponent::Type::ModelGeometry) ;
//ON_SimpleArray<int> component_index_array ;
//archive.Read3dmReferencedComponentIndexArray( ON_ModelComponent::Type::ModelGeometry, component_index_array) ;
ONX_ModelComponentIterator component_iterator ( model, ON_ModelComponent::Type::ModelGeometry) ;
int count = component_iterator.ActiveComponentCount() ;
//ON_ModelComponentReference mcr = component_iterator.FirstComponentReference() ;
//const ON_ModelGeometryComponent* mgc = ON_ModelGeometryComponent::Cast( mcr.ModelComponent()) ;
const ON_ModelComponent* mc = component_iterator.FirstComponent() ;
const ON_ModelGeometryComponent* mgc = ON_ModelGeometryComponent::Cast( mc) ;
//ON_ModelComponentReference mcr = model.ComponentFromIndex( ON_ModelComponent::Type::ModelGeometry, component_model_index) ;
//const ON_ModelGeometryComponent* mgc = ON_ModelGeometryComponent::Cast( mcr.ModelComponent()) ;
//while( ! mgc->IsEmpty()) {
for( const ON_ModelComponent* mc = component_iterator.FirstComponent() ; nullptr != mc ; mc = component_iterator.NextComponent()) {
const ON_ModelGeometryComponent* mgc = ON_ModelGeometryComponent::Cast( mc) ;
const ON_Object* oGeometry = mgc->Geometry( nullptr) ;
// individuo a che layer appartiene l'oggetto
const ON_3dmObjectAttributes* attributes = mgc->Attributes(nullptr);
int nLayer = attributes->m_layer_index ;
// aggiungo al GeomDB
ON::object_type type = oGeometry->ObjectType() ;
// se non riesco a convertire un oggetto, lo scarto e alla fine della conversione segnalo che ho balzato TOT oggetti di tipo PIPPO
switch ( type) {
case ON::object_type::point_object : {
/*ON_Point Point = oGeometry-> ;*/
/*ON_3dPoint* Point( oGeometry) ;*/
const ON_Point* oPoint = static_cast<const ON_Point*>( oGeometry) ; // qui potrei mettere anche dynamic_cast
Point3d pt ;
ConvertPoint( *oPoint, pt) ;
// lo aggiungo al GeomDB nel layer corretto
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
pGeoPnt->Set( pt) ;
m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release(pGeoPnt)) ;
break ;
}
case ON::object_type::pointset_object : {
const ON_PointCloud* pc = ON_PointCloud::Cast( oGeometry);
if ( nullptr == pc )
return false ;
int count = pc->PointCount() ;
for ( int i = 0; i < count ; i++ ) {
ON_Point onPoint( pc->m_P[i]) ;
Point3d pt ;
ConvertPoint( onPoint, pt) ;
// lo aggiungo al GeomDB nel layer corretto
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
pGeoPnt->Set( pt) ;
m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release( pGeoPnt)) ;
}
break ;
}
case ON::object_type::curve_object : {
const ON_Curve* onCurve = static_cast<const ON_Curve*>( oGeometry) ;
ICurve* pCurve = nullptr ;
ConvertCurve( onCurve, pCurve) ;
if ( pCurve == nullptr)
return false ;
m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, pCurve) ;
break ;
}
case ON::object_type::surface_object :
/*ConvertSurface( oGeometry)*/
break ;
case ON::object_type::brep_object :
break ;
case ON::object_type::extrusion_object : {
const ON_Extrusion* onExtrusion = ON_Extrusion::Cast( oGeometry) ;
Point3d ptStart, ptEnd ;
ConvertPoint( onExtrusion->PathStart(), ptStart) ;
ConvertPoint( onExtrusion->PathEnd(), ptEnd) ;
int nIsCapped = onExtrusion->IsCapped() ; // 0: no or profile is open /1: bottom cap /2: top cap /3: both ends capped.
//int nProfiles = onExtrusion->ProfileCount() ;
ON_SimpleArray<const ON_Curve*> onSaProfile ;
int nProfiles = onExtrusion->GetProfileCurves( onSaProfile) ;
CICURVEPVECTOR vCrvProfile ;
for (int i = 0 ; i < nProfiles ; ++i ) {
const ON_Curve* onCurve = onSaProfile[i] ;
ICurve* pCurve = nullptr ;
ConvertCurve( onCurve, pCurve) ;
vCrvProfile.push_back( pCurve) ;
}
Vector3d vDir = ptEnd - ptStart ;
//ISurfTriMesh* pSurfTm = GetSurfTriMeshByExtrusion( vCrvProfile, vDir) ;
//m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, pSurfTm) ;
// CONVERSIONE DELL'EXTRUSION AD UN'ALTRA SUPERFICIE RHINO PRIMA DI ESSERE CONVERTITA
//const ON_Extrusion* onExtrusion = ON_Extrusion::Cast( oGeometry) ;
//if (nullptr == onExtrusion)
// return false ;
//ON_Object* onObject = nullptr;
//if ( onExtrusion->IsCapped() || onExtrusion->ProfileCount() >= 2)
// onObject = onExtrusion->BrepForm(0) ;
//if ( nullptr == onObject)
// onObject = onExtrusion->SumSurfaceForm(0) ;
//if ( nullptr == onObject)
// onObject = onExtrusion->NurbsSurface(0) ;
//if ( nullptr == onObject)
// return false ;
//ON_Surface* onSurface = static_cast<ON_Surface*>( onObject) ;
//ISurf* pSurf = nullptr ;
//ConvertSurface( onSurface, pSurf) ;
break ;
}
case ON::object_type::mesh_object :
break ;
case ON::object_type::loop_object :
break ;
default :
break ;
}
//++ component_model_index ;
//mcr = model.ComponentFromIndex( component_type, component_model_index) ;
//mgc = ON_ModelGeometryComponent::Cast( mcr.ModelComponent()) ;
//ON_ModelComponentReference mcr = component_iterator.NextComponentReference() ;
//const ON_ModelGeometryComponent* mgc = ON_ModelGeometryComponent::Cast( mcr.ModelComponent()) ;
//const ON_ModelComponent* mc = component_iterator.NextComponent() ;
//const ON_ModelGeometryComponent* mgc = ON_ModelGeometryComponent::Cast( mc) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Import3dm::ConvertPoint( const ON_Point& onPoint, Point3d& pt)
{
double x = onPoint.point.x ;
double y = onPoint.point.y ;
double z = onPoint.point.z ;
// creo il punto nel nostro kernel
pt.Set( x, y, z) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Import3dm::ConvertPoint( const ON_3dPoint* on3dPoint, Point3d& pt)
{
double x = on3dPoint->x ;
double y = on3dPoint->y ;
double z = on3dPoint->z ;
// creo il punto nel nostro kernel
pt.Set( x, y, z) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ConvertVector( const ON_3dVector& onVector, Vector3d& vt)
{
vt.x = onVector.x ;
vt.y = onVector.y ;
vt.z = onVector.z ;
return true ;
}
//----------------------------------------------------------------------------
ON::eCurveType
ON_CurveType( const ON_Curve* curve)
{
//const ON_ClassId* curve_id = &ON_CLASS_RTTI(ON_Curve);
//const ON_ClassId* id = curve->ClassId();
//// "fake virtual" handling of fast/easy special cases
//while (0 != id && curve_id != id )
//{
// if ( &ON_CLASS_RTTI(ON_ArcCurve) == id )
// return ON::ctArc;
// if ( &ON_CLASS_RTTI(ON_LineCurve) == id )
// return ON::ctLine;
// if ( &ON_CLASS_RTTI(ON_PolylineCurve) == id )
// return ON::ctPolyline;
// if ( &ON_CLASS_RTTI(ON_CurveProxy) == id )
// return ON::ctProxy;
// if ( &ON_CLASS_RTTI(ON_PolyCurve) == id )
// return ON::ctPolycurve;
// if ( &ON_CLASS_RTTI(ON_NurbsCurve) == id )
// return ON::ctNurbs;
// if ( &ON_CLASS_RTTI(ON_CurveOnSurface) == id )
// return ON::ctOnsurface;
// id = id->BaseClass();
//}
return ON::ctCurve;
}
//----------------------------------------------------------------------------
bool
Import3dm::ConvertCurve( const ON_Curve* onCurve, ICurve* pCurve, PolyLine* pPL)
{
//const ON_Curve* on_curve = ON_Curve::Cast( oGeometry) ;
//const ON_Curve* onCurve = static_cast<const ON_Curve*>( oCurve) ; // qui potrei mettere anche dynamic_cast
ON::eCurveType curve_type = ON_CurveType( onCurve) ;
switch ( curve_type) {
case ON::eCurveType::ctArc : {
const ON_ArcCurve* onArc = static_cast<const ON_ArcCurve*>( onCurve) ;
Point3d ptCenter, ptStart, ptEnd ;
ConvertPoint( onArc->m_arc.plane.origin, ptCenter) ;
ConvertPoint( onArc->m_arc.PointAt( onArc->m_arc.Domain().Min()), ptStart) ;
ConvertPoint( onArc->m_arc.PointAt( onArc->m_arc.Domain().Max()), ptEnd) ;
Vector3d vtN ;
ON_3dVector on_vtN = onArc->m_arc.plane.zaxis ;
ConvertVector( on_vtN, vtN) ;
ICurveArc* pCurveArc( CreateCurveArc()) ;
pCurveArc->SetC2PN( ptCenter, ptStart, ptEnd, vtN) ;
pCurve = pCurveArc ;
break ;
}
case ON::eCurveType::ctCircle : {
const ON_ArcCurve* onCircle = static_cast<const ON_ArcCurve*>( onCurve) ;
Point3d ptCenter ;
ConvertPoint( onCircle->m_arc.plane.origin, ptCenter) ;
Vector3d vtN ;
ON_3dVector on_vtN = onCircle->m_arc.plane.zaxis ;
ConvertVector( on_vtN, vtN) ;
double dRad = onCircle->m_arc.Radius() ;
ICurveArc* pCurveArc( CreateCurveArc()) ;
pCurveArc->Set( ptCenter, vtN, dRad) ;
pCurve = pCurveArc ;
break ;
}
case ON::eCurveType::ctLine : {
const ON_LineCurve* onCurveLine = static_cast<const ON_LineCurve*>( onCurve) ;
Point3d ptStart, ptEnd ;
ConvertPoint( onCurveLine->m_line.from, ptStart) ;
ConvertPoint( onCurveLine->m_line.to, ptEnd) ;
ICurveLine* pCurveLine ( CreateCurveLine()) ;
pCurveLine->Set( ptStart, ptEnd) ;
pCurve = pCurveLine ;
break ;
}
case ON::eCurveType::ctNurbs : {
// da trasformare in una bezier
const ON_NurbsCurve* onNurbsCurve = static_cast<const ON_NurbsCurve*>( onCurve) ;
bool bIsRational = onNurbsCurve->IsRational() ;
CNurbsData nuCurve ;
nuCurve.bRat = bIsRational ;
nuCurve.nDeg = onNurbsCurve->Order() - 1 ;
int nCount = onNurbsCurve->CVCount() ;
if ( bIsRational) {
// vettore dei punti di controllo
PNTVECTOR vPtCtrl ;
// vettore dei pesi
DBLVECTOR vWeCtrl ;
for( int i = 0 ; i < nCount; ++i) {
ON_4dPoint o4dPoint ;
onNurbsCurve->GetCV( i, o4dPoint) ;
ON_3dPoint o3dPoint( o4dPoint) ;
Point3d ptCtrl ;
ConvertPoint( o3dPoint, ptCtrl) ;
vPtCtrl.push_back( ptCtrl) ;
vWeCtrl.push_back( o4dPoint.w) ;
}
nuCurve.vCP = vPtCtrl ;
nuCurve.vW = vWeCtrl ;
}
else {
// vettore dei punti di controllo
PNTVECTOR vPtCtrl ;
for( int i = 0 ; i < nCount; ++i) {
ON_3dPoint o3dPoint ;
onNurbsCurve->GetCV( i, o3dPoint) ;
Point3d ptCtrl ;
ConvertPoint( o3dPoint, ptCtrl) ;
vPtCtrl.push_back( ptCtrl) ;
}
nuCurve.vCP = vPtCtrl ;
}
// vettore dei nodi
DBLVECTOR vU ;
int nKnot = onNurbsCurve->KnotCount() ;
for ( int j = 0 ; j < nKnot ; ++j ) {
onNurbsCurve->Knot( j) ;
vU.push_back( j) ;
}
nuCurve.vU = vU ;
nuCurve.bClosed = onNurbsCurve->IsClosed() ;
nuCurve.bPeriodic = onNurbsCurve->IsPeriodic() ;
// ora che ho riempito la Nurbs con tutti i dati la converto in Bezier
pCurve = NurbsToBezierCurve( nuCurve) ;
break ;
}
case ON::eCurveType::ctOnsurface :{
const ON_CurveOnSurface* onProxyCurve = static_cast<const ON_CurveOnSurface*>( onCurve) ;
//
break ;
}
case ON::eCurveType::ctProxy :{
const ON_CurveProxy* onProxyCurve = static_cast<const ON_CurveProxy*>( onCurve) ;
ON_Curve* onCurveToConvert = onProxyCurve->ProxyCurve()->Duplicate() ;
// devo fare le dovute modifiche alla curva per ottenere la curva proxy
if ( onProxyCurve->ProxyCurveIsReversed())
onCurveToConvert->Reverse() ;
onCurveToConvert->SetDomain( onProxyCurve->ProxyCurveDomain()) ;
ConvertCurve( onCurveToConvert, pCurve) ;
break ;
}
case ON::eCurveType::ctPolycurve : {
const ON_PolyCurve* onPolyline = static_cast<const ON_PolyCurve*>( onCurve) ;
int nCurves = onPolyline->Count() ;
ICurveComposite* pCrvCompo( CreateCurveComposite()) ;
for ( int i = 0 ; i < nCurves; ++i) {
ICurve* pCurveToAdd = nullptr ;
ON_Curve* onCurveToAdd = onPolyline->SegmentCurve( i) ;
ConvertCurve( onCurveToAdd, pCurveToAdd) ;
pCrvCompo->AddCurve( pCurveToAdd) ;
}
pCurve = pCrvCompo ;
break ;
}
case ON::eCurveType::ctPolyline : {
const ON_PolylineCurve* onPolyline = static_cast<const ON_PolylineCurve*>( onCurve) ;
int nPoints = onPolyline->PointCount() ;
for ( int i = 0 ; i < nPoints ; ++i ) {
Point3d pt ;
ConvertPoint( onPolyline->m_pline[i], pt) ;
pPL->AddUPoint( i, pt) ;
}
break ;
}
default :
break ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ConvertSurface( const ON_Surface* onSurf, ISurf* pSurf)
{
return false ;
}