Skip to content

Commit

Permalink
Move function to RigPolygonTools
Browse files Browse the repository at this point in the history
  • Loading branch information
magnesj committed Jan 13, 2025
1 parent 7ac253a commit 36c92dc
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "Polygons/RimPolygon.h"
#include "Polygons/RimPolygonInView.h"

#include "RigCellGeometryTools.h"
#include "RigPolygonTools.h"

#include "cafSelectionManager.h"

Expand Down Expand Up @@ -57,7 +57,7 @@ void RicSimplifyPolygonFeature::onActionTriggered( bool isChecked )
for ( auto sourcePolygon : selPolygons )
{
auto coords = sourcePolygon->pointsInDomainCoords();
RigCellGeometryTools::simplifyPolygon( &coords, epsilon );
RigPolygonTools::simplifyPolygon( coords, epsilon );

sourcePolygon->setPointsInDomainCoords( coords );
sourcePolygon->coordinatesChanged.send();
Expand Down
44 changes: 0 additions & 44 deletions ApplicationLibCode/ReservoirDataModel/RigCellGeometryTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,50 +233,6 @@ void RigCellGeometryTools::createPolygonFromLineSegments( std::list<std::pair<cv
}
}

//--------------------------------------------------------------------------------------------------
/// Ramer-Douglas-Peucker simplification algorithm
///
/// https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
//--------------------------------------------------------------------------------------------------
void RigCellGeometryTools::simplifyPolygon( std::vector<cvf::Vec3d>* vertices, double epsilon )
{
CVF_ASSERT( vertices );
if ( vertices->size() < 3 ) return;

std::pair<size_t, double> maxDistPoint( 0u, 0.0 );

for ( size_t i = 1; i < vertices->size() - 1; ++i )
{
cvf::Vec3d v = vertices->at( i );
double u;
cvf::Vec3d v_proj = cvf::GeometryTools::projectPointOnLine( vertices->front(), vertices->back(), v, &u );
double distance = ( v_proj - v ).length();
if ( distance > maxDistPoint.second )
{
maxDistPoint = std::make_pair( i, distance );
}
}

if ( maxDistPoint.second > epsilon )
{
std::vector<cvf::Vec3d> newVertices1( vertices->begin(), vertices->begin() + maxDistPoint.first + 1 );
std::vector<cvf::Vec3d> newVertices2( vertices->begin() + maxDistPoint.first, vertices->end() );

// Recurse
simplifyPolygon( &newVertices1, epsilon );
simplifyPolygon( &newVertices2, epsilon );

std::vector<cvf::Vec3d> newVertices( newVertices1.begin(), newVertices1.end() - 1 );
newVertices.insert( newVertices.end(), newVertices2.begin(), newVertices2.end() );
*vertices = newVertices;
}
else
{
std::vector<cvf::Vec3d> newVertices = { vertices->front(), vertices->back() };
*vertices = newVertices;
}
}

//==================================================================================================
///
//==================================================================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class RigCellGeometryTools
static void createPolygonFromLineSegments( std::list<std::pair<cvf::Vec3d, cvf::Vec3d>>& intersectionLineSegments,
std::vector<std::vector<cvf::Vec3d>>& polygons,
double tolerance = 1.0e-4 );
static void simplifyPolygon( std::vector<cvf::Vec3d>* vertices, double epsilon );

static void findCellLocalXYZ( const std::array<cvf::Vec3d, 8>& hexCorners,
cvf::Vec3d& localXdirection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "RigCellGeometryTools.h"
#include "RigContourMapGrid.h"
#include "RigContourMapProjection.h"
#include "RigPolygonTools.h"

#include "cvfGeometryUtils.h"

Expand Down Expand Up @@ -322,7 +323,7 @@ std::pair<std::vector<RigContourMapTrianglesGenerator::ContourPolygons>, std::ve

for ( RigContourPolygonsTools::ContourPolygon& polygon : contourPolygons[i] )
{
RigCellGeometryTools::simplifyPolygon( &polygon.vertices, simplifyEpsilon );
RigPolygonTools::simplifyPolygon( polygon.vertices, simplifyEpsilon );
}
}

Expand Down
65 changes: 59 additions & 6 deletions ApplicationLibCode/ReservoirDataModel/RigPolygonTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

#include "RigPolygonTools.h"

#include "cvfGeometryTools.h"

#include <optional>
#include <stack>
#include <utility>

Expand Down Expand Up @@ -50,8 +53,8 @@ namespace internal
{
if ( !isValidImage( image ) ) return;

auto rows = image.size();
auto cols = image[0].size();
auto rows = static_cast<int>( image.size() );
auto cols = static_cast<int>( image[0].size() );
std::stack<std::pair<int, int>> stack;
stack.push( { x, y } );

Expand Down Expand Up @@ -81,8 +84,8 @@ IntegerImage erode( IntegerImage image, int kernelSize )
if ( !internal::isValidImage( image ) ) return {};
if ( kernelSize <= 0 ) return {};

auto rows = image.size();
auto cols = image[0].size();
auto rows = static_cast<int>( image.size() );
auto cols = static_cast<int>( image[0].size() );
int offset = kernelSize / 2;
IntegerImage eroded( rows, std::vector<int>( cols, 0 ) );

Expand Down Expand Up @@ -118,8 +121,8 @@ IntegerImage dilate( IntegerImage image, int kernelSize )
if ( !internal::isValidImage( image ) ) return {};
if ( kernelSize <= 0 ) return {};

auto rows = image.size();
auto cols = image[0].size();
auto rows = static_cast<int>( image.size() );
auto cols = static_cast<int>( image[0].size() );
int offset = kernelSize / 2;
IntegerImage dilated( rows, std::vector<int>( cols, 0 ) );

Expand Down Expand Up @@ -271,4 +274,54 @@ std::vector<std::pair<int, int>> boundary( const IntegerImage& image )

return boundaries;
}

