IMP logo
IMP Reference Guide  develop.cb6747d2d1,2024/03/28
The Integrative Modeling Platform
Torus3D.h
Go to the documentation of this file.
1 /**
2  * \file IMP/algebra/Torus3D.h
3  * \brief Represent a torus in 3D.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  */
7 
8 #ifndef IMPALGEBRA_TORUS_3D_H
9 #define IMPALGEBRA_TORUS_3D_H
10 
11 #include "Vector3D.h"
12 #include "Rotation3D.h"
13 #include "Transformation3D.h"
14 #include "Segment3D.h"
15 #include "GeometricPrimitiveD.h"
16 #include <IMP/showable_macros.h>
17 #include <iostream>
18 #include "constants.h"
19 
20 IMPALGEBRA_BEGIN_NAMESPACE
21 
22 //! Represent a torus in 3D.
23 /**
24  \geometry
25 */
26 class IMPALGEBRAEXPORT Torus3D : public GeometricPrimitiveD<3> {
27  public:
28  Torus3D() {}
29  Torus3D (double major_radius, double minor_radius);
30  double get_major_radius() const { return R_; }
31  double get_minor_radius() const { return r_; }
32 
33  /**
34  Computes distance and derivative of a sphere s relative
35  to the surface of a torus with major radius R and minor radius r (on z=0, the inner and outer
36  torus rings have radii R-r and R+r, respectively).
37 
38  @return a tuple (d,v) s.t.:
39  d = The shortest distance from any point on s to any point on the torus.
40  If s penetrates the torus, the opposite of the maximal penetration
41  depth is returned.
42  v = the normalized derivative vector of d
43  */
44  inline std::pair<double, algebra::Vector3D>
45  get_torus_distance(Sphere3D) const;
46 
47 
48  IMP_SHOWABLE_INLINE(Torus3D, { out << R_ << " on " << r_; });
49 
50  private:
51  double R_; // major radius
52  double r_; // minor radius
53 };
54 
56  return 4.0 * get_squared(PI)
57  * g.get_major_radius() * g.get_minor_radius(),
58  return 2.0 * get_squared(PI)
59  * g.get_major_radius()
60  * get_squared(g.get_minor_radius()),
61  IMP_UNUSED(g);
63 
64 
65 // implement inline method
66 std::pair<double, algebra::Vector3D>
67  Torus3D::get_torus_distance
68  (Sphere3D sphere) const
69 {
70  double const x=sphere[0];
71  double const y=sphere[1];
72  double const z=sphere[2];
73  const double eps = 1e-9;
74  double d_xy2 = x*x + y*y;
75  double d_xy = std::sqrt(d_xy2);
76  double d_tx, d_ty;
77  if ( d_xy > eps )
78  {
79  // (d_tx,d_ty) is the vector from the nearest point on the center line of the torus to (x,y) (projected on z=0)
80  d_tx = x - x/d_xy*R_;
81  d_ty = y - y/d_xy*R_;
82  }
83  else
84  {
85  d_tx = x - R_;
86  d_ty = y;
87  }
88 
89  // (dx*dxx + dy*dyx) =
90  // = (x-R*cosT)*[1-R*(x*cosT-dxy)/dxy2] + (y-R*sinT)(-R*sinT*x)/dxy2
91  // = x - R*cosT + [ -R*x*(x*cosT-dxy) + R^2*cosT*(x*cosT-dxy) - x*y*R*sinT + x*R^2*sinT^2 ] /dx2
92  // = x - R*cosT + [ -R*x^2*cosT + R*x*dxy + x*R^2*cosT^2 - R^2*cosT*dxy - x*y*R*sinT + x*R^2*sinT^2 ] / dx2
93  // = x - R*cosT + [ -R*x^2*cosT + R*x*dxy + x*R^2 - R^2*x - x*y*R*sinT ] /dx2
94  // = x - R*cosT + [ -R*x^2*cosT + R*x*x/cosT - x*x*R*sinT^2/cosT ] /dx2
95  // = x - R*cosT + [ -R*x^2*cosT + R*x*x*cosT ] /dx2
96  // = x - R*cosT
97 
98  if ( d_xy <= R_ )
99  {
100  double denom = std::sqrt(z*z + d_tx*d_tx + d_ty*d_ty); // magnitude of vector from nearest point on the torus center line to (x,y,z)
101  double idenom = 1.0/denom;
102  algebra::Vector3D der;
103  if ( denom > eps )
104  {
105  der[0] = d_tx*idenom;
106  der[1] = d_ty*idenom;
107  der[2] = z*idenom;
108  }
109  else
110  {
111  der[0] = d_tx/eps;
112  der[1] = d_ty/eps;
113  der[2] = z/eps;
114  }
115  return std::make_pair(denom - r_ - sphere.get_radius(), der);
116  }
117  else
118  {
119  double dz = z > 0 ? z - r_ - sphere.get_radius(): z + r_ + sphere.get_radius();
120  double denom = std::sqrt(dz*dz + d_tx*d_tx + d_ty*d_ty);
121  algebra::Vector3D der;
122  if ( denom > eps )
123  {
124  der[0] = -d_tx/denom;
125  der[1] = -d_ty/denom;
126  der[2] = dz/denom;
127  }
128  else
129  {
130  der[0] = -d_tx/eps;
131  der[1] = -d_ty/eps;
132  der[2] = dz/eps;
133  }
134  return std::make_pair(-denom - r_ - sphere.get_radius(), der);
135  }
136 }
137 
138 
139 
140 IMPALGEBRA_END_NAMESPACE
141 
142 #endif /* IMPALGEBRA_TORUS_3D_H */
Base class for geometric types.
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
static const double PI
the constant pi
Simple implementation of segments in 3D.
Base class for geometric types.
#define IMP_UNUSED(variable)
#define IMP_VOLUME_GEOMETRY_METHODS(Name, name, area, volume, bounding_box)
Implement the needed namespace methods for a geometry type.
Represent a torus in 3D.
Definition: Torus3D.h:26
Various useful constants.
Simple 3D rotation class.
Simple 3D transformation class.
VectorD< 3 > Vector3D
Definition: VectorD.h:408
Simple 3D vector class.
#define IMP_NOT_IMPLEMENTED
Use this to mark that the method is not implemented yet.
Definition: check_macros.h:81
Macros to help with objects that can be printed to a stream.