Developer Documentation
PrimitivesGenerator.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 #include <cstdlib>
44 
45 #include "PrimitivesGenerator.hh"
46 #include <OpenFlipper/BasePlugin/WhatsThisGenerator.hh>
47 
48 #ifdef ENABLE_POLYHEDRALMESH_SUPPORT
49 #include "TetrahedralCuboidGenerator.hh"
50 #endif
51 
52 #ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
54 #endif
55 
56 #ifdef ENABLE_BSPLINECURVE_SUPPORT
58 #endif
59 
60 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
62 #endif
63 
64 PrimitivesGeneratorPlugin::PrimitivesGeneratorPlugin() :
65  triMesh_(0),
66  polyMesh_(0),
67  slices_(50),
68  stacks_(50),
69  primitivesMenu_(0)
70 {
71 
72 }
73 
74 PrimitivesGeneratorPlugin::~PrimitivesGeneratorPlugin()
75 {
76 
77  if ( OpenFlipper::Options::gui()) {
78  delete primitivesMenu_;
79  }
80 
81 }
82 
84 {
85  emit setSlotDescription("addCube(Vector,double)",
86  tr("Generates a poly mesh of cube (ObjectId is returned)"),
87  QString("Position,Length").split(","),
88  QString("Center position,Length of each edge").split(","));
89 
90  emit setSlotDescription("addTetrahedron(Vector,double)",
91  tr("Generates a tetrahedron (ObjectId is returned)"),
92  QString("Position,Length").split(","),
93  QString("Center position,Length of each edge").split(","));
94 
95  emit setSlotDescription("addIcosahedron(Vector,double)",
96  tr("Generates an icosahedron (ObjectId is returned)"),
97  QString("Position,Length").split(","),
98  QString("Center position,Length of each edge").split(","));
99 
100  emit setSlotDescription("addPyramid(Vector,double)",
101  tr("Generates a pyramid (ObjectId is returned)"),
102  QString("Position,Length").split(","),
103  QString("Center position,Length of each edge").split(","));
104 
105  emit setSlotDescription("addOctahedron(Vector,double)",
106  tr("Generates an octahedron (ObjectId is returned)"),
107  QString("Position,Length").split(","),
108  QString("Center position,Length of each edge").split(","));
109 
110  emit setSlotDescription("addDodecahedron(Vector,double)",
111  tr("Generates a dodecahedron (ObjectId is returned)"),
112  QString("Position,Length").split(","),
113  QString("Center position,Length of each edge").split(","));
114 
115  emit setSlotDescription("addSphere(Vector,double)",
116  tr("Generates a triangulated sphere with all vertical lines connected to the poles (ObjectId is returned)"),
117  QString("Position, Radius").split(","),
118  QString("Center position,Radius").split(","));
119 
120  emit setSlotDescription("addSubdivisionSphere(Vector,double)",
121  tr("Generates a triangulated sphere by subdivision without poles. (ObjectId is returned)"),
122  QString("Position, Radius").split(","),
123  QString("Center position,Radius").split(","));
124 
125  emit setSlotDescription("addTriangulatedCube(Vector,double)",
126  tr("Generates a triangular mesh of cube (ObjectId is returned)"),
127  QString("Position,Length").split(","),
128  QString("Center position,Length of each edge").split(","));
129 
130  emit setSlotDescription("addTriangulatedCylinder(Vector,Vector,double,double)",
131  tr("Generates a triangulated cylinder (ObjectId is returned)") ,
132  QString("Position,Axis,Radius,Height,Top,Bottom").split(","),
133  QString("Bottom center vertex position,Center axis,radius,height,add top vertex,add bottom vertex").split(","));
134 
135 #ifdef ENABLE_BSPLINECURVE_SUPPORT
136  emit setSlotDescription("addRandomBSplineCurve(Vector,int)",
137  tr("Generates a random B-spline curve (ObjectId is returned)"),
138  QString("Position,Count").split(","),
139  QString("Center position,Number of control points").split(","));
140 #endif
141 
142 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
143  emit setSlotDescription("addRandomBSplineSurface(Vector,int)",
144  tr("Generates a random B-spline surface (ObjectId is returned)"),
145  QString("Position,Count").split(","),
146  QString("Center position,Number of control points").split(","));
147 #endif
148 
149 #ifdef ENABLE_POLYHEDRALMESH_SUPPORT
150  emit setSlotDescription("addTetrahedralCube(Vector,double)",
151  tr("Generates a tetrahedral mesh of a cube (ObjectId is returned)"),
152  QString("Position,Length").split(","),
153  QString("Center position,Length of each edge").split(","));
154 
155  emit setSlotDescription("addTetrahedralCuboid(Vector,Vector,uint,uint,uint)",
156  tr("Generates a tetrahedral mesh of a cuboid (ObjectId is returned)"),
157  QString("Position,Lengths,Count,Count,Count").split(","),
158  QString("Center position,Length of each side,Number of units in x-axis,Number of units in y-axis,Number of units in z-axis").split(","));
159 #endif
160 #ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
161  emit setSlotDescription("addHexahedralCube(Vector,double)",
162  tr("Generates a hexahedral mesh of a cube (ObjectId is returned)"),
163  QString("Position,Length").split(","),
164  QString("Center position,Length of each edge").split(","));
165 #endif
166 
167 }
168 
169 void PrimitivesGeneratorPlugin::pluginsInitialized() {
170 
171  if ( OpenFlipper::Options::gui()) {
172 
173  emit getMenubarMenu(tr("&Primitives"), primitivesMenu_, true );
174 
175  WhatsThisGenerator whatsThisGen("PrimitivesGenerator");
176  QAction* action;
177 
178  action = primitivesMenu_->addAction("Cube (Poly Mesh)" ,this,SLOT(addCube()));
179  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_cube.png"));
180  whatsThisGen.setWhatsThis(action,tr("Create a Cube."),"Cube");
181 
182  action = primitivesMenu_->addAction("Cube (Triangle Mesh)" ,this,SLOT(addTriangulatedCube()));
183  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_cube.png"));
184  whatsThisGen.setWhatsThis(action,tr("Create a Cube."),"Cube");
185 
186  action = primitivesMenu_->addAction("Dodecahedron" ,this,SLOT(addDodecahedron()));
187  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_dodecahedron.png"));
188  whatsThisGen.setWhatsThis(action,tr("Create a Dodecahedron."), "Dodecahedron");
189 
190  action = primitivesMenu_->addAction("Icosahedron" ,this,SLOT(addIcosahedron()));
191  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_icosahedron.png"));
192  whatsThisGen.setWhatsThis(action,tr("Create a Icosahedron.","Icosahedron"));
193 
194  action = primitivesMenu_->addAction("Octahedron" ,this,SLOT(addOctahedron()));
195  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_octahedron.png"));
196  whatsThisGen.setWhatsThis(action,tr("Create an Octahedron."),"Octahedron");
197 
198  action = primitivesMenu_->addAction("Pyramid" ,this,SLOT(addPyramid()));
199  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_pyramid.png"));
200  whatsThisGen.setWhatsThis(action,tr("Create a Pyramid."),"Pyramid");
201 
202  action = primitivesMenu_->addAction("Cylinder (Triangle Mesh)" ,this,SLOT(addTriangulatedCylinder()));
203  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_cylinder.png"));
204 
205  action = primitivesMenu_->addAction("Sphere (Poles,Triangle Mesh)",this,SLOT(addSphere()));
206  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_sphere.png"));
207  whatsThisGen.setWhatsThis(action,tr("Create a Sphere. All vertical lines connect to poles) "),"Sphere");
208 
209  action = primitivesMenu_->addAction("Sphere (Subdivision,Triangle Mesh)",this,SLOT(addSubdivisionSphere()));
210  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_sphere.png"));
211  whatsThisGen.setWhatsThis(action,tr("Create a Sphere. No poles due to Subdivision) "),"Sphere");
212 
213  action = primitivesMenu_->addAction("Tetrahedron",this,SLOT(addTetrahedron()));
214  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_tetrahedron.png"));
215  whatsThisGen.setWhatsThis(action,tr("Create a Tetrahedron."),"Tetrahedron");
216 
217 #ifdef ENABLE_BSPLINECURVE_SUPPORT
218  action = primitivesMenu_->addAction("Random B-spline curve",this,SLOT(addRandomBSplineCurve()));
219  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator() + "bspline_curve.png"));
220  whatsThisGen.setWhatsThis(action, tr("Create a random B-spline curve."), "B-spline curve");
221 #endif
222 
223 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
224  action = primitivesMenu_->addAction("Random B-spline surface",this,SLOT(addRandomBSplineSurface()));
225  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"bspline_surface.png"));
226  whatsThisGen.setWhatsThis(action,tr("Create a random B-spline surface."),"B-spline surface");
227 #endif
228 
229 #ifdef ENABLE_POLYHEDRALMESH_SUPPORT
230  action = primitivesMenu_->addAction("Cube (Tetrahedral Mesh)" ,this,SLOT(addTetrahedralCube()));
231  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_cube.png"));
232  whatsThisGen.setWhatsThis(action,tr("Create a Tetrahedral Cube."), "Cube");
233 
234  action = primitivesMenu_->addAction("Cuboid (Tetrahedral Mesh)" ,this,SLOT(addTetrahedralCuboid()));
235  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_cube.png"));
236  whatsThisGen.setWhatsThis(action,tr("Create a Tetrahedral Cuboid."), "Cuboid");
237 #endif
238 
239 #ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
240  action = primitivesMenu_->addAction("Cube (Hexahedral Mesh)" ,this,SLOT(addHexahedralCube()));
241  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_cube.png"));
242  whatsThisGen.setWhatsThis(action,tr("Create a Hexahedral Cube."), "Cube");
243 
244 #endif
245 
246  action = primitivesMenu_->addAction("Plane (Triangle Mesh)" ,this,SLOT(addTriangulatedPlaneFlat()));
247  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_plane_flat.png"));
248  whatsThisGen.setWhatsThis(action,tr("Create a flat simple plane."),"Plane");
249 
250  action = primitivesMenu_->addAction("Plane, bumpy (Triangle Mesh)" ,this,SLOT(addTriangulatedPlaneBumpy()));
251  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_plane_bumpy.png"));
252  whatsThisGen.setWhatsThis(action,tr("Create a bumpy plane."),"Plane");
253 
254  action = primitivesMenu_->addAction("Perpendicular planes Non-Manifold (Triangle Mesh)" ,this,SLOT(addTriangulatedPlanesNonManifold()));
255  action->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"primitive_plane_non-manifold.png"));
256  whatsThisGen.setWhatsThis(action,tr("Create a non manifold plane configuration."),"Plane");
257 
258  }
259 }
260 
261 
262 int PrimitivesGeneratorPlugin::addTriMesh() {
263  int objectId = -1;
264 
265  emit addEmptyObject( DATA_TRIANGLE_MESH, objectId );
266 
267  TriMeshObject* object;
268  if ( !PluginFunctions::getObject(objectId,object) ) {
269  emit log(LOGERR,"Unable to create new Object");
270  return -1;
271  }
272 
273  return objectId;
274 }
275 
276 int PrimitivesGeneratorPlugin::addPolyMesh() {
277  int objectId = -1;
278 
279  emit addEmptyObject( DATA_POLY_MESH, objectId );
280 
281  PolyMeshObject* object;
282  if ( !PluginFunctions::getObject(objectId,object) ) {
283  emit log(LOGERR,"Unable to create new Object");
284  return -1;
285  }
286 
287  return objectId;
288 }
289 
290 
291 #ifdef ENABLE_POLYHEDRALMESH_SUPPORT
292 int PrimitivesGeneratorPlugin::addPolyhedralMesh() {
293  int objectId = -1;
294 
295  emit addEmptyObject( DATA_POLYHEDRAL_MESH, objectId );
296 
297  PolyhedralMeshObject* object;
298  if (!PluginFunctions::getObject(objectId, object) ) {
299  emit log(LOGERR, "Unable to create new PolyhedralMesh object");
300  return -1;
301  }
302 
303  return objectId;
304 }
305 #endif
306 
307 
308 int PrimitivesGeneratorPlugin::addTetrahedron(const Vector& _position, const double _length) {
309 
310  int newObject = addTriMesh();
311 
312  TriMeshObject* object;
313  if ( !PluginFunctions::getObject(newObject,object) ) {
314  emit log(LOGERR,"Unable to create new Object");
315  return -1;
316  } else {
317 
318  object->setName( "Tetrahedron " + QString::number(newObject) );
319 
320  triMesh_ = object->mesh();
321 
322  triMesh_->clear();
323 
324  // Add 4 vertices
325  vhandles_.resize(4);
326 
327  const double halfSize = 0.5*_length;
328 
329  vhandles_[0] = triMesh_->add_vertex(TriMesh::Point(-halfSize, -halfSize, halfSize)+_position);
330  vhandles_[1] = triMesh_->add_vertex(TriMesh::Point( halfSize, halfSize, halfSize)+_position);
331  vhandles_[2] = triMesh_->add_vertex(TriMesh::Point(-halfSize, halfSize, -halfSize)+_position);
332  vhandles_[3] = triMesh_->add_vertex(TriMesh::Point( halfSize, -halfSize, -halfSize)+_position);
333 
334  // Add 4 faces
335  add_face(0,1,2);
336  add_face(0,2,3);
337  add_face(2,1,3);
338  add_face(3,1,0);
339 
340  triMesh_->update_normals();
341 
342  emit updatedObject(newObject,UPDATE_ALL);
343  emit createBackup(newObject, "Original Object");
344 
346 
347  return newObject;
348  }
349 
350  return -1;
351 }
352 
353 
354 int PrimitivesGeneratorPlugin::addTriangulatedPlaneFlat(const Vector& _position ,
355  const double _sizeX , const double _sizeY ,
356  const int _segmentsX , const int _segmentsY )
357 {
358  int newObject = addTriMesh();
359 
360  TriMeshObject* object;
361  if ( !PluginFunctions::getObject(newObject,object) ) {
362  emit log(LOGERR,"Unable to create new Object");
363  return -1;
364  } else {
365 
366  object->setName( "Cube " + QString::number(newObject) );
367 
368  triMesh_ = object->mesh();
369  triMesh_->clear();
370 
371  vhandles_.resize( (_segmentsX+1) * (_segmentsY+1) );
372 
373  for (auto i = 0 ; i < (_segmentsX + 1) ; ++i) {
374  for (auto j = 0 ; j < (_segmentsY + 1) ; ++j) {
375  vhandles_[ i * (_segmentsY + 1) + j ] = triMesh_->add_vertex(TriMesh::Point( _sizeX / _segmentsX * i , _sizeY / _segmentsY * j ,0)+_position);
376  }
377  }
378 
379  for (auto i = 0 ; i < _segmentsX ; ++i) {
380  for (auto j = 0 ; j < _segmentsY ; ++j) {
381  add_face(i * (_segmentsY+1) + j, (i + 1) * (_segmentsY+1) + j, i * (_segmentsY+1) + j + 1);
382  add_face(i * (_segmentsY+1) + j + 1, (i + 1) * (_segmentsY+1) + j, (i + 1) * (_segmentsY+1) + j + 1);
383  }
384  }
385 
386 
387  triMesh_->update_normals();
388 
389  emit updatedObject(newObject,UPDATE_ALL);
390  emit createBackup(newObject, "Original Object");
391 
393 
394  return newObject;
395  }
396 
397  return -1;
398 }
399 
400 int PrimitivesGeneratorPlugin::addTriangulatedPlaneBumpy(const Vector& _position ,
401  const double _sizeX , const double _sizeY ,
402  const int _segmentsX , const int _segmentsY )
403 {
404  int newObject = addTriMesh();
405 
406  TriMeshObject* object;
407  if ( !PluginFunctions::getObject(newObject,object) ) {
408  emit log(LOGERR,"Unable to create new Object");
409  return -1;
410  } else {
411 
412  object->setName( "Cube " + QString::number(newObject) );
413 
414  triMesh_ = object->mesh();
415  triMesh_->clear();
416 
417  vhandles_.resize( (_segmentsX+1) * (_segmentsY+1) );
418 
419  for (auto i = 0 ; i < (_segmentsX + 1) ; ++i) {
420  for (auto j = 0 ; j < (_segmentsY + 1) ; ++j) {
421 
422 
423  const double x = _sizeX / _segmentsX * i - _sizeX / 2.0;
424  const double y = _sizeY / _segmentsY * j - _sizeY / 2.0;
425  const double z = sin( x * x) * cos( y * y) ;
426  vhandles_[ i * (_segmentsY + 1) + j ] = triMesh_->add_vertex(TriMesh::Point( x , y , z ) +_position);
427  }
428  }
429 
430  for (auto i = 0 ; i < _segmentsX ; ++i) {
431  for (auto j = 0 ; j < _segmentsY ; ++j) {
432  add_face(i * (_segmentsY+1) + j, (i + 1) * (_segmentsY+1) + j, i * (_segmentsY+1) + j + 1);
433  add_face(i * (_segmentsY+1) + j + 1, (i + 1) * (_segmentsY+1) + j, (i + 1) * (_segmentsY+1) + j + 1);
434  }
435  }
436 
437 
438  triMesh_->update_normals();
439 
440  emit updatedObject(newObject,UPDATE_ALL);
441  emit createBackup(newObject, "Original Object");
442 
444 
445  return newObject;
446  }
447 
448  return -1;
449 }
450 
451 
452 int PrimitivesGeneratorPlugin::addTriangulatedPlanesNonManifold(const Vector& _position ,
453  const double _sizeX , const double _sizeY , const double _sizeZ ,
454  const int _segmentsX , const int _segmentsY , const int _segmentsZ )
455 {
456  int newObject = addTriMesh();
457 
458  TriMeshObject* object;
459  if ( !PluginFunctions::getObject(newObject,object) ) {
460  emit log(LOGERR,"Unable to create new Object");
461  return -1;
462  } else {
463 
464  object->setName( "Cube " + QString::number(newObject) );
465 
466  triMesh_ = object->mesh();
467  triMesh_->clear();
468 
469  vhandles_.resize( (_segmentsX+1) * (_segmentsY+1) );
470 
471  // Adding the flat manifold component
472  for (auto i = 0 ; i < (_segmentsX + 1) ; ++i) {
473  for (auto j = 0 ; j < (_segmentsY + 1) ; ++j) {
474  vhandles_[ i * (_segmentsY + 1) + j ] = triMesh_->add_vertex(TriMesh::Point( _sizeX / _segmentsX * i , _sizeY / _segmentsY * j ,0)+_position);
475  }
476  }
477 
478  for (auto i = 0 ; i < _segmentsX ; ++i) {
479  for (auto j = 0 ; j < _segmentsY ; ++j) {
480  add_face(i * (_segmentsY+1) + j, (i + 1) * (_segmentsY+1) + j, i * (_segmentsY+1) + j + 1);
481  add_face(i * (_segmentsY+1) + j + 1, (i + 1) * (_segmentsY+1) + j, (i + 1) * (_segmentsY+1) + j + 1);
482  }
483  }
484 
485  vhandles_.clear();
486  vhandles_.resize( (_segmentsX+1) * (_segmentsY+1) );
487 
488 
489  // Adding the perpendicular component
490  for (auto j = 0 ; j < (_segmentsY + 1) ; ++j) {
491  for (auto k = 0 ; k < (_segmentsZ + 1) ; ++k) {
492  vhandles_[ j * (_segmentsY + 1) + k ] = triMesh_->add_vertex(TriMesh::Point(_sizeX / 2, _sizeY / _segmentsY * j , _sizeZ / _segmentsZ * k )+_position);
493  }
494  }
495 
496  const int offset = (_segmentsX+1) * (_segmentsY+1);
497 
498  for (auto i = 0 ; i < _segmentsY ; ++i) {
499  for (auto j = 0 ; j < _segmentsZ ; ++j) {
500  add_face(offset + i * (_segmentsZ+1) + j, offset + (i + 1) * (_segmentsZ+1) + j, offset + i * (_segmentsZ+1) + j + 1);
501  add_face(offset + i * (_segmentsZ+1) + j + 1, offset + (i + 1) * (_segmentsZ+1) + j, offset + (i + 1) * (_segmentsZ+1) + j + 1);
502  }
503  }
504 
505  triMesh_->update_normals();
506 
507  emit updatedObject(newObject,UPDATE_ALL);
508  emit createBackup(newObject, "Original Object");
509 
511 
512  return newObject;
513  }
514 
515  return -1;
516 }
517 
518 
519 int PrimitivesGeneratorPlugin::addTriangulatedCube(const Vector& _position,const double _length) {
520  int newObject = addTriMesh();
521 
522  TriMeshObject* object;
523  if ( !PluginFunctions::getObject(newObject,object) ) {
524  emit log(LOGERR,"Unable to create new Object");
525  return -1;
526  } else {
527 
528  object->setName( "Cube " + QString::number(newObject) );
529 
530  triMesh_ = object->mesh();
531 
532  triMesh_->clear();
533 
534  // Add 8 vertices
535  vhandles_.resize(8);
536 
537  const double halfSize = 0.5*_length;
538 
539  vhandles_[0] = triMesh_->add_vertex(TriMesh::Point( halfSize, -halfSize, halfSize)+_position);
540  vhandles_[1] = triMesh_->add_vertex(TriMesh::Point( halfSize, halfSize, halfSize)+_position);
541  vhandles_[2] = triMesh_->add_vertex(TriMesh::Point(-halfSize, halfSize, halfSize)+_position);
542  vhandles_[3] = triMesh_->add_vertex(TriMesh::Point(-halfSize, -halfSize, halfSize)+_position);
543  vhandles_[4] = triMesh_->add_vertex(TriMesh::Point( halfSize, -halfSize,-halfSize)+_position);
544  vhandles_[5] = triMesh_->add_vertex(TriMesh::Point( halfSize, halfSize,-halfSize)+_position);
545  vhandles_[6] = triMesh_->add_vertex(TriMesh::Point(-halfSize, halfSize,-halfSize)+_position);
546  vhandles_[7] = triMesh_->add_vertex(TriMesh::Point(-halfSize, -halfSize,-halfSize)+_position);
547 
548 
549  // Add 12 faces
550  add_face(0,1,2);
551  add_face(0,2,3);
552  add_face(0,5,1);
553  add_face(5,0,4);
554  add_face(4,0,7);
555  add_face(7,0,3);
556 
557  add_face(7,3,6);
558  add_face(6,3,2);
559  add_face(6,2,5);
560  add_face(5,2,1);
561  add_face(6,5,4);
562  add_face(6,4,7);
563 
564  triMesh_->update_normals();
565 
566  emit updatedObject(newObject,UPDATE_ALL);
567  emit createBackup(newObject, "Original Object");
568 
570 
571  return newObject;
572  }
573 
574  return -1;
575 }
576 
577 int PrimitivesGeneratorPlugin::addCube(const Vector& _position,const double _length) {
578  int newObject = addPolyMesh();
579 
580  PolyMeshObject* object;
581  if ( !PluginFunctions::getObject(newObject,object) ) {
582  emit log(LOGERR,"Unable to create new Object");
583  return -1;
584  } else {
585 
586  object->setName( "Cube " + QString::number(newObject) );
587 
588  polyMesh_ = object->mesh();
589  polyMesh_->clear();
590 
591  // Add 8 vertices
592  vhandles_.resize(8);
593 
594  const double halfSize = 0.5*_length;
595  // 6------5
596  // /| /|
597  // 2------1 |
598  // | | | |
599  // | 7----|-4
600  // |/ |/
601  // 3------0
602  vhandles_[0] = polyMesh_->add_vertex(PolyMesh::Point( halfSize, -halfSize, halfSize)+_position);
603  vhandles_[1] = polyMesh_->add_vertex(PolyMesh::Point( halfSize, halfSize, halfSize)+_position);
604  vhandles_[2] = polyMesh_->add_vertex(PolyMesh::Point(-halfSize, halfSize, halfSize)+_position);
605  vhandles_[3] = polyMesh_->add_vertex(PolyMesh::Point(-halfSize, -halfSize, halfSize)+_position);
606  vhandles_[4] = polyMesh_->add_vertex(PolyMesh::Point( halfSize, -halfSize,-halfSize)+_position);
607  vhandles_[5] = polyMesh_->add_vertex(PolyMesh::Point( halfSize, halfSize,-halfSize)+_position);
608  vhandles_[6] = polyMesh_->add_vertex(PolyMesh::Point(-halfSize, halfSize,-halfSize)+_position);
609  vhandles_[7] = polyMesh_->add_vertex(PolyMesh::Point(-halfSize, -halfSize,-halfSize)+_position);
610 
611  // Add faces
612  add_face(0,1,2,3);
613  add_face(0,4,5,1);
614  add_face(4,7,6,5);
615  add_face(7,3,2,6);
616  add_face(1,5,6,2);
617  add_face(0,3,7,4);
618 
619  polyMesh_->update_normals();
620 
621  emit updatedObject(newObject,UPDATE_ALL);
622  emit createBackup(newObject, "Original Object");
623 
625 
626  return newObject;
627  }
628 
629  return -1;
630 }
631 
632 //========================================================================
633 // Tetrahedral cube
634 //========================================================================
635 
636 #ifdef ENABLE_POLYHEDRALMESH_SUPPORT
637 
638 int PrimitivesGeneratorPlugin::addTetrahedralCube(const Vector& _position, const double _length)
639 {
640  return addTetrahedralCuboid(_position, Vector(_length, _length, _length), 1, 1, 1);
641 }
642 
643 #endif
644 
645 //========================================================================
646 // Tetrahedral Cuboid
647 //========================================================================
648 
649 #ifdef ENABLE_POLYHEDRALMESH_SUPPORT
650 
651 int PrimitivesGeneratorPlugin::addTetrahedralCuboid(const Vector& _position,
652  const Vector& _length, const unsigned int n_x, const unsigned int n_y, const unsigned int n_z)
653 {
654 
655  int object_id = addPolyhedralMesh();
656  PolyhedralMeshObject* object;
657 
658  if (!PluginFunctions::getObject(object_id, object)) {
659  return -1;
660  }
661 
662  object->setName("Cuboid " + QString::number(object_id));
663 
664  TetrahedralCuboidGenerator gen(*(object->mesh()), _position, _length, n_x, n_y, n_z);
665 
666  emit updatedObject(object_id, UPDATE_ALL);
667  emit createBackup(object_id, "Original Object");
668 
669  object->setObjectDrawMode(ACG::SceneGraph::DrawModes::getDrawMode("Cells (flat shaded)"));
671 
672  return object_id;
673 }
674 
675 #endif
676 
677 //========================================================================
678 // Hexahedral Cube & Cuboid
679 //========================================================================
680 
681 #ifdef ENABLE_HEXAHEDRALMESH_SUPPORT
682 
683 int PrimitivesGeneratorPlugin::addHexahedralCube(const Vector& _position, const double _length)
684 {
685  int object_id;
686  emit addEmptyObject( DATA_HEXAHEDRAL_MESH, object_id);
687 
688  HexahedralMeshObject* object;
689  if (!PluginFunctions::getObject(object_id, object) ) {
690  emit log(LOGERR, "Unable to create new HexahedralMesh object");
691  return -1;
692  }
693  object->setName( "HexCube " + QString::number(object_id) );
694 
695  auto mesh = object->mesh();
696  namespace OVM = OpenVolumeMesh;
697  std::vector<OVM::VertexHandle> vertices(8);
698 
699  const double halfSize = 0.5*_length;
700  vertices[0] = mesh->add_vertex(Vector(-halfSize, -halfSize, halfSize)+_position);
701  vertices[1] = mesh->add_vertex(Vector( halfSize, -halfSize, halfSize)+_position);
702  vertices[2] = mesh->add_vertex(Vector( halfSize, halfSize, halfSize)+_position);
703  vertices[3] = mesh->add_vertex(Vector(-halfSize, halfSize, halfSize)+_position);
704  vertices[4] = mesh->add_vertex(Vector(-halfSize, -halfSize,-halfSize)+_position);
705  vertices[5] = mesh->add_vertex(Vector(-halfSize, halfSize,-halfSize)+_position);
706  vertices[6] = mesh->add_vertex(Vector( halfSize, halfSize,-halfSize)+_position);
707  vertices[7] = mesh->add_vertex(Vector( halfSize, -halfSize,-halfSize)+_position);
708 
709  mesh->add_cell(vertices);
710 
711  emit updatedObject(object_id, UPDATE_ALL);
712  emit createBackup(object_id, "Original Object");
713 
714  object->setObjectDrawMode(ACG::SceneGraph::DrawModes::getDrawMode("Cells (flat shaded)"));
715 
717 
718  return object_id;
719 }
720 
721 #endif
722 
723 //========================================================================
724 // Cylinder
725 //========================================================================
726 
727 
728 ACG::Vec3d PrimitivesGeneratorPlugin::positionOnCylinder(const int _sliceNumber,
729  const int _stackNumber,
730  const Vector _position,
731  const Vector _axis,
732  const double _radius,
733  const double _height)
734 {
735  ACG::Vec3d position;
736 
737  const ACG::Vec3d right = (ACG::Geometry::perpendicular(_axis)).normalized();
738  const ACG::Vec3d left = (cross( _axis, right)).normalized();
739 
740  double beta = ((2.0 * M_PI) / double(slices_)) * double(_sliceNumber);
741 
742  if ( _sliceNumber == 0 && _stackNumber == 0) {
743  position[0] = 0.0;
744  position[1] = 0.0;
745  position[2] = _height;
746  } else if ( _sliceNumber == slices_ && _stackNumber == stacks_ ) {
747  position[0] = 0.0;
748  position[1] = 0.0;
749  position[2] = 0.0;
750  } else {
751  position[0] = sin(beta) * _radius;
752  position[1] = cos(beta) * _radius;
753  position[2] = _height * double(stacks_ - _stackNumber -1 ) / double(stacks_-2);
754  }
755 
756  position = _position + position[0] * right + position[1] * left + position[2] * _axis ;
757 
758  return position;
759 }
760 
761 int PrimitivesGeneratorPlugin::addTriangulatedCylinder(const Vector& _position,const Vector& _axis,const double _radius,const double _height,const bool _top,const bool _bottom ) {
762 
763  // TODO: Generate texture coordinates for cylinder (Glu compatible)
764  int newObject = addTriMesh();
765 
766  TriMeshObject* object;
767  if (!PluginFunctions::getObject(newObject, object)) {
768  emit log(LOGERR, "Unable to create new Object");
769  return -1;
770  } else {
771 
772  object->setName( "Cylinder " + QString::number(newObject) );
773 
774  triMesh_ = object->mesh();
775 
776  triMesh_->clear();
777 
778  //triMesh_->request_vertex_texcoords2D();
779 
780  TriMesh::VertexHandle vh;
781  TriMesh::VertexHandle top = triMesh_->add_vertex(positionOnCylinder(0, 0,_position,_axis,_radius,_height));
782  //triMesh_->set_texcoord2D(vh, texCoordOnSphere(0, 0));
783 
784  for (int st = 1; st < stacks_; ++st) {
785  for (int sl = 0; sl < slices_; ++sl) {
786  vh = triMesh_->add_vertex(positionOnCylinder(sl, st,_position,_axis,_radius,_height));
787  //triMesh_->set_texcoord2D(vh, texCoordOnSphere(sl, st));
788  }
789  }
790 
791  TriMesh::VertexHandle bottom = triMesh_->add_vertex(positionOnCylinder(slices_, stacks_,_position,_axis,_radius,_height));
792  //triMesh_->set_texcoord2D(vh, texCoordOnSphere(slices_, stacks_));
793 
794  std::vector<TriMesh::VertexHandle> vhandles;
795 
796  // Add top triangle fan ( Vertex index is shifted by one for the first slice )
797  if ( _top ) {
798  for (int sl = 1; sl < slices_ + 1; ++sl) {
799 
800  vhandles.clear();
801 
802  vhandles.push_back(triMesh_->vertex_handle(sl));
803  vhandles.push_back(triMesh_->vertex_handle(0));
804  vhandles.push_back(triMesh_->vertex_handle(1 * 1 + (sl % slices_)));
805 
806  triMesh_->add_face(vhandles);
807  }
808  } else {
809  triMesh_->delete_vertex(top);
810  }
811 
812  for (int st = 0; st < stacks_ - 2; ++st) {
813 
814  // Move around one slice
815  for (int sl = 0; sl < slices_; ++sl) {
816 
817  // Offset 1 because of singular vertex
818  unsigned int startTop = 1 + slices_ * st;
819  unsigned int startBottom = 1 + slices_ * (st + 1);
820 
821  vhandles.clear();
822 
823  vhandles.push_back(triMesh_->vertex_handle(startTop + sl));
824  vhandles.push_back(triMesh_->vertex_handle(startTop + ((sl + 1) % slices_)));
825  vhandles.push_back(triMesh_->vertex_handle(startBottom + sl));
826 
827  triMesh_->add_face(vhandles);
828 
829  vhandles.clear();
830 
831  vhandles.push_back(triMesh_->vertex_handle(startBottom + sl));
832  vhandles.push_back(triMesh_->vertex_handle(startTop + ((sl + 1) % slices_)));
833  vhandles.push_back(triMesh_->vertex_handle(startBottom + ((sl + 1) % slices_)));
834 
835  triMesh_->add_face(vhandles);
836  }
837 
838  }
839 
840  const int startTop = 1 + (stacks_ - 2) * slices_;
841  const int bottomVertex = 1 + (stacks_ - 1) * slices_;
842 
843  // Add bottom triangle fan
844  if ( _bottom) {
845  for (int sl = 0; sl < slices_; ++sl) {
846 
847  vhandles.clear();
848 
849  vhandles.push_back(triMesh_->vertex_handle(bottomVertex));
850  vhandles.push_back(triMesh_->vertex_handle(startTop + sl));
851  vhandles.push_back(triMesh_->vertex_handle(startTop + ((sl + 1) % slices_)));
852 
853  triMesh_->add_face(vhandles);
854  }
855  } else {
856  triMesh_->delete_vertex(bottom);
857  }
858 
859  // Cleanup if bottom or top vertex is missing
860  triMesh_->garbage_collection();
861 
862  triMesh_->update_normals();
863 
864  emit updatedObject(newObject,UPDATE_ALL);
865  emit createBackup(newObject, "Original Object");
866 
868 
869  return object->id();
870  }
871 
872 }
873 
874 
875 //========================================================================
876 // Sphere
877 //========================================================================
878 
879 
880 ACG::Vec3d PrimitivesGeneratorPlugin::positionOnSphere(int _sliceNumber, int _stackNumber, double _radius, const Vector& _position)
881 {
882  ACG::Vec3d position;
883 
884  double alpha = (M_PI / double(stacks_)) * double(_stackNumber);
885  double beta = ((2.0 * M_PI) / double(slices_)) * double(_sliceNumber);
886 
887  double ringRadius = sin(alpha);
888  position[0] = sin(beta) * ringRadius * _radius;
889  position[1] = cos(beta) * ringRadius * _radius;
890  position[2] = cos(alpha)* _radius;
891 
892  return _position+position;
893 }
894 
895 //------------------------------------------------------------------------
896 
897 ACG::Vec2f PrimitivesGeneratorPlugin::texCoordOnSphere(int _sliceNumber, int _stackNumber)
898 {
899  ACG::Vec2f texCoord;
900 
901  double alpha = (M_PI / double(stacks_)) * double(_stackNumber);
902  texCoord[0] = double(_sliceNumber) / double(slices_);
903  texCoord[1] = 0.5 * (cos(alpha) + 1.0);
904 
905  return texCoord;
906 }
907 
908 
909 //------------------------------------------------------------------------
910 
911 int PrimitivesGeneratorPlugin::addSphere(const Vector& _position, const double _radius)
912 {
913  int newObject = addTriMesh();
914 
915  TriMeshObject* object;
916  if (!PluginFunctions::getObject(newObject, object)) {
917  emit log(LOGERR, "Unable to create new Object");
918  return -1;
919  } else {
920 
921  object->setName( "Sphere " + QString::number(newObject) );
922 
923  triMesh_ = object->mesh();
924 
925  triMesh_->clear();
926 
927  triMesh_->request_vertex_texcoords2D();
928 
929  TriMesh::VertexHandle vh;
930 
931  vh = triMesh_->add_vertex(positionOnSphere(0, 0, _radius,_position));
932  triMesh_->set_texcoord2D(vh, texCoordOnSphere(0, 0));
933 
934  for (int st = 1; st < stacks_; ++st) {
935  for (int sl = 0; sl < slices_; ++sl) {
936  vh = triMesh_->add_vertex(positionOnSphere(sl, st, _radius,_position));
937  triMesh_->set_texcoord2D(vh, texCoordOnSphere(sl, st));
938  }
939  }
940 
941  vh = triMesh_->add_vertex(positionOnSphere(slices_, stacks_, _radius,_position));
942  triMesh_->set_texcoord2D(vh, texCoordOnSphere(slices_, stacks_));
943 
944  std::vector<TriMesh::VertexHandle> vhandles;
945 
946  // Add top triangle fan ( Vertex index is shifted by one for the first slice )
947  for (int sl = 1; sl < slices_ + 1; ++sl) {
948 
949  vhandles.clear();
950 
951  vhandles.push_back(triMesh_->vertex_handle(sl));
952  vhandles.push_back(triMesh_->vertex_handle(0));
953  vhandles.push_back(triMesh_->vertex_handle(1 * 1 + (sl % slices_)));
954 
955  triMesh_->add_face(vhandles);
956  }
957 
958  for (int st = 0; st < stacks_ - 2; ++st) {
959 
960  // Move around one slice
961  for (int sl = 0; sl < slices_; ++sl) {
962 
963  // Offset 1 because of singular vertex
964  unsigned int startTop = 1 + slices_ * st;
965  unsigned int startBottom = 1 + slices_ * (st + 1);
966 
967  vhandles.clear();
968 
969  vhandles.push_back(triMesh_->vertex_handle(startTop + sl));
970  vhandles.push_back(triMesh_->vertex_handle(startTop + ((sl + 1) % slices_)));
971  vhandles.push_back(triMesh_->vertex_handle(startBottom + sl));
972 
973  triMesh_->add_face(vhandles);
974 
975  vhandles.clear();
976 
977  vhandles.push_back(triMesh_->vertex_handle(startBottom + sl));
978  vhandles.push_back(triMesh_->vertex_handle(startTop + ((sl + 1) % slices_)));
979  vhandles.push_back(triMesh_->vertex_handle(startBottom + ((sl + 1) % slices_)));
980 
981  triMesh_->add_face(vhandles);
982  }
983 
984  }
985 
986  const int startTop = 1 + (stacks_ - 2) * slices_;
987  const int bottomVertex = 1 + (stacks_ - 1) * slices_;
988 
989  // Add bottom triangle fan
990  for (int sl = 0; sl < slices_; ++sl) {
991 
992  vhandles.clear();
993 
994  vhandles.push_back(triMesh_->vertex_handle(bottomVertex));
995  vhandles.push_back(triMesh_->vertex_handle(startTop + sl));
996  vhandles.push_back(triMesh_->vertex_handle(startTop + ((sl + 1) % slices_)));
997 
998  triMesh_->add_face(vhandles);
999  }
1000 
1001  triMesh_->update_normals();
1002 
1003  emit updatedObject(newObject,UPDATE_ALL);
1004  emit createBackup(newObject, "Original Object");
1005 
1007 
1008  return object->id();
1009  }
1010 
1011 
1012 }
1013 
1014 //------------------------------------------------------------------------
1015 
1016 int PrimitivesGeneratorPlugin::addSubdivisionSphere(const Vector& _position, const double _radius)
1017 {
1018 
1019  // Create the underlying octahedron
1020  int newObject = addTriMesh();
1021 
1022  TriMeshObject* object;
1023  if (!PluginFunctions::getObject(newObject, object)) {
1024  emit log(LOGERR, "Unable to create new Object");
1025  return -1;
1026  } else {
1027  object->setName( "Sphere " + QString::number(newObject) );
1028 
1029  triMesh_ = object->mesh();
1030  constructOctahedron(_position, _radius);
1031 
1032  // Number of subdivision iterations for the sphere
1033  const size_t subdivisionSteps = 4;
1034 
1035  for (size_t i = 0 ; i < subdivisionSteps; ++i) {
1036 
1037  // Call the subdivision algorithm
1038  RPC::callFunction("subdivider", "subdivide", newObject, QString("loop"), 1, false);
1039 
1040  // Reposition vertices onto sphere
1041  for (TriMesh::VertexIter v_it = triMesh_->vertices_begin(); v_it != triMesh_->vertices_end(); ++v_it) {
1042  TriMesh::Point p = triMesh_->point(*v_it);
1043  p -= _position;
1044  p = _radius * p.normalize() + _position;
1045  triMesh_->set_point(*v_it, p);
1046  }
1047  }
1048 
1049  // Make sure that the normals are fine
1050  triMesh_->update_normals();
1051 
1052  emit updatedObject(newObject, UPDATE_ALL);
1053  emit createBackup(newObject, "Original Object");
1054 
1056 
1057  return newObject;
1058 
1059  }
1060 
1061 
1062 }
1063 
1064 
1065 //========================================================================
1066 // Pyramid
1067 //========================================================================
1068 
1069 int PrimitivesGeneratorPlugin::addPyramid(const Vector& _position,const double _length) {
1070  int newObject = addTriMesh();
1071 
1072  TriMeshObject* object;
1073  if ( !PluginFunctions::getObject(newObject,object) ) {
1074  emit log(LOGERR,"Unable to create new Object");
1075  return -1;
1076  } else {
1077 
1078  object->setName( "Pyramid " + QString::number(newObject) );
1079 
1080  triMesh_ = object->mesh();
1081 
1082  triMesh_->clear();
1083 
1084  // Add 5 vertices
1085  vhandles_.resize(5);
1086 
1087  const double halfLength = 0.5*_length;
1088 
1089  vhandles_[0] = triMesh_->add_vertex(TriMesh::Point( halfLength, -halfLength, 0.0)+_position);
1090  vhandles_[1] = triMesh_->add_vertex(TriMesh::Point( halfLength, halfLength, 0.0)+_position);
1091  vhandles_[2] = triMesh_->add_vertex(TriMesh::Point(-halfLength, halfLength, 0.0)+_position);
1092  vhandles_[3] = triMesh_->add_vertex(TriMesh::Point(-halfLength, -halfLength, 0.0)+_position);
1093 
1094  vhandles_[4] = triMesh_->add_vertex(TriMesh::Point(0.0, 0.0, sqrt(2.0)*halfLength));
1095 
1096  // Add 6 faces
1097  add_face(2,1,0);
1098  add_face(3,2,0);
1099  add_face(4,0,1);
1100 
1101  add_face(3,0,4);
1102  add_face(4,2,3);
1103  add_face(1,2,4);
1104 
1105  triMesh_->update_normals();
1106 
1107  emit updatedObject(newObject,UPDATE_ALL);
1108  emit createBackup(newObject, "Original Object");
1109 
1111 
1112  return newObject;
1113  }
1114 
1115  return -1;
1116 }
1117 
1118 void PrimitivesGeneratorPlugin::add_face(int _vh1 , int _vh2, int _vh3) {
1119  triMesh_->add_face(
1120  static_cast<TriMesh::VertexHandle>(_vh1),
1121  static_cast<TriMesh::VertexHandle>(_vh2),
1122  static_cast<TriMesh::VertexHandle>(_vh3)
1123  );
1124 }
1125 
1126 void PrimitivesGeneratorPlugin::add_face(int _vh1, int _vh2, int _vh3, int _vh4)
1127 {
1128  polyMesh_->add_face(
1129  static_cast<PolyMesh::VertexHandle>(_vh1),
1130  static_cast<PolyMesh::VertexHandle>(_vh2),
1131  static_cast<PolyMesh::VertexHandle>(_vh3),
1132  static_cast<PolyMesh::VertexHandle>(_vh4)
1133  );
1134 }
1135 
1136 void PrimitivesGeneratorPlugin::add_face( int _vh1 , int _vh2, int _vh3, int _vh4 , int _vh5 ) {
1137  std::vector<PolyMesh::VertexHandle> vhandles;
1138 
1139  vhandles.push_back(vphandles_[_vh1]);
1140  vhandles.push_back(vphandles_[_vh2]);
1141  vhandles.push_back(vphandles_[_vh3]);
1142  vhandles.push_back(vphandles_[_vh4]);
1143  vhandles.push_back(vphandles_[_vh5]);
1144 
1145  polyMesh_->add_face(vhandles);
1146 }
1147 
1148 int PrimitivesGeneratorPlugin::addIcosahedron(const Vector& _position,const double _length) {
1149  int newObject = addTriMesh();
1150 
1151  TriMeshObject* object;
1152  if ( !PluginFunctions::getObject(newObject,object) ) {
1153  emit log(LOGERR,"Unable to create new Object");
1154  return -1;
1155  } else {
1156 
1157  object->setName( "Icosahedron " + QString::number(newObject) );
1158 
1159  triMesh_ = object->mesh();
1160 
1161  triMesh_->clear();
1162 
1163  // Add 12 vertices
1164  vhandles_.resize(12);
1165 
1166  const double phi = 0.5 * (1.0 + sqrt(5.0));
1167  //double norm = 1.0 / sqrt(1.0 + phi*phi);
1168  const double norm = 1.0;
1169  const double halfLength = 0.5*_length;
1170 
1171  vhandles_[0 ] = triMesh_->add_vertex(norm * TriMesh::Point( 0.0 , -halfLength , -phi )+_position);
1172  vhandles_[1 ] = triMesh_->add_vertex(norm * TriMesh::Point( 0.0 , halfLength , -phi )+_position);
1173  vhandles_[2 ] = triMesh_->add_vertex(norm * TriMesh::Point( 0.0 , halfLength , phi )+_position);
1174  vhandles_[3 ] = triMesh_->add_vertex(norm * TriMesh::Point( 0.0 , -halfLength , phi )+_position);
1175 
1176  vhandles_[4 ] = triMesh_->add_vertex(norm * TriMesh::Point( -halfLength , -phi , 0.0 )+_position);
1177  vhandles_[5 ] = triMesh_->add_vertex(norm * TriMesh::Point( halfLength , -phi , 0.0 )+_position);
1178  vhandles_[6 ] = triMesh_->add_vertex(norm * TriMesh::Point( halfLength , phi , 0.0 )+_position);
1179  vhandles_[7 ] = triMesh_->add_vertex(norm * TriMesh::Point( -halfLength , phi , 0.0 )+_position);
1180 
1181  vhandles_[8 ] = triMesh_->add_vertex(norm * TriMesh::Point( -phi , 0.0 , -halfLength )+_position);
1182  vhandles_[9 ] = triMesh_->add_vertex(norm * TriMesh::Point( -phi , 0.0 , halfLength )+_position);
1183  vhandles_[10] = triMesh_->add_vertex(norm * TriMesh::Point( phi , 0.0 , halfLength )+_position);
1184  vhandles_[11] = triMesh_->add_vertex(norm * TriMesh::Point( phi , 0.0 , -halfLength )+_position);
1185 
1186 
1187  // Add 20 faces
1188  add_face(2,6,7);
1189  add_face(7,6,1);
1190 
1191  add_face(11,0,1);
1192  add_face(0, 8,1);
1193 
1194  add_face(4,9,8);
1195  add_face(8,9,7);
1196 
1197  add_face(9,3,2);
1198  add_face(10,2,3);
1199 
1200  add_face(5,11,10);
1201  add_face(11,6,10);
1202 
1203  add_face(0,5,4);
1204  add_face(5,3,4);
1205 
1206  // Upper block
1207  add_face(6,2,10);
1208  add_face(6,11,1);
1209  add_face(1,8,7);
1210  add_face(9,2,7);
1211 
1212  // Lower block
1213  add_face(3,5,10);
1214  add_face(0,11,5);
1215  add_face(3,9,4);
1216  add_face(0,4,8);
1217 
1218  triMesh_->update_normals();
1219 
1220  emit updatedObject(newObject,UPDATE_ALL);
1221  emit createBackup(newObject, "Original Object");
1222 
1224 
1225  return newObject;
1226  }
1227 
1228  return -1;
1229 }
1230 
1231 void PrimitivesGeneratorPlugin::constructOctahedron(const Vector& _position, const double _length)
1232 {
1233  triMesh_->clear();
1234 
1235  // Add 6 vertices
1236  vhandles_.resize(6);
1237 
1238  const double sqrtLength = sqrt(_length);
1239 
1240  vhandles_[0 ] = triMesh_->add_vertex(TriMesh::Point(-sqrtLength, 0.0, 0.0)+_position);
1241  vhandles_[1 ] = triMesh_->add_vertex(TriMesh::Point( 0.0, -sqrtLength, 0.0)+_position);
1242  vhandles_[2 ] = triMesh_->add_vertex(TriMesh::Point( sqrtLength, 0.0, 0.0)+_position);
1243  vhandles_[3 ] = triMesh_->add_vertex(TriMesh::Point( 0.0, sqrtLength, 0.0)+_position);
1244 
1245  vhandles_[4 ] = triMesh_->add_vertex(TriMesh::Point( 0.0, 0.0, sqrtLength)+_position);
1246  vhandles_[5 ] = triMesh_->add_vertex(TriMesh::Point( 0.0, 0.0, -sqrtLength)+_position);
1247 
1248 
1249  // Add 8 faces
1250  add_face(0,1,4);
1251  add_face(1,2,4);
1252 
1253  add_face(2,3,4);
1254  add_face(0,4,3);
1255 
1256  add_face(5,1,0);
1257  add_face(5,2,1);
1258 
1259  add_face(5,3,2);
1260  add_face(5,0,3);
1261 
1262  triMesh_->update_normals();
1263 }
1264 
1265 int PrimitivesGeneratorPlugin::addOctahedron(const Vector& _position,const double _length) {
1266  int newObject = addTriMesh();
1267 
1268  TriMeshObject* object;
1269  if ( !PluginFunctions::getObject(newObject,object) ) {
1270  emit log(LOGERR,"Unable to create new Object");
1271  return -1;
1272  } else {
1273 
1274  object->setName( "Octahedron " + QString::number(newObject) );
1275 
1276  triMesh_ = object->mesh();
1277 
1278  constructOctahedron(_position, _length);
1279 
1280  emit updatedObject(newObject,UPDATE_ALL);
1281  emit createBackup(newObject, "Original Object");
1282 
1284 
1285  return newObject;
1286  }
1287 
1288  return -1;
1289 }
1290 
1291 int PrimitivesGeneratorPlugin::addDodecahedron(const Vector& _position,const double _length) {
1292  int newObject = addPolyMesh();
1293 
1294  PolyMeshObject* object;
1295  if ( !PluginFunctions::getObject(newObject,object) ) {
1296  emit log(LOGERR,"Unable to create new Object");
1297  return -1;
1298  } else {
1299 
1300  object->setName( "Dodecahedron " + QString::number(newObject) );
1301 
1302  polyMesh_ = object->mesh();
1303 
1304  polyMesh_->clear();
1305 
1306  // Add 20 vertices
1307  vphandles_.resize(20);
1308 
1309  const double phi = (1.0 + sqrt(5.0)) / 2.0;
1310  const double halfLength = 0.5*_length;
1311 
1312 
1313  vphandles_[0 ] = polyMesh_->add_vertex(TriMesh::Point( halfLength , halfLength , halfLength )+_position);
1314  vphandles_[1 ] = polyMesh_->add_vertex(TriMesh::Point( halfLength , halfLength ,-halfLength )+_position);
1315  vphandles_[2 ] = polyMesh_->add_vertex(TriMesh::Point( halfLength , -halfLength , halfLength )+_position);
1316  vphandles_[3 ] = polyMesh_->add_vertex(TriMesh::Point( halfLength , -halfLength ,-halfLength )+_position);
1317  vphandles_[4 ] = polyMesh_->add_vertex(TriMesh::Point( -halfLength , halfLength , halfLength )+_position);
1318  vphandles_[5 ] = polyMesh_->add_vertex(TriMesh::Point( -halfLength , halfLength ,-halfLength )+_position);
1319  vphandles_[6 ] = polyMesh_->add_vertex(TriMesh::Point( -halfLength , -halfLength , halfLength )+_position);
1320  vphandles_[7 ] = polyMesh_->add_vertex(TriMesh::Point( -halfLength , -halfLength ,-halfLength )+_position);
1321 
1322  vphandles_[8 ] = polyMesh_->add_vertex(TriMesh::Point( 0.0 , halfLength / phi , phi )+_position);
1323  vphandles_[9 ] = polyMesh_->add_vertex(TriMesh::Point( 0.0 , halfLength / phi , -phi )+_position);
1324  vphandles_[10] = polyMesh_->add_vertex(TriMesh::Point( 0.0 , -halfLength / phi , phi )+_position);
1325  vphandles_[11] = polyMesh_->add_vertex(TriMesh::Point( 0.0 , -halfLength / phi , -phi )+_position);
1326 
1327  vphandles_[12] = polyMesh_->add_vertex(TriMesh::Point( halfLength / phi , phi, 0.0)+_position);
1328  vphandles_[13] = polyMesh_->add_vertex(TriMesh::Point( halfLength / phi , -phi, 0.0)+_position);
1329  vphandles_[14] = polyMesh_->add_vertex(TriMesh::Point( -halfLength / phi , phi, 0.0)+_position);
1330  vphandles_[15] = polyMesh_->add_vertex(TriMesh::Point( -halfLength / phi , -phi, 0.0)+_position);
1331 
1332  vphandles_[16] = polyMesh_->add_vertex(TriMesh::Point( phi , 0.0 , halfLength / phi)+_position);
1333  vphandles_[17] = polyMesh_->add_vertex(TriMesh::Point( phi , 0.0 ,-halfLength / phi)+_position);
1334  vphandles_[18] = polyMesh_->add_vertex(TriMesh::Point( -phi , 0.0 , halfLength / phi)+_position);
1335  vphandles_[19] = polyMesh_->add_vertex(TriMesh::Point( -phi , 0.0 ,-halfLength / phi)+_position);
1336 
1337  // Add 12 faces
1338  add_face(14, 5,19,18, 4);
1339  add_face( 5, 9,11, 7,19);
1340  add_face( 6,15,13, 2,10);
1341  add_face(12, 0,16,17, 1);
1342 
1343  add_face( 0, 8,10, 2,16);
1344  add_face(16, 2,13, 3,17);
1345  add_face( 3,13,15, 7,11);
1346  add_face( 7,15, 6,18,19);
1347 
1348  add_face( 4,18, 6,10, 8);
1349  add_face( 4, 8, 0,12,14);
1350  add_face(14,12, 1, 9, 5);
1351  add_face( 9, 1,17, 3,11);
1352 
1353  polyMesh_->update_normals();
1354 
1355  emit updatedObject(newObject,UPDATE_ALL);
1356  emit createBackup(newObject, "Original Object");
1357 
1359 
1360  return newObject;
1361  }
1362 
1363  return -1;
1364 }
1365 
1366 #ifdef ENABLE_BSPLINECURVE_SUPPORT
1367 int PrimitivesGeneratorPlugin::addRandomBSplineCurve(const Vector& _position, int nDiv)
1368 {
1369  int id = -1;
1370  emit addEmptyObject(DATA_BSPLINE_CURVE, id);
1371  if (id == -1) {
1372  return -1;
1373  }
1374 
1375  BSplineCurveObject *object = NULL;
1376  if (!PluginFunctions::getObject(id, object)) {
1377  return -1;
1378  }
1379 
1380  BSplineCurve *curve = object->splineCurve();
1381 
1382  curve->autocompute_knotvector(true);
1383  for (int i = 0; i < nDiv; ++i) {
1384  double x = _position[0] + i - nDiv / 2.0;
1385 
1386  double r = (2.0 * std::rand()) / RAND_MAX - 1.0;
1387  BSplineCurve::Point cp(x, _position[1] + r, _position[2]);
1388  curve->add_control_point(cp);
1389  }
1390 
1391  emit updatedObject(id, UPDATE_ALL);
1392  emit createBackup(id, "Original Object");
1393 
1395 
1396  return id;
1397 }
1398 #endif
1399 
1400 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
1401 int PrimitivesGeneratorPlugin::addRandomBSplineSurface(const Vector& _position, int nDiv)
1402 {
1403  int id = -1;
1404  emit addEmptyObject(DATA_BSPLINE_SURFACE, id);
1405  if (id == -1) {
1406  return -1;
1407  }
1408 
1409  BSplineSurfaceObject *object = NULL;
1410  if (!PluginFunctions::getObject(id, object)) {
1411  return -1;
1412  }
1413 
1414  BSplineSurface *surf = object->splineSurface();
1415  typedef BSplineSurface::Point Point;
1416  std::vector<Point> cp(nDiv);
1417 
1418  for (int i = 0; i < nDiv; ++i) {
1419  double x = _position[0] + i - nDiv / 2.0;
1420  for (int j = 0; j < nDiv; ++j) {
1421  double y = _position[1] + j - nDiv / 2.0;
1422  cp[j] = Point(x, y, _position[2] + (2.0 * std::rand()) / RAND_MAX - 1);
1423  }
1424  surf->add_vector_m(cp);
1425  }
1426  surf->createKnots();
1427 
1428  emit updatedObject(id, UPDATE_ALL);
1429  emit createBackup(id, "Original Object");
1430 
1432 
1433  return id;
1434 }
1435 #endif
1436 
a class which provides an link generator for WhatsThisMessages linking to the user doc If you have an...
void initializePlugin()
BaseInterface.
#define DATA_POLYHEDRAL_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:65
void add_control_point(const Point &_cp)
add a control point
QScriptValue callFunction(QString _plugin, QString _functionName, std::vector< QScriptValue > _parameters)
Call a function provided by a plugin getting multiple parameters.
Definition: RPCWrappers.cc:55
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
#define DATA_HEXAHEDRAL_MESH
void createKnots()
Creates interpolating knotvectors 0...0, 1, 2, ..., n...n.
void add_vector_m(const std::vector< Point > &_control_polygon)
Adds a control point n-vector.
ACG::Vec3d Vector
Standard Type for 3d Vector used for scripting.
Definition: DataTypes.hh:176
#define DATA_BSPLINE_SURFACE
const DrawMode & getDrawMode(const std::string &_name)
Get a custom DrawMode.
Definition: DrawModes.cc:799
#define DATA_BSPLINE_CURVE
Definition: BSplineCurve.hh:67
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
SmartVertexHandle add_vertex(const Point &_p)
Definition: PolyMeshT.hh:245
MeshT * mesh()
return a pointer to the mesh
void setWhatsThis(QAction *_action, const QString &_msg, const QString &_ref="", const QString &_site="index.html") const
sets a whatsThis Message plus link to the doc for the given QAction
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:453
VectorT< Scalar, 3 > perpendicular(const VectorT< Scalar, 3 > &v)
find a vector that&#39;s perpendicular to _v
Definition: Algorithms.cc:1152
void viewAll(int _viewer)
View the whole scene.
void setName(QString _name)
Set the name of the Object.