Changes :

- change types in the functions parameters
- make the tetrahedron based on the unit vectors
- add a function to create a pyramid
- add assertions to protect the numbers of vertices
- move the functions to BGL::helpers.h and add documentation
This commit is contained in:
Maxime Gimeno 2017-05-09 11:12:05 +02:00
parent 9d70c107b8
commit 3f72bfc8ba
5 changed files with 517 additions and 154 deletions

View File

@ -33,6 +33,10 @@ namespace CGAL {
template< typename Graph> template< typename Graph>
void fill_hole(typename boost::graph_traits<Graph>::halfedge_descriptor h, void fill_hole(typename boost::graph_traits<Graph>::halfedge_descriptor h,
Graph& g); Graph& g);
template<typename Graph , typename VertexRange >
typename boost::graph_traits<Graph>::face_descriptor add_face(const VertexRange& vr,
Graph& g);
} }
/*! /*!
@ -724,6 +728,265 @@ bool is_degenerate_triangle_face(
} }
/// \endcond /// \endcond
/**
* \ingroup PkgBGLHelperFct
* \brief Creates a regular prism.
*
* Creates a regular prism in `g`, having `nb_vertices` vertices in each of its bases.
* \param nb_vertices the number of vertices per base. It must be greater than or equals 3.
* \param g the graph in which the regular prism will be created
* \param center the point around which the regular prism will be created. It is the middle point of the prism's axis.
* \param height the distance between the two bases.
* \param radius the radius of the circle in which the bases are inscribed.
* \param is_closed determines if the bases must be created or not.
*/
template<class Graph, class P>
void make_regular_prism(
typename boost::graph_traits<Graph>::vertices_size_type nb_vertices,
Graph& g,
const P& center = P(0,0,0),
typename CGAL::Kernel_traits<P>::Kernel::FT height = 1.0,
typename CGAL::Kernel_traits<P>::Kernel::FT radius = 1.0,
bool is_closed = true)
{
CGAL_assertion(nb_vertices >= 3);
typedef typename boost::property_map<Graph,vertex_point_t>::type Point_property_map;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename CGAL::Kernel_traits<P>::Kernel::FT FT;
const FT to_rad = CGAL_PI / 180.0;
const FT precision = 360/nb_vertices;
const FT diameter = 2*radius;
Point_property_map vpmap = get(CGAL::vertex_point, g);
std::vector<vertex_descriptor> vertices;
vertices.resize(nb_vertices*2);
for(int i=0; i<nb_vertices*2; ++i)
vertices[i] = add_vertex(g);
//fill vertices
for(int i=0; i < nb_vertices; ++i)
{
put(vpmap,
vertices[i],
P(0.5*diameter*cos(i*precision*to_rad)+center.x(),
0.5*height+center.y(),
-0.5*diameter*sin(i*precision*to_rad) + center.z()));
put(vpmap,
vertices[i+nb_vertices],
P(0.5*diameter*cos(i*precision*to_rad)+center.x(),
-0.5*height+center.y(),
-0.5*diameter*sin(i*precision*to_rad)+center.z()));
}
std::vector<vertex_descriptor> face;
face.resize(3);
//fill faces
for(int i=0; i<nb_vertices; ++i)
{
face[0] = vertices[(i+1)%(nb_vertices)];
face[1] = vertices[i];
face[2] = vertices[(i+1)%(nb_vertices) + nb_vertices];
Euler::add_face(face, g);
face[0] = vertices[(i+1)%(nb_vertices) + nb_vertices];
face[1] = vertices[i];
face[2] = vertices[i + nb_vertices];
Euler::add_face(face, g);
}
//close
if(is_closed)
{
//add the center of the fans
vertex_descriptor top = add_vertex(g);
vertex_descriptor bot = add_vertex(g);
put(vpmap, top, P(center.x(),0.5*height+center.y(),center.z()));
put(vpmap, bot, P(center.x(),-0.5*height+center.y(),center.z()));
//add the faces
for(int i=0; i<nb_vertices; ++i)
{
face[0] = vertices[i];
face[1] = vertices[(i+1)%(nb_vertices)];
face[2] = top;
Euler::add_face(face, g);
face[0] = bot;
face[1] = vertices[(i+1)%(nb_vertices) + nb_vertices];
face[2] = vertices[i + nb_vertices];
Euler::add_face(face, g);
}
}
}
/**
* \ingroup PkgBGLHelperFct
* \brief Creates a pyramid.
*
* Creates a pyramid in `g`, having `nb_vertices` vertices in its base.
* \param nb_vertices the number of vertices in the base. It must be greater than or equals 3.
* \param g the graph in which the pyramid will be created
* \param base_center the center of the circle in which the base is inscribed.
* \param height the distance between the base and the apex.
* \param radius the radius of the circle in which the base is inscribed.
* \param is_closed determines if the base must be created or not.
*/
template<class Graph, class P>
void make_pyramid(
typename boost::graph_traits<Graph>::vertices_size_type nb_vertices,
Graph& g,
const P& base_center = P(0,0,0),
typename CGAL::Kernel_traits<P>::Kernel::FT height = 1.0,
typename CGAL::Kernel_traits<P>::Kernel::FT radius = 1.0,
bool is_closed = true)
{
CGAL_assertion(nb_vertices >= 3);
typedef typename boost::property_map<Graph,vertex_point_t>::type Point_property_map;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename CGAL::Kernel_traits<P>::Kernel::FT FT;
const FT to_rad = CGAL_PI / 180.0;
const FT precision = 360/nb_vertices;
const FT diameter = 2*radius;
Point_property_map vpmap = get(CGAL::vertex_point, g);
std::vector<vertex_descriptor> vertices;
vertices.resize(nb_vertices);
for(int i=0; i<nb_vertices; ++i)
vertices[i] = add_vertex(g);
vertex_descriptor apex = add_vertex(g);
//fill vertices
put(vpmap,
apex,
P(base_center.x(),
base_center.y() + height,
base_center.z()));
for(int i=0; i < nb_vertices; ++i)
{
put(vpmap,
vertices[i],
P(0.5*diameter*cos(i*precision*to_rad)+base_center.x(),
base_center.y(),
-0.5*diameter*sin(i*precision*to_rad)+base_center.z()));
}
std::vector<vertex_descriptor> face;
face.resize(3);
//fill faces
for(int i=0; i<nb_vertices; ++i)
{
face[0] = apex;
face[1] = vertices[i];
face[2] = vertices[(i+1)%(nb_vertices)];
Euler::add_face(face, g);
}
//close
if(is_closed)
{
//add the center of the fan
vertex_descriptor bot = add_vertex(g);
put(vpmap, bot, P(base_center.x(),base_center.y(),base_center.z()));
//add the faces
for(int i=0; i<nb_vertices; ++i)
{
face[0] = bot;
face[1] = vertices[(i+1)%(nb_vertices)];
face[2] = vertices[i];
Euler::add_face(face, g);
}
}
}
/**
* \ingroup PkgBGLHelperFct
* \brief Creates an icosahedron.
*
* Creates an icosahedron in `g` centered in `center`.
* \param g the graph in which the icosahedron will be created.
* \param center the center of the sphere in which the icosahedron is inscribed.
* \param radius the radius of the sphere in which the icosahedron is inscribed.
*/
template<class Graph, class P>
void make_icosahedron(
Graph& g,
const P& center = P(0,0,0),
typename CGAL::Kernel_traits<P>::Kernel::FT radius = 1.0)
{
typedef typename boost::property_map<Graph,vertex_point_t>::type Point_property_map;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Point_property_map vpmap = get(CGAL::vertex_point, g);
// create the initial icosahedron
std::vector<vertex_descriptor> v_vertices;
v_vertices.resize(12);
for(int i=0; i<12; ++i)
v_vertices[i] = add_vertex(g);
typename CGAL::Kernel_traits<P>::Kernel::FT t =
(radius + radius*CGAL::approximate_sqrt(5.0)) / 2.0;
put(vpmap, v_vertices[0],P(-radius + center.x(), t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[1],P( radius + center.x(), t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[2],P(-radius + center.x(), -t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[3],P( radius + center.x(), -t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[4],P( 0.0 + center.x(), -radius + center.y(), t + center.z()));
put(vpmap, v_vertices[5],P( 0.0 + center.x(), radius + center.y(), t + center.z()));
put(vpmap, v_vertices[6],P( 0.0 + center.x(), -radius + center.y(), -t + center.z()));
put(vpmap, v_vertices[7],P( 0.0 + center.x(), radius + center.y(), -t + center.z()));
put(vpmap, v_vertices[8],P( t + center.x(), 0.0 + center.y(), -radius + center.z()));
put(vpmap, v_vertices[9],P( t + center.x(), 0.0 + center.y(), radius + center.z()));
put(vpmap, v_vertices[10],P(-t + center.x(), 0.0 + center.y(), -radius + center.z()));
put(vpmap, v_vertices[11],P(-t + center.x(), 0.0 + center.y(), radius + center.z()));
std::vector<vertex_descriptor> face;
face.resize(3);
face[1] = v_vertices[0]; face[0] = v_vertices[11]; face[2] = v_vertices[5];
Euler::add_face(face, g);
face[1] = v_vertices[0]; face[0] = v_vertices[5]; face[2] = v_vertices[1];
Euler::add_face(face, g);
face[1] = v_vertices[0]; face[0] = v_vertices[1]; face[2] = v_vertices[7];
Euler::add_face(face, g);
face[1] = v_vertices[0]; face[0] = v_vertices[7]; face[2] = v_vertices[10];
Euler::add_face(face, g);
face[1] = v_vertices[0]; face[0] = v_vertices[10]; face[2] = v_vertices[11];
Euler::add_face(face, g);
face[1] = v_vertices[1] ; face[0] = v_vertices[5] ; face[2] = v_vertices[9];
Euler::add_face(face, g);
face[1] = v_vertices[5] ; face[0] = v_vertices[11]; face[2] = v_vertices[4];
Euler::add_face(face, g);
face[1] = v_vertices[11]; face[0] = v_vertices[10]; face[2] = v_vertices[2];
Euler::add_face(face, g);
face[1] = v_vertices[10]; face[0] = v_vertices[7] ; face[2] = v_vertices[6];
Euler::add_face(face, g);
face[1] = v_vertices[7] ; face[0] = v_vertices[1] ; face[2] = v_vertices[8];
Euler::add_face(face, g);
face[1] = v_vertices[3] ; face[0] = v_vertices[9] ; face[2] = v_vertices[4];
Euler::add_face(face, g);
face[1] = v_vertices[3] ; face[0] = v_vertices[4] ; face[2] = v_vertices[2];
Euler::add_face(face, g);
face[1] = v_vertices[3] ; face[0] = v_vertices[2] ; face[2] = v_vertices[6];
Euler::add_face(face, g);
face[1] = v_vertices[3] ; face[0] = v_vertices[6] ; face[2] = v_vertices[8];
Euler::add_face(face, g);
face[1] = v_vertices[3] ; face[0] = v_vertices[8] ; face[2] = v_vertices[9];
Euler::add_face(face, g);
face[1] = v_vertices[4] ; face[0] = v_vertices[9] ; face[2] = v_vertices[5] ;
Euler::add_face(face, g);
face[1] = v_vertices[2] ; face[0] = v_vertices[4] ; face[2] = v_vertices[11];
Euler::add_face(face, g);
face[1] = v_vertices[6] ; face[0] = v_vertices[2] ; face[2] = v_vertices[10];
Euler::add_face(face, g);
face[1] = v_vertices[8] ; face[0] = v_vertices[6] ; face[2] = v_vertices[7] ;
Euler::add_face(face, g);
face[1] = v_vertices[9] ; face[0] = v_vertices[8] ; face[2] = v_vertices[1] ;
Euler::add_face(face, g);
}
namespace internal { namespace internal {
template<typename FaceGraph> template<typename FaceGraph>

View File

@ -178,14 +178,17 @@ and <code>src/</code> directories).
<!-- Interpolation --> <!-- Interpolation -->
<!-- Kinetic Data Structures --> <!-- Kinetic Data Structures -->
<!-- Support Library --> <!-- Support Library -->
<h3>CGAL and the Boost Graph Library (BGL)</h3> <h3>CGAL and the Boost Graph Library</h3>
<ul> <ul>
<li>Helper functions to create an icosahedron, a regular prism and a
pyramid have been added.
</li>
<li> <li>
Add class <code>CGAL::Face_filtered_graph</code> that Add class <code>CGAL::Face_filtered_graph</code> that
wraps an existing graph and hide all simplices that are not wraps an existing graph and hide all simplices that are not
in the selected connected components. in the selected connected components.
</li> </li>
</ul> </ul>
<!-- Visualization --> <!-- Visualization -->
<!-- end of the div for 4.10 --> <!-- end of the div for 4.10 -->

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>672</width> <width>696</width>
<height>402</height> <height>607</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -57,7 +57,7 @@
<item> <item>
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The prism center's coordinates.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The coordinates of the prism's center.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Center:</string> <string>Center:</string>
@ -131,7 +131,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QDoubleSpinBox" name="heightSpinBox"> <widget class="QDoubleSpinBox" name="prismHeightSpinBox">
<property name="decimals"> <property name="decimals">
<number>2</number> <number>2</number>
</property> </property>
@ -174,7 +174,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="toolTip"> <property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Mark this if you want the basis of the prism to be constructed as well.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If this is unmarked, the bases will not be created.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Closed: </string> <string>Closed: </string>
@ -199,6 +199,186 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="pyramidGroupBox">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="prismLayout_3" stretch="1,0">
<item>
<widget class="QLabel" name="pyramidLabel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The number of points in the base of the pyramid. Must be at least 3.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>#Points:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="pyramidSpinBox">
<property name="minimum">
<number>3</number>
</property>
<property name="maximum">
<number>360000</number>
</property>
<property name="value">
<number>36</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11" stretch="4,1,0,0,0">
<item>
<widget class="QLabel" name="label_11">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The coordinates of the pyramid's apex.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Center:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDoubleSpinBox" name="pyramidXSpinBox">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-1000000000000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000000000000.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="pyramidYSpinBox">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-1000000000000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000000000000.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="pyramidZSpinBox">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-1000000000000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000000000000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12" stretch="1,0">
<item>
<widget class="QLabel" name="label_12">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The pyramid's height.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Height:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="pyramidHeightSpinBox">
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>1000000000000000000.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13" stretch="0,0">
<item>
<widget class="QLabel" name="label_13">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The radius of the circle in which the base is inscribed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Base Radius:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="pyramidBaseSpinBox">
<property name="maximum">
<double>1000000000000000000.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QLabel" name="label_14">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If this is unmarked, the base will not be created.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Closed: </string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="pyramidCheckBox">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="sphereGroupBox"> <widget class="QGroupBox" name="sphereGroupBox">
<property name="title"> <property name="title">

View File

@ -9,6 +9,7 @@
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h> #include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
#include "Scene_polyhedron_item.h" #include "Scene_polyhedron_item.h"
#include <CGAL/Subdivision_method_3.h> #include <CGAL/Subdivision_method_3.h>
#include <CGAL/Kernel_traits.h>
#include "ui_Basic_volumes_generator_dialog.h" #include "ui_Basic_volumes_generator_dialog.h"
class VolumeDialog : class VolumeDialog :
@ -39,24 +40,30 @@ class Q_DECL_EXPORT Basic_volumes_generator_plugin :
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
public : public :
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) void init(QMainWindow* mainWindow,
CGAL::Three::Scene_interface* scene_interface,
Messages_interface*)
{ {
this->scene = scene_interface; this->scene = scene_interface;
this->mw = mainWindow; this->mw = mainWindow;
QAction* actionCube = new QAction("Generate Cube", mw); QAction* actionCube = new QAction("Generate Cube", mw);
QAction* actionPrism = new QAction("Generate Regular Prism", mw); QAction* actionPrism = new QAction("Generate Regular Prism", mw);
QAction* actionPyramid = new QAction("Generate Pyramid", mw);
QAction* actionSphere = new QAction("Generate Sphere", mw); QAction* actionSphere = new QAction("Generate Sphere", mw);
QAction* actionTetrahedron = new QAction("Generate Tetrahedron", mw); QAction* actionTetrahedron = new QAction("Generate Tetrahedron", mw);
connect(actionCube, SIGNAL(triggered()), connect(actionCube, SIGNAL(triggered()),
this, SLOT(on_actionCube_triggered())); this, SLOT(on_actionCube_triggered()));
connect(actionPrism, SIGNAL(triggered()), connect(actionPrism, SIGNAL(triggered()),
this, SLOT(on_actionPrism_triggered())); this, SLOT(on_actionPrism_triggered()));
connect(actionPyramid, SIGNAL(triggered()),
this, SLOT(on_actionPyramid_triggered()));
connect(actionSphere, SIGNAL(triggered()), connect(actionSphere, SIGNAL(triggered()),
this, SLOT(on_actionSphere_triggered())); this, SLOT(on_actionSphere_triggered()));
connect(actionTetrahedron, SIGNAL(triggered()), connect(actionTetrahedron, SIGNAL(triggered()),
this, SLOT(on_actionTetrahedron_triggered())); this, SLOT(on_actionTetrahedron_triggered()));
_actions << actionCube _actions << actionCube
<< actionPrism << actionPrism
<< actionPyramid
<< actionSphere << actionSphere
<< actionTetrahedron; << actionTetrahedron;
Q_FOREACH(QAction* action, _actions) Q_FOREACH(QAction* action, _actions)
@ -65,6 +72,7 @@ public :
bool applicable(QAction*) const bool applicable(QAction*) const
{ {
//always applicable
return true; return true;
} }
QList<QAction*> actions() const { QList<QAction*> actions() const {
@ -73,6 +81,7 @@ public :
public Q_SLOTS: public Q_SLOTS:
void on_actionCube_triggered(); void on_actionCube_triggered();
void on_actionPrism_triggered(); void on_actionPrism_triggered();
void on_actionPyramid_triggered();
void on_actionSphere_triggered(); void on_actionSphere_triggered();
void on_actionTetrahedron_triggered(); void on_actionTetrahedron_triggered();
private: private:
@ -100,156 +109,18 @@ void Basic_volumes_generator_plugin::on_actionCube_triggered()
scene->addItem(cube_item); scene->addItem(cube_item);
} }
//make a prism //make a prism
template<class Mesh, class Traits>
void make_regular_prism(int nb_vertices,
Mesh& prism,
typename CGAL::Point_3<Traits> center = CGAL::Point_3<Traits>(0,0,0),
double height = 1.0,
double radius = 1.0,
bool is_closed = true)
{
const double to_rad = static_cast<float>(CGAL_PI / 180.0);
const double precision = 360/nb_vertices;
double diameter = 2*radius;
VPMap vpmap = get(CGAL::vertex_point, prism);
//const int nb_vertices = 360/precision * 2;
std::vector<vertex_descriptor> vertices;
vertices.resize(nb_vertices*2);
for(int i=0; i<nb_vertices*2; ++i)
vertices[i] = add_vertex(prism);
//fill vertices
for(int i=0; i < nb_vertices; ++i)
{
put(vpmap, vertices[i], Point(0.5*diameter*cos(i*precision*to_rad)+center.x(),0.5*height+center.y(),-0.5*diameter*sin(i*precision*to_rad) + center.z()));
put(vpmap, vertices[i+nb_vertices], Point(0.5*diameter*cos(i*precision*to_rad)+center.x(),-0.5*height+center.y(),-0.5*diameter*sin(i*precision*to_rad)+center.z()));
}
std::vector<vertex_descriptor> face;
face.resize(3);
//fill faces
for(int i=0; i<nb_vertices; ++i)
{
face[0] = vertices[(i+1)%(nb_vertices)];
face[1] = vertices[i];
face[2] = vertices[(i+1)%(nb_vertices) + nb_vertices];
euler::add_face(face, prism);
face[0] = vertices[(i+1)%(nb_vertices) + nb_vertices];
face[1] = vertices[i];
face[2] = vertices[i + nb_vertices];
euler::add_face(face, prism);
}
//close
if(is_closed)
{
//add the center of the fans
vertex_descriptor top = add_vertex(prism);
vertex_descriptor bot = add_vertex(prism);
put(vpmap, top, Point(center.x(),0.5*height+center.y(),center.z()));
put(vpmap, bot, Point(center.x(),-0.5*height+center.y(),center.z()));
//add the faces
for(int i=0; i<nb_vertices; ++i)
{
face[0] = vertices[i];
face[1] = vertices[(i+1)%(nb_vertices)];
face[2] = top;
euler::add_face(face, prism);
face[0] = bot;
face[1] = vertices[(i+1)%(nb_vertices) + nb_vertices];
face[2] = vertices[i + nb_vertices];
euler::add_face(face, prism);
}
}
}
template<class Mesh, class Traits>
void make_icosahedron(Mesh& mesh,
typename CGAL::Point_3<Traits> center = CGAL::Point_3<Traits>(0,0,0),
double radius = 1.0)
{
VPMap vpmap = get(CGAL::vertex_point, mesh);
// create the initial icosahedron
std::vector<vertex_descriptor> v_vertices;
v_vertices.resize(12);
for(int i=0; i<12; ++i)
v_vertices[i] = add_vertex(mesh);
double t = (radius + radius*CGAL::sqrt(5.0)) / 2.0;
put(vpmap, v_vertices[0],typename Traits::Point_3(-radius + center.x(), t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[1],typename Traits::Point_3( radius + center.x(), t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[2],typename Traits::Point_3(-radius + center.x(), -t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[3],typename Traits::Point_3( radius + center.x(), -t + center.y(), 0.0 + center.z()));
put(vpmap, v_vertices[4],typename Traits::Point_3( 0.0 + center.x(), -radius + center.y(), t + center.z()));
put(vpmap, v_vertices[5],typename Traits::Point_3( 0.0 + center.x(), radius + center.y(), t + center.z()));
put(vpmap, v_vertices[6],typename Traits::Point_3( 0.0 + center.x(), -radius + center.y(), -t + center.z()));
put(vpmap, v_vertices[7],typename Traits::Point_3( 0.0 + center.x(), radius + center.y(), -t + center.z()));
put(vpmap, v_vertices[8],typename Traits::Point_3( t + center.x(), 0.0 + center.y(), -radius + center.z()));
put(vpmap, v_vertices[9],typename Traits::Point_3( t + center.x(), 0.0 + center.y(), radius + center.z()));
put(vpmap, v_vertices[10],typename Traits::Point_3(-t + center.x(), 0.0 + center.y(), -radius + center.z()));
put(vpmap, v_vertices[11],typename Traits::Point_3(-t + center.x(), 0.0 + center.y(), radius + center.z()));
std::vector<vertex_descriptor> face;
face.resize(3);
face[1] = v_vertices[0]; face[0] = v_vertices[11]; face[2] = v_vertices[5];
euler::add_face(face, mesh);
face[1] = v_vertices[0]; face[0] = v_vertices[5]; face[2] = v_vertices[1];
euler::add_face(face, mesh);
face[1] = v_vertices[0]; face[0] = v_vertices[1]; face[2] = v_vertices[7];
euler::add_face(face, mesh);
face[1] = v_vertices[0]; face[0] = v_vertices[7]; face[2] = v_vertices[10];
euler::add_face(face, mesh);
face[1] = v_vertices[0]; face[0] = v_vertices[10]; face[2] = v_vertices[11];
euler::add_face(face, mesh);
face[1] = v_vertices[1] ; face[0] = v_vertices[5] ; face[2] = v_vertices[9];
euler::add_face(face, mesh);
face[1] = v_vertices[5] ; face[0] = v_vertices[11]; face[2] = v_vertices[4];
euler::add_face(face, mesh);
face[1] = v_vertices[11]; face[0] = v_vertices[10]; face[2] = v_vertices[2];
euler::add_face(face, mesh);
face[1] = v_vertices[10]; face[0] = v_vertices[7] ; face[2] = v_vertices[6];
euler::add_face(face, mesh);
face[1] = v_vertices[7] ; face[0] = v_vertices[1] ; face[2] = v_vertices[8];
euler::add_face(face, mesh);
face[1] = v_vertices[3] ; face[0] = v_vertices[9] ; face[2] = v_vertices[4];
euler::add_face(face, mesh);
face[1] = v_vertices[3] ; face[0] = v_vertices[4] ; face[2] = v_vertices[2];
euler::add_face(face, mesh);
face[1] = v_vertices[3] ; face[0] = v_vertices[2] ; face[2] = v_vertices[6];
euler::add_face(face, mesh);
face[1] = v_vertices[3] ; face[0] = v_vertices[6] ; face[2] = v_vertices[8];
euler::add_face(face, mesh);
face[1] = v_vertices[3] ; face[0] = v_vertices[8] ; face[2] = v_vertices[9];
euler::add_face(face, mesh);
face[1] = v_vertices[4] ; face[0] = v_vertices[9] ; face[2] = v_vertices[5] ;
euler::add_face(face, mesh);
face[1] = v_vertices[2] ; face[0] = v_vertices[4] ; face[2] = v_vertices[11];
euler::add_face(face, mesh);
face[1] = v_vertices[6] ; face[0] = v_vertices[2] ; face[2] = v_vertices[10];
euler::add_face(face, mesh);
face[1] = v_vertices[8] ; face[0] = v_vertices[6] ; face[2] = v_vertices[7] ;
euler::add_face(face, mesh);
face[1] = v_vertices[9] ; face[0] = v_vertices[8] ; face[2] = v_vertices[1] ;
euler::add_face(face, mesh);
}
void Basic_volumes_generator_plugin::on_actionPrism_triggered() void Basic_volumes_generator_plugin::on_actionPrism_triggered()
{ {
//gets the precision parameter //gets the precision parameter
VolumeDialog *dialog = new VolumeDialog(); VolumeDialog *dialog = new VolumeDialog();
dialog->sphereGroupBox->setVisible(false); dialog->sphereGroupBox->setVisible(false);
dialog->pyramidGroupBox->setVisible(false);
dialog->prismGroupBox->setVisible(true); dialog->prismGroupBox->setVisible(true);
//opens the dialog //opens the dialog
if(!dialog->exec()) if(!dialog->exec())
return; return;
int nb_vertices = dialog->prismSpinBox->value(); int nb_vertices = dialog->prismSpinBox->value();
double height(dialog->heightSpinBox->value()), double height(dialog->prismHeightSpinBox->value()),
radius(dialog->prismBaseSpinBox->value()), radius(dialog->prismBaseSpinBox->value()),
center_x(dialog->prismXSpinBox->value()), center_x(dialog->prismXSpinBox->value()),
center_y(dialog->prismYSpinBox->value()), center_y(dialog->prismYSpinBox->value()),
@ -257,17 +128,61 @@ void Basic_volumes_generator_plugin::on_actionPrism_triggered()
bool is_closed = dialog->prismCheckBox->isChecked(); bool is_closed = dialog->prismCheckBox->isChecked();
Polyhedron prism; Polyhedron prism;
make_regular_prism(nb_vertices, prism, Point(center_x,center_y,center_z), height, radius, is_closed); make_regular_prism(nb_vertices,
prism,
Point(center_x,
center_y,
center_z),
height,
radius,
is_closed);
Scene_polyhedron_item* prism_item = new Scene_polyhedron_item(prism); Scene_polyhedron_item* prism_item = new Scene_polyhedron_item(prism);
prism_item->setName(QString("Prism")); prism_item->setName(QString("Prism"));
scene->addItem(prism_item); scene->addItem(prism_item);
} }
//make a pyramid
void Basic_volumes_generator_plugin::on_actionPyramid_triggered()
{
//gets the precision parameter
VolumeDialog *dialog = new VolumeDialog();
dialog->sphereGroupBox->setVisible(false);
dialog->prismGroupBox->setVisible(false);
dialog->pyramidGroupBox->setVisible(true);
//opens the dialog
if(!dialog->exec())
return;
int nb_vertices = dialog->pyramidSpinBox->value();
double height(dialog->pyramidHeightSpinBox->value()),
radius(dialog->pyramidBaseSpinBox->value()),
center_x(dialog->pyramidXSpinBox->value()),
center_y(dialog->pyramidYSpinBox->value()),
center_z(dialog->pyramidZSpinBox->value());
bool is_closed = dialog->pyramidCheckBox->isChecked();
Polyhedron pyramid;
make_pyramid(nb_vertices,
pyramid,
Point(center_x,
center_y,
center_z),
height,
radius,
is_closed);
Scene_polyhedron_item* pyramid_item = new Scene_polyhedron_item(pyramid);
pyramid_item->setName(QString("Pyramid"));
scene->addItem(pyramid_item);
}
//make a sphere //make a sphere
void Basic_volumes_generator_plugin::on_actionSphere_triggered() void Basic_volumes_generator_plugin::on_actionSphere_triggered()
{ {
//gets the precision parameter //gets the precision parameter
VolumeDialog *dialog = new VolumeDialog(); VolumeDialog *dialog = new VolumeDialog();
dialog->prismGroupBox->setVisible(false); dialog->prismGroupBox->setVisible(false);
dialog->pyramidGroupBox->setVisible(false);
dialog->sphereGroupBox->setVisible(true); dialog->sphereGroupBox->setVisible(true);
//opens the dialog //opens the dialog
if(!dialog->exec()) if(!dialog->exec())
@ -280,7 +195,8 @@ void Basic_volumes_generator_plugin::on_actionSphere_triggered()
Polyhedron sphere; Polyhedron sphere;
make_icosahedron(sphere, center, radius); make_icosahedron(sphere, center, radius);
if(precision !=0) if(precision !=0)
CGAL::Subdivision_method_3::Sqrt3_subdivision(sphere, precision); CGAL::Subdivision_method_3::Sqrt3_subdivision(sphere,
precision);
VPMap vpmap = get(CGAL::vertex_point, sphere); VPMap vpmap = get(CGAL::vertex_point, sphere);
//emplace the points back on the sphere //emplace the points back on the sphere
BOOST_FOREACH(vertex_descriptor vd, vertices(sphere)) BOOST_FOREACH(vertex_descriptor vd, vertices(sphere))
@ -300,10 +216,10 @@ void Basic_volumes_generator_plugin::on_actionSphere_triggered()
void Basic_volumes_generator_plugin::on_actionTetrahedron_triggered() void Basic_volumes_generator_plugin::on_actionTetrahedron_triggered()
{ {
Polyhedron tetrahedron; Polyhedron tetrahedron;
CGAL::make_tetrahedron(Point(-0.5,-0.5,-0.5), CGAL::make_tetrahedron(Point(0.0, 0.0, 0.0),
Point(0.5,-0.5,-0.5), Point(1.0, 0.0, 0.0),
Point(0,0.5,-0.5), Point(0.0, 1.0, 0.0),
Point(0,0,0.5), Point(0.0, 0.0, 1.0),
tetrahedron); tetrahedron);
Scene_polyhedron_item* tet_item = new Scene_polyhedron_item(tetrahedron); Scene_polyhedron_item* tet_item = new Scene_polyhedron_item(tetrahedron);

View File

@ -13,5 +13,6 @@ polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin)
target_link_libraries(create_bbox_mesh_plugin scene_polyhedron_item) target_link_libraries(create_bbox_mesh_plugin scene_polyhedron_item)
qt5_wrap_ui( volumesUI_FILES Basic_volumes_generator_dialog.ui ) qt5_wrap_ui( volumesUI_FILES Basic_volumes_generator_dialog.ui )
polyhedron_demo_plugin(basic_volumes_generator_plugin Basic_volumes_generator_plugin ${volumesUI_FILES}) polyhedron_demo_plugin(basic_volumes_generator_plugin Basic_volumes_generator_plugin ${volumesUI_FILES})
target_link_libraries(basic_volumes_generator_plugin scene_polyhedron_item) target_link_libraries(basic_volumes_generator_plugin scene_polyhedron_item)