ffi-geos 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1015 -134
- data/.travis.yml +3 -4
- data/FUNDING.yml +2 -0
- data/Gemfile +2 -2
- data/MIT-LICENSE +1 -1
- data/lib/ffi-geos.rb +37 -4
- data/lib/ffi-geos/geometry.rb +46 -10
- data/lib/ffi-geos/strtree.rb +25 -25
- data/lib/ffi-geos/utils.rb +12 -11
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkt_writer.rb +1 -4
- data/test/coordinate_sequence_tests.rb +2 -2
- data/test/geometry_collection_tests.rb +3 -2
- data/test/geometry_tests.rb +209 -22
- data/test/strtree_tests.rb +1 -0
- data/test/test_helper.rb +33 -25
- metadata +7 -6
    
        data/.travis.yml
    CHANGED
    
    
    
        data/FUNDING.yml
    ADDED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/MIT-LICENSE
    CHANGED
    
    
    
        data/lib/ffi-geos.rb
    CHANGED
    
    | @@ -50,7 +50,7 @@ module Geos | |
| 50 50 |  | 
| 51 51 | 
             
              module FFIGeos
         | 
| 52 52 | 
             
                def self.search_paths
         | 
| 53 | 
            -
                  @search_paths ||=  | 
| 53 | 
            +
                  @search_paths ||= \
         | 
| 54 54 | 
             
                    if ENV['GEOS_LIBRARY_PATH']
         | 
| 55 55 | 
             
                      [ENV['GEOS_LIBRARY_PATH']]
         | 
| 56 56 | 
             
                    elsif FFI::Platform::IS_WINDOWS
         | 
| @@ -58,7 +58,6 @@ module Geos | |
| 58 58 | 
             
                    else
         | 
| 59 59 | 
             
                      ['/usr/local/{lib64,lib}', '/opt/local/{lib64,lib}', '/usr/{lib64,lib}', '/usr/lib/{x86_64,i386}-linux-gnu']
         | 
| 60 60 | 
             
                    end
         | 
| 61 | 
            -
                  end
         | 
| 62 61 | 
             
                end
         | 
| 63 62 |  | 
| 64 63 | 
             
                def self.find_lib(lib)
         | 
| @@ -72,10 +71,9 @@ module Geos | |
| 72 71 | 
             
                end
         | 
| 73 72 |  | 
| 74 73 | 
             
                def self.geos_library_path
         | 
| 75 | 
            -
                  @geos_library_path ||=  | 
| 74 | 
            +
                  @geos_library_path ||= \
         | 
| 76 75 | 
             
                    # On MingW the libraries have version numbers
         | 
| 77 76 | 
             
                    find_lib('{lib,}geos_c{,-?}')
         | 
| 78 | 
            -
                  end
         | 
| 79 77 | 
             
                end
         | 
| 80 78 |  | 
| 81 79 | 
             
                # For backwards compatibility with older ffi-geos versions where this
         | 
| @@ -406,6 +404,11 @@ module Geos | |
| 406 404 | 
             
                    :pointer, :pointer, :pointer, :pointer
         | 
| 407 405 | 
             
                  ],
         | 
| 408 406 |  | 
| 407 | 
            +
                  GEOSIntersectionPrec_r: [
         | 
| 408 | 
            +
                    # *geom, *handle, *geom_a, *geom_b, precision
         | 
| 409 | 
            +
                    :pointer, :pointer, :pointer, :pointer, :double
         | 
| 410 | 
            +
                  ],
         | 
| 411 | 
            +
             | 
| 409 412 | 
             
                  GEOSBufferWithParams_r: [
         | 
| 410 413 | 
             
                    # *geom, *handle, *geom, *params, width
         | 
| 411 414 | 
             
                    :pointer, :pointer, :pointer, :pointer, :double
         | 
| @@ -442,11 +445,21 @@ module Geos | |
| 442 445 | 
             
                    :pointer, :pointer, :pointer, :pointer
         | 
| 443 446 | 
             
                  ],
         | 
| 444 447 |  | 
| 448 | 
            +
                  GEOSDifferencePrec_r: [
         | 
| 449 | 
            +
                    # *geom, *handle, *geom_a, *geom_b, precision
         | 
| 450 | 
            +
                    :pointer, :pointer, :pointer, :pointer, :double
         | 
| 451 | 
            +
                  ],
         | 
| 452 | 
            +
             | 
| 445 453 | 
             
                  GEOSSymDifference_r: [
         | 
| 446 454 | 
             
                    # *geom, *handle, *geom_a, *geom_b
         | 
| 447 455 | 
             
                    :pointer, :pointer, :pointer, :pointer
         | 
| 448 456 | 
             
                  ],
         | 
| 449 457 |  | 
| 458 | 
            +
                  GEOSSymDifferencePrec_r: [
         | 
| 459 | 
            +
                    # *geom, *handle, *geom_a, *geom_b, precision
         | 
| 460 | 
            +
                    :pointer, :pointer, :pointer, :pointer, :double
         | 
| 461 | 
            +
                  ],
         | 
| 462 | 
            +
             | 
| 450 463 | 
             
                  GEOSBoundary_r: [
         | 
| 451 464 | 
             
                    # *geom, *handle, *geom
         | 
| 452 465 | 
             
                    :pointer, :pointer, :pointer
         | 
| @@ -457,6 +470,11 @@ module Geos | |
| 457 470 | 
             
                    :pointer, :pointer, :pointer, :pointer
         | 
| 458 471 | 
             
                  ],
         | 
| 459 472 |  | 
| 473 | 
            +
                  GEOSUnionPrec_r: [
         | 
| 474 | 
            +
                    # *geom, *handle, *geom_a, *geom_b, precision
         | 
| 475 | 
            +
                    :pointer, :pointer, :pointer, :pointer, :double
         | 
| 476 | 
            +
                  ],
         | 
| 477 | 
            +
             | 
| 460 478 | 
             
                  GEOSCoverageUnion_r: [
         | 
| 461 479 | 
             
                    # *geom, *handle, *geom
         | 
| 462 480 | 
             
                    :pointer, :pointer, :pointer
         | 
| @@ -467,6 +485,11 @@ module Geos | |
| 467 485 | 
             
                    :pointer, :pointer, :pointer
         | 
| 468 486 | 
             
                  ],
         | 
| 469 487 |  | 
| 488 | 
            +
                  GEOSUnaryUnionPrec_r: [
         | 
| 489 | 
            +
                    # *geom, *handle, *geom, precision
         | 
| 490 | 
            +
                    :pointer, :pointer, :pointer, :double
         | 
| 491 | 
            +
                  ],
         | 
| 492 | 
            +
             | 
| 470 493 | 
             
                  GEOSNode_r: [
         | 
| 471 494 | 
             
                    # *geom, *handle, *geom
         | 
| 472 495 | 
             
                    :pointer, :pointer, :pointer
         | 
| @@ -798,6 +821,16 @@ module Geos | |
| 798 821 | 
             
                    :pointer, :pointer, :pointer
         | 
| 799 822 | 
             
                  ],
         | 
