Files
j3ml/include/J3ML/Geometry/Circle.hpp
Redacted 47993084ff
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m29s
Build Docs With Doxygen / Explore-Gitea-Actions (push) Successful in 22s
Set up shapes for dynamic cast
2024-08-20 21:37:14 -04:00

165 lines
9.5 KiB
C++

/// Josh's 3D Math Library
/// A C++20 Library for 3D Math, Computer Graphics, and Scientific Computing.
/// Developed and Maintained by Josh O'Leary @ Redacted Software.
/// Special Thanks to William Tomasine II and Maxine Hayes.
/// (c) 2024 Redacted Software
/// This work is dedicated to the public domain.
/// @file Circle.hpp
/// @desc The Circle geometry object.
/// @edit 2024-08-01
#pragma once
#include <J3ML/Geometry/Shape.hpp>
#include <J3ML/Geometry/Forward.hpp>
#include <J3ML/LinearAlgebra.hpp>
namespace J3ML
{
/// A two-dimensional circle in 3D space.
/// This class represents both a hollow circle (only edge) and a solid circle (disc).
class Circle : public Shape
{
public:
/// The center position of this circle.
Vector3 Position;
/// The normal direction of this circle.
/** A circle is a two-dimensional object in 3D space. This normal vector (together with the Position)
specifies the plane in which this circle lies in.
This vector is always normalized. If you assign to this member directly, be sure to only assign normalized vectors. */
Vector3 Normal;
/// The radius of the circle.
/** This parameter must be strictly positive to specify a non-degenerate circle. If zero is specified, this circle
is considered to be degenerate. */
float Radius;
/// The default constructor does not initialize any members of this class.
/** This means that the values of members Position, Normal, and Radius are all undefined after creating
a new circle using this default constructor. Remember to assign them before use.
@see Position, Normal, Radius. */
Circle() {}
/// Constructs a new circle by explicitly specifying the member variables.
/** @param center The center point of the circle.
@param normal The direction vector that specifies the orientation of this circle.
This vector must be normalized, the constructor will not normalize the vector for you (for performance reasons).
@param radius The radius of the circle.
@see Position, Normal, Radius. */
Circle(const Vector3& center, const Vector3& normal, float radius);
/// Returns a normalized direction vector to the 'U direction' of the circle.
/** This vector lies on the plane of this circle.
The U direction specifies the first basis vector of a local space of this circle. */
Vector3 BasisU() const;
/// Returns a normalized direction vector to the 'V direction' of the circle.
/** This vector lies on the plane of this circle.
The V direction specifies the second basis vector of a local space of this circle. */
Vector3 BasisV() const;
/// Returns a point at the edge of this circle.
/** @param angleRadians The direction of the point to get. A full circle is generated by the range [0, 2*pi],
but it is ok to pass in values outside this range.
@note This function is equivalent to calling GetPoint(float angleRadians, float d) with a value of d == 1.
@return A point in world space at the edge of this circle. */
Vector3 GetPoint(float angleRadians) const;
/// Returns a point inside this circle.
/** @param angleRadians The direction of the point to get. A full circle is generated by the range [0, 2*pi],
but it is ok to pass in values outside this range.
@param d A value in the range [0, 1] that specifies the normalized distance of the point from the center of the circle.
A value of 0 returns the center point of this circle. A value of 1 returns a point at the edge of this circle.
The range of d is not restricted, so it is ok to pass in values larger than 1 to generate a point lying completely
outside the circle. */
Vector3 GetPoint(float angleRadians, float d) const;
/// Returns the center point of this circle.
/** This point is also the center of mass for this circle. The functions CenterPoint() and Centroid() are equivalent.
@see Position. */
Vector3 CenterPoint() const { return Position; }
Vector3 Centroid() const { return Position;}
/// Computes an extreme point of this Circle/Disc in the given direction.
/** An extreme point is a farthest point of this Circle/Disc 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 Circle/Disc in the given direction. The returned point is always at
the edge of this Circle. */
Vector3 ExtremePoint(const Vector3& direction) const;
/// Computes the plane this circle is contained in.
/** All of the points of this circle lie inside this plane.
@see class Plane. */
Plane ContainingPlane() const;
/// Translates this Circle in world space.
/** @param offset The amount of displacement to apply to this circle, in world space coordinates.
@see Transform(). */
void Translate(const Vector3& offset);
/// Applies a transformation to this Circle.
/** @param transform The transformation to apply to this Circle. This transformation must be
affine, and must contain an orthogonal set of column vectors (may not contain shear or projection).
The transformation can only contain uniform scale, and may not contain mirroring.
@see Translate(), Scale(), classes Matrix3x3, Matrix4x4, Quaternion. */
void Transform(const Matrix3x3& transform);
void Transform(const Matrix4x4& transform);
void Transform(const Quaternion& transform);
/// Tests if the given point is contained at the edge of this circle.
/** @param point The target point to test.
@param maxDistance The epsilon threshold to test the distance against. This effectively turns the circle into a torus
for this test.
@see DistanceToEdge(), DistanceToDisc(), ClosestPointToEdge(), ClosestPointToDisc().
@todo Implement DiscContains(Vector3/LineSegment/Triangle). */
bool EdgeContains(const Vector3& point, float maxDistance = 1e-6f) const;
/// Computes the distance of the given object to the edge of this circle.
/** @todo Implement DistanceToEdge(Ray/LineSegment/Line).
@return The distance of the given point to the edge of this circle. If the point is contained on this circle,
the value 0 is returned.
@see DistanceToEdge(), DistanceToDisc(), ClosestPointToDisc().*/
float DistanceToEdge(const Vector3& point) const;
/// Computes the distance of the given object to this disc (filled circle).
/** If the point is contained inside this disc, the value 0 is returned.
@see DistanceToEdge(), ClosestPointToEdge(), ClosestPointToDisc().
@todo Implement DistanceToDisc(Ray/LineSegment/Line). */
float DistanceToDisc(const Vector3& point) const;
/// Computes the closest point on the edge of this circle to the given object.
/** @todo Implement ClosestPointToEdge(Ray/LineSegment/Line).
@see DistanceToEdge(), DistanceToDisc(), ClosestPointToDisc(). */
Vector3 ClosestPointToEdge(const Vector3& point) const;
/// Computes the closest point on the disc of this circle to the given object.
/** @todo Implement ClosestPointToDisc(Ray/LineSegment/Line).
@see DistanceToEdge(), DistanceToDisc(), ClosestPointToEdge(). */
Vector3 ClosestPointToDisc(const Vector3& point) const;
/// Tests this circle for an intersection against the given plane.
/** @note For Circle-Plane intersection, there is no need to differentiate between a hollow or filled circle(disc).
@return The number of intersection points found for this circle and the given plane.
@see IntersectsDisc(). */
int Intersects(const Plane& plane, Vector3* pt1, Vector3* pt2) const;
int Intersects(const Plane& plane) const;
/// Tests this disc for an intersection against the given object.
/** @see Intersects(). */
bool IntersectsDisc(const Line& line) const;
bool IntersectsDisc(const LineSegment& lineSegment) const;
bool IntersectsDisc(const Ray& ray) const;
/// Tests if this circle intersects the faces of the given OBB.
/** @param obb The bounding box to test against. This box is treated as "hollow", i.e. only the faces of the OBB are considered to be
a part of the OBB.
@return A vector that contains all the detected points of intersection for this circle and the given OBB. If the circle is fully
contained inside the OBB, or is fully outside the OBB, no intersection occurs, and the returned vector has zero elements.
@see Intersects(), IntersectsDisc(). */
std::vector<Vector3> IntersectsFaces(const OBB& obb) const;
std::vector<Vector3> IntersectsFaces(const AABB& aabb) const;
};
Circle operator *(const Matrix3x3& transform, const Circle& circle);
Circle operator *(const Matrix4x4& transform, const Circle& circle);
Circle operator *(const Quaternion& transform, const Circle& circle);
std::ostream& operator << (std::ostream& o, const Circle& circle);
}