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 Line.h
16         @author Jukka Jyl�nki
17         @brief Implementation for the Line geometry object. */
18 #pragma once
19
20 #include "../MathGeoLibFwd.h"
21 #include "../Math/float3.h"
22
23 MATH_BEGIN_NAMESPACE
24
25 /// A line in 3D space is defined by an origin point and a direction, and extends to infinity in two directions.
26 class Line
27 {
28 public:
29         /// Specifies the origin of this line.
30         vec pos;
31
32         /// The normalized direction vector of this ray. [similarOverload: pos]
33         /** @note For proper functionality, this direction vector needs to always be normalized. If you set to this
34                 member manually, remember to make sure you only assign normalized direction vectors. */
35         vec dir;
36
37         /// The default constructor does not initialize any members of this class.
38         /** This means that the values of the members pos and dir are undefined after creating a new Line using this
39                 default constructor. Remember to assign to them before use.
40                 @see pos, dir. */
41         Line() {}
42
43         /// Constructs a new line by explicitly specifying the member variables.
44         /** @param pos The origin position of the line.
45                 @param dir The direction of the line. This vector must be normalized, this function will not normalize
46                         the vector for you (for performance reasons).
47                 @see pos, dir. */
48         Line(const vec &posconst vec &dir);
49
50         /// Converts a Ray to a Line.
51         /** This conversion simply copies the members pos and dir over from the given Ray to this Line.
52                 This means that the new Line starts at the same position, but extends to two directions in space,
53                 instead of one.
54                 @see class Ray, ToRay(). */
55         explicit Line(const Ray &ray);
56
57         /// Converts a LineSegment to a Line.
58         /** This constructor sets pos = lineSegment.a, and dir = (lineSegment.b - lineSegment.a).Normalized().
59                 @see class LineSegment, ToLineSegment(). */
60         explicit Line(const LineSegment &lineSegment);
61
62         bool IsFinite() const;
63
64         /// Gets a point along the line at the given distance.
65         /** Use this function to convert a 1D parametric point along the Line to a 3D point in the linear space.
66                 @param distance The point to compute. GetPoint(0) will return pos. GetPoint(t) will return a point
67                         at distance |t| from pos, towards the direction specified by dir. If a negative value is specified,
68                         a point towards the direction -dir is returned.
69                 @return pos + distance * dir.
70                 @see pos, dir. */
71         vec GetPoint(float distance) const;
72
73         /// Translates this Line in world space.
74         /** @param offset The amount of displacement to apply to this Line, in world space coordinates.
75                 @see Transform(). */
76         void Translate(const vec &offset);
77
78         /// Applies a transformation to this line, in-place.
79         /** @see Translate(), classes float3x3, float3x4, float4x4, Quat. */
80         void Transform(const float3x3 &transform);
81         void Transform(const float3x4 &transform);
82         void Transform(const float4x4 &transform);
83         void Transform(const Quat &transform);
84
85         /// Tests if the given object is fully contained on this line.
86         /** @param distanceThreshold The magnitude of the epsilon test threshold to use. Since a Line
87                 is a 1D object in a 3D space, an epsilon threshold is used to allow errors caused by floating-point
88                 inaccuracies.
89                 @return True if this line contains the given object, up to the given distance threshold.
90                 @see class LineSegment, class Ray, Distance(), ClosestPoint(), Intersects(). */
91         bool Contains(const vec &point, float distanceThreshold = 1e-3f) const;
92         bool Contains(const Ray &ray, float distanceThreshold = 1e-3f) const;
93         bool Contains(const LineSegment &lineSegment, float distanceThreshold = 1e-3f) const;
94
95         /// Tests if two lines are equal.
96         /** This function tests for set equality (not just member value equality). This means that the pos and dir parameters
97                 of either line can be completely different, as long as the set of points on the both lines are equal.
98                 @return True if this and the given Line represent the same set of points, up to the given epsilon. */
99         bool Equals(const Line &line, float epsilon = 1e-3f) const;
100
101         /// Compares whether this Line and the given Line are identical bit-by-bit in the underlying representation.
102         /** @note Prefer using this over e.g. memcmp, since there can be SSE-related padding in the structures. */
103         bool BitEquals(const Line &other) const return pos.BitEquals(other.pos) && dir.BitEquals(other.dir); }
104
105         /// Computes the distance between this line and the given object.
106         /** This function finds the nearest pair of points on this and the given object, and computes their distance.
107                 If the two objects intersect, or one object is contained inside the other, the returned distance is zero.
108                 @param d [out] If specified, receives the parametric distance along this line that
109                         specifies the closest point on this line to the given object. The value returned here can be negative.
110                 @see Contains(), Intersects(), ClosestPoint(), GetPoint(). */
111         float Distance(const vec &point) const float dreturn Distance(point, d); }
112         float Distance(const vec &point, float &dconst;
113         /** @param d2 [out] If specified, receives the parametric distance along the other line that specifies the
114                 closest point on that line to this line. The value returned here can be negative. */
115         float Distance(const Ray &other) const float d, d2; return Distance(other, d, d2); }
116         float Distance(const Ray &other, float &d) const float d2; return Distance(other, d, d2); }
117         float Distance(const Ray &other, float &dfloat &d2) const;
118         float Distance(const Line &other) const float d, d2; return Distance(other, d, d2); }
119         float Distance(const Line &other, float &d) const float d2; return Distance(other, d, d2); }
120         float Distance(const Line &other, float &dfloat &d2) const;
121         float Distance(const LineSegment &other) const float d, d2; return Distance(other, d, d2); }
122         float Distance(const LineSegment &other, float &d) const float d2; return Distance(other, d, d2); }
123         float Distance(const LineSegment &other, float &dfloat &d2) const;
124         float Distance(const Sphere &other) const;
125         float Distance(const Capsule &other) const;
126
127         /// Computes the closest point on this line to the given object.
128         /** If the other object intersects this line, this function will return an arbitrary point inside
129                 the region of intersection.
130                 @param d [out] If specified, receives the parametric distance along this line that
131                         specifies the closest point on this line to the given object. The value returned here can be negative.
132                 @see Contains(), Distance(), Intersects(), GetPoint(). */
133         vec ClosestPoint(const vec &targetPoint) const float dreturn ClosestPoint(targetPoint, d); }
134         vec ClosestPoint(const vec &targetPoint, float &dconst;
135         /** @param d2 [out] If specified, receives the parametric distance along the other line that specifies the
136                 closest point on that line to this line. The value returned here can be negative. */
137         vec ClosestPoint(const Ray &other) const float d, d2; return ClosestPoint(other, d, d2); }
138         vec ClosestPoint(const Ray &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
139         vec ClosestPoint(const Ray &other, float &dfloat &d2) const;
140         vec ClosestPoint(const Line &other) const float d, d2; return ClosestPoint(other, d, d2); }
141         vec ClosestPoint(const Line &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
142         vec ClosestPoint(const Line &other, float &dfloat &d2) const;
143         vec ClosestPoint(const LineSegment &other) const float d, d2; return ClosestPoint(other, d, d2); }
144         vec ClosestPoint(const LineSegment &other, float &d) const float d2; return ClosestPoint(other, d, d2); }
145         vec ClosestPoint(const LineSegment &other, float &dfloat &d2) const;
146         /** @param outBarycentricUV [out] If specified, receives the barycentric UV coordinates (in two-coordinate barycentric UV convention)
147                         representing the closest point on the triangle to this line.
148                 @see Contains(), Distance(), Intersects(), GetPoint(), Triangle::Point(float u, float v). */
149         vec ClosestPoint(const Triangle &triangle) const float dreturn ClosestPoint(triangle, d); }
150         vec ClosestPoint(const Triangle &triangle, float &dconst;
151         vec ClosestPoint(const Triangle &triangle, float &dfloat2 &outBarycentricUV) const;
152
153         /// Tests whether this line and the given object intersect.     
154         /** Both objects are treated as "solid", meaning that if one of the objects is fully contained inside
155                 another, this function still returns true.
156                 @param d [out] If specified, this parameter will receive the parametric distance of
157                         the intersection point along this object. Use the GetPoint(d) function
158                         to get the actual point of intersection. This pointer may be null.
159                 @param intersectionPoint [out] If specified, receives the actual point of intersection. This pointer
160                         may be null.
161                 @return True if an intersection occurs or one of the objects is contained inside the other, false otherwise.
162                 @see Contains(), Distance(), ClosestPoint(), GetPoint(). */
163         bool Intersects(const Triangle &triangle, float *d, vec *intersectionPoint) const;
164         bool Intersects(const Plane &plane, float *dconst;
165         /** @param intersectionNormal [out] If specified, receives the surface normal of the other object at
166                 the point of intersection. This pointer may be null. */
167         bool Intersects(const Sphere &s, vec *intersectionPoint = 0, vec *intersectionNormal = 0, float *d = 0) const;
168         /** @param dNear [out] If specified, receives the distance along this line to where the line enters
169                 the bounding box.
170                 @param dFar [out] If specified, receives the distance along this line to where the line exits
171                 the bounding box. */
172         bool Intersects(const AABB &aabb, float &dNear, float &dFar) const;
173         bool Intersects(const AABB &aabb) const;
174         bool Intersects(const OBB &obb, float &dNear, float &dFar) const;
175         bool Intersects(const OBB &obb) const;
176         bool Intersects(const Capsule &capsule) const;
177         bool Intersects(const Polygon &polygon) const;
178         bool Intersects(const Frustum &frustum) const;
179         bool Intersects(const Polyhedron &polyhedron) const;
180         /// Tests if this ray intersects the given disc.
181         /// @todo This signature will be moved to bool Intersects(const Disc &disc) const;
182         bool IntersectsDisc(const Circle &disc) const;
183
184         /// Converts this Line to a Ray.
185         /** The pos and dir members of the returned Ray will be equal to this Line. The only difference is
186                 that a Line extends to infinity in two directions, whereas the returned Ray spans only in
187                 the positive direction.
188                 @see dir, Line::Line, class Ray, ToLineSegment(). */
189         Ray ToRay() const;
190
191         /// Converts this Line to a LineSegment.
192         /** @param d Specifies the position of the other endpoint along this Line. This parameter may be negative.
193                 @return A LineSegment with point a at pos, and point b at pos + d * dir.
194                 @see pos, dir, Line::Line, class LineSegment, ToRay(). */
195         LineSegment ToLineSegment(float dconst;
196
197         /// Converts this Line to a LineSegment.
198         /** @param dStart Specifies the position of the first endpoint along this Line. This parameter may be negative,
199                 in which case the starting point lies to the opposite direction of the Line.
200                 @param dEnd Specifies the position of the second endpoint along this Line. This parameter may also be negative.
201                 @return A LineSegment with point a at pos + dStart * dir, and point b at pos + dEnd * dir.
202                 @see pos, dir, Line::Line, class LineSegment, ToLine(). */
203         LineSegment ToLineSegment(float dStart, float dEnd) const;
204
205         /// Projects this Line onto the given 1D axis direction vector.
206         /** This function collapses this Line onto an 1D axis for the purposes of e.g. separate axis test computations.
207                 The function returns a 1D range [outMin, outMax] denoting the interval of the projection.
208                 @param direction The 1D axis to project to. This vector may be unnormalized, in which case the output
209                         of this function gets scaled by the length of this vector.
210                 @param outMin [out] Returns the minimum extent of this object along the projection axis.
211                 @param outMax [out] Returns the maximum extent of this object along the projection axis. */
212         void ProjectToAxis(const vec &direction, float &outMin, float &outMax) const;
213
214         /// Tests if the given three points are collinear.
215         /** This function tests whether the given three functions all lie on the same line.
216                 @param epsilon The comparison threshold to use to account for floating-point inaccuracies. */
217         static bool AreCollinear(const vec &p1, const vec &p2, const vec &p3, float epsilon = 1e-3f);
218
219         static void ClosestPointLineLine(const vec &start0, const vec &dir0, const vec &start1, const vec &dir1, float &dfloat &d2);
220
221 #ifdef MATH_ENABLE_STL_SUPPORT
222         /// Returns a human-readable representation of this Line.
223         /** The returned string specifies the position and direction of this Line. */
224         std::string ToString() const;
225         std::string SerializeToString() const;
226
227         /// Returns a string of C++ code that can be used to construct this object. Useful for generating test cases from badly behaving objects.
228         std::string SerializeToCodeString() const;
229 #endif
230
231         static Line FromString(const char *str, const char **outEndStr = 0);
232 #ifdef MATH_ENABLE_STL_SUPPORT
233         static Line FromString(const std::string &str) { return FromString(str.c_str()); }
234 #endif
235
236 #ifdef MATH_QT_INTEROP
237         operator QString() const return toString(); }
238         QString toString() const return QString::fromStdString(ToString()); }
239 #endif
240 };
241
242 Line operator *(const float3x3 &transform, const Line &line);
243 Line operator *(const float3x4 &transform, const Line &line);
244 Line operator *(const float4x4 &transform, const Line &line);
245 Line operator *(const Quat &transform, const Line &line);
246
247 #ifdef MATH_QT_INTEROP
248 Q_DECLARE_METATYPE(Line)
249 Q_DECLARE_METATYPE(Line*)
250 #endif
251
252 #ifdef MATH_ENABLE_STL_SUPPORT
253 std::ostream &operator <<(std::ostream &o, const Line &line);
254 #endif
255
256 MATH_END_NAMESPACE

Go back to previous page