lib/terraformer/polygon.rb in terraformer-0.1.0 vs lib/terraformer/polygon.rb in terraformer-0.2.0

- old
+ new

@@ -1,28 +1,38 @@ module Terraformer class Polygon < Geometry def initialize *args - case # each arg is a position of the polygon - when Coordinate === args[0] || (Array === args[0] && Numeric === args[0][0]) + if Coordinate === args[0] || (Array === args[0] && Numeric === args[0][0]) self.coordinates = [Coordinate.from_array(args)] - # each arg is an array of positions; first is polygon, rest are "holes" - when Array === args[0] && Array === args[0][0] && Numeric === args[0][0][0] - self.coordinates = Coordinate.from args + elsif Array === args[0] - # arg is an array of polygon, holes - when Array === args[0] && Array === args[0][0] && Array === args[0][0][0] - self.coordinates = Coordinate.from *args + # each arg is an array of positions; first is polygon, rest are "holes" + if Coordinate === args[0][0] || + Array === args[0][0] && Numeric === args[0][0][0] + self.coordinates = Coordinate.from_array args + # arg is an array of polygon, holes + elsif Array === args[0][0] && Array === args[0][0][0] + self.coordinates = Coordinate.from_array *args + end + else super *args end + # must be an array of arrays of coordinates + unless Array === coordinates && + Array === coordinates[0] && + Terraformer::Coordinate === coordinates[0][0] + raise ArgumentError.new 'invalid coordinates for Terraformer::Polygon' + end + if line_strings.map(&:linear_ring?).include? false raise ArgumentError.new 'not linear ring' end end @@ -38,22 +48,22 @@ super obj do |o| equal = true # first check outer polygon - equal = self.coordinates[0].polygonally_equal_to? obj.coordinates[0] + equal = Polygon.polygonally_equal? self.coordinates[0], obj.coordinates[0] # then inner polygons (holes) # if equal if self.coordinates.length == obj.coordinates.length and obj.coordinates.length > 1 self_holes = self.coordinates[1..-1].sort obj_holes = obj.coordinates[1..-1].sort self_holes.each_with_index do |hole, idx| - equal = hole.polygonally_equal_to? obj_holes[idx] + equal = Polygon.polygonally_equal? hole, obj_holes[idx] break unless equal end end end @@ -126,9 +136,45 @@ coordinates[0].delete p end def remove_vertex_at idx coordinates[0].delete_at idx + end + + + def self.polygonally_equal? a, b + if Terraformer::Coordinate === a || + Terraformer::Coordinate === b + return a == b + end + + raise ArgumentError unless Enumerable === a + raise ArgumentError unless Enumerable === b + + # polygons must be the same length + return false if a.length != b.length + + # polygons must have the last element be a duplicate + # polygon-closing coordinate + return false if a[0] != a[-1] + return false if b[0] != b[-1] + + equal = true + + # clone so can pop/rotate + a = a.clone + b = b.clone + + # pop to drop the duplicate, polygon-closing, coordinate + a.pop + b.pop + + begin + b.rotate_until_first_equals a[0] + return a == b + rescue IndexError + return false + end end end end