246 lines
14 KiB
C++
246 lines
14 KiB
C++
#pragma once
|
|
|
|
#include <J3ML/LinearAlgebra/Common.hpp>
|
|
#include <J3ML/Geometry/Common.hpp>
|
|
#include <J3ML/LinearAlgebra/Vector3.hpp>
|
|
|
|
namespace J3ML::Geometry
|
|
{
|
|
|
|
using LinearAlgebra::Vector3;
|
|
|
|
/// A line segment in 3D space is a finite line with a start and end point.
|
|
class LineSegment
|
|
{
|
|
public:
|
|
Vector3 A; /// The starting point of this line segment.
|
|
Vector3 B; /// The end point of this line segment.
|
|
public:
|
|
/// The default constructor does not initialize any members of this class.
|
|
/** This means that the values of the members A and B are undefined after creating a new LineSegment using this
|
|
default constructor. Remember to assign to them before use.
|
|
@see A, B. */
|
|
LineSegment();
|
|
/// Constructs a line segment through the given end points.
|
|
/** @see a, b. */
|
|
LineSegment(const Vector3& a, const Vector3& b);
|
|
|
|
/// Constructs a line segment from a ray or a line.
|
|
/** This constructor takes the ray/line origin position as the starting point of this line segment, and defines the end point
|
|
of the line segment using the given distance parameter.
|
|
@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
|
|
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
|
|
the resulting line segment will not lie on the ray.
|
|
@see a, b, classes Ray, Line, Line::GetPoint(), Ray::GetPoint() */
|
|
explicit LineSegment(const Ray &ray, float d);
|
|
|
|
explicit LineSegment(const Line &line, float d);
|
|
|
|
|
|
/// Tests if the given point or line segment is contained on this line segment.
|
|
/** @param distanceThreshold Because a line segment is an one-dimensional object in 3D space, an epsilon value
|
|
is used as a threshold for this test. This effectively transforms this line segment to a capsule with
|
|
the radius indicated by this value.
|
|
@return True if this line segment contains the given point or line segment.
|
|
@see Intersects, ClosestPoint(), Distance(). */
|
|
bool Contains(const Vector3& point, float distanceThreshold = 1e-3f) const;
|
|
bool Contains(const LineSegment &lineSegment, float distanceThreshold = 1e-3f) const;
|
|
|
|
/// Quickly returns an arbitrary point inside this LineSegment. Used in GJK intersection test.
|
|
Vector3 AnyPointFast() const;
|
|
|
|
/// Computes an extreme point of this LineSegment in the given direction.
|
|
/** An extreme point is a farthest point along this LineSegment in the given direction. Given a direction,
|
|
this point is not necessarily unique.
|
|
@param direction The direction vector of the direction to find the extreme point. This vector may
|
|
be unnormalized, but may not be null.
|
|
@return An extreme point of this LineSegment in the given direction. The returned point is always
|
|
either a or b.
|
|
@see a, b.*/
|
|
[[nodiscard]] Vector3 ExtremePoint(const Vector3 &direction) const;
|
|
Vector3 ExtremePoint(const Vector3 &direction, float &projectionDistance) const;
|
|
|
|
/// Translates this LineSegment in world space.
|
|
/** @param offset The amount of displacement to apply to this LineSegment, in world space coordinates.
|
|
@see Transform(). */
|
|
void Translate(const Vector3 &offset);
|
|
|
|
/// Applies a transformation to this line.
|
|
/** This function operates in-place.
|
|
@see Translate(), classes Matrix3x3, Matrix4x4, Quaternion, Transform(). */
|
|
void Transform(const Matrix3x3 &transform);
|
|
void Transform(const Matrix4x4 &transform);
|
|
void Transform(const Quaternion &transform);
|
|
|
|
void ProjectToAxis(const Vector3 &direction, float &outMin, float &outMax) const;
|
|
|
|
/// Returns a point on the line.
|
|
/** @param d The normalized distance along the line segment to compute. If a value in the range [0, 1] is passed, then the
|
|
returned point lies along this line segment. If some other value is specified, the returned point lies on the
|
|
line defined by this line segment, but not inside the interval from a to b.
|
|
@note The meaning of d here differs from Line::GetPoint and Ray::GetPoint. For the class LineSegment,
|
|
GetPoint(0) returns a, and GetPoint(1) returns b. This means that GetPoint(1) will not generally be exactly one unit
|
|
away from the starting point of this line segment, as is the case with Line and Ray.
|
|
@return (1-d)*a + d*b.
|
|
@see a, b, Line::GetPoint(), Ray::GetPoint(). */
|
|
[[nodiscard]] Vector3 GetPoint(float d) const;
|
|
|
|
/// Returns the center point of this line segment.
|
|
/** This function is the same as calling GetPoint(0.5f), but provided here as conveniency.
|
|
@see GetPoint(). */
|
|
[[nodiscard]] Vector3 CenterPoint() const;
|
|
|
|
/// Reverses the direction of this line segment.
|
|
/** This function swaps the start and end points of this line segment so that it runs from b to a.
|
|
This does not have an effect on the set of points represented by this line segment, but it reverses
|
|
the direction of the vector returned by Dir().
|
|
@note This function operates in-place.
|
|
@see a, b, Dir(). */
|
|
void Reverse();
|
|
|
|
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Vector3& point) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @param d [out] If specified, this parameter receives the normalized distance along
|
|
this line segment which specifies the closest point on this line segment to
|
|
the specified point.
|
|
@return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Vector3& point, float& d) const;
|
|
|
|
/** @param d2 [out] If specified, this parameter receives the (normalized, in case of line segment)
|
|
distance along the other line object which specifies the closest point on that line to
|
|
this line segment. */
|
|
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Ray& other) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Ray& other, float &d) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Ray& other, float &d, float &d2) const;
|
|
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Line& other) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Line& other, float &d) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const Line &other, float &d, float &d2) const;
|
|
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const LineSegment& other) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const LineSegment& other, float &d) const;
|
|
/// Computes the closest point on this line segment to the given object.
|
|
/** @return The closest point on this line segment to the given object.
|
|
@see Contains(), Distance(), Intersects(). */
|
|
Vector3 ClosestPoint(const LineSegment& other, float &d, float &d2) const;
|
|
|
|
|
|
|
|
[[nodiscard]] float Distance(const Vector3 &point) const;
|
|
[[nodiscard]] float DistanceSq(const Vector3& point) const;
|
|
[[nodiscard]] float DistanceSq(const LineSegment &other) const;
|
|
float Distance(const Vector3 &point, float &d) const;
|
|
[[nodiscard]] float Distance(const Ray &other) const;
|
|
float Distance(const Ray &other, float &d) const;
|
|
float Distance(const Ray &other, float &d, float &d2) const;
|
|
[[nodiscard]] float Distance(const Line &other) const;
|
|
float Distance(const Line &other, float &d) const;
|
|
float Distance(const Line &other, float &d, float &d2) const;
|
|
[[nodiscard]] float Distance(const LineSegment &other) const;
|
|
float Distance(const LineSegment &other, float &d) const;
|
|
float Distance(const LineSegment &other, float &d, float &d2) const;
|
|
[[nodiscard]] float Distance(const Plane& other) const;
|
|
|
|
/// Returns the normalized direction vector that points in the direction a->b.
|
|
/** @note The returned vector is normalized, meaning that its length is 1, not |b-a|.
|
|
@see a, b. */
|
|
[[nodiscard]] Vector3 Dir() const;
|
|
|
|
/// Computes the length of this line segment.
|
|
/** @return |b-a|.
|
|
@see a, b. */
|
|
[[nodiscard]] float Length() const;
|
|
|
|
/// Computes the squared length of this line segment.
|
|
/** Calling this function is faster than calling Length(), since this function avoids computing a square root.
|
|
If you only need to compare lengths to each other and are not interested in the actual length values,
|
|
you can compare by using LengthSq(), instead of Length(), since Sqrt() is an order-preserving
|
|
(monotonous and non-decreasing) function. [similarOverload: Length] */
|
|
[[nodiscard]] float LengthSq() const;
|
|
|
|
/// Tests if this line segment is finite.
|
|
/** A line segment is <b><i>finite</i></b> if its endpoints a and b do not contain floating-point NaNs or +/-infs
|
|
in them.
|
|
@return True if both a and b have finite floating-point values. */
|
|
[[nodiscard]] bool IsFinite() const;
|
|
|
|
|
|
/// Tests whether this line segment and the given object intersect.
|
|
/** Both objects are treated as "solid", meaning that if one of the objects is fully contained inside
|
|
another, this function still returns true. (for example, if this line segment is contained inside a sphere)
|
|
@todo Output intersection point. */
|
|
bool Intersects(const Plane& plane) const;
|
|
bool Intersects(const Plane& plane, float* d) const;
|
|
bool Intersects(const Triangle& triangle, float* d, Vector3* intersectionPoint) const;
|
|
bool Intersects(const Sphere& s, Vector3* intersectionPoint = 0, Vector3* intersectionNormal = 0, float* d = 0) const;
|
|
bool Intersects(const AABB& aabb, float& dNear, float& dFar) const;
|
|
bool Intersects(const AABB& aabb) const;
|
|
bool Intersects(const OBB& obb, float& dNear, float& dFar) const;
|
|
bool Intersects(const OBB& obb) const;
|
|
bool Intersects(const Capsule& capsule) const;
|
|
bool Intersects(const Polygon& polygon) const;
|
|
bool Intersects(const Frustum& frustum) const;
|
|
bool Intersects(const Polyhedron& polyhedron) const;
|
|
/** @param epsilon If testing intersection between two line segments, a distance threshold value is used to account
|
|
for floating-point inaccuracies. */
|
|
bool Intersects(const LineSegment &segment, float epsilon = 1e-3f) const;
|
|
|
|
// TODO: Implement Circle class.
|
|
// TODO: This signature will be moved to bool Intersects(const Disc& disc) const;
|
|
//bool IntersectsDisc(const Circle& disc) const;
|
|
|
|
/// Converts this LineSegment to a Ray.
|
|
/** The pos member of the returned Ray will be equal to a, and the dir member equal to Dir().
|
|
@see class Ray, ToLine() */
|
|
[[nodiscard]] Ray ToRay() const;
|
|
|
|
/// Converts this LineSegment to a Line.
|
|
/** The pos member of the returned Line will be equal to a, and the dir member equal to Dir().
|
|
@see class Line, ToRay() */
|
|
[[nodiscard]] Line ToLine() const;
|
|
|
|
/// Tests if this line segment represents the same set of points than the given line segment.
|
|
/** @param distanceThreshold Specifies how much distance threshold to allow in the comparison.
|
|
@return True if a == rhs.a && b == rhs.b, or, a == rhs.b && b = rhs.a, within the given epsilon. */
|
|
bool Equals(const LineSegment &rhs, float distanceThreshold = 1e-3f) const;
|
|
|
|
/// Compares whether this LineSegment and the given LineSegment are identical bit-by-bit in the underlying representation.
|
|
/** @note Prefer using this over e.g. memcmp, since there can be SSE-related padding in the structures. */
|
|
//bool BitEquals(const LineSegment &other) const { return a.BitEquals(other.a) && b.BitEquals(other.b); }
|
|
|
|
|
|
/// Ret
|
|
};
|
|
|
|
LineSegment operator *(const Matrix4x4 &transform, const LineSegment &l);
|
|
} |