Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Equality returning arrays instead of true #382

@LocoDelAssembly

Description

@LocoDelAssembly

Reproduction

# Repro for rgeo 3.0.1: Polygon#eql? returns Array instead of true/false
# Run:
#   gem install rgeo -v 3.0.1
#   ruby rgeo_eql_bug_repro.rb

require 'rgeo'

puts "Ruby: #{RUBY_VERSION}"
puts "RGeo: #{Gem.loaded_specs['rgeo']&.version}"

factory = RGeo::Cartesian.simple_factory(has_z_coordinate: true)

outer = factory.line_string([
  factory.point(1,  -1, 0.0),
  factory.point(9,  -1, 0.0),
  factory.point(9,  -9, 0.0),
  factory.point(1,  -9, 0.0),
  factory.point(1,  -1, 0.0)
])

inner = factory.line_string([
  factory.point(2.5, -2.5, 0.0),
  factory.point(7.5, -2.5, 0.0),
  factory.point(7.5, -7.5, 0.0),
  factory.point(2.5, -7.5, 0.0),
  factory.point(2.5, -2.5, 0.0)
])

# Two equal polygons with an inner ring (hole)
poly_a = factory.polygon(outer, [inner])
poly_b = factory.polygon(
  factory.line_string(outer.points), # build fresh rings to avoid identity tricks
  [factory.line_string(inner.points)]
)

puts "\nImplementations:"
puts poly_a.class
puts poly_b.class
puts "eql? method source: #{poly_a.method(:eql?).source_location.inspect}"

eq_res   = (poly_a == poly_b)
eql_res  = poly_a.eql?(poly_b)

puts "\n== result:"
p eq_res # expected: true

puts "\neql? result:"
puts "class: #{eql_res.class}" # expected BUG: Array
p eql_res                      # expected BUG: array of interior rings (or [] if no holes)

# Sanity check: case-equality usually delegates to == for these objects
puts "\n=== result:"
p(poly_a === poly_b) # expected: true

# Optional: demonstrate empty-inner-ring case also returns [] instead of true
outer_only = factory.polygon(outer, [])
outer_only_2 = factory.polygon(factory.line_string(outer.points), [])
eql_outer_only = outer_only.eql?(outer_only_2)
puts "\neql? with no holes: class=#{eql_outer_only.class}, value=#{eql_outer_only.inspect}"

Output

Ruby: 3.4.4
RGeo: 3.0.1

Implementations:
RGeo::Cartesian::PolygonImpl
RGeo::Cartesian::PolygonImpl
eql? method source: ["/home/hernan/.local/share/mise/installs/ruby/3.4.4/lib/ruby/gems/3.4.0/gems/rgeo-3.0.1/lib/rgeo/feature/geometry.rb", 649]

== result:
[#<RGeo::Cartesian::LinearRingImpl:0x4478 "LINESTRING (2.5 -2.5 0.0, 7.5 -2.5 0.0, 7.5 -7.5 0.0, 2.5 -7.5 0.0, 2.5 -2.5 0.0)">]

eql? result:
class: Array
[#<RGeo::Cartesian::LinearRingImpl:0x4478 "LINESTRING (2.5 -2.5 0.0, 7.5 -2.5 0.0, 7.5 -7.5 0.0, 2.5 -7.5 0.0, 2.5 -2.5 0.0)">]

=== result:
true

eql? with no holes: class=Array, value=[]

NOTES

Likely several instances of rep_equals?(rhs) methods have a pattern like:

    proper_match = ...

    return false unless proper_match

    rhs.interior_rings.each_with_index { |r, i| return false unless @interior_rings[i].rep_equals?(r) }
  end

Maybe there should be a true right above end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions