c5503427cb
- aggiunti oggetti all'import3dm e corretti alcuni bug.
946 lines
39 KiB
C++
946 lines
39 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 "map"
|
|
#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/EGkSurfAux.h"
|
|
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
|
#include "/EgtDev/Include/EGkSurfFlatRegion.h"
|
|
#include "/EgtDev/Include/EGkSurfBezier.h"
|
|
#include "/EgtDev/Include/EGkSurf.h"
|
|
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
|
#include "/EgtDev/Include/EGkSfrCreate.h"
|
|
#include "/EgtDev/Include/EXeConst.h"
|
|
#include "C:/EgtDev/opennurbs/opennurbs.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
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" ; // ok
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V6\\my_curves.3dm" ; // ok
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V7\\v7_my_surfaces.3dm" ; // ok
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V6\\my_surfaces.3dm" ; // file vuoto!!!!!!!!!!!!!!
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V7\\v7_rhino_logo_subd.3dm" ; // non si convertono e non le gestiamo
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V7\\v7_my_mesh.3dm" ; // ok
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V7\\v7_my_mesh_with_material.3dm" ; // ok
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V7\\v7_my_brep.3dm" ; // ok
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V5\\v5_example_file.3dm" ;
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V5\\v5_rhino_logo.3dm" ;
|
|
//std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V7\\v7_rhino_logo_nurbs.3dm" ;
|
|
std::string sFile = "C:\\EgtDev\\opennurbs\\example_files\\V5\\v5_my_trimmed_surface.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 ) ;
|
|
|
|
// conto il numero di layer e li creo
|
|
|
|
//model.Internal_ComponentListConst(ON_ModelComponent::Type::Layer).m_count
|
|
ON_ModelComponent::Type component_type_l = ON_ModelComponent::Type::Layer ;
|
|
ONX_ModelComponentIterator component_iterator_l ( model, ON_ModelComponent::Type::Layer) ;
|
|
int nLayer = 0 ;
|
|
m_pGDB->Erase( 2) ;
|
|
for( const ON_ModelComponent* mc = component_iterator_l.FirstComponent() ; nullptr != mc ; mc = component_iterator_l.NextComponent()) {
|
|
++nLayer ;
|
|
m_pGDB->AddGroup( GDB_ID_NULL, 1, GLOB_FRM) ;
|
|
}
|
|
|
|
ON_ModelComponent::Type component_type = ON_ModelComponent::Type::ModelGeometry ;
|
|
ONX_ModelComponentIterator component_iterator ( model, ON_ModelComponent::Type::ModelGeometry) ;
|
|
|
|
// se non riesco a convertire un oggetto, lo scarto e incremento il contatore del suo tipo nel dizionario error_count
|
|
map< string, int> error_count ;
|
|
int nId, nCount = 0 ;
|
|
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 ;
|
|
if ( nLayer < 0)
|
|
nLayer = 2 ;
|
|
else
|
|
nLayer = nLayer + 2 ;
|
|
// recupero il colore dell'oggetto
|
|
Color cCol ;
|
|
ON_Color onCol = attributes->m_color ;
|
|
//cCol.Set( onCol.Red(), onCol.Green(), onCol.Blue(), int(onCol.Alpha()/2.55)) ;
|
|
cCol.Set( onCol.Red(), onCol.Green(), onCol.Blue(), 100) ;
|
|
// converto l'oggetto e lo aggiungo al GeomDB
|
|
ON::object_type type = oGeometry->ObjectType() ;
|
|
++nCount ;
|
|
switch ( type) {
|
|
case ON::object_type::point_object : {
|
|
const ON_Point* oPoint = ON_Point::Cast( oGeometry) ;
|
|
Point3d pt ( ConvertPoint(*oPoint)) ;
|
|
// lo aggiungo al GeomDB nel layer corretto
|
|
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
|
|
pGeoPnt->Set( pt) ;
|
|
if ( ! IsNull( pGeoPnt) && pGeoPnt->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release(pGeoPnt)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["point"] += 1 ;
|
|
break ;
|
|
}
|
|
case ON::object_type::pointset_object : {
|
|
const ON_PointCloud* pc = ON_PointCloud::Cast( oGeometry);
|
|
if ( nullptr == pc ) {
|
|
error_count["pointset"] += 1 ;
|
|
break ;
|
|
}
|
|
int count = pc->PointCount() ;
|
|
Frame3d frLayer = m_pGDB->GetGroupFrame( nLayer) ;
|
|
int nSubLayer = m_pGDB->AddGroup( GDB_ID_NULL, nLayer, frLayer) ;
|
|
for ( int i = 0; i < count ; i++ ) {
|
|
Point3d pt( ConvertPoint( pc->m_P[i])) ;
|
|
// lo aggiungo al GeomDB nel layer corretto
|
|
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
|
|
pGeoPnt->Set( pt) ;
|
|
if ( ! IsNull( pGeoPnt) && pGeoPnt->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nSubLayer, Release(pGeoPnt)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["point"] += 1 ;
|
|
}
|
|
break ;
|
|
}
|
|
case ON::object_type::curve_object : {
|
|
const ON_Curve* onCurve = ON_Curve::Cast( oGeometry) ;
|
|
PtrOwner<ICurve> pCurve( ConvertCurve( onCurve)) ;
|
|
if ( ! IsNull(pCurve) && pCurve->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release( pCurve)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["curve"] += 1 ;
|
|
break ;
|
|
}
|
|
case ON::object_type::surface_object : {
|
|
const ON_Surface* onSurface = ON_Surface::Cast( oGeometry) ;
|
|
PtrOwner<ISurf> pSurf( ConvertSurface( onSurface)) ;
|
|
if ( !IsNull(pSurf) && pSurf->IsValid() ) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release( pSurf)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["surface"] += 1 ;
|
|
break ;
|
|
}
|
|
case ON::object_type::brep_object : {
|
|
const ON_Brep* onBrep = ON_Brep::Cast( oGeometry) ;
|
|
ISURFPVECTOR vpSurf = ConvertBrep( onBrep, false) ;
|
|
for (int k = 0 ; k < int( vpSurf.size()) ; ++k) {
|
|
if ( vpSurf[k]->GetType() == SRF_TRIMESH) {
|
|
PtrOwner<ISurfTriMesh> pSurfTm( GetSurfTriMesh( vpSurf[k])) ;
|
|
if ( ! IsNull( pSurfTm) && pSurfTm->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release(pSurfTm)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["brep"] += 1 ;
|
|
}
|
|
else if ( vpSurf[k]->GetType() == SRF_BEZIER ) {
|
|
PtrOwner<ISurfBezier> pSurfBz( GetSurfBezier( vpSurf[k])) ;
|
|
if ( ! IsNull( pSurfBz) && pSurfBz->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release(pSurfBz)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["brep"] += 1 ;
|
|
}
|
|
}
|
|
break ;
|
|
}
|
|
case ON::object_type::extrusion_object : {
|
|
const ON_Extrusion* onExtrusion = ON_Extrusion::Cast( oGeometry) ;
|
|
Point3d ptStart( ConvertPoint( onExtrusion->PathStart())) ;
|
|
Point3d ptEnd( ConvertPoint( onExtrusion->PathEnd())) ;
|
|
//int nProfiles = onExtrusion->ProfileCount() ;
|
|
ON_SimpleArray<const ON_Curve*> onSaProfile ;
|
|
int nProfiles = onExtrusion->GetProfileCurves( onSaProfile) ;
|
|
Vector3d vDir = ptEnd - ptStart ;
|
|
int nIsCapped = onExtrusion->IsCapped() ; // 0: no or profile is open /1: bottom cap /2: top cap /3: both ends capped.
|
|
PtrOwner<ISurfTriMesh> pSurfTm( CreateSurfTriMesh()) ;
|
|
StmFromTriangleSoup stmSoup ;
|
|
if ( ! stmSoup.Start())
|
|
return nullptr ;
|
|
if ( IsNull(pSurfTm) ) {
|
|
error_count["memory"] += 1 ;
|
|
break ;
|
|
}
|
|
// creo la superficie a partire dalle curve
|
|
if ( nIsCapped == 0) {
|
|
for (int i = 0 ; i < nProfiles ; ++i ) {
|
|
const ON_Curve* onCurve = onSaProfile[i] ;
|
|
ICurve* pCurve = nullptr ;
|
|
pCurve = ConvertCurve( onCurve) ;
|
|
stmSoup.AddSurfTriMesh( *GetSurfTriMeshByExtrusion( pCurve, vDir, false)) ;
|
|
}
|
|
}
|
|
// se capped
|
|
else {
|
|
CICURVEPVECTOR vCrvProfile ;
|
|
for (int i = 0 ; i < nProfiles ; ++i ) {
|
|
const ON_Curve* onCurve = onSaProfile[i] ;
|
|
PtrOwner<ICurve> pCurve( ConvertCurve( onCurve)) ;
|
|
vCrvProfile.push_back( Release(pCurve)) ;
|
|
}
|
|
// se l'estrusione è capped sia sopra che sotto uso la funzione *byRegionExtrusion
|
|
if ( nIsCapped == 3) {
|
|
pSurfTm.Set( GetSurfTriMeshByRegionExtrusion( vCrvProfile, vDir)) ;
|
|
}
|
|
// controllo se la superficie è capped solo sopra o sotto ed eventualmente aggiungo alla trimesh la superficie adeguata
|
|
else {
|
|
for (int i = 0 ; i < nProfiles ; ++i ) {
|
|
PtrOwner<const ICurve> pCurveToAdd( vCrvProfile[i]) ;
|
|
stmSoup.AddSurfTriMesh( *GetSurfTriMeshByExtrusion( Release( pCurveToAdd), vDir, false)) ;
|
|
}
|
|
if ( nIsCapped == 1) {
|
|
stmSoup.AddSurfTriMesh( *GetSurfTriMeshByRegion( vCrvProfile)) ;
|
|
}
|
|
else if ( nIsCapped == 2 ) {
|
|
PtrOwner<ISurfTriMesh> pSurfTmCap( GetSurfTriMeshByRegion( vCrvProfile)) ;
|
|
pSurfTmCap->Translate(vDir) ;
|
|
stmSoup.AddSurfTriMesh( *Release(pSurfTmCap)) ;
|
|
}
|
|
}
|
|
}
|
|
if ( ! stmSoup.End())
|
|
return nullptr ;
|
|
if ( nIsCapped == 1 || nIsCapped == 2)
|
|
pSurfTm.Set( GetSurfTriMesh( stmSoup.GetSurf())) ;
|
|
if ( ! IsNull( pSurfTm) && pSurfTm->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, Release( pSurfTm)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else {
|
|
// se non sono riuscito a creare la superficie per qualche motivo, allora tento una conversione con gli strumenti di OPENURBS prima
|
|
// di convertire la superficie
|
|
//// CONVERSIONE DELL'EXTRUSION AD UN'ALTRA SUPERFICIE RHINO PRIMA DI ESSERE CONVERTITA
|
|
ON_Object* onObject = nullptr ;
|
|
ISurf* pSurf = nullptr ;
|
|
PtrOwner<const ISurfBezier> pSurfBz( CreateSurfBezier()) ;
|
|
PtrOwner<const ISurfTriMesh> pSurfTm( CreateSurfTriMesh()) ;
|
|
if ( onExtrusion->IsCapped() || onExtrusion->ProfileCount() >= 2) {
|
|
onObject = onExtrusion->BrepForm(0) ;
|
|
if ( nullptr != onObject) {
|
|
const ON_Brep* onBrep = ON_Brep::Cast( onObject) ;
|
|
ISURFPVECTOR vpSurf ;
|
|
vpSurf = ConvertBrep( onBrep, true) ; // chiedo di ottenere un'unica superficie trimesh
|
|
pSurfTm.Set( static_cast<ISurfTriMesh*>( vpSurf[0])) ;
|
|
}
|
|
}
|
|
if ( nullptr == onObject) {
|
|
onObject = onExtrusion->SumSurfaceForm(0) ;
|
|
if ( nullptr != onObject) {
|
|
const ON_Surface* onSurface = ON_Surface::Cast( onObject) ;
|
|
pSurf = ConvertSurface( onSurface) ;
|
|
pSurfTm.Set( static_cast<ISurfTriMesh*>(pSurf)) ;
|
|
}
|
|
}
|
|
if ( nullptr == onObject) {
|
|
onObject = onExtrusion->NurbsSurface(0) ;
|
|
if ( nullptr != onObject) {
|
|
const ON_NurbsSurface* onNurbsSurface = ON_NurbsSurface::Cast( onObject) ;
|
|
pSurf = ConvertSurface( onNurbsSurface) ;
|
|
// in questo caso devo anche trasformare la superficie di bezier che ho appenta ottenuto in una trimesh
|
|
pSurfBz.Set( static_cast<ISurfBezier*>( pSurf)) ;
|
|
pSurfTm.Set( pSurfBz->GetAuxSurf()) ;
|
|
}
|
|
}
|
|
if ( ! IsNull( pSurfTm) && pSurfTm->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLayer, pSurfTm->Clone()) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["extrusion"] += 1 ;
|
|
}
|
|
break ;
|
|
}
|
|
case ON::object_type::mesh_object :{
|
|
const ON_Mesh* onMesh = ON_Mesh::Cast( oGeometry) ;
|
|
ON_Mesh* onMeshToConvert = onMesh->Duplicate() ;
|
|
PtrOwner<ISurfTriMesh> pSurfTm( CreateSurfTriMesh()) ;
|
|
double x = onMesh->m_V.At( 0)->x ;
|
|
if ( IsNull( pSurfTm)) {
|
|
error_count["memory"] += 1 ;
|
|
break ;
|
|
}
|
|
int nVertices = onMesh->VertexCount() ;
|
|
bool bDoublePrec = onMesh->HasDoublePrecisionVertices() ;
|
|
if ( bDoublePrec) {
|
|
for ( int i = 0 ; i < nVertices ; ++i ) {
|
|
Point3d pt = ConvertPoint( *(onMesh->m_dV.At(i)));
|
|
pSurfTm->AddVertex( pt) ;
|
|
}
|
|
}
|
|
else {
|
|
for ( int i = 0 ; i < nVertices ; ++i ) {
|
|
Point3d pt = ConvertPoint( *(onMesh->m_V.At(i)));
|
|
pSurfTm->AddVertex( pt) ;
|
|
}
|
|
}
|
|
ON_MeshFaceList onFaceList( onMesh) ;
|
|
//int nFaces = onMesh->FaceCount() ;
|
|
int nQuads = onMesh->QuadCount() ;
|
|
//int nTrias = onMesh->TriangleCount();
|
|
|
|
//split_method - [in]
|
|
// 0 default - Currently divides along the short diagonal.
|
|
// 1 divide along the short diagonal
|
|
// 2 divide along the long diagonal
|
|
// 3 minimize resulting area
|
|
// 4 maximize resulting area
|
|
// 5 minimize angle between triangle normals
|
|
// 6 maximize angle between triangle normals
|
|
double dLinTol = ON_UNSET_VALUE ;
|
|
double dAndTolRad = ON_UNSET_VALUE ;
|
|
unsigned int nSplitMethod = 0 ;
|
|
bool bStillQuads = false ;
|
|
if ( nQuads != 0) {
|
|
// restituisce il numero di quadrati convertiti
|
|
unsigned int nQuadsNonPlanarConv = onMeshToConvert->ConvertNonPlanarQuadsToTriangles( dLinTol, dAndTolRad, nSplitMethod) ;
|
|
bStillQuads = nQuadsNonPlanarConv == 0 ? true : false ;
|
|
}
|
|
int nFaces = onMeshToConvert->FaceCount() ;
|
|
//nQuads = onMeshToConvert->QuadCount() ;
|
|
int nTrias = onMeshToConvert->TriangleCount();
|
|
for (int j = 0 ; j < nFaces ; ++j) {
|
|
const ON_MeshFace* onMeshFace = onMeshToConvert->m_F.At( j) ;
|
|
if ( ! bStillQuads ) {
|
|
int nIdVert[3] = {onMeshFace->vi[0], onMeshFace->vi[1],onMeshFace->vi[2]} ;
|
|
pSurfTm->AddTriangle( nIdVert) ;
|
|
}
|
|
else if ( onFaceList.IsQuad( j)) {
|
|
// la divisione automatica non è riuscita.
|
|
// divido lungo la diagonale più corta
|
|
Point3d pt0 = ConvertPoint( *onMesh->m_dV.At(onMeshFace->vi[0])) ;
|
|
Point3d pt1 = ConvertPoint( *onMesh->m_dV.At(onMeshFace->vi[1])) ;
|
|
Point3d pt2 = ConvertPoint( *onMesh->m_dV.At(onMeshFace->vi[2])) ;
|
|
Point3d pt3 = ConvertPoint( *onMesh->m_dV.At(onMeshFace->vi[3])) ;
|
|
if ( Dist( pt0, pt2) < Dist( pt1, pt3)) {
|
|
int nIdVert[3] = {onMeshFace->vi[0], onMeshFace->vi[1],onMeshFace->vi[2]} ;
|
|
pSurfTm->AddTriangle( nIdVert) ;
|
|
int nIdVert2[3] = {onMeshFace->vi[0], onMeshFace->vi[2],onMeshFace->vi[3]} ;
|
|
pSurfTm->AddTriangle( nIdVert2) ;
|
|
}
|
|
else {
|
|
int nIdVert[3] = {onMeshFace->vi[0], onMeshFace->vi[1],onMeshFace->vi[3]} ;
|
|
pSurfTm->AddTriangle( nIdVert) ;
|
|
int nIdVert2[3] = {onMeshFace->vi[1], onMeshFace->vi[2],onMeshFace->vi[3]} ;
|
|
pSurfTm->AddTriangle( nIdVert2) ;
|
|
}
|
|
}
|
|
}
|
|
pSurfTm->AdjustTopology() ;
|
|
if ( ! IsNull( pSurfTm) && pSurfTm->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj(GDB_ID_NULL, nLayer, Release( pSurfTm)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["mesh"] += 1 ;
|
|
break ;
|
|
}
|
|
case ON::object_type::loop_object : {// some type of ON_BrepLoop
|
|
// in teoria non dovrei mai trovare questo tipo di oggetti come model geometry indipendenti, ma solo come parte di una brep
|
|
const ON_BrepLoop* onBrepLoop = ON_BrepLoop::Cast( oGeometry) ;
|
|
PtrOwner<ICurve> pCurve( ConvertBrepLoop( onBrepLoop)) ;
|
|
if ( ! IsNull( pCurve) && pCurve->IsValid()) {
|
|
nId = m_pGDB->AddGeoObj(GDB_ID_NULL, nLayer, Release( pCurve)) ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
}
|
|
else
|
|
error_count["loop"] += 1 ;
|
|
break ;
|
|
}
|
|
case ON::object_type::subd_object: {
|
|
const ON_SubD* onSubD = ON_SubD::Cast( oGeometry) ;
|
|
// non c'è un comando per convertire le subd in altre superfici...
|
|
//ON_Surface* onSurface ; //= ON_Surface::Cast() ;
|
|
//PtrOwner<ISurf> pSurf( ConvertSurface( onSurface)) ;
|
|
//if ( ! IsNull( pSurf) && pSurf->IsValid())
|
|
// m_pGDB->AddGeoObj(GDB_ID_NULL, nLayer, Release( pSurf)) ;
|
|
//else
|
|
// error_count["subd"] += 1 ;
|
|
error_count["subd"] += 1 ;
|
|
break ;
|
|
}
|
|
case ON::object_type::annotation_object: {
|
|
const ON_Annotation* onAnnot = ON_Annotation::Cast( oGeometry) ;
|
|
ON_wString wsText = onAnnot->PlainText() ;
|
|
const wchar_t* wchar = wsText ;
|
|
std::wstring ws( wchar) ;
|
|
std::string str( ws.begin(), ws.end()) ;
|
|
LOG_ERROR( GetEExLogger(), str.c_str()) ;
|
|
break ;
|
|
}
|
|
default :
|
|
break ;
|
|
}
|
|
//if ( nCount > 19)
|
|
// break ;
|
|
}
|
|
// messaggio di errore da mettere nel log per dire quanti oggetti sono stati ignorati perché la conversione non è riuscita
|
|
map<string, int>::iterator it = error_count.begin() ;
|
|
while (it != error_count.end()) {
|
|
string type = it->first ;
|
|
int count = it->second ;
|
|
if ( type != "memory" ) {
|
|
string sOut = "Sono stati ignorati " + to_string( count) + " oggetti di tipo " + type ;
|
|
LOG_ERROR( GetEExLogger(), sOut.c_str()) ;
|
|
}
|
|
else {
|
|
string sOut = "Sono stati ignorati " + to_string( count) + " oggetti perché è finita la memoria" ;
|
|
LOG_ERROR( GetEExLogger(), sOut.c_str()) ;
|
|
}
|
|
it++;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Point3d
|
|
Import3dm::ConvertPoint( const ON_Point& onPoint)
|
|
{
|
|
double x = onPoint.point.x ;
|
|
double y = onPoint.point.y ;
|
|
double z = onPoint.point.z ;
|
|
// creo il punto nel nostro kernel
|
|
Point3d pt( x, y, z) ;
|
|
return pt ;
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Point3d
|
|
Import3dm::ConvertPoint( const ON_3dPoint& on3dPoint)
|
|
{
|
|
double x = on3dPoint.x ;
|
|
double y = on3dPoint.y ;
|
|
double z = on3dPoint.z ;
|
|
// creo il punto nel nostro kernel
|
|
Point3d pt( x, y, z) ;
|
|
return pt ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Point3d
|
|
Import3dm::ConvertPoint( const ON_4dPoint& on4dPoint)
|
|
{
|
|
double x = on4dPoint.x ;
|
|
double y = on4dPoint.y ;
|
|
double z = on4dPoint.z ;
|
|
// creo il punto nel nostro kernel
|
|
Point3d pt( x, y, z) ;
|
|
return pt ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Point3d
|
|
Import3dm::ConvertPoint( const ON_3fPoint& on3fPoint)
|
|
{
|
|
double x = on3fPoint.x ;
|
|
double y = on3fPoint.y ;
|
|
double z = on3fPoint.z ;
|
|
// creo il punto nel nostro kernel
|
|
Point3d pt( x, y, z) ;
|
|
return pt ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Vector3d
|
|
ConvertVector( const ON_3dVector& onVector)
|
|
{
|
|
Vector3d vt ;
|
|
vt.x = onVector.x ;
|
|
vt.y = onVector.y ;
|
|
vt.z = onVector.z ;
|
|
return vt ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
Import3dm::ConvertCurve( const ON_Curve* onCurve)
|
|
{
|
|
ON::eCurveType curve_type = onCurve->ON_CurveType() ;
|
|
|
|
switch ( curve_type) {
|
|
case ON::eCurveType::ctArc : {
|
|
const ON_ArcCurve* onArc = ON_ArcCurve::Cast( onCurve) ;
|
|
Vector3d vStart = ConvertVector( onArc->TangentAt( 0)) ;
|
|
Point3d ptCenter( ConvertPoint( onArc->m_arc.plane.origin)) ;
|
|
Point3d ptStart( ConvertPoint( onArc->m_arc.PointAt( onArc->m_arc.Domain().Min()))) ;
|
|
Point3d ptEnd( ConvertPoint( onArc->m_arc.PointAt( onArc->m_arc.Domain().Max()))) ;
|
|
ON_3dVector on_vtN = onArc->m_arc.plane.zaxis ;
|
|
Vector3d vtN = ConvertVector( on_vtN) ;
|
|
ICurveArc* pCurveArc( CreateCurveArc()) ;
|
|
if ( ! AreSamePointApprox( ptStart, ptEnd)){
|
|
if ( ! pCurveArc->Set2PVN( ptStart, ptEnd, vStart, vtN)) {
|
|
pCurveArc->SetC2PN( ptCenter, ptStart, ptEnd, vtN) ;
|
|
}
|
|
}
|
|
else {
|
|
double dRad = onArc->m_arc.Radius() ;
|
|
pCurveArc->Set( ptCenter, vtN, dRad) ;
|
|
}
|
|
return pCurveArc ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctCircle : {
|
|
const ON_ArcCurve* onCircle = ON_ArcCurve::Cast( onCurve) ;
|
|
Point3d ptCenter( ConvertPoint(onCircle->m_arc.plane.origin)) ;
|
|
ON_3dVector on_vtN = onCircle->m_arc.plane.zaxis ;
|
|
Vector3d vtN = ConvertVector( on_vtN) ;
|
|
double dRad = onCircle->m_arc.Radius() ;
|
|
ICurveArc* pCurveArc( CreateCurveArc()) ;
|
|
pCurveArc->Set( ptCenter, vtN, dRad) ;
|
|
return pCurveArc ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctLine : {
|
|
const ON_LineCurve* onCurveLine = ON_LineCurve::Cast( onCurve) ;
|
|
Point3d ptStart( ConvertPoint(onCurveLine->m_line.from)) ;
|
|
Point3d ptEnd( ConvertPoint(onCurveLine->m_line.to)) ;
|
|
ICurveLine* pCurveLine ( CreateCurveLine()) ;
|
|
pCurveLine->Set( ptStart, ptEnd) ;
|
|
return pCurveLine ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctNurbs : {
|
|
// da trasformare in una bezier
|
|
const ON_NurbsCurve* onNurbsCurve = ON_NurbsCurve::Cast( onCurve) ;
|
|
bool bIsRational = onNurbsCurve->IsRational() ;
|
|
CNurbsData nuCurve ;
|
|
nuCurve.bRat = bIsRational ;
|
|
nuCurve.nDeg = onNurbsCurve->Degree() ; // == 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) ;
|
|
Point3d ptCtrl( ConvertPoint( o4dPoint)) ;
|
|
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)) ;
|
|
vPtCtrl.push_back( ptCtrl) ;
|
|
}
|
|
nuCurve.vCP = vPtCtrl ;
|
|
}
|
|
|
|
// vettore dei nodi
|
|
DBLVECTOR vU ;
|
|
int nKnot = onNurbsCurve->KnotCount() ;
|
|
for ( int j = 0 ; j < nKnot ; ++j ) {
|
|
double nKnot = onNurbsCurve->Knot( j) ;
|
|
vU.push_back( nKnot) ;
|
|
}
|
|
nuCurve.vU = vU ;
|
|
nuCurve.bClosed = onNurbsCurve->IsClosed() ;
|
|
// dovrei aggiungere la gestione delle curve periodiche ( unclamped) in modo da poter importare anche le curve chiuse
|
|
nuCurve.bPeriodic = onNurbsCurve->IsPeriodic() ;
|
|
|
|
|
|
// controllo relazione nodi - punti di controllo
|
|
int nU = int( nuCurve.vCP.size()) + nuCurve.nDeg - 1 ;
|
|
// se ho due nodi di troppo mi basta togliere il primo e l'ultimo per rendere la curva canonica
|
|
if ( nU == int( nuCurve.vU.size()) + 2)
|
|
NurbsCurveCanonicalize( nuCurve) ;
|
|
|
|
// ora che ho riempito la Nurbs con tutti i dati la converto in Bezier
|
|
return NurbsToBezierCurve( nuCurve) ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctOnsurface :{
|
|
const ON_CurveOnSurface* onCurveOnSurface = ON_CurveOnSurface::Cast( onCurve) ;
|
|
ON_NurbsCurve onNurbsCurve ;
|
|
onCurveOnSurface->GetNurbForm( onNurbsCurve) ;
|
|
return ConvertCurve( &onNurbsCurve) ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctProxy :{
|
|
const ON_CurveProxy* onProxyCurve = ON_CurveProxy::Cast( onCurve) ;
|
|
ON_Curve* onCurve = onProxyCurve->DuplicateCurve() ;
|
|
return ConvertCurve( onCurve) ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctPolycurve : {
|
|
const ON_PolyCurve* onPolyline = ON_PolyCurve::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) ;
|
|
pCurveToAdd = ConvertCurve( onCurveToAdd) ;
|
|
pCrvCompo->AddCurve( pCurveToAdd) ;
|
|
}
|
|
return pCrvCompo ;
|
|
break ;
|
|
}
|
|
case ON::eCurveType::ctPolyline : {
|
|
const ON_PolylineCurve* onPolyline = ON_PolylineCurve::Cast( onCurve) ;
|
|
int nPoints = onPolyline->PointCount() ;
|
|
ICurveComposite* pCrvCompo( CreateCurveComposite()) ;
|
|
Point3d ptNew , ptOld( ConvertPoint(onPolyline->m_pline[0])) ;
|
|
for ( int i = 1 ; i < nPoints ; ++i ) {
|
|
ICurveLine* pCurveLine( CreateCurveLine()) ;
|
|
ptNew = ConvertPoint( onPolyline->m_pline[i]) ;
|
|
pCurveLine->Set( ptOld, ptNew) ;
|
|
pCrvCompo->AddCurve( pCurveLine) ;
|
|
ptNew = ptOld ;
|
|
}
|
|
return pCrvCompo ;
|
|
break ;
|
|
}
|
|
default :
|
|
break ;
|
|
}
|
|
return nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ISurf*
|
|
Import3dm::ConvertSurface( const ON_Surface* onSurf)
|
|
{
|
|
if ( const ON_NurbsSurface* onNurbsSurface = ON_NurbsSurface::Cast( onSurf)) {
|
|
CNurbsSurfData cNurbsSurf ;
|
|
cNurbsSurf.bClosedU = onNurbsSurface->IsClosed( 0) ;
|
|
cNurbsSurf.bClosedV = onNurbsSurface->IsClosed( 1) ;
|
|
cNurbsSurf.bPeriodicU = onNurbsSurface->IsPeriodic( 0) ;
|
|
cNurbsSurf.bPeriodicV = onNurbsSurface->IsPeriodic( 1) ;
|
|
cNurbsSurf.bRat = onNurbsSurface->IsRational() ;
|
|
cNurbsSurf.nDegU = onNurbsSurface->Degree( 0) ;
|
|
cNurbsSurf.nDegV = onNurbsSurface->Degree( 1) ;
|
|
cNurbsSurf.nCPU = onNurbsSurface->CVCount( 0) ;
|
|
cNurbsSurf.nCPV = onNurbsSurface->CVCount( 1) ;
|
|
vector<Point3d> vCPV( cNurbsSurf.nCPV) ;
|
|
cNurbsSurf.mCP.resize( cNurbsSurf.nCPU, vCPV) ;
|
|
DBLVECTOR vWV( cNurbsSurf.nCPV) ;
|
|
cNurbsSurf.mW.resize( cNurbsSurf.nCPU, vWV) ;
|
|
for ( int i = 0 ; i < cNurbsSurf.nCPU ; ++i) {
|
|
for ( int j = 0 ; j < cNurbsSurf.nCPV ; ++j) {
|
|
ON_4dPoint o4dPoint = onNurbsSurface->ControlPoint(i, j) ;
|
|
cNurbsSurf.mCP[i][j] = ConvertPoint( o4dPoint) ;
|
|
cNurbsSurf.mW[i][j] = o4dPoint.w ;
|
|
}
|
|
}
|
|
for ( int i = 0 ; i < onNurbsSurface->KnotCount(0) ; ++i ) {
|
|
cNurbsSurf.vU.push_back( onNurbsSurface->Knot( 0, i)) ;
|
|
}
|
|
for ( int j = 0 ; j < onNurbsSurface->KnotCount(1) ; ++j ) {
|
|
cNurbsSurf.vV.push_back( onNurbsSurface->Knot( 1, j)) ;
|
|
}
|
|
return NurbsToBezierSurface( cNurbsSurf) ;
|
|
}
|
|
else if ( const ON_PlaneSurface* onPlaneSurface = ON_PlaneSurface::Cast( onSurf)) {
|
|
// recupero i riferimenti del piano e li converto in oggetti nostri
|
|
Point3d ptOrig = ConvertPoint( onPlaneSurface->m_plane.origin) ;
|
|
Vector3d vtZ = ConvertVector( onPlaneSurface->m_plane.Normal()) ;
|
|
ON_Interval on_inX = onPlaneSurface->Extents(0) ;
|
|
ON_Interval on_inY = onPlaneSurface->Extents(1) ;
|
|
Point3d pt0( on_inX[0], on_inY[0]) ;
|
|
Point3d pt1( on_inX[1], on_inY[0]) ;
|
|
Point3d pt2( on_inX[1], on_inY[1]) ;
|
|
Point3d pt3( on_inX[0], on_inY[1]) ;
|
|
Frame3d frPlane ;
|
|
frPlane.Set( ptOrig, vtZ) ;
|
|
pt0.ToGlob( frPlane) ;
|
|
pt1.ToGlob( frPlane) ;
|
|
pt2.ToGlob( frPlane) ;
|
|
pt3.ToGlob( frPlane) ;
|
|
// costruisco la figura e la inserisco nel GDB
|
|
PolyLine PL ;
|
|
PL.AddUPoint( 0, pt0) ;
|
|
PL.AddUPoint( 1, pt1) ;
|
|
PL.AddUPoint( 2, pt2) ;
|
|
PL.AddUPoint( 3, pt3) ;
|
|
PL.AddUPoint( 4, pt0) ;
|
|
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
|
pCrvCompo->FromPolyLine( PL) ;
|
|
PtrOwner<ISurfTriMesh> pSurf ( GetSurfTriMeshByFlatContour( Release(pCrvCompo))) ;
|
|
return Release( pSurf) ;
|
|
}
|
|
else if ( const ON_RevSurface* onRevSurface = ON_RevSurface::Cast( onSurf)) {
|
|
ICurve* pCurve = ConvertCurve( onRevSurface->m_curve) ;
|
|
ON_Line onAxis = onRevSurface->m_axis ;
|
|
Point3d ptFrom = ConvertPoint( onAxis.from) ;
|
|
Point3d ptTo = ConvertPoint( onAxis.to) ;
|
|
Vector3d vtDir = ptTo - ptFrom ;
|
|
// intervallo angolare su cui si vuole la superficie di rivoluzione
|
|
ON_Interval onInter = onRevSurface->m_angle ;
|
|
double dAngRotDeg = ( onInter[1] - onInter[0]) * RADTODEG ;
|
|
double dAngStartDeg = onInter[0] * RADTODEG ;
|
|
PtrOwner<ISurfTriMesh> pSurf( CreateSurfTriMesh()) ;
|
|
// se l'angolo è significativo allora effettuo la rivoluzione
|
|
if ( dAngRotDeg > EPS_SMALL * 10 )
|
|
pSurf.Set( GetSurfTriMeshByScrewing( pCurve, ptFrom, vtDir, dAngRotDeg, 0., false)) ;
|
|
// se la rivoluzione è meno di un angolo giro e la partenza non era a zero devo ruotare la superficie ottenuta
|
|
if ( dAngRotDeg < 360 - EPS_SMALL * 50 && onInter[0] * RADTODEG > EPS_SMALL * 50){
|
|
pSurf->Rotate( ptFrom, vtDir, dAngStartDeg) ;
|
|
}
|
|
return Release( pSurf) ;
|
|
}
|
|
else if ( const ON_SumSurface* onSumSurface = ON_SumSurface::Cast( onSurf)) {
|
|
ON_NurbsSurface onNurbsSurface ;
|
|
// prima di usare la nurbs form tento di costruire la superficie con una rail ( funzione seguente)
|
|
//GetSurfTriMeshSwept
|
|
int bOk = onSumSurface->GetNurbForm( onNurbsSurface) ;
|
|
PtrOwner<ISurf> pSurf( ConvertSurface( &onNurbsSurface)) ;
|
|
if ( bOk != 0)
|
|
return Release( pSurf) ;
|
|
else {
|
|
// se fallisce questo tentativo di conversione allora recupero le curve e costruisco la superficie di Bezier
|
|
ON_Interval onIntDomain0 = onSumSurface->Domain(0) ;
|
|
ON_Interval onIntDomain1 = onSumSurface->Domain(1) ;
|
|
PtrOwner<ON_Curve> pCrvWest( onSumSurface->IsoCurve(1, onIntDomain0[0])) ;
|
|
PtrOwner<ON_Curve> pCrvEast( onSumSurface->IsoCurve(1, onIntDomain0[1])) ;
|
|
PtrOwner<ON_Curve> pCrvNorth( onSumSurface->IsoCurve(0, onIntDomain1[1])) ;
|
|
PtrOwner<ON_Curve> pCrvSouth( onSumSurface->IsoCurve(0, onIntDomain1[0])) ;
|
|
}
|
|
|
|
}
|
|
else if ( const ON_SurfaceProxy* onSurfaceProxy = ON_SurfaceProxy::Cast( onSurf)) {
|
|
PtrOwner<ISurf> pSurf ;
|
|
if ( const ON_BrepFace* onBrepFace = ON_BrepFace::Cast( onSurfaceProxy)) {
|
|
ON_NurbsSurface onNurbsSurface ;
|
|
int nOk = onBrepFace->GetNurbForm( onNurbsSurface) ;
|
|
if ( nOk != 0)
|
|
pSurf.Set( ConvertSurface( & onNurbsSurface)) ;
|
|
else
|
|
return nullptr ;
|
|
}
|
|
else if ( const ON_OffsetSurface* onOffsetSurface = ON_OffsetSurface::Cast( onSurfaceProxy)) {
|
|
pSurf.Set( ConvertSurface( onOffsetSurface->BaseSurface())) ;
|
|
}
|
|
else
|
|
pSurf.Set( ConvertSurface( onSurfaceProxy->DuplicateSurface())) ;
|
|
return Release( pSurf) ;
|
|
}
|
|
return nullptr ;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
ISURFPVECTOR
|
|
Import3dm::ConvertBrep( const ON_Brep* onBrep, const bool bForceTriMesh )
|
|
{
|
|
// se le facce della Brep sono tutte trimesh restituisco un'unica trimesh
|
|
// se le facce sono delle NURBS restituisco un vettore di superfici Bezier
|
|
ISURFPVECTOR vSurf ;
|
|
//surfaces
|
|
int nSurf = onBrep->m_S.Count() ;
|
|
StmFromTriangleSoup stmSoup ;
|
|
if ( ! stmSoup.Start())
|
|
return vSurf ;
|
|
bool bSurfTm = false ;
|
|
for ( int i = 0 ; i < nSurf ; ++i) {
|
|
//ON_BrepFace* onBrepFace = onBrep->Face( i) ;
|
|
//onBrepFace->LoopCount() ;
|
|
ON_Surface* onSurface = onBrep->m_S[i] ;
|
|
ON_BrepFace* onFace = onBrep->Face( i) ;
|
|
int nLoop = onFace->LoopCount() ;
|
|
static bool bDone = false ;
|
|
|
|
//// da attivare per il debug del file V5/V5_example_file.3dm
|
|
//if ( ! bDone ) {
|
|
// // provo a replicare la nurbs a mano per vedere se esce il cerchio
|
|
// ON_BrepLoop* onLoop0 = onFace->Loop( 0) ;
|
|
// ON_BrepTrim* onBrepTrim = onLoop0->Trim( 0) ;
|
|
// ON_CurveProxy* onCurveProxy = ON_CurveProxy::Cast( onBrepTrim);
|
|
// ON_Curve* onCurve = onCurveProxy->DuplicateCurve() ;
|
|
// const ON_NurbsCurve* onNurbs = ON_NurbsCurve::Cast( onCurve) ;
|
|
|
|
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// int nMax = 4 ;
|
|
// for ( int k = 0 ; k < nMax; ++k) {
|
|
// ICurveBezier* crvBz( CreateCurveBezier()) ;
|
|
// crvBz->Init( onNurbs->Degree(), onNurbs->IsRational());
|
|
// int nCount = onNurbs->CVCount() ;
|
|
// if ( onNurbs->IsRational()) {
|
|
// for( int i = 0 ; i < 3; ++i) {
|
|
// ON_4dPoint o4dPoint ;
|
|
// onNurbs->GetCV( i + 2*k, o4dPoint) ;
|
|
// Point3d ptCtrl( ConvertPoint( o4dPoint)) ;
|
|
// crvBz->SetControlPoint( i, ptCtrl, o4dPoint.w) ;
|
|
// }
|
|
// }
|
|
// m_pGDB->AddGeoObj(GDB_ID_NULL, 0, crvBz) ;
|
|
// }
|
|
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ICurve* pCurve0 = ConvertBrepLoop( onLoop0) ;
|
|
//
|
|
// m_pGDB->AddGeoObj(GDB_ID_NULL, 0, pCurve0) ;
|
|
// ON_BrepLoop* onLoop1 = onFace->Loop( 1) ;
|
|
// ICurve* pCurve1 = ConvertBrepLoop( onLoop1) ;
|
|
// m_pGDB->AddGeoObj(GDB_ID_NULL, 0, pCurve1) ;
|
|
// bDone = true ;
|
|
//}
|
|
|
|
PtrOwner<ISurf> pSurf( ConvertSurface( onSurface)) ;
|
|
if ( IsNull(pSurf)) {
|
|
string sOut = "Non è riuscita la conversione di " + to_string( nSurf - i) + " superfici appartenenti ad una Brep" ;
|
|
LOG_ERROR( GetEExLogger(), sOut.c_str()) ;
|
|
return vSurf ;
|
|
}
|
|
// se ho una trimesh la aggiungo, se è una bezier ricavo la trimesh prima di aggiungerla
|
|
int nType = pSurf->GetType() ;
|
|
if ( nType == SRF_TRIMESH ) {
|
|
bSurfTm = true ;
|
|
PtrOwner<ISurfTriMesh> pSurfTm ( GetSurfTriMesh( Release( pSurf))) ;
|
|
if ( ! IsNull( pSurfTm) )
|
|
stmSoup.AddSurfTriMesh( *Release( pSurfTm)) ;
|
|
else {
|
|
string sOut = "Non è riuscita la conversione di " + to_string( nSurf - i) + " superfici trimesh appartenenti ad una Brep" ;
|
|
LOG_ERROR( GetEExLogger(), sOut.c_str()) ;
|
|
return vSurf ;
|
|
}
|
|
}
|
|
else if ( nType == SRF_BEZIER ) {
|
|
PtrOwner<ISurfBezier> pSurfBezNew ( GetSurfBezier( Release( pSurf))) ;
|
|
// se ho più di un loop vuol dire che ho dei trim sulla faccia e quindi li aggiungo alla superficie di bezier
|
|
// prima della triangolazione
|
|
ON_BrepFace* onFace = onBrep->Face( i) ;
|
|
SurfFlatRegionByContours SfrCntr ;
|
|
if ( onFace->LoopCount() > 1) {
|
|
for ( int k = 0 ; k < onFace->LoopCount() ; ++k)
|
|
SfrCntr.AddCurve( ConvertBrepLoop( onFace->Loop( k))) ;
|
|
}
|
|
ISurfFlatRegion* sfrTrim = SfrCntr.GetSurf() ;
|
|
if ( ! IsNull( pSurfBezNew) ) {
|
|
// questa regione di Trim deve essere riferita al rettangolo parametrico totale ( spaz param 1x1 -> regione trim 1000x1000)
|
|
// devo anche controllare che il sistema di riferimento dello spazio di trim totale sia giusto ( con l'angolo BottomLeft in (0,0)
|
|
//posizonato nel primo quadrante del piano XY)
|
|
if ( onFace->LoopCount() > 1)
|
|
pSurfBezNew->SetTrimRegion( *sfrTrim) ;
|
|
if ( ! bForceTriMesh)
|
|
vSurf.push_back( Release( pSurfBezNew)) ;
|
|
else
|
|
stmSoup.AddSurfTriMesh( *(Release( pSurfBezNew)->GetAuxSurf())) ;
|
|
}
|
|
else {
|
|
string sOut = "Non è riuscita la conversione di " + to_string( nSurf - i) + " superfici NURBS appartenenti ad una Brep" ;
|
|
LOG_ERROR( GetEExLogger(), sOut.c_str()) ;
|
|
return vSurf ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! stmSoup.End())
|
|
return vSurf ;
|
|
if ( bSurfTm || bForceTriMesh)
|
|
vSurf.push_back( GetSurfTriMesh( stmSoup.GetSurf())) ;
|
|
|
|
return vSurf ;
|
|
}
|
|
|
|
ICurve*
|
|
Import3dm::ConvertBrepLoop( const ON_BrepLoop* onBrepLoop)
|
|
{
|
|
int nTrim = onBrepLoop->TrimCount() ;
|
|
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
|
for ( int i = 0 ; i < nTrim ; ++i) {
|
|
ON_BrepTrim* onBrepTrim = onBrepLoop->Trim( i) ;
|
|
ON_CurveProxy* onCurveProxy = ON_CurveProxy::Cast( onBrepTrim);
|
|
pCrvCompo->AddCurve( ConvertCurve( onCurveProxy)) ;
|
|
}
|
|
return Release( pCrvCompo) ;
|
|
}
|