ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
HollowConicalFrustum.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <shapes/HollowConicalFrustum.hpp>
21
22#include <utils/Vector.hpp>
24
25#include <cmath>
26
27namespace Shapes {
29 double &dist,
30 Utils::Vector3d &vec) const {
31
32 /* Transform pos to the frame of the frustum (origin = center, z = axis, x =
33 * orientation, y = cross(z,x) ). Get the angle relative to orientation to
34 * determine whether pos is in the gap defined by m_central_angle or not.
35 */
36 auto const hcf_frame_y_axis = Utils::vector_product(
37 m_cyl_transform_params->axis(), m_cyl_transform_params->orientation());
38 auto const pos_hcf_frame = Utils::basis_change(
39 m_cyl_transform_params->orientation(), hcf_frame_y_axis,
40 m_cyl_transform_params->axis(), pos - m_cyl_transform_params->center());
41 auto const pos_phi =
43
44 /* The closest point of the frustum to pos will be determined by projection
45 * onto a line. Which line, depends on where pos is relative to the frustum
46 * gap. If pos is not within the gap region of central_angle, the closest
47 * point will be in the plane defined by axis and pos_cyl, as shown in the
48 * figure below:
49 *
50 * r1
51 * * ----->X r1_endpoint
52 * ^ a \
53 * | x \
54 * | i \
55 * | s \ *pos_hcf_frame
56 * X center \
57 * | \
58 * | X pos_closest (to be determined)
59 * | \
60 * | r2 \
61 * ----------------->X r2_endpoint
62 *
63 * In this case, the line is the intersection between the frustum and the
64 * plane of interest. The endpoints of the line are determined by the radii of
65 * the frustum, its length and the phi-coordinate of the plane.
66 *
67 * If pos is in the gap region, the projection must be made onto the closest
68 * edge (imagine pos is out-of-plane in the figure). In this case, for the
69 * endpoints we do not use the phi-coordinate of pos_cyl, but instead the
70 * phi-coordinate of the closer gap edge.
71 */
72
73 auto endpoint_angle = pos_phi;
74 if (std::fabs(pos_phi) < m_central_angle / 2.) {
75 // Cannot use Utils::sgn because of pos_phi==0 corner case
76 endpoint_angle =
77 pos_phi > 0. ? m_central_angle / 2. : -m_central_angle / 2.;
78 }
79
81 Utils::Vector3d{{m_r1, endpoint_angle, m_length / 2.}});
83 Utils::Vector3d{{m_r2, endpoint_angle, -m_length / 2.}});
84 auto const line_director = (r2_endpoint - r1_endpoint).normalized();
85
86 auto project_on_line = [](auto const vec, auto const line_start,
87 auto const line_director) {
88 return line_start + line_director * ((vec - line_start) * line_director);
89 };
90
91 auto pos_closest_hcf_frame =
92 project_on_line(pos_hcf_frame, r1_endpoint, line_director);
93
94 /* It can be that the projection onto the (infinite) line is outside the
95 * frustum. In that case, the closest point is actually one of the endpoints.
96 */
97 if (std::fabs(pos_closest_hcf_frame[2]) > m_length / 2.) {
98 pos_closest_hcf_frame =
99 pos_closest_hcf_frame[2] > 0. ? r1_endpoint : r2_endpoint;
100 }
101
102 // calculate distance and distance vector respecting thickness and direction
103 auto const u = (pos_hcf_frame - pos_closest_hcf_frame).normalize();
104 auto const d =
105 (pos_hcf_frame - pos_closest_hcf_frame).norm() - 0.5 * m_thickness;
106
107 // dist does not depend on reference frame, it can be calculated in the hcf
108 // frame.
109 dist = d * m_direction;
110
111 // vec must be rotated back to the original frame
112 auto const vec_hcf_frame = d * u;
113 vec = Utils::basis_change(m_cyl_transform_params->orientation(),
114 hcf_frame_y_axis, m_cyl_transform_params->axis(),
115 vec_hcf_frame, true);
116}
117} // namespace Shapes
Vector implementation and trait types for boost qvm interoperability.
void calculate_dist(const Utils::Vector3d &pos, double &dist, Utils::Vector3d &vec) const override
Calculate the distance vector and its norm between a given position and the cone.
Convert coordinates from the Cartesian system to the cylindrical system.
Vector< T, 3 > vector_product(Vector< T, 3 > const &a, Vector< T, 3 > const &b)
Definition Vector.hpp:368
Vector3d transform_coordinate_cylinder_to_cartesian(Vector3d const &pos)
Coordinate transformation from cylindrical to Cartesian coordinates.
Vector3d transform_coordinate_cartesian_to_cylinder(Vector3d const &pos)
Coordinate transformation from Cartesian to cylindrical coordinates.
Vector3d basis_change(Vector3d const &b1, Vector3d const &b2, Vector3d const &b3, Vector3d const &v, bool reverse=false)
Basis change.