Skip to content

Commit

Permalink
Merge pull request #364 from arkirchner/main
Browse files Browse the repository at this point in the history
feat: Segmentize for GeosCapi geometries.
  • Loading branch information
keithdoggett committed Nov 15, 2023
2 parents 5ed969a + 964e54b commit 4772e00
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions History.md
Expand Up @@ -6,6 +6,7 @@
* Fix Naming/VariableNumber from rubocop_todos. (@haroon26) #351
* Fix Lint/MissingSuper from rubocop_todos. (@haroon26) #352
* Drop support for Ruby 2.6. (@seuros) #353
* Add `segmentize` method to CAPI geometires (@arkirchner) #364

**Bug Fixes**

Expand Down
1 change: 1 addition & 0 deletions ext/geos_c_impl/extconf.rb
Expand Up @@ -45,6 +45,7 @@ def create_dummy_makefile
have_func("GEOSPreparedDisjoint_r", "geos_c.h")
have_func("GEOSUnaryUnion_r", "geos_c.h")
have_func("GEOSCoordSeq_isCCW_r", "geos_c.h")
have_func("GEOSDensify", "geos_c.h")
have_func("rb_memhash", "ruby.h")
have_func("rb_gc_mark_movable", "ruby.h")
end
Expand Down
25 changes: 25 additions & 0 deletions ext/geos_c_impl/geometry.c
Expand Up @@ -740,6 +740,27 @@ method_geometry_buffer(VALUE self, VALUE distance)
return result;
}

#ifdef RGEO_GEOS_SUPPORTS_DENSIFY
static VALUE
method_geometry_segmentize(VALUE self, VALUE max_segment_length)
{
VALUE result;
RGeo_GeometryData* self_data;
const GEOSGeometry* self_geom;
VALUE factory;

result = Qnil;
self_data = RGEO_GEOMETRY_DATA_PTR(self);
self_geom = self_data->geom;
if (self_geom) {
factory = self_data->factory;
result = rgeo_wrap_geos_geometry(
factory, GEOSDensify(self_geom, rb_num2dbl(max_segment_length)), Qnil);
}
return result;
}
#endif

static VALUE
method_geometry_buffer_with_style(VALUE self,
VALUE distance,
Expand Down Expand Up @@ -1308,6 +1329,10 @@ rgeo_init_geos_geometry()
geos_geometry_methods, "make_valid", method_geometry_make_valid, 0);
rb_define_method(
geos_geometry_methods, "polygonize", method_geometry_polygonize, 0);
#ifdef RGEO_GEOS_SUPPORTS_DENSIFY
rb_define_method(
geos_geometry_methods, "segmentize", method_geometry_segmentize, 1);
#endif
}

RGEO_END_C
Expand Down
3 changes: 3 additions & 0 deletions ext/geos_c_impl/preface.h
Expand Up @@ -23,6 +23,9 @@
#ifdef HAVE_GEOSCOORDSEQ_ISCCW_R
#define RGEO_GEOS_SUPPORTS_ISCCW
#endif
#ifdef HAVE_GEOSDENSIFY
#define RGEO_GEOS_SUPPORTS_DENSIFY
#endif
#ifdef HAVE_RB_GC_MARK_MOVABLE
#define mark rb_gc_mark_movable
#else
Expand Down
15 changes: 15 additions & 0 deletions test/geos_capi/line_string_test.rb
Expand Up @@ -7,9 +7,11 @@
# -----------------------------------------------------------------------------

require_relative "../test_helper"
require_relative "./skip_capi"

class GeosLineStringTest < Minitest::Test # :nodoc:
include RGeo::Tests::Common::LineStringTests
prepend SkipCAPI

def setup
skip "CAPI not supported" unless RGeo::Geos.capi_supported?
Expand Down Expand Up @@ -52,4 +54,17 @@ def test_polygonize_dangle

assert_equal expected, input.polygonize
end

def test_segmentize
skip_geos_version_less_then("3.10")

input = @factory.parse_wkt("LINESTRING(0 0, 0 10)")
expected = @factory.parse_wkt("LINESTRING (0 0, 0 5, 0 10)")

assert_equal expected, input.segmentize(5)

assert_raises(TypeError, "no implicit conversion to float from string") { input.segmentize("a") }
assert_raises(TypeError, "no implicit conversion to float from nil") { input.segmentize(nil) }
assert_raises(RGeo::Error::InvalidGeometry, "Tolerance must be positive") { input.segmentize(0) }
end
end
13 changes: 13 additions & 0 deletions test/geos_capi/polygon_test.rb
Expand Up @@ -179,4 +179,17 @@ def test_polygonize

assert_equal expected, input.polygonize
end

def test_segmentize
skip_geos_version_less_then("3.10")

input = @factory.parse_wkt("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))")
expected = @factory.parse_wkt("POLYGON ((0 0, 5 0, 10 0, 10 5, 10 10, 5 10, 0 10, 0 5, 0 0))")

assert_equal expected, input.segmentize(5)

assert_raises(TypeError, "no implicit conversion to float from string") { input.segmentize("a") }
assert_raises(TypeError, "no implicit conversion to float from nil") { input.segmentize(nil) }
assert_raises(RGeo::Error::InvalidGeometry, "Tolerance must be positive") { input.segmentize(0) }
end
end
6 changes: 6 additions & 0 deletions test/geos_capi/skip_capi.rb
Expand Up @@ -5,4 +5,10 @@ def setup
skip "Needs GEOS CAPI." unless RGeo::Geos.capi_supported?
super
end

def skip_geos_version_less_then(version)
return if Gem::Version.new(RGeo::Geos.version) >= Gem::Version.new(version)

skip "Needs GEOS version #{version} or later."
end
end

0 comments on commit 4772e00

Please sign in to comment.