From cdcf12a7ce66d00c43f5e9c714e7bce22eef6268 Mon Sep 17 00:00:00 2001 From: J Smith Date: Fri, 2 Aug 2024 00:10:39 -0300 Subject: [PATCH] Add `Geos::Geometry#polygon_hull_simplfy`. --- lib/ffi-geos.rb | 15 ++++++ lib/ffi-geos/geometry.rb | 13 +++++ test/geometry/polygon_hull_simplify_tests.rb | 55 ++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 test/geometry/polygon_hull_simplify_tests.rb diff --git a/lib/ffi-geos.rb b/lib/ffi-geos.rb index f7fadc2..ab7c16b 100644 --- a/lib/ffi-geos.rb +++ b/lib/ffi-geos.rb @@ -153,6 +153,11 @@ def self.geos_library_paths :keep_collapsed, 1 << 1 ]) + Geos::PolygonHullSimplifyModes = enum(:polygon_hull_simplify_mode, [ + :vertex_ratio, 1, + :area_ratio, 2 + ]) + FFI_LAYOUT = { #### Utility functions #### @@ -470,6 +475,16 @@ def self.geos_library_paths :pointer, :pointer, :pointer, :double, :uint ], + GEOSPolygonHullSimplify_r: [ + # *geom, *handle, *geom, is_outer, vertex_num_fraction + :pointer, :pointer, :pointer, :uint, :double + ], + + GEOSPolygonHullSimplifyMode_r: [ + # *geom, *handle, *geom, is_outer, parameter_mode, parameter + :pointer, :pointer, :pointer, :uint, :uint, :double + ], + GEOSDifference_r: [ # *geom, *handle, *geom_a, *geom_b :pointer, :pointer, :pointer, :pointer diff --git a/lib/ffi-geos/geometry.rb b/lib/ffi-geos/geometry.rb index 313adb8..0b4457d 100644 --- a/lib/ffi-geos/geometry.rb +++ b/lib/ffi-geos/geometry.rb @@ -176,6 +176,19 @@ def concave_hull(ratio: 0.0, allow_holes: false, length: nil) end end + if FFIGeos.respond_to?(:GEOSPolygonHullSimplify_r) && FFIGeos.respond_to?(:GEOSPolygonHullSimplifyMode_r) + def polygon_hull_simplify(parameter, outer: false, mode: :vertex_ratio) + check_enum_value(Geos::PolygonHullSimplifyModes, mode) + + case mode + when :vertex_ratio + cast_geometry_ptr(FFIGeos.GEOSPolygonHullSimplify_r(Geos.current_handle_pointer, ptr, bool_to_int(outer), parameter), srid_copy: srid) + when :area_ratio + cast_geometry_ptr(FFIGeos.GEOSPolygonHullSimplifyMode_r(Geos.current_handle_pointer, ptr, bool_to_int(outer), 2, parameter), srid_copy: srid) + end + end + end + def difference(geom, precision: nil) check_geometry(geom) diff --git a/test/geometry/polygon_hull_simplify_tests.rb b/test/geometry/polygon_hull_simplify_tests.rb new file mode 100644 index 0000000..766b73a --- /dev/null +++ b/test/geometry/polygon_hull_simplify_tests.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'test_helper' + +describe '#polygon_hull_simplify' do + include TestHelper + + def setup + super + writer.trim = true + end + + def tester(expected, geom, *args, **options) + skip unless ENV['FORCE_TESTS'] || !geom.respond_to?(:polygon_hull_simplify) + + simple_tester(:polygon_hull_simplify, expected, geom, *args, **options) + end + + it 'handles a POLYGON' do + tester( + 'POLYGON ((10 90, 50 90, 90 90, 90 10, 10 10, 10 90))', + 'POLYGON ((10 90, 40 60, 20 40, 40 20, 70 50, 40 30, 30 40, 60 70, 50 90, 90 90, 90 10, 10 10, 10 90))', + 0.5, + outer: true + ) + + tester( + 'POLYGON ((10 90, 40 60, 30 40, 60 70, 50 90, 90 90, 90 10, 10 10, 10 90))', + 'POLYGON ((10 90, 40 60, 20 40, 40 20, 70 50, 40 30, 30 40, 60 70, 50 90, 90 90, 90 10, 10 10, 10 90))', + 0.7, + outer: true + ) + + tester( + 'POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', + 'POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', + 0.7, + outer: true + ) + end + + it 'handles an empty POLYGON' do + tester('POLYGON EMPTY', 'POLYGON EMPTY', 0.5, outer: true) + end + + it 'handles a mode' do + tester( + 'POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', + 'POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', + 0.7, + mode: :area_ratio, + outer: true + ) + end +end