-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b84d6df
commit 2711472
Showing
3 changed files
with
452 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
#include "SFCGAL/Cylinder.h" | ||
|
||
namespace SFCGAL { | ||
|
||
Cylinder::Cylinder(const Point_3 &base_center, const Vector_3 &axis, | ||
const Kernel::FT &radius, const Kernel::FT &height, | ||
int num_radial) | ||
: m_base_center(base_center), m_axis(axis), m_radius(radius), | ||
m_height(height), m_num_radial(num_radial) | ||
{ | ||
} | ||
|
||
Cylinder & | ||
Cylinder::operator=(Cylinder other) | ||
{ | ||
std::swap(m_base_center, other.m_base_center); | ||
std::swap(m_axis, other.m_axis); | ||
std::swap(m_radius, other.m_radius); | ||
std::swap(m_height, other.m_height); | ||
std::swap(m_num_radial, other.m_num_radial); | ||
std::swap(m_polyhedron, other.m_polyhedron); | ||
std::swap(m_surface_mesh, other.m_surface_mesh); | ||
return *this; | ||
} | ||
|
||
void | ||
Cylinder::setBaseCenter(const Point_3 &base_center) | ||
{ | ||
m_base_center = base_center; | ||
invalidateCache(); | ||
} | ||
|
||
void | ||
Cylinder::setAxis(const Vector_3 &axis) | ||
{ | ||
m_axis = axis; | ||
invalidateCache(); | ||
} | ||
|
||
void | ||
Cylinder::setRadius(const Kernel::FT &radius) | ||
{ | ||
m_radius = radius; | ||
invalidateCache(); | ||
} | ||
|
||
void | ||
Cylinder::setHeight(const Kernel::FT &height) | ||
{ | ||
m_height = height; | ||
invalidateCache(); | ||
} | ||
|
||
void | ||
Cylinder::setNumRadial(int num) | ||
{ | ||
m_num_radial = num; | ||
invalidateCache(); | ||
} | ||
|
||
void | ||
Cylinder::invalidateCache() | ||
{ | ||
m_polyhedron.reset(); | ||
m_surface_mesh.reset(); | ||
} | ||
|
||
Cylinder::Vector_3 | ||
Cylinder::normalize(const Vector_3 &v) | ||
{ | ||
double length = std::sqrt(CGAL::to_double(v.squared_length())); | ||
if (length < 1e-8) | ||
return v; | ||
return v / length; | ||
} | ||
|
||
Cylinder::Polyhedron_3 | ||
Cylinder::generatePolyhedron() | ||
{ | ||
if (m_polyhedron) { | ||
return *m_polyhedron; | ||
} | ||
|
||
Polyhedron_3 poly; | ||
Surface_mesh sm = generateSurfaceMesh(); | ||
CGAL::copy_face_graph(sm, poly); | ||
m_polyhedron = poly; | ||
return poly; | ||
} | ||
|
||
Cylinder::Surface_mesh | ||
Cylinder::generateSurfaceMesh() | ||
{ | ||
if (m_surface_mesh) { | ||
return *m_surface_mesh; | ||
} | ||
|
||
Surface_mesh mesh; | ||
|
||
Vector_3 normalized_axis = normalize(m_axis); | ||
Vector_3 perpendicular = | ||
normalize(CGAL::cross_product(normalized_axis, Vector_3(0, 0, 1))); | ||
if (perpendicular.squared_length() < 1e-8) { | ||
perpendicular = | ||
normalize(CGAL::cross_product(normalized_axis, Vector_3(0, 1, 0))); | ||
} | ||
Vector_3 perpendicular2 = CGAL::cross_product(normalized_axis, perpendicular); | ||
|
||
std::vector<Surface_mesh::Vertex_index> base_vertices, top_vertices; | ||
|
||
// Create vertices for the base and top | ||
for (int i = 0; i < m_num_radial; ++i) { | ||
double angle = 2.0 * M_PI * i / m_num_radial; | ||
Vector_3 offset = m_radius * (std::cos(angle) * perpendicular + | ||
std::sin(angle) * perpendicular2); | ||
base_vertices.push_back(mesh.add_vertex(m_base_center + offset)); | ||
top_vertices.push_back( | ||
mesh.add_vertex(m_base_center + offset + m_height * normalized_axis)); | ||
} | ||
|
||
// Add side faces | ||
for (int i = 0; i < m_num_radial; ++i) { | ||
int next = (i + 1) % m_num_radial; | ||
mesh.add_face(base_vertices[i], top_vertices[i], top_vertices[next]); | ||
mesh.add_face(base_vertices[i], top_vertices[next], base_vertices[next]); | ||
} | ||
|
||
// Add base and top faces | ||
Surface_mesh::Vertex_index base_center = mesh.add_vertex(m_base_center); | ||
Surface_mesh::Vertex_index top_center = | ||
mesh.add_vertex(m_base_center + m_height * normalized_axis); | ||
|
||
for (int i = 0; i < m_num_radial; ++i) { | ||
int next = (i + 1) % m_num_radial; | ||
mesh.add_face(base_center, base_vertices[i], base_vertices[next]); | ||
mesh.add_face(top_center, top_vertices[next], top_vertices[i]); | ||
} | ||
m_surface_mesh = mesh; | ||
return mesh; | ||
} | ||
|
||
} // namespace SFCGAL |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
// Copyright (c) 2024-2024, Oslandia. | ||
// SPDX-License-Identifier: LGPL-2.0-or-later | ||
|
||
#ifndef _SFCGAL_CYLINDER_H_ | ||
#define _SFCGAL_CYLINDER_H_ | ||
|
||
#include "SFCGAL/Kernel.h" | ||
#include "SFCGAL/export.h" | ||
#include <CGAL/Polyhedron_3.h> | ||
#include <CGAL/Surface_mesh.h> | ||
#include <optional> | ||
#include <vector> | ||
|
||
namespace SFCGAL { | ||
|
||
/** | ||
* @class Cylinder | ||
* @brief Represents a cylinder in 3D space | ||
* | ||
* This class provides methods to generate a polyhedron and a surface mesh | ||
* representation of a cylinder. It uses SFCGAL's Kernel for exact computations. | ||
*/ | ||
class SFCGAL_API Cylinder { | ||
public: | ||
using Point_3 = Kernel::Point_3; | ||
using Vector_3 = Kernel::Vector_3; | ||
using Polyhedron_3 = CGAL::Polyhedron_3<Kernel>; | ||
using Surface_mesh = CGAL::Surface_mesh<Point_3>; | ||
|
||
/** | ||
* @brief Constructs a Cylinder object | ||
* @param base_center The center point of the base of the cylinder | ||
* @param axis The axis of the cylinder | ||
* @param radius The radius of the cylinder | ||
* @param height The height of the cylinder | ||
* @param num_radial The number of radial divisions | ||
*/ | ||
Cylinder(const Point_3 &base_center = Point_3(0, 0, 0), | ||
const Vector_3 &axis = Vector_3(0, 0, 1), | ||
const Kernel::FT &radius = 1.0, const Kernel::FT &height = 1.0, | ||
int num_radial = 32); | ||
|
||
/** | ||
* @brief Copy constructor | ||
*/ | ||
Cylinder(const Cylinder &other) = default; | ||
|
||
/** | ||
* @brief Assignment operator | ||
*/ | ||
Cylinder & | ||
operator=(Cylinder other); | ||
|
||
/** | ||
* @brief Destructor | ||
*/ | ||
~Cylinder() = default; | ||
|
||
/** | ||
* @brief Sets the base center of the cylinder | ||
* @param base_center The new base center point | ||
*/ | ||
void | ||
setBaseCenter(const Point_3 &base_center); | ||
|
||
/** | ||
* @brief Sets the axis of the cylinder | ||
* @param axis The new axis vector | ||
*/ | ||
void | ||
setAxis(const Vector_3 &axis); | ||
|
||
/** | ||
* @brief Sets the radius of the cylinder | ||
* @param radius The new radius | ||
*/ | ||
void | ||
setRadius(const Kernel::FT &radius); | ||
|
||
/** | ||
* @brief Sets the height of the cylinder | ||
* @param height The new height | ||
*/ | ||
void | ||
setHeight(const Kernel::FT &height); | ||
|
||
/** | ||
* @brief Sets the number of radial divisions | ||
* @param num The new number of radial divisions | ||
*/ | ||
void | ||
setNumRadial(int num); | ||
|
||
/** | ||
* @brief Gets the base center of the cylinder | ||
* @return The base center point | ||
*/ | ||
const Point_3 & | ||
baseCenter() const | ||
{ | ||
return m_base_center; | ||
} | ||
|
||
/** | ||
* @brief Gets the axis of the cylinder | ||
* @return The axis vector | ||
*/ | ||
const Vector_3 & | ||
axis() const | ||
{ | ||
return m_axis; | ||
} | ||
|
||
/** | ||
* @brief Gets the radius of the cylinder | ||
* @return The radius | ||
*/ | ||
const Kernel::FT & | ||
radius() const | ||
{ | ||
return m_radius; | ||
} | ||
|
||
/** | ||
* @brief Gets the height of the cylinder | ||
* @return The height | ||
*/ | ||
const Kernel::FT & | ||
height() const | ||
{ | ||
return m_height; | ||
} | ||
|
||
/** | ||
* @brief Gets the number of radial divisions | ||
* @return The number of radial divisions | ||
*/ | ||
int | ||
numRadial() const | ||
{ | ||
return m_num_radial; | ||
} | ||
|
||
/** | ||
* @brief Generates a polyhedron representation of the cylinder | ||
* @return A CGAL::Polyhedron_3 object representing the cylinder | ||
*/ | ||
Polyhedron_3 | ||
generatePolyhedron(); | ||
|
||
/** | ||
* @brief Generates a surface mesh representation of the cylinder | ||
* @return A CGAL::Surface_mesh object representing the cylinder | ||
*/ | ||
Surface_mesh | ||
generateSurfaceMesh(); | ||
|
||
double | ||
volume() const | ||
{ | ||
return CGAL::to_double(m_radius * m_radius * m_height * CGAL_PI); | ||
} | ||
|
||
double | ||
area() const | ||
{ | ||
return CGAL::to_double(2 * m_radius * m_radius * CGAL_PI + | ||
2 * m_radius * m_height * CGAL_PI); | ||
} | ||
|
||
private: | ||
Point_3 m_base_center; | ||
Vector_3 m_axis; | ||
Kernel::FT m_radius; | ||
Kernel::FT m_height; | ||
int m_num_radial; | ||
std::optional<Polyhedron_3> m_polyhedron; | ||
std::optional<Surface_mesh> m_surface_mesh; | ||
|
||
/** | ||
* @brief Invalidates the cached polyhedron and surface mesh | ||
*/ | ||
void | ||
invalidateCache(); | ||
|
||
/** | ||
* @brief Normalizes a vector | ||
* @param v The vector to normalize | ||
* @return The normalized vector | ||
*/ | ||
Vector_3 | ||
normalize(const Vector_3 &v); | ||
}; | ||
|
||
} // namespace SFCGAL | ||
|
||
#endif // _SFCGAL_CYLINDER_H_ |
Oops, something went wrong.