mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 06:38:13 -05:00
Implements type-safe angle (degrees and radians) representation classes. Provides utilities for converting between Cartesian and cylindrical coordinate systems. Includes a unit test suite for validation.
207 lines
6.7 KiB
C++
207 lines
6.7 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2025 Equinor ASA
|
|
//
|
|
// ResInsight is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// ResInsight 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 GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "RiaAngleUtils.h"
|
|
|
|
using namespace Ria;
|
|
|
|
TEST( RiaAngleUtilsTest, DegreesBasicOperations )
|
|
{
|
|
Degreesd d1( 90.0 );
|
|
Degreesd d2( 45.0 );
|
|
|
|
EXPECT_DOUBLE_EQ( 90.0, d1.value() );
|
|
EXPECT_DOUBLE_EQ( 45.0, d2.value() );
|
|
|
|
auto sum = d1 + d2;
|
|
EXPECT_DOUBLE_EQ( 135.0, sum.value() );
|
|
|
|
auto diff = d1 - d2;
|
|
EXPECT_DOUBLE_EQ( 45.0, diff.value() );
|
|
|
|
auto scaled = d1 * 2.0;
|
|
EXPECT_DOUBLE_EQ( 180.0, scaled.value() );
|
|
|
|
auto divided = d1 / 2.0;
|
|
EXPECT_DOUBLE_EQ( 45.0, divided.value() );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, RadiansBasicOperations )
|
|
{
|
|
Radiansd r1( cvf::PI_D / 2.0 ); // 90 degrees
|
|
Radiansd r2( cvf::PI_D / 4.0 ); // 45 degrees
|
|
|
|
EXPECT_DOUBLE_EQ( cvf::PI_D / 2.0, r1.value() );
|
|
EXPECT_DOUBLE_EQ( cvf::PI_D / 4.0, r2.value() );
|
|
|
|
auto sum = r1 + r2;
|
|
EXPECT_DOUBLE_EQ( 3.0 * cvf::PI_D / 4.0, sum.value() );
|
|
|
|
auto diff = r1 - r2;
|
|
EXPECT_DOUBLE_EQ( cvf::PI_D / 4.0, diff.value() );
|
|
|
|
auto scaled = r1 * 2.0;
|
|
EXPECT_DOUBLE_EQ( cvf::PI_D, scaled.value() );
|
|
|
|
auto divided = r1 / 2.0;
|
|
EXPECT_DOUBLE_EQ( cvf::PI_D / 4.0, divided.value() );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, DegreesRadiansConversion )
|
|
{
|
|
Degreesd degrees( 180.0 );
|
|
Radiansd radians( degrees );
|
|
double diff1 = cvf::Math::abs( cvf::PI_D - radians.value() );
|
|
EXPECT_LT( diff1, 1e-10 );
|
|
|
|
Radiansd piRadians( cvf::PI_D );
|
|
Degreesd fromRadians( piRadians );
|
|
double diff2 = cvf::Math::abs( 180.0 - fromRadians.value() );
|
|
EXPECT_LT( diff2, 1e-10 );
|
|
|
|
Degreesd deg90( 90.0 );
|
|
Radiansd rad90( deg90 );
|
|
double diff3 = cvf::Math::abs( cvf::PI_D / 2.0 - rad90.value() );
|
|
EXPECT_LT( diff3, 1e-10 );
|
|
|
|
Degreesd original( 45.0 );
|
|
Radiansd converted( original );
|
|
Degreesd backToOriginal( converted );
|
|
double diff4 = cvf::Math::abs( 45.0 - backToOriginal.value() );
|
|
EXPECT_LT( diff4, 1e-10 );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, TrigonometricFunctions )
|
|
{
|
|
Degreesd deg90( 90.0 );
|
|
double sin90 = sin( deg90 );
|
|
double cos90 = cos( deg90 );
|
|
EXPECT_LT( cvf::Math::abs( 1.0 - sin90 ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( 0.0 - cos90 ), 1e-10 );
|
|
|
|
Degreesd deg45( 45.0 );
|
|
double sin45 = sin( deg45 );
|
|
double cos45 = cos( deg45 );
|
|
double tan45 = tan( deg45 );
|
|
EXPECT_LT( cvf::Math::abs( cvf::SQRT1_2_D - sin45 ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( cvf::SQRT1_2_D - cos45 ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( 1.0 - tan45 ), 1e-10 );
|
|
|
|
Radiansd radPiOver2( cvf::PI_D / 2.0 );
|
|
double sinPi2 = sin( radPiOver2 );
|
|
double cosPi2 = cos( radPiOver2 );
|
|
EXPECT_LT( cvf::Math::abs( 1.0 - sinPi2 ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( 0.0 - cosPi2 ), 1e-10 );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, CylindricalToCartesianConversion )
|
|
{
|
|
double radius = 5.0;
|
|
Radiansd angle( cvf::PI_D / 4.0 ); // 45 degrees
|
|
double height = 10.0;
|
|
|
|
auto cartesian = CoordinateConverter::cylindricalToCartesian( radius, angle, height );
|
|
|
|
double expectedX = radius * cvf::SQRT1_2_D;
|
|
double expectedY = radius * cvf::SQRT1_2_D;
|
|
|
|
EXPECT_LT( cvf::Math::abs( expectedX - cartesian.x() ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( expectedY - cartesian.y() ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( height - cartesian.z() ), 1e-10 );
|
|
|
|
Degreesd angleDeg( 45.0 );
|
|
auto cartesianFromDeg = CoordinateConverter::cylindricalToCartesian( radius, angleDeg, height );
|
|
|
|
EXPECT_LT( cvf::Math::abs( cartesian.x() - cartesianFromDeg.x() ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( cartesian.y() - cartesianFromDeg.y() ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( cartesian.z() - cartesianFromDeg.z() ), 1e-10 );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, CartesianToCylindricalConversion )
|
|
{
|
|
cvf::Vec3d cartesian( 3.0, 4.0, 5.0 );
|
|
|
|
auto cylindrical = CoordinateConverter::cartesianToCylindrical( cartesian );
|
|
|
|
EXPECT_LT( cvf::Math::abs( 5.0 - cylindrical.radius ), 1e-10 ); // sqrt(3^2 + 4^2) = 5
|
|
EXPECT_LT( cvf::Math::abs( std::atan2( 4.0, 3.0 ) - cylindrical.angle ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( 5.0 - cylindrical.height ), 1e-10 );
|
|
|
|
cvf::Vec3d backToCartesian = CoordinateConverter::cylindricalToCartesian<double>( cylindrical );
|
|
|
|
EXPECT_LT( cvf::Math::abs( cartesian.x() - backToCartesian.x() ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( cartesian.y() - backToCartesian.y() ), 1e-10 );
|
|
EXPECT_LT( cvf::Math::abs( cartesian.z() - backToCartesian.z() ), 1e-10 );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, ComparisonOperators )
|
|
{
|
|
Degreesd deg45( 45.0 );
|
|
Degreesd deg90( 90.0 );
|
|
Degreesd deg45_2( 45.0 );
|
|
|
|
EXPECT_TRUE( deg45 == deg45_2 );
|
|
EXPECT_FALSE( deg45 == deg90 );
|
|
EXPECT_TRUE( deg45 != deg90 );
|
|
EXPECT_FALSE( deg45 != deg45_2 );
|
|
|
|
EXPECT_TRUE( deg45 < deg90 );
|
|
EXPECT_FALSE( deg90 < deg45 );
|
|
EXPECT_TRUE( deg45 <= deg90 );
|
|
EXPECT_TRUE( deg45 <= deg45_2 );
|
|
|
|
EXPECT_TRUE( deg90 > deg45 );
|
|
EXPECT_FALSE( deg45 > deg90 );
|
|
EXPECT_TRUE( deg90 >= deg45 );
|
|
EXPECT_TRUE( deg45 >= deg45_2 );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, FloatPrecision )
|
|
{
|
|
Degreesf degf( 90.0f );
|
|
Radiansf radf( degf );
|
|
|
|
float expectedRad = cvf::PI_F / 2.0f;
|
|
EXPECT_LT( cvf::Math::abs( expectedRad - radf.value() ), 1e-6f );
|
|
|
|
float sinResult = sin( degf );
|
|
EXPECT_LT( cvf::Math::abs( 1.0f - sinResult ), 1e-6f );
|
|
|
|
cvf::Vec3f cartesianf = CoordinateConverter::cylindricalToCartesian( 5.0f, degf, 10.0f );
|
|
EXPECT_LT( cvf::Math::abs( 0.0f - cartesianf.x() ), 1e-6f );
|
|
EXPECT_LT( cvf::Math::abs( 5.0f - cartesianf.y() ), 1e-6f );
|
|
EXPECT_LT( cvf::Math::abs( 10.0f - cartesianf.z() ), 1e-6f );
|
|
}
|
|
|
|
TEST( RiaAngleUtilsTest, AngleLiterals )
|
|
{
|
|
auto deg90 = 90.0_deg;
|
|
EXPECT_LT( cvf::Math::abs( 90.0 - deg90.value() ), 1e-10 );
|
|
|
|
auto degFloat = 45.0_degf;
|
|
EXPECT_LT( cvf::Math::abs( 45.0f - degFloat.value() ), 1e-6f );
|
|
|
|
auto radPi = 3.14159265_rad;
|
|
EXPECT_LT( cvf::Math::abs( 3.14159265 - radPi.value() ), 1e-8 );
|
|
|
|
auto radFloat = 1.57079633_radf;
|
|
EXPECT_LT( cvf::Math::abs( 1.57079633f - radFloat.value() ), 1e-6f );
|
|
}
|