Files
EgtExch3dm/Export3dm.cpp
T
Daniele Bariletti b6d788ea4f EgtExch3dm 3.1b1 :
- correzione all'export delle trimesh.
- cambio versione.
2026-02-17 12:30:21 +01:00

924 lines
34 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2023
//----------------------------------------------------------------------------
// File : Export3dm.cpp Data : 21.09.23 Versione :
// Contenuto : Implementazione della classe per l'esportazione in formato 3dm.
//
//
//
// Modifiche : 21.09.23 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Export3dm.h"
#include "DllMain.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Include/EGkCurveArc.h"
#include "/EgtDev/Include/EGkCurveBezier.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkSurfFlatRegion.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkExtText.h"
#include "/EgtDev/Include/EGkExtDimension.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtKeyCodes.h"
#include <fstream>
using namespace std ;
//N.B.:
// se si vuole richiamare qualche variabile di default definita in una classe come statica e a cui viene assegnato un valore
// nel file opennurbs_statics.cpp bisogna richiamarla in questo elenco per evitare problemi di compilazione ( errore di LINK)
//----------------------------------------------------------------------------
IExport3dm*
CreateExport3dm( void)
{
// verifico la chiave e le opzioni
if ( ! VerifyKey( KEYOPT_EEX_EXPBASE))
return nullptr ;
// creo l'oggetto
return static_cast<IExport3dm*> ( new( nothrow) Export3dm) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::SetOptions( int nFilter)
{
m_nFilter = nFilter ;
CalcGroupFilter() ;
return true ;
}
//----------------------------------------------------------------------------
static void
Internal_SetExampleModelProperties( ONX_Model& model, const char* source_file_name)
{
const bool bHaveFileName = ( nullptr != source_file_name && 0 != source_file_name[0]) ;
if ( ! bHaveFileName)
source_file_name = "" ;
model.m_sStartSectionComments = "This file was created using openNURBS to convert an .nge into .3dm" ;
// set application information
const ON_wString wide_source_file_name( source_file_name) ;
model.m_properties.m_Application.m_application_URL = L"http://www.opennurbs.org" ;
// set revision history information
model.m_properties.m_RevisionHistory.NewRevision() ;
}
//----------------------------------------------------------------------------
bool
Export3dm::Export( IGeomDB* pGDB, int nId, const string& sFile)
{
Internal_SetExampleModelProperties( m_model, sFile.c_str()) ;
ON::Begin() ;
// verifico il DB geometrico
if ( pGDB == nullptr) {
LOG_ERROR( GetEE3Logger(), "Export3dm : Error on GeomDB")
return false ;
}
// verifico l'Id dell'oggetto da esportare
if ( ! pGDB->ExistsObj( nId)) {
LOG_ERROR( GetEE3Logger(), "Export3dm : Error on Id")
return false ;
}
//// file settings ( units, tolerances, views, ...)
//// OPTIONAL - change values from defaults
m_model.m_settings.m_ModelUnitsAndTolerances.m_unit_system = ON::LengthUnitSystem::Millimeters ;
m_model.m_settings.m_ModelUnitsAndTolerances.m_absolute_tolerance = 0.01 ;
m_model.m_settings.m_ModelUnitsAndTolerances.m_angle_tolerance = ON_PI/180.0 ;// radians
m_model.m_settings.m_ModelUnitsAndTolerances.m_relative_tolerance = 0.01 ;// 1%
m_model.m_settings.m_current_material_source = ON::object_material_source::material_from_object ;
m_model.m_settings.m_RenderSettings.m_bFlatShade = true ;
// creo un iteratore
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( pGDB)) ;
if ( IsNull( pIter))
return false ;
pIter->GoTo( nId) ;
// esporto l'oggetto e i suoi eventuali figli
bool bAdded = false ;
bool bOk = ExportObject( *pIter, 0, bAdded) ;
// stampo il file
int version = 8 ;
// errors printed to stdout
ON_TextLog error_log ;
// writes model to archive
bOk = bOk && m_model.Write( ConvertString( sFile).c_str(), version, &error_log) ;
ON::End() ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportObject( const IGdbIterator& iIter, const int& nLayer, bool& bAdded)
{
// recupero il livello dell'oggetto
int nLev = GDB_LV_USER ;
iIter.GetCalcLevel( nLev) ;
// recupero il modo dell'oggetto
int nMode = GDB_MD_STD ;
iIter.GetCalcMode( nMode) ;
// recupero lo stato dell'oggetto
int nStat = GDB_ST_ON ;
iIter.GetCalcStatus( nStat) ;
int nType = iIter.GetGdbType() ;
// se il filtro lo abilita
if ( TestFilter( nLev, nMode, nStat, nType == GDB_TY_GROUP)) {
switch ( nType) {
case GDB_TY_GEO :
{
// recupero il riferimento globale dell'oggetto
Frame3d frFrame ;
if ( ! iIter.GetGlobFrame( frFrame))
return false ;
//recupero il colore dell'oggetto
Color cCol ;
iIter.GetCalcMaterial( cCol) ;
// recupero eventuale nome
string sName ;
if ( ! iIter.GetName( sName))
sName = ToString( iIter.GetId()) ;
// emetto l'oggetto
switch ( iIter.GetGeoType()) {
case GEO_PNT3D: {
if ( ! ExportPnt( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
}
case SRF_BEZIER: {
if ( ! ExportSrfBz( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
}
case SRF_FLATRGN :
case SRF_TRIMESH :
if ( ! ExportSTM( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
case CRV_ARC : {
if ( ! ExportCrvArc( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
}
case CRV_BEZIER : {
if ( ! ExportCrvBezier( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
}
case CRV_COMPO : {
if ( ! ExportCrvCompo( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
}
case CRV_LINE : {
if ( ! ExportCrvLine( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
case EXT_TEXT :
if ( ! ExportText( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
case EXT_DIMENSION :
if ( ! ExportDimension( sName, iIter, frFrame, cCol, nLayer))
return false ;
else
bAdded = true ;
break ;
}
default :
break ;
}
}
return true ;
case GDB_TY_GROUP: {
int nLayer = iIter.GetId() ;
if ( nLayer == 0) {
m_model.RemoveModelComponent( ON_ModelComponent::Type::Layer, m_model.LayerFromIndex( 0).ModelComponentId()) ;
bool bEmpty = false ;
return ScanGroup( iIter, nLayer, bEmpty) ;
}
// creo il layer e setto le proprietà
ON_Layer* layer = new ON_Layer() ;
std::string sLayName ;
iIter.GetName( sLayName) ;
if ( sLayName == "" ) {
sLayName = "Layer " + ToString( nLayer) ;
}
layer->SetName( ConvertString( sLayName).c_str()) ;
layer->SetIndex( nLayer) ;
ON_Color onCol( 0, 0, 0) ; // black
layer->SetColor( onCol) ;
layer->SetVisible( true) ;
layer->SetLocked( false) ;
int nParent = iIter.GetParentId() ;
if ( nParent != 0) {
// setto il parent
const ON_Layer* onParLay = ON_Layer::Cast( m_model.LayerFromIndex( m_mLayer[nParent]).ModelComponent()) ;
layer->SetParentLayerId( onParLay->Id()) ;
}
// copio le info
STRVECTOR vStrInfo, vStrInfo_split ;
iIter.GetAllInfo( vStrInfo) ;
for ( string sInfo : vStrInfo) {
Tokenize( sInfo, "=", vStrInfo_split) ;
layer->SetUserString( ConvertString( vStrInfo_split[0]).c_str(), ConvertString( vStrInfo_split[1]).c_str()) ;
}
// aggiungo il layer
ON_ModelComponentReference mcr = m_model.AddManagedModelComponent( layer) ;
ON_UUID uuid = mcr.ModelComponentId() ;
int nIndex = mcr.ModelComponentIndex() ;
m_mLayer.insert( pair< int, int>( nLayer, nIndex)) ;
// esploro il gruppo
bool bEmpty = false ;
bool bOk = ScanGroup( iIter, nIndex, bEmpty) ;
if ( bEmpty)
;
//m_model.RemoveModelComponent( ON_ModelComponent::Type::Layer, uuid) ; // se si volessero cancellare i layer vuoti
else
bAdded = true ;
return bOk ;
}
default :
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Export3dm::AddObjectToModel( const IGdbIterator& iIter, ON_Object* onObject, const int& nLayer, const std::string& sName, const Color& cCol,
ON_3dmObjectAttributes* pOnAttr)
{
if ( onObject == nullptr)
return false ;
if ( pOnAttr == nullptr)
pOnAttr = new ON_3dmObjectAttributes() ;
pOnAttr->m_layer_index = nLayer ;
int nType = iIter.GetGeoType() ;
string sCompleteName = sName ;
if ( nType == EXT_DIMENSION) {
sCompleteName = "dim_" + sCompleteName ;
}
pOnAttr->m_name = ConvertString( sCompleteName).c_str() ;
pOnAttr->SetColorSource( ON::color_from_object) ;
//N.B. RHINO ha i valori di Alpha invertiti rispetto ai nostri, oltre che su una scala diversa! per loro 0 = opaco e 255 = trasparente
// per noi invece 0 = trasparente, 100 = opaco
ON_Color onCol( cCol.GetIntRed(), cCol.GetIntGreen(), cCol.GetIntBlue(), Clamp( 255 - lround( cCol.GetIntAlpha() * 2.55), 0, 255)) ;
pOnAttr->m_color = onCol ;
// se è una mesh aggiungo il materiale
if ( const ON_Mesh* onMesh = ON_Mesh::Cast( onObject)) {
// aggiungo il materiale al modello se necessario
std::string sCol = ToString(cCol.GetIntRed()) + "," + ToString( cCol.GetIntGreen()) + "," + ToString( cCol.GetIntBlue()) ;
if ( m_mMaterial.find( sCol) == m_mMaterial.end()) {
ON_Material* onMat = new ON_Material ;
ON_Color onCAmb( 126, 126, 126) ; // gray126
onMat->m_reflection_glossiness = 0.0 ;
onMat->SetEmission( onCol) ;
onMat->SetDiffuse( onCol) ;
onMat->SetAmbient( onCAmb) ;
onMat->SetReflectivity( 0) ;
onMat->SetTransparency( Clamp( 255 - lround( cCol.GetIntAlpha() * 2.55), 0, 255)) ;
ON_ModelComponentReference mcr = m_model.AddManagedModelComponent( onMat) ;
int nIndex = mcr.ModelComponentIndex() ;
m_mMaterial.insert( pair< std::string, int>( sCol, nIndex)) ;
pOnAttr->SetMaterialSource( ON::object_material_source::material_from_object) ;
pOnAttr->m_material_index = nIndex ;
}
// sennò richiamo un materiale già definito
else {
pOnAttr->SetMaterialSource( ON::object_material_source::material_from_object) ;
pOnAttr->m_material_index = m_mMaterial[sCol] ;
}
}
// copio le info
STRVECTOR vStrInfo, vStrInfo_split ;
iIter.GetAllInfo(vStrInfo) ;
for ( string sInfo : vStrInfo) {
Tokenize( sInfo, "=", vStrInfo_split) ;
pOnAttr->SetUserString( ConvertString( vStrInfo_split[0]).c_str(), ConvertString( vStrInfo_split[1]).c_str()) ;
}
// aggiungo al modello
ON_ModelComponentReference mcr = m_model.AddManagedModelGeometryComponent( onObject, pOnAttr) ;
return ! mcr.IsEmpty() ;
}
//----------------------------------------------------------------------------
bool
Export3dm::AddInfoToObject( const IGdbIterator& iIter, ON_Object* onObject)
{
// copio le info
STRVECTOR vStrInfo, vStrInfo_split ;
iIter.GetAllInfo( vStrInfo) ;
for ( string sInfo : vStrInfo) {
Tokenize( sInfo, "=", vStrInfo_split) ;
onObject->SetUserString( ConvertString( vStrInfo_split[0]).c_str(), ConvertString( vStrInfo_split[1]).c_str()) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Export3dm::TestFilter( int nLev, int nMode, int nStat, bool bGroup)
{
int nFilter = bGroup ? m_nGroupFilter : m_nFilter ;
if ( ( nLev == GDB_LV_USER && ( nFilter & EEXFLT_LEVUSER) == 0) ||
( nLev == GDB_LV_SYSTEM && ( nFilter & EEXFLT_LEVSYSTEM) == 0) ||
( nLev == GDB_LV_TEMP && ( nFilter & EEXFLT_LEVTEMP) == 0))
return false ;
if ( ( nMode == GDB_MD_STD && ( nFilter & EEXFLT_MODESTD) == 0) ||
( nMode == GDB_MD_LOCKED && ( nFilter & EEXFLT_MODELOCKED) == 0) ||
( nMode == GDB_MD_HIDDEN && ( nFilter & EEXFLT_MODEHIDDEN) == 0))
return false ;
if ( ( nStat == GDB_ST_OFF && ( nFilter & EEXFLT_STAOFF) == 0) ||
( nStat == GDB_ST_ON && ( nFilter & EEXFLT_STAON) == 0) ||
( nStat == GDB_ST_SEL && ( nFilter & EEXFLT_STASEL) == 0))
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Export3dm::CalcGroupFilter( void)
{
m_nGroupFilter = 0 ;
// Status
if ( ( m_nFilter & EEXFLT_STASEL) != 0)
m_nGroupFilter += EEXFLT_STASEL + EEXFLT_STAOFF + EEXFLT_STAON ;
else if ( ( m_nFilter & EEXFLT_STAOFF) != 0)
m_nGroupFilter += EEXFLT_STAOFF + EEXFLT_STAON ;
else
m_nGroupFilter += EEXFLT_STAON ;
// Mode
if ( ( m_nFilter & EEXFLT_MODELOCKED) != 0)
m_nGroupFilter += EEXFLT_MODELOCKED + EEXFLT_MODEHIDDEN + EEXFLT_MODESTD ;
else if ( ( m_nFilter & EEXFLT_MODEHIDDEN) != 0)
m_nGroupFilter += EEXFLT_MODEHIDDEN + EEXFLT_MODESTD ;
else
m_nGroupFilter += EEXFLT_MODESTD ;
// Level
if ( ( m_nFilter & EEXFLT_LEVSYSTEM) != 0)
m_nGroupFilter += EEXFLT_LEVSYSTEM + EEXFLT_LEVTEMP + EEXFLT_LEVUSER ;
else if ( ( m_nFilter & EEXFLT_LEVTEMP) != 0)
m_nGroupFilter += EEXFLT_LEVTEMP + EEXFLT_LEVUSER ;
else
m_nGroupFilter += EEXFLT_LEVUSER ;
return true ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportPnt(const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<IGeoPoint3d> pGeoPnt( GetGeoPoint3d( pGeoObj->Clone())) ;
if ( IsNull( pGeoPnt))
return false ;
// lo porto nel riferimento globale
pGeoPnt->ToGlob( frFrame) ;
Point3d pt = pGeoPnt->GetPoint() ;
ON_Point* onPt = new ON_Point( ConvertPoint( pt)) ;
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onPt, nLayer, sName, cCol) ; ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportSrfBz( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
//MANCA DA IMPLEMENTARE IL TRIM DELLE SUPERFICI!!/////////////////////////////////////////////////////////////////////////////////////////////////////
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<ISurfBezier> pSrfBz( GetSurfBezier( pGeoObj->Clone())) ;
if ( IsNull( pSrfBz))
return false ;
// lo porto nel riferimento globale
pSrfBz->ToGlob( frFrame) ;
bool bOk = true ;
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat = false ;
bool bTrimmed = false ;
pSrfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
int nCPU = nDegU * nSpanU + 1 ;
int nCPV = nDegV * nSpanV + 1 ;
ON_NurbsSurface* onNurbsSurf = new ON_NurbsSurface( 3, bRat, nDegU + 1, nDegV + 1, nCPU, nCPV) ;
for ( int u = 0 ; u < nCPU ; ++u) {
for ( int v = 0 ; v < nCPV ; ++v) {
Point3d ptCV = pSrfBz->GetControlPoint( u, v, &bOk) ;
if ( ! bRat) {
onNurbsSurf->SetCV( u, v, ConvertPoint( ptCV)) ;
}
else {
double dW = pSrfBz->GetControlWeight( u, v, &bOk) ;
onNurbsSurf->SetCV( u, v, ConvertPoint( ptCV * dW)) ;
onNurbsSurf->SetWeight( u, v, dW) ;
}
}
}
// imposto il vettore dei nodi in U
int nKnotCountU = nDegU + nCPU - 1 ;
double dKnot = 0 ;
// per costruzione nKnotCount é un multiplo di nDegU
for ( int u = 0 ; u < int ( nKnotCountU / nDegU) ; ++u) {
for ( int p = 0 ; p < nDegU ; ++p)
onNurbsSurf->SetKnot( 0, u * nDegU + p, dKnot) ;
++dKnot ;
}
// imposto il vettore dei nodi in V
int nKnotCountV = nDegV + nCPV - 1 ;
dKnot = 0 ;
// per costruzione nKnotCount é un multiplo di nDegV
for ( int v = 0 ; v < int ( nKnotCountV / nDegV) ; ++v) {
for ( int p = 0 ; p < nDegV ; ++p)
onNurbsSurf->SetKnot( 1, v * nDegV + p, dKnot) ;
++dKnot ;
}
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onNurbsSurf, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportSTM( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<ISurfTriMesh> pSrfTm ;
if ( pGeoObj->GetType() == SRF_TRIMESH)
pSrfTm.Set( GetSurfTriMesh( pGeoObj->Clone())) ;
else {
const ISurfFlatRegion* pSrfFr = GetSurfFlatRegion( pGeoObj) ;
const ISurfTriMesh* pSrfTm_ = pSrfFr->GetAuxSurf() ;
if ( pSrfTm_ == nullptr){
return false ;
}
pSrfTm.Set( pSrfTm_->Clone()) ;
}
if ( IsNull( pSrfTm))
return false ;
// lo porto nel frame globale
pSrfTm->ToGlob( frFrame) ;
int nVertices = pSrfTm->GetVertexSize() ;
int nTriangles = pSrfTm->GetTriangleSize() ;
ON_Mesh* onMesh = new ON_Mesh ;
bool bOk = true ;
for ( int v = 0 ; v < nVertices ; ++v) {
Point3d pt ; pSrfTm->GetVertex( v, pt) ;
bOk = onMesh->SetVertex( v, ConvertPoint( pt)) ;
if ( ! bOk) {
LOG_ERROR( GetEE3Logger(), "Export3dm SurfTm: Error adding vertex")
bOk = true ;
}
}
bOk = true ;
for ( int t = 0 ; t < nTriangles ; ++t) {
int nIdVert[3] ;
if ( ! pSrfTm->GetTriangle( t, nIdVert))
continue ;
bOk = onMesh->SetTriangle( t, nIdVert[0], nIdVert[1], nIdVert[2]) ;
if ( ! bOk) {
LOG_ERROR( GetEE3Logger(), "Export3dm SurfTm: Error adding triangle")
bOk = true ;
}
}
ON_MeshVertexFaceMap onMeshVertMap ;
onMeshVertMap.SetFromMesh( onMesh, false) ;
onMesh->AddPlanarNgons( onMeshVertMap.VertexFaceMap(), 0.1, 3, 1, true) ;
onMesh->ComputeFaceNormals() ;
onMesh->Compact() ;
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onMesh, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
ON_ArcCurve*
Export3dm::ConvertCrvArc( const ICurveArc* pCrvArc)
{
double dRad = pCrvArc->GetRadius() ;
Point3d ptCen ;
pCrvArc->GetCenterPoint( ptCen) ;
PtrOwner<ON_ArcCurve> onArcCrv( new ON_ArcCurve()) ;
if ( ! pCrvArc->IsACircle()) {
Vector3d vtZ = pCrvArc->GetNormVersor() ;
Vector3d vtX, vtY ;
vtX = pCrvArc->GetStartVersor() ;
vtY = vtZ ^ vtX ;
double dAngDeg = pCrvArc->GetAngCenter() ;
ON_Plane onPlane( ConvertPoint( ptCen), ConvertVector( vtX), ConvertVector( vtY)) ;
onArcCrv.Set( new ON_ArcCurve( ON_Arc( onPlane, dRad, dAngDeg * DEGTORAD))) ;
}
else
onArcCrv.Set( new ON_ArcCurve ( ON_Circle( ConvertPoint( ptCen), dRad))) ;
return Release( onArcCrv) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportCrvArc( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<ICurveArc> pCrvArc( GetCurveArc( pGeoObj->Clone())) ;
if ( IsNull( pCrvArc))
return false ;
// lo porto nel fram globale
pCrvArc->ToGlob( frFrame) ;
ON_ArcCurve* onArcCrv = ConvertCrvArc( pCrvArc) ;
if ( onArcCrv == nullptr)
return false ;
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onArcCrv, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
ON_NurbsCurve*
Export3dm::ConvertCrvBezier( const ICurveBezier* pCrvBz)
{
// creo l'oggetto da esportare
int nDeg = pCrvBz->GetDegree() ;
int nCV = nDeg + 1 ;
PtrOwner<ON_NurbsCurve> onNurbsCrv( new ON_NurbsCurve( 3, // dim
pCrvBz->IsRational(), // bRat
nDeg + 1, // order = deg + 1
nCV)) ; // numero di CP
// imposto i punti di controllo con gli eventuali pesi
if ( ! pCrvBz->IsRational()) {
bool bOk = true ;
for ( int i = 0 ; i < nCV ; ++i) {
ON_3dPoint onPt = ConvertPoint( pCrvBz->GetControlPoint( i, &bOk)) ;
onNurbsCrv->SetCV( i, onPt) ;
}
}
else {
bool bOk = true ;
for ( int i = 0 ; i < nCV ; ++i) {
ON_3dPoint onPt = ConvertPoint( pCrvBz->GetControlPoint( i, &bOk)) ;
double dWeight = pCrvBz->GetControlWeight( i, &bOk) ;
onNurbsCrv->SetCV( i, onPt * dWeight) ;
onNurbsCrv->SetWeight( i, dWeight) ;
}
}
// imposto il vettore dei nodi
int nKnotCount = nDeg + nCV - 1 ;
double dKnot = 0 ;
for ( int u = 0 ; u < int ( nKnotCount / nDeg) ; ++u) {
for ( int p = 0 ; p < nDeg ; ++p)
onNurbsCrv->SetKnot( u * nDeg + p, dKnot) ;
++dKnot ;
}
return Release( onNurbsCrv) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportCrvBezier( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<ICurveBezier> pCrvBz( GetCurveBezier( pGeoObj->Clone())) ;
if ( IsNull( pCrvBz))
return false ;
// lo porto nel riferimento globale
pCrvBz->ToGlob( frFrame) ;
ON_NurbsCurve* onNurbsCrv = ConvertCrvBezier( pCrvBz) ;
if ( onNurbsCrv == nullptr)
return false ;
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onNurbsCrv, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportCrvCompo( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<ICurveComposite> pCrvCompo( GetCurveComposite( pGeoObj->Clone())) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->IsValid())
return false ;
// lo porto nel riferimento globale
pCrvCompo->ToGlob( frFrame) ;
// converto
ON_PolyCurve* onPolyCrv = ConvertCrvCompo( pCrvCompo) ;
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onPolyCrv, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
ON_PolyCurve*
Export3dm::ConvertCrvCompo( const ICurveComposite* pCrvCompo)
{
ON_PolyCurve* onPolyCrv = new ON_PolyCurve ;
for ( const ICurve* pCrv = pCrvCompo->GetFirstCurve() ; pCrv != nullptr ; pCrv = pCrvCompo->GetNextCurve()) {
GeoObjType type = pCrv->GetType() ;
switch ( type) {
case CRV_LINE : {
PtrOwner<ICurveLine> pCrvL( GetCurveLine( pCrv->Clone())) ;
if ( IsNull( pCrvL) || ! pCrvL->IsValid()) {
delete onPolyCrv ;
return nullptr ;
}
ON_LineCurve* onLine = ConvertCrvLine( pCrvL) ;
if ( onLine == nullptr) {
delete onPolyCrv ;
return nullptr ;
}
onPolyCrv->Append( onLine) ;
break ;
}
case CRV_ARC : {
PtrOwner<ICurveArc> pCrvArc( GetCurveArc( pCrv->Clone())) ;
if ( IsNull( pCrvArc) || ! pCrvArc->IsValid()) {
delete onPolyCrv ;
return nullptr ;
}
ON_ArcCurve* onArcCrv = ConvertCrvArc( pCrvArc) ;
if ( onArcCrv == nullptr) {
delete onPolyCrv ;
return nullptr ;
}
onPolyCrv->Append( onArcCrv) ;
break ;
}
case CRV_BEZIER : {
PtrOwner<ICurveBezier> pCrvBz( GetCurveBezier( pCrv->Clone())) ;
if ( IsNull( pCrvBz) || ! pCrvBz->IsValid()) {
delete onPolyCrv ;
return nullptr ;
}
ON_NurbsCurve* onNurbsCrv = ConvertCrvBezier( pCrvBz) ;
if ( onNurbsCrv == nullptr) {
delete onPolyCrv ;
return nullptr ;
}
onPolyCrv->Append( onNurbsCrv) ;
break ;
}
default : break ;
}
}
return onPolyCrv ;
}
//----------------------------------------------------------------------------
ON_LineCurve*
Export3dm::ConvertCrvLine( const ICurveLine* pCrvL)
{
Point3d ptStart, ptEnd ;
pCrvL->GetStartPoint( ptStart) ;
pCrvL->GetEndPoint( ptEnd) ;
PtrOwner<ON_LineCurve> onCrvLine( new ON_LineCurve( ON_Line( ConvertPoint( ptStart), ConvertPoint( ptEnd)))) ;
return Release( onCrvLine) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportCrvLine( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<ICurveLine> pCrvL( GetCurveLine( pGeoObj->Clone())) ;
if ( IsNull( pCrvL) || ! pCrvL->IsValid())
return false ;
// lo porto nel frame globale
pCrvL->ToGlob( frFrame) ;
ON_LineCurve* onCrvLine = ConvertCrvLine( pCrvL) ;
// aggiungo l'oggetto al modello
return AddObjectToModel( iIter, onCrvLine, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
ON_Text*
Export3dm::ConvertText( const IExtText* pText, const Frame3d& frDim)
{
string sText = pText->GetText() ;
wstring wText = wstring(sText.begin(), sText.end());
const wchar_t* wcText = wText.c_str();
ON_Text* ontText = new ON_Text() ;
double dHeight = pText->GetHeight() ;
// controllo se esiste già un dim style con quell'altezza sennò lo creo
ON_DimStyle onDimStyle = ON_DimStyle::SystemDimstyleFromIndex( -1) ; // default
const ON_DimStyle* onDimStyleNew = nullptr ;
ONX_ModelComponentIterator component_iterator_ds( m_model, ON_ModelComponent::Type::DimStyle) ;
bool bFound = false ;
for ( const ON_ModelComponent* mc = component_iterator_ds.FirstComponent() ; mc != nullptr ; mc = component_iterator_ds.NextComponent()) {
const ON_DimStyle* onDim = ON_DimStyle::Cast( mc) ;
double dTextHeight = onDim->TextHeight() ;
if ( abs( dHeight - dTextHeight) < 0.1 ) {
onDimStyle = *onDim ;
bFound = true ;
break ;
}
}
if ( ! bFound) {
ON_DimStyle onDimStyleOver = onDimStyle.CreateOverrideCandidate() ;
onDimStyleOver.SetFieldOverride( ON_DimStyle::field::TextHeight, true) ;
onDimStyleOver.SetTextHeight( dHeight) ;
ON_ModelComponentReference mcr = m_model.AddModelComponent( onDimStyleOver, true) ;
onDimStyleNew = ON_DimStyle::FromModelComponentRef( mcr, nullptr) ;
}
// il punto di riferimento di rhino è in alto a sinistra, mentre il nostro è in basso a sinistra
Point3d pt ; pText->GetOverStartPoint( pt) ;
ON_Plane onPlane( ConvertPoint( pt), ConvertVector(frDim.VersX()), ConvertVector(frDim.VersY())) ;
BBox3d bbox3d ; pText->GetBBox( GLOB_FRM, bbox3d, 0) ;
if ( onDimStyleNew != nullptr)
ontText->Create( wcText, onDimStyleNew, onPlane, true, bbox3d.GetDimX() * 10, 0.) ;
else
ontText->Create( wcText, &onDimStyle, onPlane, true, bbox3d.GetDimX() * 10, 0.) ;
return ontText ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportText( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<IExtText> pText( GetExtText( pGeoObj->Clone())) ;
if ( IsNull( pText) || ! pText->IsValid())
return false ;
// lo porto nel frame globale
pText->ToGlob( frFrame) ;
ON_Text* onText = ConvertText( pText, frFrame) ;
return AddObjectToModel( iIter, onText, nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
ON_Dimension*
Export3dm::ConvertExtDimension( const IExtDimension* pExtDim, const Frame3d& frDim)
{
const ON_DimStyle onDimStyle = ON_DimStyle::DimStyleOrDefault( nullptr) ;
ON_UUID onIdDim = onDimStyle.Id() ;
// versione con le classi di Rhino
string sSubType = pExtDim->GetSubType() ;
if ( sSubType == "Linear") {
ON_Plane onPlane(ConvertPoint( frDim.Orig()), ConvertVector( frDim.VersX()), ConvertVector( frDim.VersY())) ;
ON_DimLinear* onDimLinear( new ON_DimLinear()) ;
ON_3dPoint onPt1 = ConvertPoint( pExtDim->GetStart()) ;
ON_3dPoint onPt2 = ConvertPoint( pExtDim->GetEnd()) ;
ON_3dPoint onPtDim = ConvertPoint( pExtDim->GetPosition()) ;
Vector3d vtDir = pExtDim->GetDirVersor() ;
// aligned
if ( ! AreSameVectorApprox( vtDir, X_AX) && ! AreSameVectorApprox( vtDir, Y_AX))
ON_DimLinear::CreateAligned( onPt1, onPt2, onPtDim, ConvertVector( frDim.VersZ()), onIdDim, onDimLinear) ;
//horizontal o vertical
else {
ON_3dPoint onPtDim2 = onPtDim + ConvertVector( vtDir) ;
ON_DimLinear::CreateRotated( onPt1, onPt2, ON_Line( onPtDim, onPtDim2), ConvertVector( frDim.VersZ()), onIdDim, onDimLinear) ;
}
return onDimLinear ;
}
else if ( sSubType == "Radial" || sSubType == "Diametral") {
ON_Plane onPlane(ConvertPoint( frDim.Orig()), ConvertVector( frDim.VersX()), ConvertVector( frDim.VersY())) ;
ON_DimRadial* onDimRadial( new ON_DimRadial()) ;
ON_3dPoint onPtV = ConvertPoint( pExtDim->GetStart()) ;
ON_3dPoint onPtPos = ConvertPoint( pExtDim->GetEnd()) ;
//ON_3dPoint onPtDim = ConvertPoint( pExtDim->GetPosition()) ;
Vector3d vtDir = pExtDim->GetDirVersor() ;
ON_3dPoint onPtDim = onPtPos + ConvertVector( vtDir) * ( onPtPos - onPtV).Length() / 10. ; // allontano la misura dall'arco di un decimo del raggio
double dRot = 0 ;
if ( ! AreSameVectorApprox( vtDir, X_AX))
X_AX.GetAngleXY(vtDir, dRot) ;
if ( sSubType == "Radial")
onDimRadial->Create( ON::AnnotationType::Radius, onIdDim, onPlane, onPtV, onPtPos, onPtDim) ;
else if ( sSubType == "Diametral")
onDimRadial->Create( ON::AnnotationType::Diameter, onIdDim, onPlane, onPtV, onPtPos, onPtDim) ;
return onDimRadial ;
}
else if ( sSubType == "Angular") {
ON_Plane onPlane(ConvertPoint( frDim.Orig()), ConvertVector( frDim.VersX()), ConvertVector( frDim.VersY())) ;
ON_DimAngular* onDimAngular( new ON_DimAngular()) ;
ON_3dPoint onPtV = ConvertPoint( pExtDim->GetStart()) ;
ON_3dPoint onPt1 = ConvertPoint( pExtDim->GetOverStart()) ;
ON_3dPoint onPt2 = ConvertPoint( pExtDim->GetOverEnd()) ;
ON_3dPoint onPtDim = ConvertPoint( pExtDim->GetPosition()) ;
Vector3d vtDir = pExtDim->GetDirVersor() ;
double dRot = 0 ;
if ( ! AreSameVectorApprox( vtDir, X_AX))
X_AX.GetAngleXY(vtDir, dRot) ;
// per arco
//onDimAngular->Create( onIdDim, onPlane, ConvertVector( frDim.VersX()), onPtV, onPt1, onPt2, onPtDim) ;
// con linee prolungate fino al vertice
onDimAngular->Create( onIdDim, onPlane, ConvertVector( frDim.VersX()), onPtV, onPtV, onPt1, onPt2, onPtDim) ;
return onDimAngular ;
}
return nullptr ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ExportDimension( const string& sName, const IGdbIterator& iIter, const Frame3d& frFrame, const Color& cCol, const int& nLayer)
{
// recupero l'oggetto geometrico
const IGeoObj* pGeoObj = iIter.GetGeoObj() ;
if ( pGeoObj == nullptr)
return false ;
// verifico oggetto
PtrOwner<IExtDimension> pExtDim( GetExtDimension( pGeoObj->Clone())) ;
if ( IsNull( pExtDim) || ! pExtDim->IsValid())
return false ;
// lo porto nel frame globale
pExtDim->ToGlob( frFrame) ;
return AddObjectToModel( iIter, ConvertExtDimension( pExtDim, frFrame), nLayer, sName, cCol) ;
}
//----------------------------------------------------------------------------
bool
Export3dm::ScanGroup( const IGdbIterator& iIter, const int& nLayer, bool& bEmpty)
{
// creo un iteratore
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( iIter.GetGDB())) ;
if ( IsNull( pIter))
return false ;
// scandisco il gruppo
bool bOk = true ;
int nCount = 0 ;
for ( bool bNext = pIter->GoToFirstInGroup( iIter) ;
bNext ;
bNext = pIter->GoToNext()) {
bool bAdded = false ;
if ( ! ExportObject( *pIter, nLayer, bAdded))
bOk = false ;
else if ( bAdded)
++ nCount ;
}
if ( nCount == 0)
bEmpty = true ;
return bOk ;
}