A way to remove pairs of the same (but with different orientation) geometries from a (small) LineString collection

Say you have a small collection of LineString geometries, and you want to remove pairs of same geometries with different directions. Here are some solutions using JTS (JTS Topology Suite) from Ruby, using Rjb (Ruby Java Bridge.)

Point

The OGC-style geometry method Geometry#equals does not take care about the orientation of the LineString. So, if you just use this method as equality definition for geometry set operation, the problem is solved.

Solution

# find_line_pairs.rb
require 'rubygems'
require 'rjb'
require 'ostruct'

Rjb::load('jts-1.11.jar')

Java = OpenStruct.new(Hash[*%w{
com.vividsolutions.jts.io.WKTReader
}.map{|v| [v.split('.')[-1], Rjb::import(v)]}.flatten])

class Geometry
  @@wktr = Java.WKTReader.new
  def initialize(wkt)
    @g = @@wktr.read(wkt)
  end
  attr_reader :g
 
  def ==(other)
    g.equals(other.g)
  end

  def inspect
    g.toString
  end
end

set = []

wkts = <<-EOS
LINESTRING (0 0, 1 1)
LINESTRING (1 1, 0 0)
LINESTRING (3 3, 4 4)
LINESTRING (0 0, 2 2)
EOS

wkts.each_line{|wkt| 
  g = Geometry.new(wkt.chop)
  set << g unless set.delete(g)
}

p set

This Ruby script runs as following;

$ ruby find_line_pairs.rb
[LINESTRING (3 3, 4 4), LINESTRING (0 0, 2 2)]

This means the pair of same (but with different orientation) geometries are successflly eliminated.

Solution 2 (simpler version)

Ruby's Array#reject! provides simpler solution as following;

# find_line_pairs_star.rb
require 'rubygems'
require 'rjb'
require 'ostruct'

Rjb::load('jts-1.11.jar')

Java = OpenStruct.new(Hash[*%w{
com.vividsolutions.jts.io.WKTReader
}.map{|v| [v.split('.')[-1], Rjb::import(v)]}.flatten])

wktr = Java.WKTReader.new

list = []

wkts = <<-EOS
LINESTRING (0 0, 1 1)
LINESTRING (1 1, 0 0)
LINESTRING (3 3, 4 4)
LINESTRING (0 0, 2 2)
EOS

wkts.each_line{|wkt| 
  g = wktr.read(wkt.chop)
  list << g unless list.reject! {|g_| g.equals(g_)}
}

p list.map{|g| g.toString}
$ ruby find_line_pairs_star.rb
["LINESTRING (3 3, 4 4)", "LINESTRING (0 0, 2 2)"]