| 800 823 |  | 
| 824 | 
            +
                  GEOSMaximumInscribedCircle_r: [
         | 
| 825 | 
            +
                    # *geom, *handle, *geom, tolerance
         | 
| 826 | 
            +
                    :pointer, :pointer, :pointer, :double
         | 
| 827 | 
            +
                  ],
         | 
| 828 | 
            +
             | 
| 829 | 
            +
                  GEOSLargestEmptyCircle_r: [
         | 
| 830 | 
            +
                    # *geom, *handle, *geom, *geom, tolerance
         | 
| 831 | 
            +
                    :pointer, :pointer, :pointer, :pointer, :double
         | 
| 832 | 
            +
                  ],
         | 
| 833 | 
            +
             | 
| 801 834 | 
             
                  GEOSMinimumWidth_r: [
         | 
| 802 835 | 
             
                    # *geom, *handle, *geom
         | 
| 803 836 | 
             
                    :pointer, :pointer, :pointer
         | 
    
        data/lib/ffi-geos/geometry.rb
    CHANGED
    
    | @@ -83,9 +83,14 @@ module Geos | |
| 83 83 | 
             
                  CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle_pointer, ptr), false, self)
         | 
| 84 84 | 
             
                end
         | 
| 85 85 |  | 
| 86 | 
            -
                def intersection(geom)
         | 
| 86 | 
            +
                def intersection(geom, precision: nil)
         | 
| 87 87 | 
             
                  check_geometry(geom)
         | 
| 88 | 
            -
             | 
| 88 | 
            +
             | 
| 89 | 
            +
                  if precision
         | 
| 90 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSIntersectionPrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 91 | 
            +
                  else
         | 
| 92 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 93 | 
            +
                  end
         | 
| 89 94 | 
             
                end
         | 
| 90 95 |  | 
| 91 96 | 
             
                if FFIGeos.respond_to?(:GEOSBufferWithParams_r)
         | 
