G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsWriteOpenNurbs.hpp
1 
16 
17 #include <gsCore/gsTemplateTools.h>
18 
19 #include <gsCore/gsMultiPatch.h>
21 
22 #include <gsNurbs/gsBSplineBasis.h>
23 #include <gsNurbs/gsKnotVector.h>
24 #include <gsUtils/gsMesh/gsMesh.h>
25 
26 #include <onurbs/opennurbs.h>
27 
28 #include <sstream>
29 #include <string>
30 #include <fstream>
31 #include <iomanip>
32 
33 
34 namespace gismo {
35 
36 namespace extensions {
37 
38 void writeON_Init(ONX_Model & model)
39 {
40  ON::Begin();
41  // If you want to learn to write b-rep models, first work through
42  // this example paying close attention to write_trimmed_surface_example(),
43  // then examime example_brep.cpp.
44 
45  // set revision history information
46  model.m_properties.m_RevisionHistory.NewRevision();
47 
48  // set application information
49  model.m_properties.m_Application.m_application_name = "OpenNURBS write_curves_example() function";
50  model.m_properties.m_Application.m_application_URL = "http://www.opennurbs.org";
51  model.m_properties.m_Application.m_application_details = "Example program in OpenNURBS toolkit.";
52 
53  // some notes
54  model.m_properties.m_Notes.m_notes = "This file was made with the OpenNURBS write_curves_example() function.";
55  model.m_properties.m_Notes.m_bVisible = true;
56 
57 
58  // file settings (units, tolerances, views, ...)
59  model.m_settings.m_ModelUnitsAndTolerances.m_unit_system = ON::inches;
60  model.m_settings.m_ModelUnitsAndTolerances.m_absolute_tolerance = 0.001;
61  model.m_settings.m_ModelUnitsAndTolerances.m_angle_tolerance = ON_PI/180.0; // radians
62  model.m_settings.m_ModelUnitsAndTolerances.m_relative_tolerance = 0.01; // 1%
63 
64 
65 /* ON_Layer layer;
66  layer.SetLayerName("Default");
67  layer.SetVisible(true);
68  layer.SetLocked(false);
69  layer.SetColor( ON_Color(0,0,0) );
70  model.m_layer_table.Append(layer);
71 */
72 }
73 
74 bool writeON_Write3dm(ONX_Model & model, const std::string & fname)
75 {
76  const char* filename = fname.c_str();
77 
78  // errors printed to stdout
79  ON_TextLog error_log;
80 
81  // messages printed to stdout
82  ON_TextLog message_log;
83 
84  // errors logged in text file
85  //FILE* error_log_fp = ON::OpenFile("error_log.txt","w");
86  //ON_TextLog error_log(error_log_fp);
87 
88  // The OpenNURBS toolkit will write version 2 and 3 and read
89  // version 1, 2 and 3 of the 3DM file format.
90  //
91  // version 1 is the legacy Rhino I/O tookit format and was used by Rhino 1.x.
92  // version 2 is the OpenNURBS format (released 1 July 2000) and is used by Rhino 2.x
93  // version 3 is the OpenNURBS format (released 1 November 2002) and is used by Rhino 3.x
94  // version 4 is the OpenNURBS format (released September 2006) and is used by Rhino 4.x
95  // version 5 is the OpenNURBS format (released September 2009) and is used by Rhino 5.x
96 
97  // version to write
98  int version = 0; // version will be ON_BinaryArchive::CurrentArchiveVersion()
99 
100  FILE* fp = ON::OpenFile( filename, "wb" );
101  ON_BinaryFile archive( ON::write3dm, fp ); // fp = pointer from fopoen(...,"wb")
102  // start section comment
103  const char* sStartSectionComment = __FILE__ "write_points_example()" __DATE__;
104  // Set uuid's, indices, etc.
105  model.Polish();
106  // writes model to archive
107  bool ok = model.Write(archive, version, sStartSectionComment, &error_log );
108 
109  ON::CloseFile( fp );
110  if (ok)
111  message_log.Print("Successfully wrote %s.\n",filename);
112  else
113  message_log.Print("Errors while writing %s.\n",filename);
114 
115  ON::End();
116 
117  return true;
118 }
119 
120 
122 template<class T>
123 bool writeON_NurbsCurve( const gsCurve<T> & curve, ONX_Model & model, const std::string & name)
124 {
125  // write a wiggly cubic curve on the "green NURBS wiggle" layer
126  ON_NurbsCurve* wiggle = new ON_NurbsCurve(
127  3, // dimension
128  false, // true if rational
129  curve.degree()+1, // order = degree+1
130  curve.coefsSize() // number of control vertices
131  );
132 
133  for (int k = 0; k < wiggle->CVCount(); k++ )
134  {
135  ON_3dPoint pt( cast<T,double>(curve.coef(k,0)), cast<T,double>(curve.coef(k,1)), 0.0 ); // pt = some 3d point
136  wiggle->SetCV( k, pt );
137  }
138 
139  const gsKnotVector<T> & kv =
140  dynamic_cast<const gsBSplineBasis<T>&>( curve.basis() ).knots();
141 
142  // ON_NurbsCurve's have order+cv_count-2 knots.
143  for (size_t k = 1; k < kv.size()-1; k++ )
144  {
145  wiggle->SetKnot(k-1, cast<T,double>(kv[k]) );
146  }
147 
148  ON_TextLog log;
149  if ( wiggle->IsValid(&log) )
150  {
151  ONX_Model_Object& mo = model.m_object_table.AppendNew();
152  mo.m_object = wiggle;
153  mo.m_bDeleteObject = true;
154  mo.m_attributes.m_layer_index = 0;
155  mo.m_attributes.m_name = name.c_str();
156  //mo.m_attributes.m_uuid = ON_UUID();
157  }
158  else
159  delete wiggle;
160 
161  return true;
162 }
163 
165 template<class T>
166 bool writeON_NurbsSurface( const gsSurface<T> & surface,
167  ONX_Model & model, const std::string & name)
168 {
169  ON_NurbsSurface* onsurf = new ON_NurbsSurface(
170  3, // dimension
171  false, // true if rational
172  surface.basis().degree(0)+1, // order u
173  surface.basis().degree(1)+1, // order v
174  surface.basis().component(0).size(), // number of control vertices in u
175  surface.basis().component(1).size() // number of control vertices in v
176  );
177 
178  int c = 0;
179  bool fs = (surface.geoDim()<3?false:true);
180  for ( int j = 0; j < onsurf->CVCount(1); j++ )
181  for ( int i = 0; i < onsurf->CVCount(0); i++ )
182  {
183  ON_3dPoint pt(cast<T,double>(surface.coef(c,0)), cast<T,double>(surface.coef(c,1)), (fs? cast<T,double>(surface.coef(c,2)) : 0.0) );
184  //ON_3dPoint pt( surface.coef(c,0), surface.coef(c,1), 0 );
185  onsurf->SetCV( i, j, pt );//Note: j runs faster than i for CP(i,j)
186  c++;
187  }
188 
189  const gsKnotVector<T> & kv1 =
190  dynamic_cast<const gsBSplineBasis<T>&>( surface.basis().component(0) ).knots();
191  const gsKnotVector<T> & kv2 =
192  dynamic_cast<const gsBSplineBasis<T>&>( surface.basis().component(1) ).knots();
193  //Note: ON_NurbsSurface's have order+cv_count-2 knots per direction.
194  for (size_t k = 1; k < kv1.size()-1; k++ )
195  onsurf->SetKnot(0, k-1, cast<T,double>(kv1[k]) );
196 
197  for (size_t k = 1; k < kv2.size()-1; k++ )
198  onsurf->SetKnot(1, k-1, cast<T,double>(kv2[k]) );
199 
200  ON_TextLog log;
201  if ( onsurf->IsValid(&log) )
202  {
203  ONX_Model_Object& mo = model.m_object_table.AppendNew();
204  mo.m_object = onsurf;
205  mo.m_bDeleteObject = true;
206  mo.m_attributes.m_layer_index = 0;
207  mo.m_attributes.m_name = name.c_str();
208  //mo.m_attributes.m_uuid = ON_UUID();
209  }
210  else
211  delete onsurf;
212 
213  return true;
214 }
215 
216 template<class T>
217 bool writeON_NurbsSurface( const gsSurface<T> & srf, const std::string & name)
218 {
219  ONX_Model model;
220  writeON_Init(model);
221  writeON_NurbsSurface(srf, model, "srf");
222  return writeON_Write3dm(model,name+".3dm");
223 }
224 
225 template<class T>
226 bool writeON_NurbsCurve( const gsCurve<T> & curve, const std::string & name)
227 {
228  ONX_Model model;
229  writeON_Init(model);
230  writeON_NurbsCurve(curve, model, "curve");
231  return writeON_Write3dm(model,name+".3dm");
232 }
233 
235 template<class T>
236 bool writeON_MultiPatch( const gsMultiPatch<T> & patches, const std::string & name)
237 {
238  ONX_Model model;
239  writeON_Init(model);
240 
241  for(size_t i = 0; i < patches.nPatches(); ++i)
242  {
243  //gsInfo<< "Write patch "<< i << "\n";
244  std::stringstream nm("patch");
245  nm << i ;
246 
247  if ( const gsCurve<T> * c = dynamic_cast<const gsCurve<T>*>(&patches.patch(i) ) )
248  {
249  writeON_NurbsCurve(*c, model, nm.str() );
250  }
251 
252  if ( const gsSurface<T> * c = dynamic_cast<const gsSurface<T>*>(&patches.patch(i) ) )
253  {
254  writeON_NurbsSurface(*c, model, nm.str() );
255  }
256  }
257 
258  return writeON_Write3dm(model,name+".3dm");
259 }
260 
262 template<class T>
263 bool writeON_PlanarDomain( const gsPlanarDomain<T> & pd, const std::string & name)
264 {
265  ONX_Model model;
266  writeON_Init(model);
267 
268  for(index_t i =0; i<pd.numLoops();i++)
269  for(index_t j =0; j< pd.loop(i).numCurves() ; j++)
270  {
271  const gsCurve<T> & c = pd.loop(i).curve(j);
272  gsInfo<< "Write loop "<< i <<", curve "<<j<<"\n";
273 
274  std::stringstream nm("curve");
275  nm << i <<"_"<<j;
276 
277  writeON_NurbsCurve(c, model, nm.str() );
278  }
279 
280  return writeON_Write3dm(model,name+".3dm");
281 }
282 
283 
285 template<class T>
286 bool writeON_Mesh(const gsMesh<T> & msh, const std::string & name)
287 {
288  ONX_Model model;
289  writeON_Init(model);
290 
291  const size_t nf = msh.numFaces();
292  const size_t nv = msh.numVertices();
293 
294  ON_Mesh* mesh = new ON_Mesh(nf, nv, true, false);
295 
296  for (size_t i = 0; i < nv; i++)
297  {
298  const gsVertex<T> & v = msh.vertex(i);
299  mesh->SetVertex(i, ON_3fPoint(cast<T,double>(v.x()), cast<T,double>(v.y()), cast<T,double>(v.z())) );
300  }
301 
302  gsVector<index_t> v;
303  for (size_t i = 0; i < nf; i++)
304  {
305  v = msh.faceIndices(i);
306  switch (v.size())
307  {
308  case 3:
309  mesh->SetTriangle(i, v[0], v[1], v[2]);
310  break;
311  case 4:
312  mesh->SetQuad(i, v[0], v[1], v[2], v[3]);
313  break;
314  default:
315  break;
316  }
317  }
318 
319  mesh->ComputeVertexNormals();
320  mesh->Compact();
321 
322  ON_TextLog log;
323  if ( mesh->IsValid(&log) )
324  {
325  ONX_Model_Object& mo = model.m_object_table.AppendNew();
326  mo.m_object = mesh;
327  mo.m_bDeleteObject = true;
328  mo.m_attributes.m_layer_index = 0;
329  mo.m_attributes.m_name = name.c_str();
330  //mo.m_attributes.m_uuid = ON_UUID();
331  }
332  else
333  delete mesh;
334 
335  return writeON_Write3dm(model,name+".3dm");
336 }
337 
338 }// namespace extensions
339 
340 }// namespace gismo
Knot vector for B-splines.
Provides declaration of functions that write 3DM file format.
#define index_t
Definition: gsConfig.h:32
EIGEN_STRONG_INLINE onormal_expr< T > nv(const gsGeometryMap< T > &u)
The (outer pointing) boundary normal of a geometry map.
Definition: gsExpressions.h:4508
Provides declaration of BSplineBasis class.
Provides declaration of the MultiPatch class.
#define gsInfo
Definition: gsDebug.h:43
Provides declaration of the Mesh class.
Utilities related to template programming.
Provides declaration of gsPlanarDomain class. The outer boundary (m_loops[0]) is a loop of curves...