Files
j3ml/include/J3ML/Geometry/Sphere.hpp
josh bf794ce092
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m37s
Build Docs With Doxygen / Explore-Gitea-Actions (push) Successful in 29s
Sending up work
2024-10-23 14:16:41 -04:00

124 lines
6.1 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 Sphere.hpp
/// @desc The Sphere geometry object.
/// @edit 2024-07-06
#pragma once
#include <J3ML/Geometry/Shape.hpp>
#include <J3ML/Geometry/Forward.hpp>
#include <J3ML/LinearAlgebra.hpp>
namespace J3ML::Geometry
{
// A mathematical representation of a 3-dimensional sphere
class Sphere : public Shape
{
public: // Properties
Vector3 Position; // The center point of this sphere.
float Radius; /// The radius of this sphere.
public: // Constructors
/// The default constructor does not initialize any members of this class.
/** This means that the values of the members pos and r are undefined after creating a new Sphere using this
default constructor. Remember to assign to them before use.
@see pos, r. */
Sphere() {}
/// Constructs a sphere with a given position and radius.
/** @param radius A value > 0 constructs a sphere with positive volume. A value of <= 0 is valid, and constructs a degenerate sphere.
@see pos, r, IsFinite(), IsDegenerate() */
Sphere(const Vector3& pos, float radius) : Position(pos), Radius(radius) {}
/// Constructs a sphere that passes through the given two points.
/** The constructed sphere will be the minimal sphere that encloses the given two points. The center point of this
sphere will lie midway between pointA and pointB, and the radius will be half the distance between pointA and
pointB. Both input points are assumed to be finite. */
Sphere(const Vector3 &pointA, const Vector3 &pointB);
/// Constructs a sphere that passes through the given three points.
/** @note The resulting sphere may not be the minimal enclosing sphere for the three points! */
Sphere(const Vector3 &pointA, const Vector3 &pointB, const Vector3 &pointC);
/// Constructs a sphere that passes through the given four points.
/** @note The resulting sphere may not be the minimal enclosing sphere for the four points! */
Sphere(const Vector3 &pointA, const Vector3 &pointB, const Vector3 &pointC, const Vector3 &pointD);
public:
/// Generates a random point on the surface of this sphere
/** The points are distributed uniformly.
This function uses the rejection method to generate a uniform distribution of points on the surface.
Therefore, it is assumed that this sphere is not degenerate, i.e. it has a positive radius.
A fixed number of 1000 tries is performed, after which a fixed point on the surface is returned as a fallback.
@param rng A pre-seeded random number generator object that is to be used by this function to generate random vlaues.
@see class RNG, RandomPointInside(), IsDegenerate()
@todo Add Sphere::PointOnSurface(polarYaw, polarPitch). */
Vector3 RandomPointOnSurface(RNG& rng) const;
static Vector3 RandomPointOnSurface(RNG& rng, const Vector3& center, float radius);
/// Generates a random point inside this sphere.
/** The points are distributed uniformly.
This function uses the rejection method to generate a uniform distribution of points inside a sphere.
Therefore, it is assumed that this sphere is not degenerate, i.e. it has a positive radius.
A fixed number of 1000 tries is performed, after which the sphere center position is returned as a fallback.
@param rng A pre-seeded random number generator object that is to be used by this function to generate random values.
@see class RNG, RandomPointOnSurface(), IsDegenerate().
@todo Add Sphere::Point(polarYaw, polarPitch, radius). */
Vector3 RandomPointInside(RNG& rng);
static Vector3 RandomPointInside(RNG& rng, const Vector3& center, float radius);
public:
/// Quickly returns an arbitrary point inside this Sphere. Used in GJK intersection test.
[[nodiscard]] Vector3 AnyPointFast() const { return Position; }
/// Computes the extreme point of this Sphere in the given direction.
/** An extreme point is a farthest point of this Sphere in the given direction. For
a Sphere, this point is 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 The extreme point of this Sphere in the given direction. */
[[nodiscard]] Vector3 ExtremePoint(const Vector3 &direction) const;
Vector3 ExtremePoint(const Vector3 &direction, float &projectionDistance) const;
Vector3 Centroid() const { return Position; }
Vector3 CenterPos() const { return Centroid(); }
/// Translates this Sphere in world space.
/** @param offset The amount of displacement to apply to this Sphere, in world space coordinates.
@see Transform(). */
void Translate(const Vector3& offset);
void Transform(const Matrix3x3& transform);
void Transform(const Matrix4x4& transform);
static inline float Cube(float inp);
[[nodiscard]] float Volume() const;
[[nodiscard]] float SurfaceArea() const;
[[nodiscard]] bool IsFinite() const;
[[nodiscard]] bool IsDegenerate() const;
[[nodiscard]] bool Contains(const Vector3& point) const;
[[nodiscard]] bool Contains(const Vector3& point, float epsilon) const;
[[nodiscard]] bool Contains(const LineSegment& lineseg) const;
TriangleMesh GenerateUVSphere(int subdivisions = 10.f) const;
TriangleMesh GenerateIcososphere() const;
TriangleMesh GenerateCubesphere() const;
void ProjectToAxis(const Vector3 &direction, float &outMin, float &outMax) const;
};
}