From 11dfdc2c21b37e4a278854d4feb61d3d44f5093a Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 9 Jan 2026 15:13:28 +0100 Subject: [PATCH] Refactor: convert RigBoundingBoxIjk to template class. --- .../ReservoirDataModel/CMakeLists_files.cmake | 2 +- .../ReservoirDataModel/RigBoundingBoxIjk.cpp | 101 ------------------ .../ReservoirDataModel/RigBoundingBoxIjk.h | 17 +-- .../ReservoirDataModel/RigBoundingBoxIjk.inl | 80 ++++++++++++++ .../RigGridExportAdapter.cpp | 2 +- .../SimulationFile/RigSimulationInputTool.cpp | 33 +++--- .../SimulationFile/RigSimulationInputTool.h | 16 +-- .../UnitTests/RigBoundingBoxIjk-Test.cpp | 70 ++++++------ 8 files changed, 154 insertions(+), 167 deletions(-) delete mode 100644 ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.inl diff --git a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake index 5b75a1ca85..126fb93136 100644 --- a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake @@ -8,6 +8,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigAllanDiagramData.h ${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.h ${CMAKE_CURRENT_LIST_DIR}/RigBoundingBoxIjk.h + ${CMAKE_CURRENT_LIST_DIR}/RigBoundingBoxIjk.inl ${CMAKE_CURRENT_LIST_DIR}/RigCaseCellResultCalculator.h ${CMAKE_CURRENT_LIST_DIR}/RigCaseCellResultsData.h ${CMAKE_CURRENT_LIST_DIR}/RigCaseRealizationParameters.h @@ -95,7 +96,6 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigActiveCellInfo.cpp ${CMAKE_CURRENT_LIST_DIR}/RigActiveCellLocalGrid.cpp ${CMAKE_CURRENT_LIST_DIR}/RigAllanDiagramData.cpp - ${CMAKE_CURRENT_LIST_DIR}/RigBoundingBoxIjk.cpp ${CMAKE_CURRENT_LIST_DIR}/RigBasicPlane.cpp ${CMAKE_CURRENT_LIST_DIR}/RigCaseCellResultCalculator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigCaseCellResultsData.cpp diff --git a/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.cpp b/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.cpp deleted file mode 100644 index 91d84213a4..0000000000 --- a/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.cpp +++ /dev/null @@ -1,101 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////// -// -// 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 -// for more details. -// -///////////////////////////////////////////////////////////////////////////////// - -#include "RigBoundingBoxIjk.h" - -#include - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RigBoundingBoxIjk::RigBoundingBoxIjk() - : m_min( cvf::Vec3st::ZERO ) - , m_max( cvf::Vec3st::ZERO ) -{ -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RigBoundingBoxIjk::RigBoundingBoxIjk( const cvf::Vec3st& min, const cvf::Vec3st& max ) - : m_min( min ) - , m_max( max ) -{ -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RigBoundingBoxIjk::isValid() const -{ - return m_min.x() <= m_max.x() && m_min.y() <= m_max.y() && m_min.z() <= m_max.z(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RigBoundingBoxIjk::contains( const cvf::Vec3st& point ) const -{ - return point.x() >= m_min.x() && point.x() <= m_max.x() && point.y() >= m_min.y() && point.y() <= m_max.y() && point.z() >= m_min.z() && - point.z() <= m_max.z(); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool RigBoundingBoxIjk::overlaps( const RigBoundingBoxIjk& other ) const -{ - // Two boxes overlap if they overlap in all three dimensions - // No overlap if: this.max < other.min OR this.min > other.max (for any dimension) - bool overlapsI = m_max.x() >= other.m_min.x() && m_min.x() <= other.m_max.x(); - bool overlapsJ = m_max.y() >= other.m_min.y() && m_min.y() <= other.m_max.y(); - bool overlapsK = m_max.z() >= other.m_min.z() && m_min.z() <= other.m_max.z(); - - return overlapsI && overlapsJ && overlapsK; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::optional RigBoundingBoxIjk::intersection( const RigBoundingBoxIjk& other ) const -{ - if ( !overlaps( other ) ) - { - return std::nullopt; - } - - // Compute intersection box - cvf::Vec3st intersectMin( std::max( m_min.x(), other.m_min.x() ), - std::max( m_min.y(), other.m_min.y() ), - std::max( m_min.z(), other.m_min.z() ) ); - - cvf::Vec3st intersectMax( std::min( m_max.x(), other.m_max.x() ), - std::min( m_max.y(), other.m_max.y() ), - std::min( m_max.z(), other.m_max.z() ) ); - - return RigBoundingBoxIjk( intersectMin, intersectMax ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::optional RigBoundingBoxIjk::clamp( const RigBoundingBoxIjk& bounds ) const -{ - // Clamp is the same as intersection for bounding boxes - return intersection( bounds ); -} diff --git a/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.h b/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.h index 366ca02889..385980fc97 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.h +++ b/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.h @@ -20,26 +20,29 @@ #include "cvfVector3.h" +#include #include //================================================================================================== /// /// Value type representing an axis-aligned bounding box in IJK (integer) grid coordinates +/// Template parameter T should be a 3D vector type with x(), y(), z() accessors (e.g., cvf::Vec3st, caf::VecIjk0) /// //================================================================================================== +template class RigBoundingBoxIjk { public: RigBoundingBoxIjk(); - RigBoundingBoxIjk( const cvf::Vec3st& min, const cvf::Vec3st& max ); + RigBoundingBoxIjk( const T& min, const T& max ); - const cvf::Vec3st& min() const { return m_min; } - const cvf::Vec3st& max() const { return m_max; } + const T& min() const { return m_min; } + const T& max() const { return m_max; } bool isValid() const; // Check if a point is inside this bounding box (inclusive) - bool contains( const cvf::Vec3st& point ) const; + bool contains( const T& point ) const; // Check if this box overlaps with another box bool overlaps( const RigBoundingBoxIjk& other ) const; @@ -53,6 +56,8 @@ public: std::optional clamp( const RigBoundingBoxIjk& bounds ) const; private: - cvf::Vec3st m_min; - cvf::Vec3st m_max; + T m_min; + T m_max; }; + +#include "RigBoundingBoxIjk.inl" diff --git a/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.inl b/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.inl new file mode 100644 index 0000000000..164815adf6 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigBoundingBoxIjk.inl @@ -0,0 +1,80 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigBoundingBoxIjk.h" + +template +RigBoundingBoxIjk::RigBoundingBoxIjk() + : m_min( T::ZERO ) + , m_max( T::ZERO ) +{ +} + +template +RigBoundingBoxIjk::RigBoundingBoxIjk( const T& min, const T& max ) + : m_min( min ) + , m_max( max ) +{ +} + +template +bool RigBoundingBoxIjk::isValid() const +{ + return m_min.x() <= m_max.x() && m_min.y() <= m_max.y() && m_min.z() <= m_max.z(); +} + +template +bool RigBoundingBoxIjk::contains( const T& point ) const +{ + return point.x() >= m_min.x() && point.x() <= m_max.x() && point.y() >= m_min.y() && point.y() <= m_max.y() && point.z() >= m_min.z() && + point.z() <= m_max.z(); +} + +template +bool RigBoundingBoxIjk::overlaps( const RigBoundingBoxIjk& other ) const +{ + // Two boxes overlap if they overlap in all three dimensions + // No overlap if: this.max < other.min OR this.min > other.max (for any dimension) + bool overlapsI = m_max.x() >= other.m_min.x() && m_min.x() <= other.m_max.x(); + bool overlapsJ = m_max.y() >= other.m_min.y() && m_min.y() <= other.m_max.y(); + bool overlapsK = m_max.z() >= other.m_min.z() && m_min.z() <= other.m_max.z(); + + return overlapsI && overlapsJ && overlapsK; +} + +template +std::optional> RigBoundingBoxIjk::intersection( const RigBoundingBoxIjk& other ) const +{ + if ( !overlaps( other ) ) + { + return std::nullopt; + } + + // Compute intersection box + T intersectMin( std::max( m_min.x(), other.m_min.x() ), std::max( m_min.y(), other.m_min.y() ), std::max( m_min.z(), other.m_min.z() ) ); + T intersectMax( std::min( m_max.x(), other.m_max.x() ), std::min( m_max.y(), other.m_max.y() ), std::min( m_max.z(), other.m_max.z() ) ); + + return RigBoundingBoxIjk( intersectMin, intersectMax ); +} + +template +std::optional> RigBoundingBoxIjk::clamp( const RigBoundingBoxIjk& bounds ) const +{ + // Clamp is the same as intersection for bounding boxes + return intersection( bounds ); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp b/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp index 2c6cc03c5a..110e2a8faa 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp +++ b/ApplicationLibCode/ReservoirDataModel/RigGridExportAdapter.cpp @@ -432,7 +432,7 @@ std::expected RigGridExportAdapter::transformIjkToSectorC bool isBoxMaxCoordinate ) { // Check if original IJK is within the sector bounds - RigBoundingBoxIjk sectorBox( min, max ); + RigBoundingBoxIjk sectorBox( min, max ); if ( !sectorBox.contains( ijk ) ) { return std::unexpected( QString( "IJK coordinates (%1) are outside sector bounds [(%2), (%3)]" ) diff --git a/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp b/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp index 37e5146175..83a8b7c927 100644 --- a/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp +++ b/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.cpp @@ -592,7 +592,7 @@ std::expected RigSimulationInputTool::addFaultsToDeckFile( RimEcl /// //-------------------------------------------------------------------------------------------------- std::vector - RigSimulationInputTool::findIntersectingWells( RimEclipseCase* eclipseCase, const cvf::Vec3st& min, const cvf::Vec3st& max ) + RigSimulationInputTool::findIntersectingWells( RimEclipseCase* eclipseCase, const caf::VecIjk0& min, const caf::VecIjk0& max ) { std::vector intersectingWells; @@ -601,7 +601,7 @@ std::vector const auto& wellResults = eclipseCase->eclipseCaseData()->wellResults(); // Create sector bounding box for intersection checks - RigBoundingBoxIjk sectorBox( min, max ); + RigBoundingBoxIjk sectorBox( min, max ); for ( size_t wellIdx = 0; wellIdx < wellResults.size(); ++wellIdx ) { @@ -834,15 +834,16 @@ caf::VecIjk1 RigSimulationInputTool::extractIjk( const Opm::DeckRecord& record, /// Performs intersection, clamping, and coordinate transformation /// Returns bounding box with 0-based sector-relative coordinates //-------------------------------------------------------------------------------------------------- -std::expected RigSimulationInputTool::transformBoxToSectorCoordinates( const RigBoundingBoxIjk& inputBox, - const caf::VecIjk0& sectorMin, - const caf::VecIjk0& sectorMax, - const cvf::Vec3st& refinement, - const QString& keywordName, - const QString& recordIdentifier ) +std::expected, QString> + RigSimulationInputTool::transformBoxToSectorCoordinates( const RigBoundingBoxIjk& inputBox, + const caf::VecIjk0& sectorMin, + const caf::VecIjk0& sectorMax, + const cvf::Vec3st& refinement, + const QString& keywordName, + const QString& recordIdentifier ) { // Create sector bounding box - RigBoundingBoxIjk sectorBox( sectorMin, sectorMax ); + RigBoundingBoxIjk sectorBox( sectorMin, sectorMax ); // Check if boxes overlap and get intersection auto intersection = inputBox.intersection( sectorBox ); @@ -918,7 +919,7 @@ std::expected RigSimulationInputTool::transformBoxTo } // Return bounding box with 0-based sector-relative coordinates - return RigBoundingBoxIjk( *transformResult1, *transformResult2 ); + return RigBoundingBoxIjk( *transformResult1, *transformResult2 ); } //-------------------------------------------------------------------------------------------------- /// @@ -950,7 +951,7 @@ std::expected RigSimulationInputTool::processEqualsRec caf::VecIjk1 origMax = extractIjk( record, 3, 5, 7 ); // I2, J2, K2 // Create input bounding box (0-based, inclusive) - RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); + RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); // Get field name for logging QString fieldName = QString::fromStdString( record.getItem( 0 ).get( 0 ) ); @@ -1005,7 +1006,7 @@ std::expected RigSimulationInputTool::processMultiplyR caf::VecIjk1 origMax = extractIjk( record, 3, 5, 7 ); // I2, J2, K2 // Create input bounding box (0-based, inclusive) - RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); + RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); // Get field name for logging QString fieldName = QString::fromStdString( record.getItem( 0 ).get( 0 ) ); @@ -1060,7 +1061,7 @@ std::expected RigSimulationInputTool::processAddRecord caf::VecIjk1 origMax = extractIjk( record, 3, 5, 7 ); // I2, J2, K2 // Create input bounding box (0-based, inclusive) - RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); + RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); // Get field name for logging QString fieldName = QString::fromStdString( record.getItem( 0 ).get( 0 ) ); @@ -1114,7 +1115,7 @@ std::expected RigSimulationInputTool::processAquconRec caf::VecIjk1 origMax = extractIjk( record, 2, 4, 6 ); // I2, J2, K2 // Create input bounding box (0-based, inclusive) - RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); + RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); // Get aquifer ID for logging int aquiferId = record.getItem( 0 ).get( 0 ); @@ -1184,7 +1185,7 @@ std::expected RigSimulationInputTool::processCopyRecor caf::VecIjk1 origMax = extractIjk( record, 3, 5, 7 ); // I2, J2, K2 // Create input bounding box (0-based, inclusive) - RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); + RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); // Get array names for logging QString srcArray = QString::fromStdString( record.getItem( 0 ).get( 0 ) ); @@ -1242,7 +1243,7 @@ std::expected RigSimulationInputTool::processBoxRecord caf::VecIjk1 origMax = extractIjk( record, 1, 3, 5 ); // I2, J2, K2 // Create input bounding box (0-based, inclusive) - RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); + RigBoundingBoxIjk inputBox( origMin.toZeroBased(), origMax.toZeroBased() ); // Transform box to sector coordinates auto transformResult = transformBoxToSectorCoordinates( inputBox, min, max, refinement, "BOX", "" ); diff --git a/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.h b/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.h index ce7349a117..2e9ae4d4a5 100644 --- a/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.h +++ b/ApplicationLibCode/ReservoirDataModel/SimulationFile/RigSimulationInputTool.h @@ -34,6 +34,7 @@ class RimEclipseCase; class RigSimulationInputSettings; class RifOpmFlowDeckFile; class RigSimWellData; +template class RigBoundingBoxIjk; class RigGridExportAdapter; @@ -121,7 +122,7 @@ private: int operNumRegion, double porvMultiplier ); - static std::vector findIntersectingWells( RimEclipseCase* eclipseCase, const cvf::Vec3st& min, const cvf::Vec3st& max ); + static std::vector findIntersectingWells( RimEclipseCase* eclipseCase, const caf::VecIjk0& min, const caf::VecIjk0& max ); static std::expected processWelspecsRecord( const Opm::DeckRecord& record, const std::string& wellName, const RigSimulationInputSettings& settings ); @@ -146,12 +147,13 @@ private: // Helper function to transform bounding box from global to sector coordinates // Returns bounding box with 0-based sector-relative coordinates - static std::expected transformBoxToSectorCoordinates( const RigBoundingBoxIjk& inputBox, - const caf::VecIjk0& sectorMin, - const caf::VecIjk0& sectorMax, - const cvf::Vec3st& refinement, - const QString& keywordName, - const QString& recordIdentifier ); + static std::expected, QString> + transformBoxToSectorCoordinates( const RigBoundingBoxIjk& inputBox, + const caf::VecIjk0& sectorMin, + const caf::VecIjk0& sectorMax, + const cvf::Vec3st& refinement, + const QString& keywordName, + const QString& recordIdentifier ); // Helper function to extract IJK coordinates from a deck record // Returns a VecIjk1 (1-based) constructed from values at the specified item indices diff --git a/ApplicationLibCode/UnitTests/RigBoundingBoxIjk-Test.cpp b/ApplicationLibCode/UnitTests/RigBoundingBoxIjk-Test.cpp index 76086dbc8d..771892b7f5 100644 --- a/ApplicationLibCode/UnitTests/RigBoundingBoxIjk-Test.cpp +++ b/ApplicationLibCode/UnitTests/RigBoundingBoxIjk-Test.cpp @@ -26,19 +26,19 @@ TEST( RigBoundingBoxIjk, BasicConstruction ) { // Default constructor - RigBoundingBoxIjk defaultBox; + RigBoundingBoxIjk defaultBox; EXPECT_TRUE( defaultBox.isValid() ); // Min and max are both (0,0,0) EXPECT_EQ( cvf::Vec3st::ZERO, defaultBox.min() ); EXPECT_EQ( cvf::Vec3st::ZERO, defaultBox.max() ); // Constructor with min and max - RigBoundingBoxIjk box( cvf::Vec3st( 1, 2, 3 ), cvf::Vec3st( 5, 6, 7 ) ); + RigBoundingBoxIjk box( cvf::Vec3st( 1, 2, 3 ), cvf::Vec3st( 5, 6, 7 ) ); EXPECT_TRUE( box.isValid() ); EXPECT_EQ( cvf::Vec3st( 1, 2, 3 ), box.min() ); EXPECT_EQ( cvf::Vec3st( 5, 6, 7 ), box.max() ); // Invalid box (min > max) - RigBoundingBoxIjk invalidBox( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 5, 5, 5 ) ); + RigBoundingBoxIjk invalidBox( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 5, 5, 5 ) ); EXPECT_FALSE( invalidBox.isValid() ); } @@ -48,14 +48,14 @@ TEST( RigBoundingBoxIjk, BasicConstruction ) TEST( RigBoundingBoxIjk, IsValid ) { // Valid boxes - EXPECT_TRUE( RigBoundingBoxIjk( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ).isValid() ); - EXPECT_TRUE( RigBoundingBoxIjk( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 5, 5, 5 ) ).isValid() ); // Single point + EXPECT_TRUE( RigBoundingBoxIjk( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ).isValid() ); + EXPECT_TRUE( RigBoundingBoxIjk( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 5, 5, 5 ) ).isValid() ); // Single point // Invalid boxes (min > max in at least one dimension) - EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 10, 0, 0 ), cvf::Vec3st( 5, 10, 10 ) ).isValid() ); // X invalid - EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 0, 10, 0 ), cvf::Vec3st( 10, 5, 10 ) ).isValid() ); // Y invalid - EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 0, 0, 10 ), cvf::Vec3st( 10, 10, 5 ) ).isValid() ); // Z invalid - EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 5, 5, 5 ) ).isValid() ); // All invalid + EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 10, 0, 0 ), cvf::Vec3st( 5, 10, 10 ) ).isValid() ); // X invalid + EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 0, 10, 0 ), cvf::Vec3st( 10, 5, 10 ) ).isValid() ); // Y invalid + EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 0, 0, 10 ), cvf::Vec3st( 10, 10, 5 ) ).isValid() ); // Z invalid + EXPECT_FALSE( RigBoundingBoxIjk( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 5, 5, 5 ) ).isValid() ); // All invalid } //-------------------------------------------------------------------------------------------------- @@ -63,33 +63,33 @@ TEST( RigBoundingBoxIjk, IsValid ) //-------------------------------------------------------------------------------------------------- TEST( RigBoundingBoxIjk, OverlapDetection ) { - RigBoundingBoxIjk box1( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); + RigBoundingBoxIjk box1( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); // Same box overlaps with itself EXPECT_TRUE( box1.overlaps( box1 ) ); // Completely inside - RigBoundingBoxIjk box2( cvf::Vec3st( 2, 2, 2 ), cvf::Vec3st( 8, 8, 8 ) ); + RigBoundingBoxIjk box2( cvf::Vec3st( 2, 2, 2 ), cvf::Vec3st( 8, 8, 8 ) ); EXPECT_TRUE( box1.overlaps( box2 ) ); EXPECT_TRUE( box2.overlaps( box1 ) ); // Symmetric // Partially overlapping - RigBoundingBoxIjk box3( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); + RigBoundingBoxIjk box3( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); EXPECT_TRUE( box1.overlaps( box3 ) ); EXPECT_TRUE( box3.overlaps( box1 ) ); // Touching at edge (inclusive bounds - should overlap) - RigBoundingBoxIjk box4( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 20, 20, 20 ) ); + RigBoundingBoxIjk box4( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 20, 20, 20 ) ); EXPECT_TRUE( box1.overlaps( box4 ) ); EXPECT_TRUE( box4.overlaps( box1 ) ); // Completely separate (no overlap) - RigBoundingBoxIjk box5( cvf::Vec3st( 20, 20, 20 ), cvf::Vec3st( 30, 30, 30 ) ); + RigBoundingBoxIjk box5( cvf::Vec3st( 20, 20, 20 ), cvf::Vec3st( 30, 30, 30 ) ); EXPECT_FALSE( box1.overlaps( box5 ) ); EXPECT_FALSE( box5.overlaps( box1 ) ); // Overlap in 2D but not 3D (separated in Z) - RigBoundingBoxIjk box6( cvf::Vec3st( 5, 5, 20 ), cvf::Vec3st( 15, 15, 30 ) ); + RigBoundingBoxIjk box6( cvf::Vec3st( 5, 5, 20 ), cvf::Vec3st( 15, 15, 30 ) ); EXPECT_FALSE( box1.overlaps( box6 ) ); } @@ -98,23 +98,23 @@ TEST( RigBoundingBoxIjk, OverlapDetection ) //-------------------------------------------------------------------------------------------------- TEST( RigBoundingBoxIjk, Intersection ) { - RigBoundingBoxIjk box1( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); + RigBoundingBoxIjk box1( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); // No overlap returns nullopt - RigBoundingBoxIjk box2( cvf::Vec3st( 20, 20, 20 ), cvf::Vec3st( 30, 30, 30 ) ); - auto result1 = box1.intersection( box2 ); + RigBoundingBoxIjk box2( cvf::Vec3st( 20, 20, 20 ), cvf::Vec3st( 30, 30, 30 ) ); + auto result1 = box1.intersection( box2 ); EXPECT_FALSE( result1.has_value() ); // Partial overlap - RigBoundingBoxIjk box3( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); - auto result2 = box1.intersection( box3 ); + RigBoundingBoxIjk box3( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); + auto result2 = box1.intersection( box3 ); EXPECT_TRUE( result2.has_value() ); EXPECT_EQ( cvf::Vec3st( 5, 5, 5 ), result2->min() ); EXPECT_EQ( cvf::Vec3st( 10, 10, 10 ), result2->max() ); // Complete containment (box4 inside box1) - RigBoundingBoxIjk box4( cvf::Vec3st( 2, 2, 2 ), cvf::Vec3st( 8, 8, 8 ) ); - auto result3 = box1.intersection( box4 ); + RigBoundingBoxIjk box4( cvf::Vec3st( 2, 2, 2 ), cvf::Vec3st( 8, 8, 8 ) ); + auto result3 = box1.intersection( box4 ); EXPECT_TRUE( result3.has_value() ); EXPECT_EQ( cvf::Vec3st( 2, 2, 2 ), result3->min() ); EXPECT_EQ( cvf::Vec3st( 8, 8, 8 ), result3->max() ); @@ -126,8 +126,8 @@ TEST( RigBoundingBoxIjk, Intersection ) EXPECT_EQ( cvf::Vec3st( 10, 10, 10 ), result4->max() ); // Single cell intersection - RigBoundingBoxIjk box5( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 20, 20, 20 ) ); - auto result5 = box1.intersection( box5 ); + RigBoundingBoxIjk box5( cvf::Vec3st( 10, 10, 10 ), cvf::Vec3st( 20, 20, 20 ) ); + auto result5 = box1.intersection( box5 ); EXPECT_TRUE( result5.has_value() ); EXPECT_EQ( cvf::Vec3st( 10, 10, 10 ), result5->min() ); EXPECT_EQ( cvf::Vec3st( 10, 10, 10 ), result5->max() ); @@ -138,25 +138,25 @@ TEST( RigBoundingBoxIjk, Intersection ) //-------------------------------------------------------------------------------------------------- TEST( RigBoundingBoxIjk, Clamp ) { - RigBoundingBoxIjk bounds( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); + RigBoundingBoxIjk bounds( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); // Box completely inside bounds - RigBoundingBoxIjk box1( cvf::Vec3st( 2, 2, 2 ), cvf::Vec3st( 8, 8, 8 ) ); - auto result1 = box1.clamp( bounds ); + RigBoundingBoxIjk box1( cvf::Vec3st( 2, 2, 2 ), cvf::Vec3st( 8, 8, 8 ) ); + auto result1 = box1.clamp( bounds ); EXPECT_TRUE( result1.has_value() ); EXPECT_EQ( cvf::Vec3st( 2, 2, 2 ), result1->min() ); EXPECT_EQ( cvf::Vec3st( 8, 8, 8 ), result1->max() ); // Box partially outside bounds - should be clamped - RigBoundingBoxIjk box2( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); - auto result2 = box2.clamp( bounds ); + RigBoundingBoxIjk box2( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); + auto result2 = box2.clamp( bounds ); EXPECT_TRUE( result2.has_value() ); EXPECT_EQ( cvf::Vec3st( 5, 5, 5 ), result2->min() ); EXPECT_EQ( cvf::Vec3st( 10, 10, 10 ), result2->max() ); // Box completely outside bounds - RigBoundingBoxIjk box3( cvf::Vec3st( 20, 20, 20 ), cvf::Vec3st( 30, 30, 30 ) ); - auto result3 = box3.clamp( bounds ); + RigBoundingBoxIjk box3( cvf::Vec3st( 20, 20, 20 ), cvf::Vec3st( 30, 30, 30 ) ); + auto result3 = box3.clamp( bounds ); EXPECT_FALSE( result3.has_value() ); } @@ -166,8 +166,8 @@ TEST( RigBoundingBoxIjk, Clamp ) TEST( RigBoundingBoxIjk, ClampBehavesLikeIntersection ) { // Verify that clamp() and intersection() behave identically - RigBoundingBoxIjk bounds( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); - RigBoundingBoxIjk box( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); + RigBoundingBoxIjk bounds( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); + RigBoundingBoxIjk box( cvf::Vec3st( 5, 5, 5 ), cvf::Vec3st( 15, 15, 15 ) ); auto clampResult = box.clamp( bounds ); auto intersectionResult = box.intersection( bounds ); @@ -185,7 +185,7 @@ TEST( RigBoundingBoxIjk, ClampBehavesLikeIntersection ) //-------------------------------------------------------------------------------------------------- TEST( RigBoundingBoxIjk, ContainsPoint ) { - RigBoundingBoxIjk box( cvf::Vec3st( 10, 20, 30 ), cvf::Vec3st( 50, 60, 70 ) ); + RigBoundingBoxIjk box( cvf::Vec3st( 10, 20, 30 ), cvf::Vec3st( 50, 60, 70 ) ); // Points inside the box EXPECT_TRUE( box.contains( cvf::Vec3st( 25, 40, 50 ) ) ); // Center @@ -252,7 +252,7 @@ TEST( RigBoundingBoxIjk, ContainsSinglePointBox ) TEST( RigBoundingBoxIjk, ContainsZeroBasedBox ) { // Box starting at origin (common case in grid applications) - RigBoundingBoxIjk box( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); + RigBoundingBoxIjk box( cvf::Vec3st( 0, 0, 0 ), cvf::Vec3st( 10, 10, 10 ) ); // Origin should be inside EXPECT_TRUE( box.contains( cvf::Vec3st( 0, 0, 0 ) ) );