//---------------------------------------------------------------------------- // 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 ( 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 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( oGeometry) ; // qui potrei mettere anche dynamic_cast Point3d pt ; ConvertPoint( *oPoint, pt) ; // lo aggiungo al GeomDB nel layer corretto PtrOwner 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 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( 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 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( 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( 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( 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( 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( 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( 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( onCurve) ; // break ; } case ON::eCurveType::ctProxy :{ const ON_CurveProxy* onProxyCurve = static_cast( 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( 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( 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 ; }