1 /* Copyright Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file LineSegment.h
16         @author Jukka Jyl�nki
17         @brief The LineSegment geometry object. */
18 #pragma once
19
20 #include "../MathGeoLibFwd.h"
21 #include "../Math/float3.h"
22
23 MATH_BEGIN_NAMESPACE
24
25 /// A line segment in 3D space is a finite line with a start and end point.
26 class LineSegment
27 {
28 public:
29         /// The starting point of this line segment.
30         vec a;
31         /// The end point of this line segment. [similarOverload: a]
32         vec b;
33
34         /// The default constructor does not initialize any members of this class.
35         /** This means that the values of the members a and b are undefined after creating a new LineSegment using this
36                 default constructor. Remember to assign to them before use.
37                 @see a, b. */
38         LineSegment() {}
39
40         /// Constructs a line segment through the given end points.
41         /** @see a, b. */
42         LineSegment(const vec &aconst vec &b);
43
44         /// Constructs a line segment from a ray or a line.
45         /** This constructor takes the ray/line origin position as the starting point of this line segment, and defines the end point
46                 of the line segment using the given distance parameter.
47                 @param d The distance along the ray/line for the end point of this line segment. This will set b = ray.pos + d * ray.dir
48                         as the end point. When converting a ray to a line segment, it is possible to pass in a d value < 0, but in that case
49                         the resulting line segment will not lie on the ray.
50                 @see a, b, classes Ray, Line, Line::GetPoint(), Ray::GetPoint(). */
51         explicit LineSegment(const Ray &ray, float d);
52         explicit LineSegment(const Line &line, float d);
53
54         /// Returns a point on the line.
55         /** @param d The normalized distance along the line segment to compute. If a value in the range [0, 1] is passed, then the
56                         returned point lies along this line segment. If some other value is specified, the returned point lies on the
57                         line defined by this line segment, but not inside the interval from a to b.
58                 @note The meaning of d here differs from Line::GetPoint and Ray::GetPoint. For the class LineSegment,
59                         GetPoint(0) returns a, and GetPoint(1) returns b. This means that GetPoint(1) will not generally be exactly one unit
60                         away from the starting point of this line segment, as is the case with Line and Ray.
61                 @return (1-d)*a + d*b.
62                 @see a, b, Line::GetPoint(), Ray::GetPoint(). */
63         vec GetPoint(float dconst;
64
65         /// Returns the center point of this line segment.
66         /** This function is the same as calling GetPoint(0.5f), but provided here as conveniency.
67                 @see GetPoint(). */
68         vec CenterPoint() const;
69
70         /// Reverses the direction of this line segment.
71         /** This function swaps the start and end points of this line segment so that it runs from b to a.
72                 This does not have an effect on the set of points represented by this line segment, but it reverses
73                 the direction of the vector returned by Dir().
74                 @note This function operates in-place.
75                 @see a, b, Dir(). */
76         void Reverse();
77
78         /// Returns the normalized direction vector that points in the direction a->b.
79         /** @note The returned vector is normalized, meaning that its length is 1, not |b-a|.
80                 @see a, b. */
81         vec Dir() const;
82
83         /// Quickly returns an arbitrary point inside this LineSegment. Used in GJK intersection test.
84         inline vec AnyPointFast() const return a; }
85
86         /// Computes an extreme point of this LineSegment in the given direction.
87         /** An extreme point is a farthest point along this LineSegment in the given direction. Given a direction,
88                 this point is not necessarily unique.
89                 @param direction The direction vector of the direction to find the extreme point. This vector may
90                         be unnormalized, but may not be null.
91                 @return An extreme point of this LineSegment in the given direction. The returned point is always
92                         either a or b.
93                 @see a, b.*/
94         vec ExtremePoint(const vec &direction) const;
95         vec ExtremePoint(const vec &direction, float &projectionDistance) const;
96
97         /// Translates this LineSegment in world space.
98         /** @param offset The amount of displacement to apply to this LineSegment, in world space coordinates.
99                 @see Transform(). */
100         void Translate(const vec &offset);
101
102         /// Applies a transformation to this line.
103         /** This function operates in-place.
104                 @see Translate(), classes float3x3, float3x4, float4x4, Quat, Transform(). */
105         void Transform(const float3x3 &transform);
106         void Transform(const float3x4 &transform);
107         void Transform(const float4x4 &transform);
108         void Transform(const Quat &transform);
109
110         /// Computes the length of this line segment.
111         /** @return |b-a|.
112                 @see a, b. */
113         float Length() const;
114         /// Computes the squared length of this line segment.
115         /** Calling this function is faster than calling Length(), since this function avoids computing a square root.
116                 If you only need to compare lengths to each other and are not interested in the actual length values,
117                 you can compare by using LengthSq(), instead of Length(), since Sqrt() is an order-preserving
118                 (monotonous and non-decreasing) function. [similarOverload: Length] */
119         float LengthSq() const;
120
121         /// Tests if this line segment is finite.
122         /** A line segment is <b><i>finite</i></b> if its endpoints a and b do not contain floating-point NaNs or +/-infs
123                 in them.
124                 @return True if both a and b have finite floating-point values. */
125         bool IsFinite() const;
126
127         /// Tests if this line segment represents the same set of points than the given line segment.
128         /** @param distanceThreshold Specifies how much distance threshold to allow in the comparison.
129                 @return True if a == rhs.a && b == rhs.b, or, a == rhs.b && b = rhs.a, within the given epsilon. */
130         bool Equals(const LineSegment &rhs, float distanceThreshold = 1e-3f) const;
131
132         /// Compares whether this LineSegment and the given LineSegment are identical bit-by-bit in the underlying representation.
133         /** @note Prefer using this over e.g. memcmp, since there can be SSE-related padding in the structures. */
134         bool BitEquals(const LineSegment &other) const return a.BitEquals(other.a) && b.BitEquals(other.b); }
135
136         /// Tests if the given point or line segment is contained on this line segment.
137         /** @param distanceThreshold Because a line segment is an one-dimensional object in 3D space, an epsilon value
138                         is used as a threshold for this test. This effectively transforms this line segment to a capsule with
139                         the radius indicated by this value.
140                 @return True if this line segment contains the given point or line segment.
141                 @see Intersects, ClosestPoint(), Distance(). */
142         bool Contains(const vec &point, float distanceThreshold = 1e-3f) const;
143         bool Contains(const LineSegment &lineSegment, float distanceThreshold = 1e-3f) const;
144
145         /// Computes the closest point on this line segment to the given object.
146         /** @param d [out] If specified, this parameter receives the normalized distance along
147                         this line segment which specifies the closest point on this line segment to
148                         the specified point.
149                 @return The closest point on this line segment to the given object.
150                 @see Contains(), Distance(), Intersects(). */
151         vec ClosestPoint(const vec &point) const float dreturn ClosestPoint(point, d); }
152         vec ClosestPoint(const vec &point, float &dconst;
153         /** @param d2 [out] If specified, this parameter receives the (normalized, in case of line segment)
154                         distance along the other line object which specifies the closest point on that line to
155                         this line segment. */
156         vec ClosestPoint(const Ray &other) const float d, d2; return ClosestPoint(other, d, d2); }
157         vec ClosestPoint(const Ray &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
158         vec ClosestPoint(const Ray &other, float &dfloat &d2) const;
159         vec ClosestPoint(const Line &other) const float d, d2; return ClosestPoint(other, d, d2); }
160         vec ClosestPoint(const Line &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
161         vec ClosestPoint(const Line &other, float &dfloat &d2) const;
162         vec ClosestPoint(const LineSegment &other) const float d, d2; return ClosestPoint(other, d, d2); }
163         vec ClosestPoint(const LineSegment &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
164         vec ClosestPoint(const LineSegment &other, float &dfloat &d2) const;
165
166         /// Computes the distance between this line segment and the given object.
167         /** @param d [out] If specified, this parameter receives the normalized distance along
168                         this line segment which specifies the closest point on this line segment to
169                         the specified point.
170                 @return The distance between this line segment and the given object.
171                 @see Constains(), ClosestPoint(), Intersects(). */
172         float Distance(const vec &point) const float dreturn Distance(point, d); }
173         float Distance(const vec &point, float &dconst;
174         /** @param d2 [out] If specified, this parameter receives the (normalized, in case of line segment)
175                         distance along the other line object which specifies the closest point on that line to
176                         this line segment. */
177         float Distance(const Ray &other) const float d, d2; return Distance(other, d, d2); }
178         float Distance(const Ray &other, float &d) const float d2; return Distance(other, d, d2); }
179         float Distance(const Ray &other, float &dfloat &d2) const;
180         float Distance(const Line &other) const float d, d2; return Distance(other, d, d2); }
181         float Distance(const Line &other, float &d) const float d2; return Distance(other, d, d2); }
182         float Distance(const Line &other, float &dfloat &d2) const;
183         float Distance(const LineSegment &other) const float d, d2; return Distance(other, d, d2); }
184         float Distance(const LineSegment &other, float &d) const float d2; return Distance(other, d, d2); }
185         float Distance(const LineSegment &other, float &dfloat &d2) const;
186         float Distance(const Plane &other) const;
187         float Distance(const Sphere &other) const;
188         float Distance(const Capsule &other) const;
189
190         float DistanceSq(const vec &point) const;
191         float DistanceSq(const LineSegment &other) const;
192
193         /// Tests whether this line segment and the given object intersect.     
194         /** Both objects are treated as "solid", meaning that if one of the objects is fully contained inside
195                 another, this function still returns true. (for example, if this line segment is contained inside a sphere)
196                 @todo Output intersection point. */
197         bool Intersects(const Plane &plane) const;
198         /** @param d [out] If specified, this parameter receives the normalized distance along
199                         this line segment which specifies the closest point on this line segment to
200                         the specified point. This pointer may be null. */
201         bool Intersects(const Plane &plane, float *dconst;
202         /** @param intersectionPoint [out] If specified, receives the point of intersection. This pointer may be null. */
203         bool Intersects(const Triangle &triangle, float *d, vec *intersectionPoint) const;
204         /** @param intersectionNormal [out] If specified, receives the normal vector of the other object at the point of intersection.
205                         This pointer may be null. */
206         bool Intersects(const Sphere &s, vec *intersectionPoint = 0, vec *intersectionNormal = 0, float *d = 0) const;
207         /** @param dNear [out] If specified, receives the parametric distance along this line segment denoting where the line entered the
208                         bounding box object.
209                 @param dFar [out] If specified, receives the parametric distance along this line segment denoting where the line exited the
210                         bounding box object. */
211         bool Intersects(const AABB &aabb, float &dNear, float &dFar) const;
212         bool Intersects(const AABB &aabb) const;
213         bool Intersects(const OBB &obb, float &dNear, float &dFar) const;
214         bool Intersects(const OBB &obb) const;
215         bool Intersects(const Capsule &capsule) const;
216         bool Intersects(const Polygon &polygon) const;
217         bool Intersects(const Frustum &frustum) const;
218         bool Intersects(const Polyhedron &polyhedron) const;
219         /** @param epsilon If testing intersection between two line segments, a distance threshold value is used to account
220                         for floating-point inaccuracies. */
221         bool Intersects(const LineSegment &lineSegment, float epsilon = 1e-3f) const;
222         /// Tests if this line segment intersects the given disc.
223         /// @todo This signature will be moved to bool Intersects(const Disc &disc) const;
224         bool IntersectsDisc(const Circle &disc) const;
225
226         /// Converts this LineSegment to a Ray.
227         /** The pos member of the returned Ray will be equal to a, and the dir member equal to Dir().
228                 @see class Ray, ToLine(). */
229         Ray ToRay() const;
230         /// Converts this LineSegment to a Line.
231         /** The pos member of the returned Line will be equal to a, and the dir member equal to Dir().
232                 @see class Line, ToRay(). */
233         Line ToLine() const;
234
235         /// Projects this LineSegment onto the given 1D axis direction vector.
236         /** This function collapses this LineSegment onto an 1D axis for the purposes of e.g. separate axis test computations.
237                 The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
238                 @param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
239                         of this function gets scaled by the length of this vector.
240                 @param outMin [out] Returns the minimum extent of this object along the projection axis.
241                 @param outMax [out] Returns the maximum extent of this object along the projection axis. */
242         void ProjectToAxis(const vec &direction, float &outMin, float &outMax) const;
243
244 #ifdef MATH_ENABLE_STL_SUPPORT
245         /// Returns a human-readable representation of this LineSegment. Most useful for debugging purposes.
246         std::string ToString() const;
247         std::string SerializeToString() const;
248
249         /// Returns a string of C++ code that can be used to construct this object. Useful for generating test cases from badly behaving objects.
250         std::string SerializeToCodeString() const;
251 #endif
252
253         static LineSegment FromString(const char *str, const char **outEndStr = 0);
254 #ifdef MATH_ENABLE_STL_SUPPORT
255         static LineSegment FromString(const std::string &str) { return FromString(str.c_str()); }
256 #endif
257
258 #ifdef MATH_QT_INTEROP
259         operator QString() const return toString(); }
260         QString toString() const return QString::fromStdString(ToString()); }
261 #endif
262
263 #ifdef MATH_GRAPHICSENGINE_INTEROP
264         void ToLineList(VertexBuffer &vb) const;
265 #endif
266 };
267
268 struct LineSegment_storage
269 {
270         vec_storage a,b;
271         LineSegment_storage(){}
272         LineSegment_storage(const LineSegment &rhs)
273         {
274                 *reinterpret_cast<LineSegment*>(this) = rhs;
275         }
276         operator LineSegment() const return *reinterpret_cast<const LineSegment*>(this); }
277 };
278
279 LineSegment operator *(const float3x3 &transform, const LineSegment &line);
280 LineSegment operator *(const float3x4 &transform, const LineSegment &line);
281 LineSegment operator *(const float4x4 &transform, const LineSegment &line);
282 LineSegment operator *(const Quat &transform, const LineSegment &line);
283
284 #ifdef MATH_QT_INTEROP
285 Q_DECLARE_METATYPE(LineSegment)
286 Q_DECLARE_METATYPE(LineSegment*)
287 #endif
288
289 #ifdef MATH_ENABLE_STL_SUPPORT
290 std::ostream &operator <<(std::ostream &o, const LineSegment &lineSegment);
291 #endif
292
293 MATH_END_NAMESPACE

Go back to previous page