diff --git a/src/core/shapes/CMakeLists.txt b/src/core/shapes/CMakeLists.txt index aaae1ed0cbf..be7f24c110e 100644 --- a/src/core/shapes/CMakeLists.txt +++ b/src/core/shapes/CMakeLists.txt @@ -9,6 +9,7 @@ set(Shapes_SRC Sphere.cpp SpheroCylinder.cpp Stomatocyte.cpp + Torus.cpp Wall.cpp ) add_library(Shapes SHARED ${Shapes_SRC}) diff --git a/src/core/shapes/Torus.cpp b/src/core/shapes/Torus.cpp new file mode 100644 index 00000000000..ec39ada043c --- /dev/null +++ b/src/core/shapes/Torus.cpp @@ -0,0 +1,24 @@ +#include "Torus.hpp" +#include "utils.hpp" +#include + +namespace Shapes { + +int Torus::calculate_dist(const double *ppos, double *dist, double *vec) const { + /* Coordinate transform to cylinder coords + with origin at m_center. */ + Vector3d const c_dist = Vector3d(ppos, ppos + 3) - m_center; + auto const z = e_z * c_dist; + auto const r_vec = c_dist - z * e_z; + auto const r = r_vec.norm(); + + *dist = (sqrt(Utils::sqr(r - m_rad) + z * z) - m_tube_rad) * m_direction; + Vector3d const dir_vec = c_dist - r_vec * m_rad / r; + auto const dir_vec_norm = dir_vec / dir_vec.norm(); + vec[0] = dir_vec_norm[0] * m_direction; + vec[1] = dir_vec_norm[1] * m_direction; + vec[2] = dir_vec_norm[2] * m_direction; + + return 0; +} +} // namespace Shapes diff --git a/src/core/shapes/Torus.hpp b/src/core/shapes/Torus.hpp new file mode 100644 index 00000000000..9ba768d3c2e --- /dev/null +++ b/src/core/shapes/Torus.hpp @@ -0,0 +1,59 @@ +#ifndef __TORUS_HPP +#define __TORUS_HPP + +#include "Shape.hpp" +#include "Vector.hpp" + +namespace Shapes { +class Torus : public Shape { +public: + /* center of the cylinder. */ + Vector3d m_center; + /* Normal axis of the cylinder. */ + Vector3d m_normal; + /* radius. */ + double m_rad; + /* tube radius. */ + double m_tube_rad; + /* direction -1: inside, +1 outside */ + double m_direction; + + /* Unit vector in z direction */ + Vector3d e_z; + + /** @brief Calculate derived parameters. */ + void precalc() { e_z = m_normal / m_normal.norm(); } + +public: + Torus() + : m_center({0.0, 0.0, 0.0}), m_normal({1.0, 0.0, 0.0}), m_rad(0.0), + m_tube_rad(0.0), m_direction(1.0) { + precalc(); + } + + double radius() const { return m_rad; } + void set_radius(double const &radius) { + m_rad = radius; + precalc(); + } + + double tube_radius() const { return m_tube_rad; } + void set_tube_radius(double const &tube_rad) { + m_tube_rad = tube_rad; + precalc(); + } + + Vector3d const &normal() const { return m_normal; } + void set_normal(Vector3d const &normal) { + m_normal = normal; + precalc(); + } + + Vector3d ¢er() { return m_center; } + double &direction() { return m_direction; } + + int calculate_dist(const double *ppos, double *dist, + double *vec) const override; +}; +} // namespace Shapes +#endif diff --git a/src/python/espressomd/shapes.py b/src/python/espressomd/shapes.py index 8870baf34a5..783736b6057 100644 --- a/src/python/espressomd/shapes.py +++ b/src/python/espressomd/shapes.py @@ -231,6 +231,29 @@ class Stomatocyte(ScriptInterfaceHelper): _so_name = "Shapes::Stomatocyte" +@script_interface_register +class Torus(ScriptInterfaceHelper): + + """ + A torus shape. + Attributes + ---------- + center : array_like :obj:`float` + Coordinates of the center of the torus. + normal : array_like :obj:`float` + Normal axis of the torus. + radius : :obj:`float` + Radius of the torus. + tube_radius : :obj:`float` + Radius of the tube. + direction : :obj:`int` + Surface orientation, for +1 the normal points + out of the mantel, for -1 it points inward. + + """ + _so_name = "Shapes::Torus" + + @script_interface_register class Wall(ScriptInterfaceHelper): diff --git a/src/script_interface/shapes/Torus.hpp b/src/script_interface/shapes/Torus.hpp new file mode 100644 index 00000000000..0a8fdd06f87 --- /dev/null +++ b/src/script_interface/shapes/Torus.hpp @@ -0,0 +1,31 @@ +#ifndef SCRIPT_INTERFACE_TORUS_WALL_HPP +#define SCRIPT_INTERFACE_TORUS_WALL_HPP + +#include "Shape.hpp" +#include "core/shapes/Torus.hpp" + +namespace ScriptInterface { +namespace Shapes { + +class Torus : public Shape { + using CoreShape = ::Shapes::Torus; + std::shared_ptr<::Shapes::Torus> m_torus; + +public: + Torus() : m_torus(new ::Shapes::Torus()) { + add_parameters( + {{"radius", m_torus, &CoreShape::set_radius, &CoreShape::radius}, + {"tube_radius", m_torus, &CoreShape::set_tube_radius, + &CoreShape::tube_radius}, + {"normal", m_torus, &CoreShape::set_normal, &CoreShape::normal}, + {"center", m_torus, &CoreShape::center}, + {"direction", m_torus, &CoreShape::direction}}); + } + + std::shared_ptr<::Shapes::Shape> shape() const override { return m_torus; } +}; + +} /* namespace Shapes */ +} /* namespace ScriptInterface */ + +#endif diff --git a/src/script_interface/shapes/initialize.cpp b/src/script_interface/shapes/initialize.cpp index a5bc3e548d1..0e40a443198 100644 --- a/src/script_interface/shapes/initialize.cpp +++ b/src/script_interface/shapes/initialize.cpp @@ -30,6 +30,7 @@ #include "Sphere.hpp" #include "SpheroCylinder.hpp" #include "Stomatocyte.hpp" +#include "Torus.hpp" #include "Wall.hpp" namespace ScriptInterface { @@ -57,6 +58,8 @@ void initialize() { "Shapes::Stomatocyte"); ScriptInterface::register_new( "Shapes::SimplePore"); + ScriptInterface::register_new( + "Shapes::Torus"); } } /* namespace Shapes */ } /* namespace ScriptInterface */