// Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumEllipsoid.h" #include "CesiumEllipsoidFunctions.h" #include "CesiumGeoreference.h" #include "CesiumRuntime.h" #include "VecMath.h" #include "EngineUtils.h" #include "MathUtil.h" #include "UObject/ConstructorHelpers.h" #include "UObject/ObjectSaveContext.h" #if WITH_EDITOR #include "Editor.h" #include "LevelEditor.h" #endif #include using namespace CesiumGeospatial; UCesiumEllipsoid* UCesiumEllipsoid::Create(const FVector& Radii) { UCesiumEllipsoid* pEllipsoid = NewObject(); pEllipsoid->SetRadii(Radii); return pEllipsoid; } FVector UCesiumEllipsoid::GetRadii() { return this->Radii; } void UCesiumEllipsoid::SetRadii(const FVector& NewRadii) { this->Radii = NewRadii; } double UCesiumEllipsoid::GetMaximumRadius() { return this->Radii.X; } double UCesiumEllipsoid::GetMinimumRadius() { return this->Radii.Z; } FVector UCesiumEllipsoid::ScaleToGeodeticSurface( const FVector& EllipsoidCenteredEllipsoidFixedPosition) { return CesiumEllipsoidFunctions::ScaleToGeodeticSurface( this->GetNativeEllipsoid(), EllipsoidCenteredEllipsoidFixedPosition); } FVector UCesiumEllipsoid::GeodeticSurfaceNormal( const FVector& EllipsoidCenteredEllipsoidFixedPosition) { return CesiumEllipsoidFunctions::GeodeticSurfaceNormal( this->GetNativeEllipsoid(), EllipsoidCenteredEllipsoidFixedPosition); } FVector UCesiumEllipsoid::LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( const FVector& LongitudeLatitudeHeight) { return CesiumEllipsoidFunctions:: LongitudeLatitudeHeightToEllipsoidCenteredEllipsoidFixed( this->GetNativeEllipsoid(), LongitudeLatitudeHeight); } FVector UCesiumEllipsoid::EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( const FVector& EllipsoidCenteredEllipsoidFixedPosition) { return CesiumEllipsoidFunctions:: EllipsoidCenteredEllipsoidFixedToLongitudeLatitudeHeight( this->GetNativeEllipsoid(), EllipsoidCenteredEllipsoidFixedPosition); } FMatrix UCesiumEllipsoid::EastNorthUpToEllipsoidCenteredEllipsoidFixed( const FVector& EllipsoidCenteredEllipsoidFixedPosition) { return CesiumEllipsoidFunctions::EastNorthUpToEllipsoidCenteredEllipsoidFixed( this->GetNativeEllipsoid(), EllipsoidCenteredEllipsoidFixedPosition); } LocalHorizontalCoordinateSystem UCesiumEllipsoid::CreateCoordinateSystem(const FVector& Center, double Scale) { { return LocalHorizontalCoordinateSystem( VecMath::createVector3D(Center), LocalDirection::East, LocalDirection::South, LocalDirection::Up, 1.0 / Scale, this->GetNativeEllipsoid()); } } const Ellipsoid& UCesiumEllipsoid::GetNativeEllipsoid() { const double MinRadiiValue = TMathUtilConstants::Epsilon; if (!this->NativeEllipsoid.IsSet()) { // Radii of zero will throw Infs and NaNs into our calculations which will // cause Unreal to crash when the values reach a transform. if (this->Radii.X < MinRadiiValue || this->Radii.Y < MinRadiiValue || this->Radii.Z < MinRadiiValue) { UE_LOG( LogCesium, Error, TEXT( "Radii must be greater than 0 - clamping to minimum value to avoid crashes.")); } this->NativeEllipsoid.Emplace(Ellipsoid( FMath::Max(this->Radii.X, MinRadiiValue), FMath::Max(this->Radii.Y, MinRadiiValue), FMath::Max(this->Radii.Z, MinRadiiValue))); } return *this->NativeEllipsoid; } #if WITH_EDITOR void UCesiumEllipsoid::PostSaveRoot( FObjectPostSaveRootContext ObjectSaveContext) { if (!IsValid(GEditor)) { return; } GEditor->GetWorld(); UWorld* World = GEditor->GetEditorWorldContext().World(); if (!IsValid(World)) { return; } // Go through every georeference and update its ellipsoid if it's this // ellipsoid, since we might have modified values after saving. if (ObjectSaveContext.SaveSucceeded()) { for (TActorIterator It(World); It; ++It) { ACesiumGeoreference* Georeference = *It; if (Georeference->GetEllipsoid() == this) { Georeference->SetEllipsoid(this); } } } } #endif