// Copyright Epic Games, Inc. All Rights Reserved. #include "MinVolumeSphere3.h" #include "ThirdParty/GTEngine/Mathematics/GteBSNumber.h" #include "ThirdParty/GTEngine/Mathematics/GteBSRational.h" #include "ThirdParty/GTEngine/Mathematics/GteUIntegerFP32.h" #include "ThirdParty/GTEngine/Mathematics/GteUIntegerAP32.h" #include "ThirdParty/GTEngine/Mathematics/GteMinimumVolumeSphere3.h" using namespace UE::Geometry; using namespace UE::Math; namespace UE { namespace Geometry { template struct TMinVolumeSphere3Internal { //using PreciseNumberType = gte::BSRational>; using PreciseNumberType = gte::BSRational; using DVector3 = gte::Vector3; bool bUseExact; TArray DoubleInput; TVector Center; RealType Radius; bool bIsMinimalSphere; bool bSolutionOK; void SetPoint(int32 Index, const TVector& Point) { DoubleInput[Index] = DVector3{ {(double)Point.X, (double)Point.Y, (double)Point.Z} }; } gte::MinimumVolumeSphere3 DoubleCompute; gte::MinimumVolumeSphere3 PreciseCompute; bool ComputeResult() { gte::Sphere3 MinimalSphere; if (bUseExact) { bIsMinimalSphere = PreciseCompute(DoubleInput.Num(), &DoubleInput[0], MinimalSphere); bSolutionOK = true; } else { bIsMinimalSphere = DoubleCompute(DoubleInput.Num(), &DoubleInput[0], MinimalSphere); bSolutionOK = true; } Center = TVector((RealType)MinimalSphere.center[0], (RealType)MinimalSphere.center[1], (RealType)MinimalSphere.center[2]); Radius = (RealType)MinimalSphere.radius; return true; } }; } // end namespace UE::Geometry } // end namespace UE template bool TMinVolumeSphere3::Solve(int32 NumPoints, TFunctionRef(int32)> GetPointFunc, bool bUseExactComputation) { Initialize(NumPoints, bUseExactComputation); check(Internal); for (int32 k = 0; k < NumPoints; ++k) { TVector Point = GetPointFunc(k); Internal->SetPoint(k, Point); } return Internal->ComputeResult(); } template bool TMinVolumeSphere3::IsSolutionAvailable() const { return Internal && Internal->bSolutionOK; } template void TMinVolumeSphere3::GetResult(TSphere3& SphereOut) { ensure(IsSolutionAvailable()); SphereOut.Center = Internal->Center; SphereOut.Radius = Internal->Radius; } template void TMinVolumeSphere3::Initialize(int32 NumPoints, bool bUseExactComputation) { Internal = MakePimpl>(); Internal->bUseExact = bUseExactComputation; Internal->DoubleInput.SetNum(NumPoints); } namespace UE { namespace Geometry { template class GEOMETRYALGORITHMS_API TMinVolumeSphere3; template class GEOMETRYALGORITHMS_API TMinVolumeSphere3; } // end namespace UE::Geometry } // end namespace UE