#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2015 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_GEOMETRY_VOLUMES_GENERATORS_SPHERE3GENERATOR_H
#define NUCLEX_GEOMETRY_VOLUMES_GENERATORS_SPHERE3GENERATOR_H
#include "Nuclex/Geometry/Config.h"
#include "Nuclex/Geometry/Volumes/Sphere3.h"
#include "Nuclex/Geometry/Volumes/Box3.h"
namespace Nuclex { namespace Geometry { namespace Volumes { namespace Generators {
// ------------------------------------------------------------------------------------------- //
/// Point and volume generation methods for 3D spheres
template
class Sphere3Generator {
/// Generates a random point within a sphere
/// Sphere in which a random point will be generated
/// Random number generator that will be used
/// A random point inside the sphere
public: template Point3
static GetRandomPointInside(const Sphere3 &sphere, TRandomNumberEngine &random) {
TScalar x = Math::Random(random, -1, +1);
TScalar y = Math::Random(random, -1, +1);
TScalar z = Math::Random(random, -1, +1);
TScalar distance = Math::SquareRoot(x * x + y * y + z * z);
TScalar factor = (sphere.Radius * Math::Random(random, 1)) / distance;
return Point3(
sphere.Center.X + x * factor,
sphere.Center.Y + y * factor,
sphere.Center.Z + z * factor
);
}
/// Generates a random point on the hull of a sphere
/// Sphere on which a random point will be generated
/// Random number generator that will be used
/// A random point on the hull of the sphere
public: template Point3
static GetRandomPointOnHull(const Sphere3 &sphere, TRandomNumberEngine &random) {
TScalar z = Math::Random(random, -1, +1);
TScalar t = Math::Random(random, Math::Perigon());
TScalar r = Math::SquareRoot(1 - (z * z));
return Point3(
sphere.Center.X + sphere.Radius * r * Math::Cosine(t),
sphere.Center.Y + sphere.Radius * r * Math::Sine(t),
sphere.Center.Z + sphere.Radius * z
);
}
/// Determines the closest point to another point on the sphere's hull
/// Sphere upon which the closest point will be found
/// Point to which the closest point will be determined
/// The closest point to the specified point on the sphere's hull
public: Point3 GetClosestPointOnHull(
const Sphere3 &sphere, const Point3 &point
) {
TScalar offsetX = point.X - sphere.Center.X;
TScalar offsetY = point.Y - sphere.Center.Y;
TScalar offsetZ = point.Z - sphere.Center.Z;
TScalar squaredDistance = (offsetX * offsetX) + (offsetY * offsetY) + (offsetZ * offsetZ);
if(squaredDistance == 0) {
return Point3(
sphere.Center.X + sphere.Radius, sphere.Center.Y, sphere.Center->Z
);
} else {
float distanceFactor = sphere.Radius / Math::SquareRoot(squaredDistance);
return Point3(
sphere.Center.X + (offsetX * distanceFactor),
sphere.Center.Y + (offsetY * distanceFactor),
sphere.Center.Z + (offsetZ * distanceFactor)
);
}
}
/// Determines the closest point to another point inside the sphere
/// Sphere within which the closest point will be found
/// Point to which the closest point will be determined
/// The closest point to the specified point inside the sphere
public: Point3 GetClosestPointInside(
const Sphere3 &sphere, const Point3 &point
) {
TScalar offsetX = point.X - sphere.Center.X;
TScalar offsetY = point.Y - sphere.Center.Y;
TScalar offsetZ = point.Z - sphere.Center.Z;
TScalar squaredDistance = (offsetX * offsetX) + (offsetY * offsetY) + (offsetZ * offsetZ);
if(squaredDistance <= (sphere.Radius * sphere.Radius)) {
return point;
} else {
float distanceFactor = sphere.Radius / Math::SquareRoot(squaredDistance);
return Point3(
sphere.Center.X + (offsetX * distanceFactor),
sphere.Center.Y + (offsetY * distanceFactor),
sphere.Center.Z + (offsetZ * distanceFactor)
);
}
}
/// Calculates the bounding box of the specified sphere
/// Sphere of which the bounding box will be calculated
/// The bounding box of the specified sphere
public: static Box3 GetBoundingBox(const Sphere3 &sphere) {
return Box3::FromMinMax(
sphere.Center.X - sphere.Radius,
sphere.Center.Y - sphere.Radius,
sphere.Center.Z - sphere.Radius,
sphere.Center.X + sphere.Radius,
sphere.Center.Y + sphere.Radius,
sphere.Center.Z + sphere.Radius
);
}
/// Calculates the bounding sphere of the specified sphere
/// Sphere of which the bounding sphere will be calculated
/// The bounding sphere of the specified sphere
///
/// This is a no-op, but provided for completeness so templated algorithms
/// can assume this member to be there in any generator type.
///
public: static Sphere3 GetBoundingSphere(const Sphere3 &sphere) {
return sphere;
}
};
// ------------------------------------------------------------------------------------------- //
}}}} // namespace Nuclex::Geometry::Volumes::Generators
#endif // NUCLEX_GEOMETRY_VOLUMES_GENERATORS_SPHERE3GENERATOR_H