IMP logo
IMP Reference Guide  2.17.0
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 depth is returnd.
41  v = the normalized derivative vector of d
42  */
43  inline std::pair<double, algebra::Vector3D>
44  get_torus_distance(Sphere3D) const;
45 
46 
47  IMP_SHOWABLE_INLINE(Torus3D, { out << R_ << " on " << r_; });
48 
49  private:
50  double R_; // major radius
51  double r_; // minor radius
52 };
53 
55  return 4.0 * get_squared(PI)
56  * g.get_major_radius() * g.get_minor_radius(),
57  return 2.0 * get_squared(PI)
58  * g.get_major_radius()
59  * get_squared(g.get_minor_radius()),
60  IMP_UNUSED(g);
62 
63 
64 // implememt inline method
65 std::pair<double, algebra::Vector3D>
66  Torus3D::get_torus_distance
67  (Sphere3D sphere) const
68 {
69  double const x=sphere[0];
70  double const y=sphere[1];
71  double const z=sphere[2];
72  const double eps = 1e-9;
73  double d_xy2 = x*x + y*y;
74  double d_xy = std::sqrt(d_xy2);
75  double d_tx, d_ty;
76  if ( d_xy > eps )
77  {
78  // (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)
79  d_tx = x - x/d_xy*R_;
80  d_ty = y - y/d_xy*R_;
81  }
82  else
83  {
84  d_tx = x - R_;
85  d_ty = y;
86  }
87 
88  // (dx*dxx + dy*dyx) =
89  // = (x-R*cosT)*[1-R*(x*cosT-dxy)/dxy2] + (y-R*sinT)(-R*sinT*x)/dxy2
90  // = x - R*cosT + [ -R*x*(x*cosT-dxy) + R^2*cosT*(x*cosT-dxy) - x*y*R*sinT + x*R^2*sinT^2 ] /dx2
91  // = 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
92  // = x - R*cosT + [ -R*x^2*cosT + R*x*dxy + x*R^2 - R^2*x - x*y*R*sinT ] /dx2
93  // = x - R*cosT + [ -R*x^2*cosT + R*x*x/cosT - x*x*R*sinT^2/cosT ] /dx2
94  // = x - R*cosT + [ -R*x^2*cosT + R*x*x*cosT ] /dx2
95  // = x - R*cosT
96 
97  if ( d_xy <= R_ )
98  {
99  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)
100  double idenom = 1.0/denom;
101  algebra::Vector3D der;
102  if ( denom > eps )
103  {
104  der[0] = d_tx*idenom;
105  der[1] = d_ty*idenom;
106  der[2] = z*idenom;
107  }
108  else
109  {
110  der[0] = d_tx/eps;
111  der[1] = d_ty/eps;
112  der[2] = z/eps;
113  }
114  return std::make_pair(denom - r_ - sphere.get_radius(), der);
115  }
116  else
117  {
118  double dz = z > 0 ? z - r_ - sphere.get_radius(): z + r_ + sphere.get_radius();
119  double denom = std::sqrt(dz*dz + d_tx*d_tx + d_ty*d_ty);
120  algebra::Vector3D der;
121  if ( denom > eps )
122  {
123  der[0] = -d_tx/denom;
124  der[1] = -d_ty/denom;
125  der[2] = dz/denom;
126  }
127  else
128  {
129  der[0] = -d_tx/eps;
130  der[1] = -d_ty/eps;
131  der[2] = dz/eps;
132  }
133  return std::make_pair(-denom - r_ - sphere.get_radius(), der);
134  }
135 }
136 
137 
138 
139 IMPALGEBRA_END_NAMESPACE
140 
141 #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:421
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.