Thea
HyperplaneN.hpp
1 //============================================================================
2 //
3 // This file is part of the Thea toolkit.
4 //
5 // This software is distributed under the BSD license, as detailed in the
6 // accompanying LICENSE.txt file. Portions are derived from other works:
7 // their respective licenses and copyright information are reproduced in
8 // LICENSE.txt and/or in the relevant source files.
9 //
10 // Author: Siddhartha Chaudhuri
11 // First version: 2011
12 //
13 //============================================================================
14 
15 #ifndef __Thea_HyperplaneN_hpp__
16 #define __Thea_HyperplaneN_hpp__
17 
18 #include "Common.hpp"
19 #include "Array.hpp"
20 #include "Math.hpp"
21 #include "MatVec.hpp"
22 #include "RayIntersectableN.hpp"
23 
24 namespace Thea {
25 
26 // Forward declarations
27 template <int N, typename T> class HyperplaneN;
28 
29 namespace Internal {
30 
37 template <int N, typename T>
38 class /* THEA_DLL_LOCAL */ HyperplaneNBase : public RayIntersectableN<N, T>
39 {
40  public:
43 
44  THEA_DECL_SMART_POINTERS(HyperplaneT)
45 
46 
47  HyperplaneNBase() : normal(VectorT::Zero()), dist(0) {}
48 
53  static HyperplaneT fromDistanceAndNormal(T dist_, VectorT const & normal_, bool normalize = true)
54  {
55  HyperplaneT hyperplane;
56  hyperplane.normal = normal_; if (normalize) hyperplane.normal.normalize();
57  hyperplane.dist = dist_;
58 
59  return hyperplane;
60  }
61 
66  static HyperplaneT fromPointAndNormal(VectorT const & point_, VectorT const & normal_, bool normalize = true)
67  {
68  HyperplaneT hyperplane;
69  hyperplane.normal = normal_; if (normalize) hyperplane.normal.normalize();
70  hyperplane.dist = hyperplane.normal.dot(point_);
71 
72  return hyperplane;
73  }
74 
76  static HyperplaneT fromNPoints(Array<VectorT> const & points)
77  {
78  alwaysAssertM(points.size() >= N,
79  format("HyperplaneN: Too few points specified (provided %ld points, hyperplane requires %ld points)",
80  (intx)points.size(), N));
81 
83  for (intx i = 0; i < N; ++i)
84  a.setRow(i, points[i]);
85 
86  try
87  {
88  a = a.inverse();
89  }
90  catch (...)
91  {
92  throw Error("HyperplaneN: Points are degenerate");
93  }
94 
95  HyperplaneT hyperplane;
96  hyperplane.normal = -(a * VectorT::Ones()).normalized();
97  hyperplane.dist = hyperplane.normal.dot(points[0]);
98  return hyperplane;
99  }
100 
102  template <typename U> HyperplaneN<N, U> cast() const
103  {
104  return HyperplaneN<N, U>::fromDistanceAndNormal(static_cast<U>(dist), normal.template cast<U>(), /* normalize = */ false);
105  }
106 
108  VectorT getPoint() const { return dist * normal; }
109 
111  VectorT const & getNormal() const { return normal; }
112 
117  {
118  Vector<N + 1, T> coeffs;
119 
120  for (intx i = 0; i < N; ++i)
121  coeffs[i] = normal[i];
122 
123  coeffs[N] = -dist;
124 
125  return coeffs;
126  }
127 
129  void flip()
130  {
131  normal = -normal;
132  dist = -dist;
133  }
134 
136  T distance(VectorT const & p) const
137  {
138  return std::abs(signedDistance(p));
139  }
140 
145  T signedDistance(VectorT const & p) const
146  {
147  return p.dot(normal) - dist;
148  }
149 
151  T squaredDistance(VectorT const & p) const
152  {
153  return Math::square(signedDistance(p));
154  }
155 
157  VectorT closestPoint(VectorT const & p) const
158  {
159  return p - signedDistance(p) * normal;
160  }
161 
166  bool positiveHalfSpaceContains(VectorT const & p) const
167  {
168  return signedDistance(p) >= 0;
169  }
170 
175  bool negativeHalfSpaceContains(VectorT const & p) const
176  {
177  return signedDistance(p) <= 0;
178  }
179 
181  VectorT reflect(VectorT const & p) const
182  {
183  return p - 2 * signedDistance(p) * normal;
184  }
185 
186  bool rayIntersects(RayN<N, T> const & ray, T max_time = -1) const
187  {
188  return rayIntersectionTime(ray, max_time) >= 0;
189  }
190 
191  T rayIntersectionTime(RayN<N, T> const & ray, T max_time = -1) const
192  {
193  T numer = dist - normal.dot(ray.getOrigin());
194  T denom = normal.dot(ray.getDirection());
195  if (std::abs(denom) < Math::eps(numer, denom))
196  return -1;
197  else
198  {
199  T t = numer / denom;
200  return (max_time < 0 || t <= max_time) ? t : -1;
201  }
202  }
203 
204  RayIntersectionN<N, T> rayIntersection(RayN<N, T> const & ray, T max_time = -1) const
205  {
206  T t = rayIntersectionTime(ray, max_time);
207  if (t >= 0)
208  return RayIntersectionN<N, T>(t, &normal);
209  else
210  return RayIntersectionN<N, T>(-1);
211  }
212 
214  std::string toString() const
215  {
216  std::ostringstream oss;
217  oss << "[N: " << Thea::toString(normal) << ", D: " << dist << ']';
218  return oss.str();
219  }
220 
221  protected:
222  VectorT normal;
223  T dist;
224 
225 }; // class HyperplaneNBase
226 
227 } // namespace Internal
228 
230 template <int N, typename T = Real>
231 class /* THEA_API */ HyperplaneN : public Internal::HyperplaneNBase<N, T>
232 {
233  public:
236 
237 }; // class HyperplaneN
238 
240 template <int N, typename T>
241 std::ostream &
242 operator<<(std::ostream & os, HyperplaneN<N, T> const & plane)
243 {
244  return os << plane.toString();
245 }
246 
247 } // namespace Thea
248 
249 #include "Hyperplane3.hpp"
250 
251 #endif
Eigen::Matrix< T, Size, 1, Options|((Options &Eigen::DontAlign)==0 &&Size==Eigen::Dynamic?Eigen::AutoAlign:Eigen::DontAlign), MaxRowsAtCompileTime, 1 > Vector
General 1D dense column vector template, alias for Eigen::Matrix<T, Size, 1,...>, with a custom align...
Definition: MatVec.hpp:146
static HyperplaneT fromNPoints(Array< VectorT > const &points)
Construct a hyperplane from N points on it.
Definition: HyperplaneN.hpp:76
bool positiveHalfSpaceContains(VectorT const &p) const
Check if the positive half space (the side of the hyperplane containing the normal) contains a given ...
bool negativeHalfSpaceContains(VectorT const &p) const
Check if the negative half space (the side of the hyperplane not containing the normal) contains a gi...
VectorT closestPoint(VectorT const &p) const
Get the point on the hyperplane closest to a given point.
std::ptrdiff_t intx
A signed integer suitable for indexing a structure held in memory.
Definition: Platform.hpp:161
std::string toString(char const *s)
Convert a C-string to a std::string object, returning an empty string if the input is a null pointer...
static HyperplaneT fromPointAndNormal(VectorT const &point_, VectorT const &normal_, bool normalize=true)
Construct a hyperplane from a point on it, and its normal vector (need not be a unit vector)...
Definition: HyperplaneN.hpp:66
VectorT getPoint() const
Get a point on the hyperplane.
VectorT const & getOrigin() const
Get the origin of the ray.
Definition: RayN.hpp:50
VectorT reflect(VectorT const &p) const
Reflect a point in the hyperplane.
A ray in N-dimensional space, having an originating point and a direction vector (not necessarily uni...
Definition: RayN.hpp:27
Root namespace for the Thea library.
static HyperplaneT fromDistanceAndNormal(T dist_, VectorT const &normal_, bool normalize=true)
Construct a hyperplane from its signed distance from the origin, and its normal vector (need not be a...
Definition: HyperplaneN.hpp:53
void flip()
Flip the hyperplane so that the normal points the other way.
VectorT normal
The unit normal vector of the hyperplane.
RayIntersectionN< N, T > rayIntersection(RayN< N, T > const &ray, T max_time=-1) const
Get the intersection of a ray with the object, including the hit time and the normal at the intersect...
T eps()
An "epsilon" threshold for comparing a number to zero.
Definition: Math.hpp:189
T dist
The signed distance of the hyperplane from the origin.
A hyperplane ((N - 1)-flat) in N-dimensional space, where N is any positive (non-zero) integer and T ...
Definition: HyperplaneN.hpp:27
bool rayIntersects(RayN< N, T > const &ray, T max_time=-1) const
Check if a ray intersects the object in the forward direction.
Vector< N+1, T > getEquation() const
Get the coefficients {a_i} of the hyperplane equation a_0 * x_0 + a_1 * x_1 + ... ...
T signedDistance(VectorT const &p) const
Get the signed distance of a given point from the hyperplane.
std::string format(char const *fmt,...)
Produces a string from arguments in the style of printf.
Definition: StringAlg.cpp:305
HyperplaneN()
Default constructor.
T square(T const &x)
Compute the square of a value.
Definition: Math.hpp:97
std::string toString() const
Get a textual description of the hyperplane.
T rayIntersectionTime(RayN< N, T > const &ray, T max_time=-1) const
Get the time taken for a ray to intersect the object, or a negative value if there was no intersectio...
Vector< N, T > VectorT
N-dimensional vector.
Definition: HyperplaneN.hpp:42
std::runtime_error Error
An error class.
Definition: Error.hpp:27
VectorT const & getDirection() const
Get the direction of the ray.
Definition: RayN.hpp:56
Abstract base class for an object that supports ray intersection queries in N-space.
HyperplaneN< N, U > cast() const
Cast the hyperplane to a different scalar type.
std::vector< T, Alloc > Array
Dynamically resizable array.
Definition: Array.hpp:25
Eigen::Matrix< T, Rows, Cols, Options|((Options &Eigen::DontAlign)==0 &&(Rows==Eigen::Dynamic||Cols==Eigen::Dynamic)?Eigen::AutoAlign:Eigen::DontAlign), MaxRowsAtCompileTime, MaxColsAtCompileTime > Matrix
General 2D dense matrix template, alias for Eigen::Matrix with a custom default layout (row or column...
Definition: MatVec.hpp:114
VectorT const & getNormal() const
Get the unit normal vector of the hyperplane.
A description of the intersection point of a ray with an object.
T distance(VectorT const &p) const
Get the (unsigned) distance of a given point from the hyperplane.
void alwaysAssertM(CondT const &test, MessageT const &msg)
Check if a test condition is true, and immediately abort the program with an error code if not...
Definition: Common.hpp:66
[Internal] Base class for hyperplanes ((N - 1)-flats) in N-dimensional space, where N is any positive...
Definition: HyperplaneN.hpp:38
T squaredDistance(VectorT const &p) const
Get the square of the distance of the hyperplane from a given point.
HyperplaneN< N, T > HyperplaneT
N-dimensional hyperplane.
Definition: HyperplaneN.hpp:41