Class: NSWTopo::GeoJSON::Polygon

Inherits:
Object
  • Object
show all
Includes:
SVG
Defined in:
lib/nswtopo/gis/geojson/polygon.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.[](coordinates, properties = nil, &block) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 6

def self.[](coordinates, properties = nil, &block)
  new(coordinates, properties) do
    @coordinates.each.with_index do |coordinates, index|
      LineString[coordinates] do |ring|
        ring.coordinates << ring.first unless ring.closed?
        ring.coordinates.reverse! if index.zero? ^ ring.exterior?
      end
    end
    block.call self if block_given?
  end
end

Instance Method Details

#add_ring(ring) ⇒ Object



52
53
54
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 52

def add_ring(ring)
  Polygon.new [*@coordinates, ring.coordinates], @properties
end

#areaObject



56
57
58
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 56

def area
  rings.sum(&:signed_area)
end

#boundsObject



25
26
27
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 25

def bounds
  first.transpose.map(&:minmax)
end

#centroidObject



37
38
39
40
41
42
43
44
45
46
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 37

def centroid
  flat_map do |ring|
    ring.each_cons(2).map do |p0, p1|
      next (p0 + p1) * p0.cross(p1), 3 * p0.cross(p1)
    end
  end.transpose.then do |centroids_x6, signed_areas_x6|
    point = centroids_x6.inject(&:+) / signed_areas_x6.inject(&:+)
    Point.new point, @properties
  end
end

#contains?(geometry) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 66

def contains?(geometry)
  geometry = Point.new(geometry) if Vector === geometry
  geometry.dissolve_points.coordinates.all? do |point|
    sum do |ring|
      ring.each_cons(2).inject(0) do |winding, (p0, p1)|
        case
        when p1.y  > point.y && p0.y <= point.y && (p0 - p1).cross(p0 - point) >= 0 then winding + 1
        when p0.y  > point.y && p1.y <= point.y && (p1 - p0).cross(p0 - point) >= 0 then winding - 1
        when p0.y == point.y && p1.y == point.y && p0.x >= point.x && p1.x < point.x then winding + 1
        when p0.y == point.y && p1.y == point.y && p1.x >= point.x && p0.x < point.x then winding - 1
        else winding
        end
      end
    end.nonzero?
  end
end

#freeze!Object



18
19
20
21
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 18

def freeze!
  @coordinates.each(&:freeze)
  freeze
end

#remove_holes(&block) ⇒ Object



60
61
62
63
64
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 60

def remove_holes(&block)
  rings.reject_linestrings do |ring|
    ring.interior? && (block_given? ? block.call(ring) : true)
  end.to_polygon
end

#ringsObject



48
49
50
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 48

def rings
  MultiLineString.new @coordinates, @properties
end

#svg_path_dataObject



83
84
85
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 83

def svg_path_data
  rings.map(&:svg_path_data).join(?\s)
end

#wktObject



29
30
31
32
33
34
35
# File 'lib/nswtopo/gis/geojson/polygon.rb', line 29

def wkt
  map do |ring|
    ring.map do |point|
      point.join(" ")
    end.join(", ").prepend("(").concat(")")
  end.join(", ").prepend("POLYGON (").concat(")")
end