lib/terraformer/polygon.rb in terraformer-0.0.1 vs lib/terraformer/polygon.rb in terraformer-0.0.2
- old
+ new
@@ -1,14 +1,120 @@
module Terraformer
class Polygon < Geometry
+ def initialize *args
+ case
+ when Coordinate === args[0] # each arg is a position of the polygon
+ self.coordinates = [Coordinate.from_array(args)]
+ when Array === args[0] # each arg is an array of positions; first is polygon, rest are "holes"
+ self.coordinates = Coordinate.from args
+ else
+ super *args
+ end
+
+ if line_strings.map(&:linear_ring?).include? false
+ raise ArgumentError.new 'not linear ring'
+ end
+ end
+
def has_holes?
coordinates.length > 1
end
def first_coordinate
coordinates[0][0]
+ end
+
+ def == obj
+ super obj do |o|
+
+ equal = true
+
+ # first check outer polygon
+ equal = self.coordinates[0].polygonally_equal_to? obj.coordinates[0]
+
+
+ # then inner polygons (holes)
+ #
+ if equal and obj.coordinates.length > 1
+ 1.upto(obj.coordinates.length - 1) do |i|
+ equal = self.coordinates[i].polygonally_equal_to? obj.coordinates[i]
+ break unless equal
+ end
+ end
+
+ equal
+ end
+ end
+
+ def line_strings
+ coordinates.map {|lr| LineString.new lr}
+ end
+
+ def holes
+ return nil unless has_holes?
+ coordinates[1..-1].map {|hole| Polygon.new hole}
+ end
+
+ def contains? obj
+ obj = Coordinate.new obj if Array === obj and Numeric === obj[0]
+ obj = obj.to_point if Coordinate === obj
+ contained = false
+ case obj
+ when Point
+ contained = Geometry.coordinates_contain_point? coordinates[0], obj.coordinates
+ contained = !holes.any? {|h| h.contains? obj} if contained and has_holes?
+ when MultiPoint
+ contained = obj.points.all? {|p| contains? p}
+ when LineString
+ contained = contains?(obj.first_coordinate) && !Geometry.array_intersects_multi_array?(obj.coordinates, coordinates)
+ when MultiLineString
+ contained = obj.line_strings.all? {|ls| contains? ls}
+ when Polygon
+ contained = obj.within? self
+ when MultiPolygon
+ contained = obj.polygons.all? {|p| p.within? self}
+ else
+ raise ArgumentError.new "unsupported type: #{obj.type rescue obj.class}"
+ end
+ contained
+ end
+
+ def within? obj
+ case obj
+ when Polygon
+ if self == obj
+ true
+ elsif obj.contains? first_coordinate
+ !Geometry.arrays_intersect_arrays?(coordinates, obj.coordinates)
+ end
+ when MultiPolygon
+ obj.polygons.any? {|p| p.contains? self}
+ else
+ raise ArgumentError.new "unsupported type: #{obj.type rescue obj.class}"
+ end
+ end
+
+ def add_vertex p
+ insert_vertex coordinates[0].length - 2, p
+ end
+ alias_method :<<, :add_vertex
+
+ def insert_vertex idx, p
+ p = p.coordinates if Point === p
+ raise ArgumentError unless Coordinate === p
+ coordinates[0].insert idx, p
+ end
+
+ def remove_vertex p
+ p = p.coordinates if Point === p
+ raise ArgumentError unless Coordinate === p
+ coordinates[0].delete p
+ end
+
+ def remove_vertex_at idx
+ coordinates[0].delete_at idx
end
end
end