Module: H3::GeoJSON

Included in:
H3
Defined in:
lib/h3/geo_json.rb

Overview

GeoJSON helper methods.

This module allows conversions between GeoJSON polygon data and a nested set of coordinates.

It should be noted that H3 describes coordinates as number pairs in the form

[latitude, longitude]

whereas the GeoJSON standard uses

[longitude, latitude]

Both use degrees.

Coordinates Array

We use a nested array to hold coordinates describing a geographical region.

The first element in the array is an external geofence boundary, composed of an array of coordinates as 2-element arrays of the form [latitude, longitude].

Any further elements in the array are further geofence arrays of coordinates which describe holes that may be present in the polygon.

Specific examples are shown in the individual method details.

Instance Method Summary collapse

Instance Method Details

#coordinates_to_geo_json(coordinates) ⇒ String

Convert a nested array of coordinates to a GeoJSON document

Examples:

Convert a set of nested coordinates of Banbury to a GeoJSON document.

coordinates = [
  [
    [52.24630137198303, -1.7358398437499998], [52.05249047600099, -1.8923950195312498],
    [51.891749018068246, -1.56829833984375], [51.91208502557545, -1.27716064453125],
    [52.032218104145294, -1.19476318359375], [52.19413974159753, -1.24420166015625],
    [52.24125614966341, -1.5902709960937498], [52.24630137198303, -1.7358398437499998]
  ],
  [
    [52.12590076522272, -1.58203125], [52.12590076522272, -1.476287841796875],
    [52.075285904832334, -1.46392822265625], [52.06937709602395, -1.58203125],
    [52.12590076522272, -1.58203125]
  ],
  [
    [52.01531743663362, -1.4556884765625], [51.97642166216334, -1.483154296875],
    [51.96626938051444, -1.3677978515625], [52.0102459910103, -1.3568115234375],
    [52.01531743663362, -1.4556884765625]
  ]
]
H3.coordinates_to_geo_json(coordinates)
"{\"type\":\"Polygon\",\"coordinates\":[
  [
    [-1.7358398437499998,52.24630137198303], [-1.8923950195312498,52.05249047600099],
    [-1.56829833984375,51.891749018068246], [-1.27716064453125,51.91208502557545],
    [-1.19476318359375,52.032218104145294], [-1.24420166015625,52.19413974159753],
    [-1.5902709960937498,52.24125614966341], [-1.7358398437499998,52.24630137198303]
  ],
  [
    [-1.58203125,52.12590076522272], [-1.476287841796875,52.12590076522272],
    [-1.46392822265625,52.075285904832334], [-1.58203125,52.06937709602395],
    [-1.58203125,52.12590076522272]
  ],
  [
    [-1.4556884765625,52.01531743663362], [-1.483154296875,51.97642166216334],
    [-1.3677978515625,51.96626938051444], [-1.3568115234375,52.0102459910103],
    [-1.4556884765625,52.01531743663362]
  ]
]}"

Parameters:

  • coordinates (Array<Array<Array>>)

    Nested array of coordinates.

Returns:

  • (String)

    GeoJSON document.

Raises:

  • (ArgumentError)

    Failed to parse the given coordinates.



140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/h3/geo_json.rb', line 140

def coordinates_to_geo_json(coordinates)
  coordinates = swap_lat_lon(coordinates)
  outer_coords, *inner_coords = coordinates
  factory = RGeo::Cartesian.simple_factory
  exterior = factory.linear_ring(outer_coords.map { |lon, lat| factory.point(lon, lat) })
  interior_rings = inner_coords.map do |polygon|
    factory.linear_ring(polygon.map { |lon, lat| factory.point(lon, lat) })
  end
  polygon = factory.polygon(exterior, interior_rings)
  RGeo::GeoJSON.encode(polygon).to_json
rescue RGeo::Error::InvalidGeometry, NoMethodError
  invalid_coordinates!
end

#geo_json_to_coordinates(input) ⇒ Array<Array<Array>>

Convert a GeoJSON document to a nested array of coordinates.

Examples:

Convert a GeoJSON document of Banbury to a set of nested coordinates.

document = "{\"type\":\"Polygon\",\"coordinates\":[
  [
    [-1.7358398437499998,52.24630137198303], [-1.8923950195312498,52.05249047600099],
    [-1.56829833984375,51.891749018068246], [-1.27716064453125,51.91208502557545],
    [-1.19476318359375,52.032218104145294], [-1.24420166015625,52.19413974159753],
    [-1.5902709960937498,52.24125614966341], [-1.7358398437499998,52.24630137198303]
  ],
  [
    [-1.58203125,52.12590076522272], [-1.476287841796875,52.12590076522272],
    [-1.46392822265625,52.075285904832334], [-1.58203125,52.06937709602395],
    [-1.58203125,52.12590076522272]
  ],
  [
    [-1.4556884765625,52.01531743663362], [-1.483154296875,51.97642166216334],
    [-1.3677978515625,51.96626938051444], [-1.3568115234375,52.0102459910103],
    [-1.4556884765625,52.01531743663362]
  ]
]}"
H3.geo_json_to_coordinates(document)
[
  [
    [52.24630137198303, -1.7358398437499998], [52.05249047600099, -1.8923950195312498],
    [51.891749018068246, -1.56829833984375], [51.91208502557545, -1.27716064453125],
    [52.032218104145294, -1.19476318359375], [52.19413974159753, -1.24420166015625],
    [52.24125614966341, -1.5902709960937498], [52.24630137198303, -1.7358398437499998]
  ],
  [
    [52.12590076522272, -1.58203125], [52.12590076522272, -1.476287841796875],
    [52.075285904832334, -1.46392822265625], [52.06937709602395, -1.58203125],
    [52.12590076522272, -1.58203125]
  ],
  [
    [52.01531743663362, -1.4556884765625], [51.97642166216334, -1.483154296875],
    [51.96626938051444, -1.3677978515625], [52.0102459910103, -1.3568115234375],
    [52.01531743663362, -1.4556884765625]
  ]
]

Parameters:

  • input (String)

    The GeoJSON document. This can be a feature collection, feature, or polygon. If a feature collection is provided, the first feature is used.

Returns:

  • (Array<Array<Array>>)

    Nested array of coordinates.

Raises:

  • (ArgumentError)

    Failed to parse the GeoJSON document.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/h3/geo_json.rb', line 78

def geo_json_to_coordinates(input)
  geom = RGeo::GeoJSON.decode(input)
  coordinates = if geom.respond_to?(:first) # feature collection
                  geom.first.geometry.coordinates
                elsif geom.respond_to?(:geometry) # feature
                  geom.geometry.coordinates
                elsif geom.respond_to?(:coordinates) # polygon
                  geom.coordinates
                else
                  failed_to_parse!
                end
  swap_lat_lon(coordinates) || failed_to_parse!
rescue JSON::ParserError
  failed_to_parse!
end