| @@ -139,14 +144,24 @@ module Geos | |
| 139 144 | 
             
                  cast_geometry_ptr(FFIGeos.GEOSConvexHull_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
         | 
| 140 145 | 
             
                end
         | 
| 141 146 |  | 
| 142 | 
            -
                def difference(geom)
         | 
| 147 | 
            +
                def difference(geom, precision: nil)
         | 
| 143 148 | 
             
                  check_geometry(geom)
         | 
| 144 | 
            -
             | 
| 149 | 
            +
             | 
| 150 | 
            +
                  if precision
         | 
| 151 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSDifferencePrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 152 | 
            +
                  else
         | 
| 153 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 154 | 
            +
                  end
         | 
| 145 155 | 
             
                end
         | 
| 146 156 |  | 
| 147 | 
            -
                def sym_difference(geom)
         | 
| 157 | 
            +
                def sym_difference(geom, precision: nil)
         | 
| 148 158 | 
             
                  check_geometry(geom)
         | 
| 149 | 
            -
             | 
| 159 | 
            +
             | 
| 160 | 
            +
                  if precision
         | 
| 161 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSSymDifferencePrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 162 | 
            +
                  else
         | 
| 163 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 164 | 
            +
                  end
         | 
| 150 165 | 
             
                end
         | 
| 151 166 | 
             
                alias symmetric_difference sym_difference
         | 
| 152 167 |  | 
| @@ -157,10 +172,15 @@ module Geos | |
| 157 172 | 
             
                # Calling without a geom argument is equivalent to calling unary_union when
         | 
| 158 173 | 
             
                # using GEOS 3.3+ and is equivalent to calling union_cascaded in older
         | 
| 159 174 | 
             
                # versions.
         | 
| 160 | 
            -
                def union(geom = nil)
         | 
| 175 | 
            +
                def union(geom = nil, precision: nil)
         | 
| 161 176 | 
             
                  if geom
         | 
| 162 177 | 
             
                    check_geometry(geom)
         | 
| 163 | 
            -
             | 
| 178 | 
            +
             | 
| 179 | 
            +
                    if precision
         | 
| 180 | 
            +
                      cast_geometry_ptr(FFIGeos.GEOSUnionPrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 181 | 
            +
                    else
         | 
| 182 | 
            +
                      cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
         | 
| 183 | 
            +
                    end
         | 
| 164 184 | 
             
                  elsif respond_to?(:unary_union)
         | 
| 165 185 | 
             
                    unary_union
         | 
| 166 186 | 
             
                  else
         | 
| @@ -181,8 +201,12 @@ module Geos | |
| 181 201 |  | 
| 182 202 | 
             
                if FFIGeos.respond_to?(:GEOSUnaryUnion_r)
         | 
| 183 203 | 
             
                  # Available in GEOS 3.3+
         | 
| 184 | 
            -
                  def unary_union
         | 
| 185 | 
            -
                     | 
| 204 | 
            +
                  def unary_union(precision = nil)
         | 
| 205 | 
            +
                    if precision
         | 
| 206 | 
            +
                      cast_geometry_ptr(FFIGeos.GEOSUnaryUnionPrec_r(Geos.current_handle_pointer, ptr, precision), srid_copy: srid)
         | 
| 207 | 
            +
                    else
         | 
| 208 | 
            +
                      cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
         | 
| 209 | 
            +
                    end
         | 
| 186 210 | 
             
                  end
         | 
| 187 211 | 
             
                end
         | 
| 188 212 |  | 
| @@ -695,6 +719,18 @@ module Geos | |
| 695 719 | 
             
                  end
         | 
| 696 720 | 
             
                end
         | 
| 697 721 |  | 
| 722 | 
            +
                if FFIGeos.respond_to?(:GEOSMaximumInscribedCircle_r)
         | 
| 723 | 
            +
                  def maximum_inscribed_circle(precision)
         | 
| 724 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSMaximumInscribedCircle_r(Geos.current_handle_pointer, ptr, precision))
         | 
| 725 | 
            +
                  end
         | 
| 726 | 
            +
                end
         | 
| 727 | 
            +
             | 
| 728 | 
            +
                if FFIGeos.respond_to?(:GEOSLargestEmptyCircle_r)
         | 
| 729 | 
            +
                  def largest_empty_circle(precision, boundary: nil)
         | 
| 730 | 
            +
                    cast_geometry_ptr(FFIGeos.GEOSLargestEmptyCircle_r(Geos.current_handle_pointer, ptr, boundary ? boundary.ptr : nil, precision))
         | 
| 731 | 
            +
                  end
         | 
| 732 | 
            +
                end
         | 
| 733 | 
            +
             | 
| 698 734 | 
             
                if FFIGeos.respond_to?(:GEOSMinimumWidth_r)
         | 
| 699 735 | 
             
                  def minimum_width
         | 
| 700 736 | 
             
                    cast_geometry_ptr(FFIGeos.GEOSMinimumWidth_r(Geos.current_handle_pointer, ptr))
         | 
    
        data/lib/ffi-geos/strtree.rb
    CHANGED
    
    | @@ -23,18 +23,19 @@ module Geos | |
| 23 23 | 
             
                  geoms_and_objects = nil # forward declaration
         | 
| 24 24 | 
             
                  capacity = 10
         | 
| 25 25 |  | 
| 26 | 
            -
                   | 
| 27 | 
            -
                     | 
| 28 | 
            -
             | 
| 29 | 
            -
                     | 
| 30 | 
            -
                      args.first
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                       | 
| 33 | 
            -
             | 
| 26 | 
            +
                  case args.first
         | 
| 27 | 
            +
                    when Integer
         | 
| 28 | 
            +
                      capacity = args.first
         | 
| 29 | 
            +
                    when Array
         | 
| 30 | 
            +
                      geoms_and_objects = if args.first.first.is_a?(Array)
         | 
| 31 | 
            +
                        args.first
         | 
| 32 | 
            +
                      else
         | 
| 33 | 
            +
                        args
         | 
| 34 | 
            +
                      end
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 36 | 
            +
                      geoms_and_objects.each do |geom, _obj|
         | 
| 37 | 
            +
                        check_geometry(geom)
         | 
| 38 | 
            +
                      end
         | 
| 38 39 | 
             
                  end
         | 
| 39 40 |  | 
| 40 41 | 
             
                  raise ArgumentError, 'STRtree capacity must be greater than 0' if capacity <= 0
         | 
| @@ -97,7 +98,7 @@ module Geos | |
| 97 98 | 
             
                def remove(geom, item)
         | 
| 98 99 | 
             
                  check_geometry(geom)
         | 
| 99 100 |  | 
| 100 | 
            -
                  key = if storage = @storage.detect { |_k, v| v[:item] == item }
         | 
| 101 | 
            +
                  key = if (storage = @storage.detect { |_k, v| v[:item] == item })
         | 
| 101 102 | 
             
                    storage[0]
         | 
| 102 103 | 
             
                  end
         | 
| 103 104 |  | 
| @@ -137,16 +138,17 @@ module Geos | |
| 137 138 |  | 
| 138 139 | 
             
                def query(geom, ret = :item)
         | 
| 139 140 | 
             
                  query_all(geom).collect { |storage|
         | 
| 140 | 
            -
                    item =  | 
| 141 | 
            -
                       | 
| 142 | 
            -
                         | 
| 143 | 
            -
                          memo | 
| 141 | 
            +
                    item = case ret
         | 
| 142 | 
            +
                      when Array
         | 
| 143 | 
            +
                        storage.inject({}) do |memo, k|
         | 
| 144 | 
            +
                          memo.tap do
         | 
| 145 | 
            +
                            memo[k] = storage[k]
         | 
| 146 | 
            +
                          end
         | 
| 144 147 | 
             
                        end
         | 
| 145 | 
            -
                       | 
| 146 | 
            -
             | 
| 147 | 
            -
                       | 
| 148 | 
            -
             | 
| 149 | 
            -
                      storage[ret]
         | 
| 148 | 
            +
                      when :all
         | 
| 149 | 
            +
                        storage
         | 
| 150 | 
            +
                      else
         | 
| 151 | 
            +
                        storage[ret]
         | 
| 150 152 | 
             
                    end
         | 
| 151 153 |  | 
| 152 154 | 
             
                    item.tap do
         | 
| @@ -164,10 +166,8 @@ module Geos | |
| 164 166 | 
             
                end
         | 
| 165 167 | 
             
                alias query_geoms query_geometries
         | 
| 166 168 |  | 
| 167 | 
            -
                def iterate
         | 
| 168 | 
            -
                  @storage.each_value | 
| 169 | 
            -
                    yield(v)
         | 
| 170 | 
            -
                  end
         | 
| 169 | 
            +
                def iterate(&block)
         | 
| 170 | 
            +
                  @storage.each_value(&block)
         | 
| 171 171 | 
             
                end
         | 
| 172 172 |  | 
| 173 173 | 
             
                if FFIGeos.respond_to?(:GEOSSTRtree_nearest_generic_r)
         | 
    
        data/lib/ffi-geos/utils.rb
    CHANGED
    
    | @@ -30,17 +30,18 @@ module Geos | |
| 30 30 | 
             
                  def create_point(*args)
         | 
| 31 31 | 
             
                    options = extract_options!(args)
         | 
| 32 32 |  | 
| 33 | 
            -
                     | 
| 34 | 
            -
                       | 
| 35 | 
            -
             | 
| 36 | 
            -
                       | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
                       | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                       | 
| 33 | 
            +
                    case args.length
         | 
| 34 | 
            +
                      when 1
         | 
| 35 | 
            +
                        cs = args.first
         | 
| 36 | 
            +
                      when 2
         | 
| 37 | 
            +
                        cs = CoordinateSequence.new(1, 2)
         | 
| 38 | 
            +
                        cs.x[0] = args[0].to_f
         | 
| 39 | 
            +
                        cs.y[0] = args[1].to_f
         | 
| 40 | 
            +
                      when 3
         | 
| 41 | 
            +
                        cs = CoordinateSequence.new(1, 3)
         | 
| 42 | 
            +
                        cs.x[0], cs.y[0], cs.z[0] = args.map(&:to_f)
         | 
| 43 | 
            +
                      else
         | 
| 44 | 
            +
                        raise ArgumentError, "Wrong number of arguments (#{args.length} for 1-3)"
         | 
| 44 45 | 
             
                    end
         | 
| 45 46 |  | 
| 46 47 | 
             
                    raise ArgumentError, 'IllegalArgumentException: Point coordinate list must contain a single element' if cs.length != 1
         | 
    
        data/lib/ffi-geos/version.rb
    CHANGED
    
    
    
        data/lib/ffi-geos/wkt_writer.rb
    CHANGED
    
    
| @@ -284,7 +284,7 @@ class CoordinateSequenceTests < Minitest::Test | |
| 284 284 |  | 
| 285 285 | 
             
                assert_kind_of(Enumerable, cs.x.each)
         | 
| 286 286 | 
             
                assert_kind_of(Enumerable, cs.x.to_enum)
         | 
| 287 | 
            -
                assert_equal(cs.x, cs.x.each | 
| 287 | 
            +
                assert_equal(cs.x, cs.x.each(&EMPTY_BLOCK))
         | 
| 288 288 | 
             
              end
         | 
| 289 289 |  | 
| 290 290 | 
             
              def test_options_hash
         | 
| @@ -299,7 +299,7 @@ class CoordinateSequenceTests < Minitest::Test | |
| 299 299 |  | 
| 300 300 | 
             
                assert_kind_of(Enumerable, cs.each)
         | 
| 301 301 | 
             
                assert_kind_of(Enumerable, cs.to_enum)
         | 
| 302 | 
            -
                assert_equal(cs, cs.each | 
| 302 | 
            +
                assert_equal(cs, cs.each(&EMPTY_BLOCK))
         | 
| 303 303 | 
             
              end
         | 
| 304 304 |  | 
| 305 305 | 
             
              def test_array_like_access
         | 
| @@ -16,7 +16,7 @@ class GeometryCollectionTests < Minitest::Test | |
| 16 16 | 
             
                geom = read('GEOMETRYCOLLECTION(POINT(0 0))')
         | 
| 17 17 | 
             
                assert_kind_of(Enumerable, geom.each)
         | 
| 18 18 | 
             
                assert_kind_of(Enumerable, geom.to_enum)
         | 
| 19 | 
            -
                assert_equal(geom, geom.each | 
| 19 | 
            +
                assert_equal(geom, geom.each(&EMPTY_BLOCK))
         | 
| 20 20 | 
             
              end
         | 
| 21 21 |  | 
| 22 22 | 
             
              def test_geometry_collection_array
         | 
| @@ -173,7 +173,8 @@ class GeometryCollectionTests < Minitest::Test | |
| 173 173 | 
             
              end
         | 
| 174 174 |  | 
| 175 175 | 
             
              def test_snap_to_grid
         | 
| 176 | 
            -
                wkt = 'GEOMETRYCOLLECTION (LINESTRING (-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0),  | 
| 176 | 
            +
                wkt = 'GEOMETRYCOLLECTION (LINESTRING (-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0), ' \
         | 
| 177 | 
            +
                  'POLYGON ((-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0)), POINT (10.12 10.12))'
         | 
| 177 178 |  | 
| 178 179 | 
             
                expected = 'GEOMETRYCOLLECTION (LINESTRING (-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0), POLYGON ((-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0)), POINT (10 10))'
         | 
| 179 180 |  | 
    
        data/test/geometry_tests.rb
    CHANGED
    
    | @@ -13,12 +13,36 @@ class GeometryTests < Minitest::Test | |
| 13 13 | 
             
              def test_intersection
         | 
| 14 14 | 
             
                comparison_tester(
         | 
| 15 15 | 
             
                  :intersection,
         | 
| 16 | 
            -
                   | 
| 16 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 17 | 
            +
                    'POLYGON ((10 10, 10 5, 5 5, 5 10, 10 10))'
         | 
| 18 | 
            +
                  else
         | 
| 19 | 
            +
                    'POLYGON ((5 10, 10 10, 10 5, 5 5, 5 10))'
         | 
| 20 | 
            +
                  end,
         | 
| 17 21 | 
             
                  'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 18 22 | 
             
                  'POLYGON ((5 5, 15 5, 15 15, 5 15, 5 5))'
         | 
| 19 23 | 
             
                )
         | 
| 20 24 | 
             
              end
         | 
| 21 25 |  | 
| 26 | 
            +
              def test_intersection_with_precision
         | 
| 27 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSIntersectionPrec_r)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                comparison_tester(
         | 
| 30 | 
            +
                  :intersection,
         | 
| 31 | 
            +
                  'GEOMETRYCOLLECTION (POLYGON ((1 2, 1 1, 0.5 1, 1 2)), POLYGON ((9.5 1, 2 1, 2 2, 9 2, 9.5 1)), LINESTRING (1 1, 2 1), LINESTRING (2 2, 1 2))',
         | 
| 32 | 
            +
                  'MULTIPOLYGON(((0 0,5 10,10 0,0 0),(1 1,1 2,2 2,2 1,1 1),(100 100,100 102,102 102,102 100,100 100)))',
         | 
| 33 | 
            +
                  'POLYGON((0 1,0 2,10 2,10 1,0 1))',
         | 
| 34 | 
            +
                  precision: 0
         | 
| 35 | 
            +
                )
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                comparison_tester(
         | 
| 38 | 
            +
                  :intersection,
         | 
| 39 | 
            +
                  'GEOMETRYCOLLECTION (LINESTRING (2 0, 4 0), POINT (0 0), POINT (10 0))',
         | 
| 40 | 
            +
                  'LINESTRING(0 0, 10 0)',
         | 
| 41 | 
            +
                  'LINESTRING(9 0, 12 0, 12 20, 4 0, 2 0, 2 10, 0 10, 0 -10)',
         | 
| 42 | 
            +
                  precision: 2
         | 
| 43 | 
            +
                )
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 22 46 | 
             
              def test_buffer
         | 
| 23 47 | 
             
                simple_tester(
         | 
| 24 48 | 
             
                  :buffer,
         | 
| @@ -182,26 +206,50 @@ class GeometryTests < Minitest::Test | |
| 182 206 |  | 
| 183 207 | 
             
                comparison_tester(
         | 
| 184 208 | 
             
                  :difference,
         | 
| 185 | 
            -
                   | 
| 209 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 210 | 
            +
                    'POLYGON ((0 10, 5 10, 10 10, 10 0, 5 0, 0 0, 0 10))'
         | 
| 211 | 
            +
                  else
         | 
| 212 | 
            +
                    'POLYGON ((0 0, 0 10, 5 10, 10 10, 10 0, 5 0, 0 0))'
         | 
| 213 | 
            +
                  end,
         | 
| 186 214 | 
             
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 187 215 | 
             
                  'LINESTRING(5 -10, 5 10)'
         | 
| 188 216 | 
             
                )
         | 
| 189 217 |  | 
| 190 218 | 
             
                comparison_tester(
         | 
| 191 219 | 
             
                  :difference,
         | 
| 192 | 
            -
                   | 
| 220 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 221 | 
            +
                    'POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10))'
         | 
| 222 | 
            +
                  else
         | 
| 223 | 
            +
                    'POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))'
         | 
| 224 | 
            +
                  end,
         | 
| 193 225 | 
             
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 194 226 | 
             
                  'LINESTRING(10 0, 20 0)'
         | 
| 195 227 | 
             
                )
         | 
| 196 228 |  | 
| 197 229 | 
             
                comparison_tester(
         | 
| 198 230 | 
             
                  :difference,
         | 
| 199 | 
            -
                   | 
| 231 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 232 | 
            +
                    'POLYGON ((0 10, 10 10, 10 5, 5 5, 5 0, 0 0, 0 10))'
         | 
| 233 | 
            +
                  else
         | 
| 234 | 
            +
                    'POLYGON ((0 0, 0 10, 10 10, 10 5, 5 5, 5 0, 0 0))'
         | 
| 235 | 
            +
                  end,
         | 
| 200 236 | 
             
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 201 237 | 
             
                  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
         | 
| 202 238 | 
             
                )
         | 
| 203 239 | 
             
              end
         | 
| 204 240 |  | 
| 241 | 
            +
              def test_difference_with_precision
         | 
| 242 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSDifferencePrec_r)
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                comparison_tester(
         | 
| 245 | 
            +
                  :difference,
         | 
| 246 | 
            +
                  'MULTILINESTRING ((2 8, 4 8), (6 8, 10 8))',
         | 
| 247 | 
            +
                  'LINESTRING (2 8, 10 8)',
         | 
| 248 | 
            +
                  'LINESTRING (3.9 8.1, 6.1 7.9)',
         | 
| 249 | 
            +
                  precision: 2
         | 
| 250 | 
            +
                )
         | 
| 251 | 
            +
              end
         | 
| 252 | 
            +
             | 
| 205 253 | 
             
              def test_sym_difference
         | 
| 206 254 | 
             
                %w{ sym_difference symmetric_difference }.each do |method|
         | 
| 207 255 | 
             
                  comparison_tester(
         | 
| @@ -255,27 +303,51 @@ class GeometryTests < Minitest::Test | |
| 255 303 |  | 
| 256 304 | 
             
                  comparison_tester(
         | 
| 257 305 | 
             
                    method,
         | 
| 258 | 
            -
                     | 
| 306 | 
            +
                    if Geos::GEOS_VERSION > '3.9.0'
         | 
| 307 | 
            +
                      'GEOMETRYCOLLECTION (POLYGON ((0 10, 5 10, 10 10, 10 0, 5 0, 0 0, 0 10)), LINESTRING (5 -10, 5 0))'
         | 
| 308 | 
            +
                    else
         | 
| 309 | 
            +
                      'GEOMETRYCOLLECTION (LINESTRING (5 -10, 5 0), POLYGON ((0 0, 0 10, 5 10, 10 10, 10 0, 5 0, 0 0)))'
         | 
| 310 | 
            +
                    end,
         | 
| 259 311 | 
             
                    'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 260 312 | 
             
                    'LINESTRING(5 -10, 5 10)'
         | 
| 261 313 | 
             
                  )
         | 
| 262 314 |  | 
| 263 315 | 
             
                  comparison_tester(
         | 
| 264 316 | 
             
                    method,
         | 
| 265 | 
            -
                     | 
| 317 | 
            +
                    if Geos::GEOS_VERSION > '3.9.0'
         | 
| 318 | 
            +
                      'GEOMETRYCOLLECTION (POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10)), LINESTRING (10 0, 20 0))'
         | 
| 319 | 
            +
                    else
         | 
| 320 | 
            +
                      'GEOMETRYCOLLECTION (LINESTRING (10 0, 20 0), POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0)))'
         | 
| 321 | 
            +
                    end,
         | 
| 266 322 | 
             
                    'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 267 323 | 
             
                    'LINESTRING(10 0, 20 0)'
         | 
| 268 324 | 
             
                  )
         | 
| 269 325 |  | 
| 270 326 | 
             
                  comparison_tester(
         | 
| 271 327 | 
             
                    method,
         | 
| 272 | 
            -
                     | 
| 328 | 
            +
                    if Geos::GEOS_VERSION > '3.9.0'
         | 
| 329 | 
            +
                      'MULTIPOLYGON (((0 10, 10 10, 10 5, 5 5, 5 0, 0 0, 0 10)), ((10 0, 10 5, 15 5, 15 -5, 5 -5, 5 0, 10 0)))'
         | 
| 330 | 
            +
                    else
         | 
| 331 | 
            +
                      'MULTIPOLYGON (((0 0, 0 10, 10 10, 10 5, 5 5, 5 0, 0 0)), ((5 0, 10 0, 10 5, 15 5, 15 -5, 5 -5, 5 0)))'
         | 
| 332 | 
            +
                    end,
         | 
| 273 333 | 
             
                    'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 274 334 | 
             
                    'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
         | 
| 275 335 | 
             
                  )
         | 
| 276 336 | 
             
                end
         | 
| 277 337 | 
             
              end
         | 
| 278 338 |  | 
| 339 | 
            +
              def test_sym_difference_with_precision
         | 
| 340 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSSymDifferencePrec_r)
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                comparison_tester(
         | 
| 343 | 
            +
                  :sym_difference,
         | 
| 344 | 
            +
                  'GEOMETRYCOLLECTION (POLYGON ((0 10, 6 10, 10 10, 10 0, 6 0, 0 0, 0 10)), LINESTRING (6 -10, 6 0))',
         | 
| 345 | 
            +
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 346 | 
            +
                  'LINESTRING(5 -10, 5 10)',
         | 
| 347 | 
            +
                  precision: 2
         | 
| 348 | 
            +
                )
         | 
| 349 | 
            +
              end
         | 
| 350 | 
            +
             | 
| 279 351 | 
             
              def test_boundary
         | 
| 280 352 | 
             
                simple_tester(
         | 
| 281 353 | 
             
                  :boundary,
         | 
| @@ -348,32 +420,59 @@ class GeometryTests < Minitest::Test | |
| 348 420 |  | 
| 349 421 | 
             
                comparison_tester(
         | 
| 350 422 | 
             
                  :union,
         | 
| 351 | 
            -
                   | 
| 423 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 424 | 
            +
                    'GEOMETRYCOLLECTION (POLYGON ((0 10, 5 10, 10 10, 10 0, 5 0, 0 0, 0 10)), LINESTRING (5 -10, 5 0))'
         | 
| 425 | 
            +
                  else
         | 
| 426 | 
            +
                    'GEOMETRYCOLLECTION (LINESTRING (5 -10, 5 0), POLYGON ((0 0, 0 10, 5 10, 10 10, 10 0, 5 0, 0 0)))'
         | 
| 427 | 
            +
                  end,
         | 
| 352 428 | 
             
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 353 429 | 
             
                  'LINESTRING(5 -10, 5 10)'
         | 
| 354 430 | 
             
                )
         | 
| 355 431 |  | 
| 356 432 | 
             
                comparison_tester(
         | 
| 357 433 | 
             
                  :union,
         | 
| 358 | 
            -
                   | 
| 434 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 435 | 
            +
                    'GEOMETRYCOLLECTION (POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10)), LINESTRING (10 0, 20 0))'
         | 
| 436 | 
            +
                  else
         | 
| 437 | 
            +
                    'GEOMETRYCOLLECTION (LINESTRING (10 0, 20 0), POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0)))'
         | 
| 438 | 
            +
                  end,
         | 
| 359 439 | 
             
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 360 440 | 
             
                  'LINESTRING(10 0, 20 0)'
         | 
| 361 441 | 
             
                )
         | 
| 362 442 |  | 
| 363 443 | 
             
                comparison_tester(
         | 
| 364 444 | 
             
                  :union,
         | 
| 365 | 
            -
                   | 
| 445 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 446 | 
            +
                    'POLYGON ((0 10, 10 10, 10 5, 15 5, 15 -5, 5 -5, 5 0, 0 0, 0 10))'
         | 
| 447 | 
            +
                  else
         | 
| 448 | 
            +
                    'POLYGON ((0 0, 0 10, 10 10, 10 5, 15 5, 15 -5, 5 -5, 5 0, 0 0))'
         | 
| 449 | 
            +
                  end,
         | 
| 366 450 | 
             
                  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
         | 
| 367 451 | 
             
                  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
         | 
| 368 452 | 
             
                )
         | 
| 369 453 | 
             
              end
         | 
| 370 454 |  | 
| 455 | 
            +
              def test_union_with_precision
         | 
| 456 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSUnionPrec_r)
         | 
| 457 | 
            +
             | 
| 458 | 
            +
                geom_a = read('POINT (1.9 8.2)')
         | 
| 459 | 
            +
                geom_b = read('POINT (4.1 9.8)')
         | 
| 460 | 
            +
             | 
| 461 | 
            +
                result = geom_a.union(geom_b, precision: 2)
         | 
| 462 | 
            +
             | 
| 463 | 
            +
                assert_equal('MULTIPOINT (2 8, 4 10)', write(result))
         | 
| 464 | 
            +
              end
         | 
| 465 | 
            +
             | 
| 371 466 | 
             
              def test_union_cascaded
         | 
| 372 467 | 
             
                skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:union_cascaded)
         | 
| 373 468 |  | 
| 374 469 | 
             
                simple_tester(
         | 
| 375 470 | 
             
                  :union_cascaded,
         | 
| 376 | 
            -
                   | 
| 471 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 472 | 
            +
                    'POLYGON ((0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0, 0 0), (12 12, 11 12, 11 11, 12 11, 12 12))'
         | 
| 473 | 
            +
                  else
         | 
| 474 | 
            +
                    'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))'
         | 
| 475 | 
            +
                  end,
         | 
| 377 476 | 
             
                  'MULTIPOLYGON(
         | 
| 378 477 | 
             
                    ((0 0, 1 0, 1 1, 0 1, 0 0)),
         | 
| 379 478 | 
             
                    ((10 10, 10 14, 14 14, 14 10, 10 10),
         | 
| @@ -388,7 +487,11 @@ class GeometryTests < Minitest::Test | |
| 388 487 |  | 
| 389 488 | 
             
                simple_tester(
         | 
| 390 489 | 
             
                  :union_cascaded,
         | 
| 391 | 
            -
                   | 
| 490 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 491 | 
            +
                    'POLYGON ((0 1, 1 1, 2 1, 2 0, 1 0, 0 0, 0 1))'
         | 
| 492 | 
            +
                  else
         | 
| 493 | 
            +
                    'POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))'
         | 
| 494 | 
            +
                  end,
         | 
| 392 495 | 
             
                  'MULTIPOLYGON(
         | 
| 393 496 | 
             
                    ((0 0, 0 1, 1 1, 1 0, 0 0)),
         | 
| 394 497 | 
             
                    ((1 0, 1 1, 2 1, 2 0, 1 0))
         | 
| @@ -401,7 +504,11 @@ class GeometryTests < Minitest::Test | |
| 401 504 |  | 
| 402 505 | 
             
                simple_tester(
         | 
| 403 506 | 
             
                  :unary_union,
         | 
| 404 | 
            -
                   | 
| 507 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 508 | 
            +
                    'POLYGON ((0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0, 0 0), (12 12, 11 12, 11 11, 12 11, 12 12))'
         | 
| 509 | 
            +
                  else
         | 
| 510 | 
            +
                    'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))'
         | 
| 511 | 
            +
                  end,
         | 
| 405 512 | 
             
                  'MULTIPOLYGON(
         | 
| 406 513 | 
             
                    ((0 0, 1 0, 1 1, 0 1, 0 0)),
         | 
| 407 514 | 
             
                    ((10 10, 10 14, 14 14, 14 10, 10 10),
         | 
| @@ -411,6 +518,22 @@ class GeometryTests < Minitest::Test | |
| 411 518 | 
             
                )
         | 
| 412 519 | 
             
              end
         | 
| 413 520 |  | 
| 521 | 
            +
              def test_unary_union_with_precision
         | 
| 522 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSUnaryUnionPrec_r)
         | 
| 523 | 
            +
             | 
| 524 | 
            +
                simple_tester(
         | 
| 525 | 
            +
                  :unary_union,
         | 
| 526 | 
            +
                  'POLYGON ((0 0, 0 12, 9 12, 9 15, 15 15, 15 9, 12 9, 12 0, 0 0))',
         | 
| 527 | 
            +
                  'MULTIPOLYGON(
         | 
| 528 | 
            +
                    ((0 0, 1 0, 1 1, 0 1, 0 0)),
         | 
| 529 | 
            +
                    ((10 10, 10 14, 14 14, 14 10, 10 10),
         | 
| 530 | 
            +
                    (11 11, 11 12, 12 12, 12 11, 11 11)),
         | 
| 531 | 
            +
                    ((0 0, 11 0, 11 11, 0 11, 0 0))
         | 
| 532 | 
            +
                  ))',
         | 
| 533 | 
            +
                  3
         | 
| 534 | 
            +
                )
         | 
| 535 | 
            +
              end
         | 
| 536 | 
            +
             | 
| 414 537 | 
             
              def test_node
         | 
| 415 538 | 
             
                skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:node)
         | 
| 416 539 |  | 
| @@ -424,7 +547,11 @@ class GeometryTests < Minitest::Test | |
| 424 547 | 
             
              def test_union_without_arguments
         | 
| 425 548 | 
             
                simple_tester(
         | 
| 426 549 | 
             
                  :union,
         | 
| 427 | 
            -
                   | 
| 550 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 551 | 
            +
                    'POLYGON ((0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0, 0 0), (12 12, 11 12, 11 11, 12 11, 12 12))'
         | 
| 552 | 
            +
                  else
         | 
| 553 | 
            +
                    'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))'
         | 
| 554 | 
            +
                  end,
         | 
| 428 555 | 
             
                  'MULTIPOLYGON(
         | 
| 429 556 | 
             
                    ((0 0, 1 0, 1 1, 0 1, 0 0)),
         | 
| 430 557 | 
             
                    ((10 10, 10 14, 14 14, 14 10, 10 10),
         | 
| @@ -1230,7 +1357,11 @@ class GeometryTests < Minitest::Test | |
| 1230 1357 | 
             
                  cs = geom_1.nearest_points(geom_2)
         | 
| 1231 1358 | 
             
                  result = cs.to_s if cs
         | 
| 1232 1359 |  | 
| 1233 | 
            -
                   | 
| 1360 | 
            +
                  if expected.nil?
         | 
| 1361 | 
            +
                    assert_nil(result)
         | 
| 1362 | 
            +
                  else
         | 
| 1363 | 
            +
                    assert_equal(expected, result)
         | 
| 1364 | 
            +
                  end
         | 
| 1234 1365 | 
             
                }
         | 
| 1235 1366 |  | 
| 1236 1367 | 
             
                tester[
         | 
| @@ -1424,7 +1555,14 @@ class GeometryTests < Minitest::Test | |
| 1424 1555 |  | 
| 1425 1556 | 
             
                geom = read('POLYGON((0 0, 1 1, 0 1, 1 0, 0 0))')
         | 
| 1426 1557 |  | 
| 1427 | 
            -
                assert_equal( | 
| 1558 | 
            +
                assert_equal(
         | 
| 1559 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 1560 | 
            +
                    'MULTIPOLYGON (((1 0, 0 0, 0.5 0.5, 1 0)), ((1 1, 0.5 0.5, 0 1, 1 1)))'
         | 
| 1561 | 
            +
                  else
         | 
| 1562 | 
            +
                    'MULTIPOLYGON (((0 0, 0.5 0.5, 1 0, 0 0)), ((0.5 0.5, 0 1, 1 1, 0.5 0.5)))'
         | 
| 1563 | 
            +
                  end,
         | 
| 1564 | 
            +
                  write(geom.make_valid)
         | 
| 1565 | 
            +
                )
         | 
| 1428 1566 | 
             
              end
         | 
| 1429 1567 |  | 
| 1430 1568 | 
             
              def test_shared_paths
         | 
| @@ -1482,7 +1620,7 @@ class GeometryTests < Minitest::Test | |
| 1482 1620 | 
             
                geom = read('LINESTRING(0 0, 10 10))')
         | 
| 1483 1621 | 
             
                assert_kind_of(Enumerable, geom.each)
         | 
| 1484 1622 | 
             
                assert_kind_of(Enumerable, geom.to_enum)
         | 
| 1485 | 
            -
                assert_equal(geom, geom.each | 
| 1623 | 
            +
                assert_equal(geom, geom.each(&EMPTY_BLOCK))
         | 
| 1486 1624 | 
             
              end
         | 
| 1487 1625 |  | 
| 1488 1626 | 
             
              def test_normalize
         | 
| @@ -1668,7 +1806,9 @@ class GeometryTests < Minitest::Test | |
| 1668 1806 |  | 
| 1669 1807 | 
             
                # polygon with a hole
         | 
| 1670 1808 | 
             
                tester[
         | 
| 1671 | 
            -
                  'GEOMETRYCOLLECTION (POLYGON ((8 2, 10 10, 8.5 1, 8 2)), POLYGON ((7 8, 10 10, 8 2, 7 8)), POLYGON ((3 8, 10 10, 7 8, 3 8)),  | 
| 1809 | 
            +
                  'GEOMETRYCOLLECTION (POLYGON ((8 2, 10 10, 8.5 1, 8 2)), POLYGON ((7 8, 10 10, 8 2, 7 8)), POLYGON ((3 8, 10 10, 7 8, 3 8)), ' \
         | 
| 1810 | 
            +
                    'POLYGON ((2 2, 8 2, 8.5 1, 2 2)), POLYGON ((2 2, 7 8, 8 2, 2 2)), POLYGON ((2 2, 3 8, 7 8, 2 2)), POLYGON ((0.5 9, 10 10, 3 8, 0.5 9)), ' \
         | 
| 1811 | 
            +
                    'POLYGON ((0.5 9, 3 8, 2 2, 0.5 9)), POLYGON ((0 0, 2 2, 8.5 1, 0 0)), POLYGON ((0 0, 0.5 9, 2 2, 0 0)))',
         | 
| 1672 1812 | 
             
                  'POLYGON((0 0, 8.5 1, 10 10, 0.5 9, 0 0),(2 2, 3 8, 7 8, 8 2, 2 2)))',
         | 
| 1673 1813 | 
             
                  0
         | 
| 1674 1814 | 
             
                ]
         | 
| @@ -1701,7 +1841,14 @@ class GeometryTests < Minitest::Test | |
| 1701 1841 |  | 
| 1702 1842 | 
             
                geom = 'MULTIPOINT(0 0, 100 0, 100 100, 0 100)'
         | 
| 1703 1843 |  | 
| 1704 | 
            -
                tester[ | 
| 1844 | 
            +
                tester[
         | 
| 1845 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 1846 | 
            +
                    'GEOMETRYCOLLECTION (POLYGON ((200 200, 200 50, 50 50, 50 200, 200 200)), POLYGON ((-100 200, 50 200, 50 50, -100 50, -100 200)), POLYGON ((-100 -100, -100 50, 50 50, 50 -100, -100 -100)), POLYGON ((200 -100, 50 -100, 50 50, 200 50, 200 -100)))'
         | 
| 1847 | 
            +
                  else
         | 
| 1848 | 
            +
                    'GEOMETRYCOLLECTION (POLYGON ((50 200, 200 200, 200 50, 50 50, 50 200)), POLYGON ((-100 50, -100 200, 50 200, 50 50, -100 50)), POLYGON ((50 -100, -100 -100, -100 50, 50 50, 50 -100)), POLYGON ((200 50, 200 -100, 50 -100, 50 50, 200 50)))'
         | 
| 1849 | 
            +
                  end,
         | 
| 1850 | 
            +
                  geom
         | 
| 1851 | 
            +
                ]
         | 
| 1705 1852 |  | 
| 1706 1853 | 
             
                tester['MULTILINESTRING ((50 50, 50 200), (200 50, 50 50), (50 50, -100 50), (50 50, 50 -100))', geom, tolerance: 0, only_edges: true]
         | 
| 1707 1854 |  | 
| @@ -1712,7 +1859,15 @@ class GeometryTests < Minitest::Test | |
| 1712 1859 |  | 
| 1713 1860 | 
             
                # Allows a tolerance for the first argument
         | 
| 1714 1861 | 
             
                @writer.rounding_precision = 3
         | 
| 1715 | 
            -
                tester[ | 
| 1862 | 
            +
                tester[
         | 
| 1863 | 
            +
                  if Geos::GEOS_VERSION > '3.9.0'
         | 
| 1864 | 
            +
                    'GEOMETRYCOLLECTION (POLYGON ((290 140, 185 140, 185 215, 188 235, 290 252, 290 140)), POLYGON ((80 340, 101 340, 188 235, 185 215, 80 215, 80 340)), POLYGON ((80 140, 80 215, 185 215, 185 140, 80 140)), POLYGON ((290 340, 290 252, 188 235, 101 340, 290 340)))'
         | 
| 1865 | 
            +
                  else
         | 
| 1866 | 
            +
                    'GEOMETRYCOLLECTION (POLYGON ((290 252, 290 140, 185 140, 185 215, 188 235, 290 252)), POLYGON ((80 215, 80 340, 101 340, 188 235, 185 215, 80 215)), POLYGON ((185 140, 80 140, 80 215, 185 215, 185 140)), POLYGON ((101 340, 290 340, 290 252, 188 235, 101 340)))'
         | 
| 1867 | 
            +
                  end,
         | 
| 1868 | 
            +
                  'MULTIPOINT ((150 210), (210 270), (150 220), (220 210), (215 269))',
         | 
| 1869 | 
            +
                  10
         | 
| 1870 | 
            +
                ]
         | 
| 1716 1871 | 
             
              end
         | 
| 1717 1872 |  | 
| 1718 1873 | 
             
              def test_precision
         | 
| @@ -1785,11 +1940,37 @@ class GeometryTests < Minitest::Test | |
| 1785 1940 | 
             
                tester['LINESTRING (200 200, 200 100)', 'POLYGON ((100 100, 300 100, 200 200, 100 100))']
         | 
| 1786 1941 | 
             
                tester[
         | 
| 1787 1942 | 
             
                  'LINESTRING (-112.712119 33.575919, -112.712127 33.575885)',
         | 
| 1788 | 
            -
                  ' | 
| 1943 | 
            +
                  '0106000000010000000103000000010000001a00000035d42824992d5cc01b834e081dca404073b9c150872d5cc03465a71fd4c940400ec00644882d5cc03b8a' \
         | 
| 1944 | 
            +
                    '73d4d1c94040376dc669882d5cc0bf9cd9aed0c940401363997e892d5cc002f4fbfecdc94040ca4e3fa88b2d5cc0a487a1d5c9c940408f1ce90c8c2d5cc06989' \
         | 
| 1945 | 
            +
                    '95d1c8c94040fab836548c2d5cc0bd175fb4c7c940409f1f46088f2d5cc0962023a0c2c940407b15191d902d5cc068041bd7bfc940400397c79a912d5cc0287d' \
         | 
| 1946 | 
            +
                    '21e4bcc940403201bf46922d5cc065e3c116bbc940409d9d0c8e922d5cc0060fd3beb9c940400ef7915b932d5cc09012bbb6b7c940404fe61f7d932d5cc0e4a0' \
         | 
| 1947 | 
            +
                    '8499b6c94040fc71fbe5932d5cc0ea9106b7b5c94040eaec6470942d5cc0c2323674b3c94040601dc70f952d5cc043588d25acc94040aea06989952d5cc03ecf' \
         | 
| 1948 | 
            +
                    '9f36aac94040307f85cc952d5cc0e5eb32fca7c94040dd0a6135962d5cc01b615111a7c9404048a7ae7c962d5cc00a2aaa7ea5c94040f4328ae5962d5cc05eb8' \
         | 
| 1949 | 
            +
                    '7361a4c94040c49448a2972d5cc04d81cccea2c940407c80eecb992d5cc06745d4449fc9404035d42824992d5cc01b834e081dca4040'
         | 
| 1789 1950 | 
             
                ]
         | 
| 1790 1951 | 
             
                tester['LINESTRING EMPTY', 'POLYGON EMPTY']
         | 
| 1791 1952 | 
             
              end
         | 
| 1792 1953 |  | 
| 1954 | 
            +
              def test_maximum_inscribed_circle
         | 
| 1955 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:maximum_inscribed_circle)
         | 
| 1956 | 
            +
             | 
| 1957 | 
            +
                geom = read('POLYGON ((100 200, 200 200, 200 100, 100 100, 100 200))')
         | 
| 1958 | 
            +
                output = geom.maximum_inscribed_circle(0.001)
         | 
| 1959 | 
            +
                assert_equal('LINESTRING (150 150, 150 200)', write(output))
         | 
| 1960 | 
            +
              end
         | 
| 1961 | 
            +
             | 
| 1962 | 
            +
              def test_largest_empty_circle
         | 
| 1963 | 
            +
                skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:largest_empty_circle)
         | 
| 1964 | 
            +
             | 
| 1965 | 
            +
                geom = read('MULTIPOINT ((100 100), (100 200), (200 200), (200 100))')
         | 
| 1966 | 
            +
                output = geom.largest_empty_circle(0.001)
         | 
| 1967 | 
            +
                assert_equal('LINESTRING (150 150, 100 100)', write(output))
         | 
| 1968 | 
            +
             | 
| 1969 | 
            +
                geom = read('MULTIPOINT ((100 100), (100 200), (200 200), (200 100))')
         | 
| 1970 | 
            +
                output = geom.largest_empty_circle(0.001, boundary: read('MULTIPOINT ((100 100), (100 200), (200 200), (200 100))'))
         | 
| 1971 | 
            +
                assert_equal('LINESTRING (100 100, 100 100)', write(output))
         | 
| 1972 | 
            +
              end
         | 
| 1973 | 
            +
             | 
| 1793 1974 | 
             
              def test_minimum_width
         | 
| 1794 1975 | 
             
                skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:minimum_width)
         | 
| 1795 1976 |  | 
| @@ -1856,7 +2037,13 @@ class GeometryTests < Minitest::Test | |
| 1856 2037 | 
             
                simple_tester(:reverse, 'POINT (3 5)', 'POINT (3 5)')
         | 
| 1857 2038 | 
             
                simple_tester(:reverse, 'MULTIPOINT (100 100, 10 100, 30 100)', 'MULTIPOINT (100 100, 10 100, 30 100)')
         | 
| 1858 2039 | 
             
                simple_tester(:reverse, 'LINESTRING (200 200, 200 100)', 'LINESTRING (200 100, 200 200)')
         | 
| 1859 | 
            -
             | 
| 2040 | 
            +
             | 
| 2041 | 
            +
                if Geos::GEOS_VERSION >= '3.8.1'
         | 
| 2042 | 
            +
                  simple_tester(:reverse, 'MULTILINESTRING ((3 3, 4 4), (1 1, 2 2))', 'MULTILINESTRING ((4 4, 3 3), (2 2, 1 1))')
         | 
| 2043 | 
            +
                else
         | 
| 2044 | 
            +
                  simple_tester(:reverse, 'MULTILINESTRING ((1 1, 2 2), (3 3, 4 4))', 'MULTILINESTRING ((4 4, 3 3), (2 2, 1 1))')
         | 
| 2045 | 
            +
                end
         | 
| 2046 | 
            +
             | 
| 1860 2047 | 
             
                simple_tester(:reverse, 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))', 'POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))')
         | 
| 1861 2048 | 
             
                simple_tester(:reverse, 'MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1)), ((100 100, 100 200, 200 200, 100 100)))', 'MULTIPOLYGON (((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1)), ((100 100, 200 200, 100 200, 100 100)))')
         | 
| 1862 2049 | 
             
                simple_tester(:reverse, 'GEOMETRYCOLLECTION (LINESTRING (1 1, 2 2), GEOMETRYCOLLECTION (LINESTRING (3 5, 2 9)))', 'GEOMETRYCOLLECTION (LINESTRING (2 2, 1 1), GEOMETRYCOLLECTION(LINESTRING (2 9, 3 5)))')
         |