class NSWTopo::GeoJSON::Polygon

def self.[](coordinates, properties = nil, &block)

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

def add_ring(ring)

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

def area

def area
  rings.sum(&:signed_area)
end

def bounds

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

def centroid

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

def contains?(geometry)

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

def freeze!

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

def remove_holes(&block)

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

def rings

def rings
  MultiLineString.new @coordinates, @properties
end

def svg_path_data

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

def wkt

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