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
64PrimitivesGeneratorPlugin::PrimitivesGeneratorPlugin() :
65 triMesh_(0),
66 polyMesh_(0),
67 slices_(50),
68 stacks_(50),
69 primitivesMenu_(0)
70{
71
72}
73
74PrimitivesGeneratorPlugin::~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
169void 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
262int 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
276int 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
292int 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
308int 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
354int 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
400int 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
452int 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
519int 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
577int 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
638int 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
651int 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
683int 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
728ACG::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
761int 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
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
880ACG::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
897ACG::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
911int 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
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
1016int 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 (auto v_it : triMesh_->vertices()) {
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
1069int 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
1118void 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
1126void 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
1136void 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
1148int 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
1231void 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
1265int 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
1291int 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
1367int 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
1401int 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
#define DATA_BSPLINE_CURVE
Definition: BSplineCurve.hh:67
#define DATA_BSPLINE_SURFACE
ACG::Vec3d Vector
Standard Type for 3d Vector used for scripting.
Definition: DataTypes.hh:176
@ LOGERR
#define DATA_HEXAHEDRAL_MESH
#define DATA_POLYHEDRAL_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
void add_control_point(const Point &_cp)
add a control point
void add_vector_m(const std::vector< Point > &_control_polygon)
Adds a control point n-vector.
void createKnots()
Creates interpolating knotvectors 0...0, 1, 2, ..., n...n.
void setName(QString _name)
Set the name of the Object.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
SmartVertexHandle add_vertex(const Point _p)
Definition: PolyMeshT.hh:255
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
Definition: Vector11T.hh:454
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:65
void initializePlugin()
BaseInterface.
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
MeshT * mesh()
return a pointer to the mesh
a class which provides an link generator for WhatsThisMessages linking to the user doc If you have an...
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
VectorT< Scalar, 3 > perpendicular(const VectorT< Scalar, 3 > &v)
find a vector that's perpendicular to _v
Definition: Algorithms.cc:1152
const DrawMode & getDrawMode(const std::string &_name)
Get a custom DrawMode.
Definition: DrawModes.cc:797
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
void viewAll(int _viewer)
View the whole scene.
void callFunction(QString _plugin, QString _functionName)
call a function in another plugin
Definition: RPCWrappers.cc:129