549f3d47bd
- aggiunto l'import per file 3dm.
468 lines
18 KiB
C++
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 ;
|
|
}
|