//--------------------------------------------------------------------------------------------------
/// Ramer-Douglas-Peucker simplification algorithm
///
/// https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
//--------------------------------------------------------------------------------------------------
void simplifyPolygon( std::vector<cvf::Vec3d>& vertices, double epsilon )
{
// If the polygon has fewer than 3 vertices, it cannot be simplified.
if ( vertices.size() < 3 ) return;

// Find the point with the maximum perpendicular distance from the line connecting the endpoints.
std::optional<std::pair<size_t, double>> maxDistPoint;

for ( size_t i = 1; i < vertices.size() - 1; ++i )
{
const cvf::Vec3d& point = vertices[i];
cvf::Vec3d projected = cvf::GeometryTools::projectPointOnLine( vertices.front(), vertices.back(), point );
double distance = ( projected - point ).length();

if ( !maxDistPoint || distance > maxDistPoint->second )
{
maxDistPoint = std::make_pair( i, distance );
}
}

// If the maximum distance exceeds epsilon, split and simplify recursively.
if ( maxDistPoint && maxDistPoint->second > epsilon )
{
size_t splitIndex = maxDistPoint->first;

// Divide the vertices into two segments.
std::vector<cvf::Vec3d> segment1( vertices.begin(), vertices.begin() + splitIndex + 1 );
std::vector<cvf::Vec3d> segment2( vertices.begin() + splitIndex, vertices.end() );

// Recursively simplify both segments.
simplifyPolygon( segment1, epsilon );
simplifyPolygon( segment2, epsilon );

// Combine the simplified segments, avoiding duplication at the split point.
vertices = std::move( segment1 );
vertices.pop_back(); // Remove duplicate at the split point.
vertices.insert( vertices.end(), segment2.begin(), segment2.end() );
}
else
{
// If no point exceeds the threshold, reduce to endpoints.
vertices = { vertices.front(), vertices.back() };
}
}
} // namespace RigPolygonTools
7 changes: 6 additions & 1 deletion ApplicationLibCode/ReservoirDataModel/RigPolygonTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

#pragma once

#include "vector"
#include "cvfVector3.h"

#include <vector>

namespace RigPolygonTools
{
Expand All @@ -31,4 +33,7 @@ IntegerImage fillInterior( IntegerImage sourceImage );

std::vector<std::pair<int, int>> boundary( const IntegerImage& image );

// Recursive function modifying the incoming vertices
void simplifyPolygon( std::vector<cvf::Vec3d>& vertices, double epsilon );

} // namespace RigPolygonTools
34 changes: 34 additions & 0 deletions ApplicationLibCode/UnitTests/RigPolygonTools-Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,37 @@ TEST( RigPolygonToolsTest, BoundaryInvalidInputTest )
EXPECT_TRUE( RigPolygonTools::boundary( emptyImage ).empty() );
EXPECT_TRUE( RigPolygonTools::boundary( { { 1, 1 }, { 1 } } ).empty() ); // Inconsistent row sizes
}

// Test for simplifyPolygon function
TEST( RigPolygonToolsTest, SimplifyPolygonTest )
{
// Arrange
std::vector<cvf::Vec3d> vertices =
{ { 0.0, 0.0, 0.0 }, { 1.0, 0.1, 0.0 }, { 1.5, -0.1, 0.0 }, { 3.0, 5.0, 0.0 }, { 5.0, 6.0, 0.0 }, { 7.0, 7.0, 0.0 }, { 8.0, 8.0, 0.0 } };
double epsilon = 1;
std::vector<cvf::Vec3d> expected = { { 0.0, 0.0, 0.0 }, { 1.5, -0.1, 0.0 }, { 3.0, 5.0, 0.0 }, { 8.0, 8.0, 0.0 } };

// Act
RigPolygonTools::simplifyPolygon( vertices, epsilon );

// Assert
EXPECT_EQ( vertices.size(), expected.size() );
for ( size_t i = 0; i < vertices.size(); ++i )
{
EXPECT_DOUBLE_EQ( vertices[i].x(), expected[i].x() );
EXPECT_DOUBLE_EQ( vertices[i].y(), expected[i].y() );
EXPECT_DOUBLE_EQ( vertices[i].z(), expected[i].z() );
}
}

// Test for simplifyPolygon function with invalid input
TEST( RigPolygonToolsTest, SimplifyPolygonInvalidInputTest )
{
// Arrange
std::vector<cvf::Vec3d> emptyVertices;
double epsilon = 1.0;

// Act & Assert
EXPECT_NO_THROW( RigPolygonTools::simplifyPolygon( emptyVertices, epsilon ) );
EXPECT_EQ( emptyVertices.size(), 0 );
}

0 comments on commit 36c92dc

Please sign in to comment.