Class: Terraformer::Polygon

Inherits:
Geometry show all
Defined in:
lib/terraformer/polygon.rb

Constant Summary

Constants inherited from Geometry

Geometry::MULTI_REGEX

Instance Attribute Summary

Attributes inherited from Geometry

#coordinates, #crs

Instance Method Summary collapse

Methods inherited from Geometry

#convex_hull, #geographic?, #get, #intersects?, #mercator?, #to_feature, #to_geographic, #to_hash, #to_mercator

Methods included from Geometry::ClassMethods

#arrays_intersect_arrays?, #coordinates_contain_point?, #edge_intersects_edge?, #line_contains_point?

Methods inherited from Primitive

#bbox, #envelope, #to_json, #type

Constructor Details

#initialize(*args) ⇒ Polygon

Returns a new instance of Polygon.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/terraformer/polygon.rb', line 5

def initialize *args
  case

  # each arg is a position of the polygon
  when 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

  # 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

  else
    super *args
  end

  if line_strings.map(&:linear_ring?).include? false
    raise ArgumentError.new 'not linear ring'
  end
end

Instance Method Details

#==(obj) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/terraformer/polygon.rb', line 37

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
      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]
          break unless equal
        end
      end
    end

    equal
  end
end

#add_vertex(p) ⇒ Object Also known as: <<



112
113
114
# File 'lib/terraformer/polygon.rb', line 112

def add_vertex p
  insert_vertex coordinates[0].length - 2, p
end

#contains?(obj) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/terraformer/polygon.rb', line 73

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

#first_coordinateObject



33
34
35
# File 'lib/terraformer/polygon.rb', line 33

def first_coordinate
  coordinates[0][0]
end

#has_holes?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/terraformer/polygon.rb', line 29

def has_holes?
  coordinates.length > 1
end

#holesObject



68
69
70
71
# File 'lib/terraformer/polygon.rb', line 68

def holes
  return nil unless has_holes?
  coordinates[1..-1].map {|hole| Polygon.new hole}
end

#insert_vertex(idx, p) ⇒ Object

Raises:

  • (ArgumentError)


117
118
119
120
121
# File 'lib/terraformer/polygon.rb', line 117

def insert_vertex idx, p
  p = p.coordinates if Point === p
  raise ArgumentError unless Coordinate === p
  coordinates[0].insert idx, p
end

#line_stringsObject



64
65
66
# File 'lib/terraformer/polygon.rb', line 64

def line_strings
  coordinates.map {|lr| LineString.new lr}
end

#remove_vertex(p) ⇒ Object

Raises:

  • (ArgumentError)


123
124
125
126
127
# File 'lib/terraformer/polygon.rb', line 123

def remove_vertex p
  p = p.coordinates if Point === p
  raise ArgumentError unless Coordinate === p
  coordinates[0].delete p
end

#remove_vertex_at(idx) ⇒ Object



129
130
131
# File 'lib/terraformer/polygon.rb', line 129

def remove_vertex_at idx
  coordinates[0].delete_at idx
end

#within?(obj) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/terraformer/polygon.rb', line 97

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