class AIPP::Border

Border GeoJSON file reader

The border GeoJSON files must be a geometry collection of one or more line strings:

{
  "type": "GeometryCollection",
  "geometries": [
    {
      "type": "LineString",
      "coordinates": [
        [6.009531650000042, 45.12013319700009],
        [6.015747738000073, 45.12006702600007]
      ]
    }
  ]
}

@example

border = AIPP::Border.new("/path/to/file.geojson")
border.geometries
# => [[#<AIXM::XY 45.12013320N 006.00953165E>, <AIXM::XY 45.12006703N 006.01574774E>]]

Attributes

file[R]
geometries[R]

Public Class Methods

new(file) click to toggle source
   # File lib/aipp/border.rb
29 def initialize(file)
30   @file = file.is_a?(Pathname) ? file : Pathname(file)
31   fail(ArgumentError, "file must have extension .geojson") unless @file.extname == '.geojson'
32   @geometries = load_geometries
33 end

Public Instance Methods

closed?(geometry_index:) click to toggle source

Whether the given geometry is closed or not

A geometry is considered closed when it's first coordinate equals the last coordinate.

@param geometry_index [Integer] geometry to check @return [Boolean] true if the geometry is closed or false otherwise

   # File lib/aipp/border.rb
58 def closed?(geometry_index:)
59   geometry = @geometries[geometry_index]
60   geometry.first == geometry.last
61 end
inspect() click to toggle source

@return [String]

   # File lib/aipp/border.rb
36 def inspect
37   %Q(#<#{self.class} file=#{@file}>)
38 end
name() click to toggle source

Name of the border

By convention, the name of the border is taken from the filename with both the extension .geojson and all non alphanumeric characters dropped and the resulting string upcased.

@return [String]

   # File lib/aipp/border.rb
47 def name
48   @file.basename('.geojson').to_s.gsub(/\W/, '').upcase
49 end
nearest(geometry_index: nil, xy:) click to toggle source

Find a position on a geometry nearest to the given coordinates

@param geometry_index [Integer] index of the geometry on which to search

or +nil+ to search on all geometries

@param xy [AIXM::XY] coordinates to approximate @return [AIPP::Border::Position] position nearest to the given coordinates

   # File lib/aipp/border.rb
69 def nearest(geometry_index: nil, xy:)
70   position = nil
71   min_distance = 21_000_000   # max distance on earth in meters
72   @geometries.each.with_index do |geometry, g_index|
73     next unless geometry_index.nil? || geometry_index == g_index
74     geometry.each.with_index do |coordinates, c_index|
75       distance = xy.distance(coordinates).dist
76       if distance < min_distance
77         position = Position.new(geometries: geometries, geometry_index: g_index, coordinates_index: c_index)
78         min_distance = distance
79       end
80     end
81   end
82   position
83 end
segment(from_position:, to_position:) click to toggle source

Get a segment of a geometry between the given starting and ending positions

The segment ends either at the given ending position or at the last coordinates of the geometry. However, if the geometry is closed, the segment always continues up to the given ending position.

@param from_position [AIPP::Border::Position] starting position @param to_position [AIPP::Border::Position] ending position @return [Array<AIXM::XY>] array of coordinates describing the segment

    # File lib/aipp/border.rb
 95 def segment(from_position:, to_position:)
 96   fail(ArgumentError, "both positions must be on the same geometry") unless from_position.geometry_index == to_position.geometry_index
 97   geometry_index = from_position.geometry_index
 98   geometry = @geometries[geometry_index]
 99   if closed?(geometry_index: geometry_index)
100     up = from_position.coordinates_index.upto(to_position.coordinates_index)
101     down = from_position.coordinates_index.downto(0) + (geometry.count - 2).downto(to_position.coordinates_index)
102     geometry.values_at(*(up.count < down.count ? up : down).to_a)
103   else
104     geometry.values_at(*from_position.coordinates_index.up_or_downto(to_position.coordinates_index).to_a)
105   end
106 end

Private Instance Methods

load_geometries() click to toggle source
    # File lib/aipp/border.rb
110 def load_geometries
111   JSON.load(@file)['geometries'].map do |line_string|
112     line_string['coordinates'].map do |long, lat|
113       AIXM.xy(long: long, lat: lat)
114     end
115   end
116 end