#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