module Turf

Ruby port of Turf.js, an advance geospatial analysis library. @see turfjs.org/

Constants

AREA_RADIUS
EARTH_RADIUS
FACTORS
VERSION

Version of turf-ruby

Public Instance Methods

along(line, distance, units: "kilometers") click to toggle source

Takes a LineString and returns a Point at a specified distance along the line. @see turfjs.org/docs/#along @param line [Feature<LineString>] input line @param distance [number] distance along the line @param units [string] can be degrees, radians, miles, or kilometers (optional, default “kilometers”) @return [Feature<Point>] Point distance units along the line

# File lib/turf/along.rb, line 13
def along(line, distance, units: "kilometers")
  line = deep_symbolize_keys line
  travelled = 0

  geom = get_geom line
  coords = geom[:coordinates]

  coords.each_with_index do |coord, i|
    break if distance >= travelled && i == coords.length - 1

    if travelled >= distance
      overshot = distance - travelled
      return point(coord) if overshot.zero?

      direction = bearing(coord, coords[i - 1]) - 180
      interpolated = destination(coord, overshot, direction, units: units)
      return interpolated
    else
      travelled += distance(coords[i], coords[i + 1], units: units)
    end
  end

  point(coords.last)
end
area(geojson) click to toggle source

Takes one or more features and returns their area in square meters. @see turfjs.org/docs/#area @param geojson [GeoJSON] input GeoJSON feature(s) @return [number] aria in square meters

# File lib/turf/area.rb, line 9
def area(geojson)
  geom_reduce(geojson, initial_value: 0) do |value, geom|
    value + area_calculate_area(geom)
  end
end
bearing(from, to, final: false) click to toggle source

Takes two points and finds the geographic bearing between them, i.e. the angle measured in degrees from the north line (0 degrees) @see turfjs.org/docs/#bearing @param from [Coord] starting Point @param to [Coord] ending Point @param final boolean calculates the final bearing if true @return [number] bearing in decimal degrees, between -180 and 180 degrees (positive clockwise)

# File lib/turf/bearing.rb, line 14
def bearing(from, to, final: false)
  return calculate_final_bearing(from, to) if final

  coordinates1 = get_coord from
  coordinates2 = get_coord to

  lon1 = degrees_to_radians(coordinates1[0])
  lon2 = degrees_to_radians(coordinates2[0])
  lat1 = degrees_to_radians(coordinates1[1])
  lat2 = degrees_to_radians(coordinates2[1])
  a = Math.sin(lon2 - lon1) * Math.cos(lat2)
  b = Math.cos(lat1) * Math.sin(lat2) -
      Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)

  radians_to_degrees(Math.atan2(a, b))
end
boolean_point_in_polygon(point, polygon, ignore_boundary: false) click to toggle source

Takes a Point and a Polygon or MultiPolygon and determines if the point resides inside the polygon. The polygon can be convex or concave. The function accounts for holes. @see turfjs.org/docs/#booleanPointInPolygon @param point [Coord] input point @param polygon [Feature<(Polygon | MultiPolygon)>] input polygon or multipolygon @param ignore_boundary [boolean] True if polygon boundary should be ignored when determining if the point is inside the polygon otherwise false. @return [boolean] true if the Point is inside the Polygon; false if the Point is not inside the Polygon

# File lib/turf/boolean_point_in_polygon.rb, line 16
def boolean_point_in_polygon(point, polygon, ignore_boundary: false)
  polygon = deep_symbolize_keys(polygon)
  pt = get_coord(point)
  geom = get_geom(polygon)
  type = geom.fetch(:type)
  bbox = polygon[:bbox]
  polys = geom.fetch(:coordinates)

  # Quick elimination if point is not inside bbox
  return false if bbox && !in_bbox(pt, bbox)

  # normalize to multipolygon
  polys = [polys] if type == "Polygon"

  inside_poly = false
  polys.each do |poly|
    # check if it is in the outer ring first
    next unless in_ring(pt, poly[0], ignore_boundary)

    in_hole = false

    # check for the point in any of the holes
    poly.slice(1, poly.size - 1).each do |hole|
      if in_ring(pt, hole, !ignore_boundary)
        in_hole = true
      end
    end
    if !in_hole
      inside_poly = true
    end
  end
  inside_poly
end
centroid(geojson, properties: {}) click to toggle source

Takes one or more features and calculates the centroid using the mean of all vertices. This lessens the effect of small islands and artifacts when calculating the centroid of a set of polygons. @see turfjs.org/docs/#centroid @param geojson [GeoJSON] GeoJSON to be centered @param properties [Hash] a [Hash] that is used as the Feature's properties @return [Feature<Point>] the centroid of the input features

# File lib/turf/centroid.rb, line 13
def centroid(geojson, properties: {})
  x_sum = 0
  y_sum = 0
  len = 0

  coord_each geojson, exclude_wrap_coord: true do |coord|
    x_sum += coord[0]
    y_sum += coord[1]
    len += 1
  end

  point(
    [x_sum / len, y_sum / len],
    properties: properties,
  )
end
coord_all(geojson, exclude_wrap_coord: false) click to toggle source

Get all coordinates from any GeoJSON object. @see turfjs.org/docs/#coordAll @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @param exclude_wrap_coord [boolean] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration @return [Array<Array<number>>] coordinate position array

# File lib/turf/meta.rb, line 25
def coord_all(geojson, exclude_wrap_coord: false)
  geometries = self.geometries(geojson)
  geometries.flat_map do |geometry|
    next [] if geometry.nil?

    case geometry[:type]
    when "Point"
      [geometry[:coordinates]]
    when "LineString", "MultiPoint"
      geometry[:coordinates]
    when "Polygon", "MultiLineString"
      geometry[:coordinates].flat_map do |line_coords|
        (
          exclude_wrap_coord ? line_coords.slice(0...-1) : line_coords
        )
      end
    when "MultiPolygon"
      geometry[:coordinates].flat_map do |polygon_coords|
        polygon_coords.flat_map do |line_coords|
          (
            exclude_wrap_coord ? line_coords.slice(0...-1) : line_coords
          )
        end
      end
    when "Feature"
      [].tap do |feature_coords|
        coord_each geometry, exclude_wrap_coord: exclude_wrap_coord do |coord|
          feature_coords.push coord
        end
      end
    else
      raise Error, "Unknown Geometry Type: #{geometry[:type]}"
    end
  end
end
coord_each(geojson, exclude_wrap_coord: false, &block) click to toggle source

Iterate over coordinates in any GeoJSON object, similar to Array.forEach() @see turfjs.org/docs/#coordEach @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @param exclude_wrap_coord [boolean] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration @yield [current_coord, coord_index] given any coordinate @yieldparam current_coord [Array<number>] The current coordinate being processed. @yieldparam coord_index [number] The current index of the coordinate being processed.

# File lib/turf/meta.rb, line 15
def coord_each(geojson, exclude_wrap_coord: false, &block)
  coord_all(geojson, exclude_wrap_coord: exclude_wrap_coord).each_with_index(&block)
end
coord_reduce(geojson, initial_value: nil, exclude_wrap_coord: false) { |previous_value, current_coord, coord_index| ... } click to toggle source

Reduce coordinates in any GeoJSON object, similar to Array.reduce() @see turfjs.org/docs/#coordReduce @param geojson [FeatureCollection|Geometry|Feature] any GeoJSON object @param initial_value [*] Value to use as the first argument to the first call of the callback. @param exclude_wrap_coord [Boolean] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration. @return [*] The value that results from the reduction.

# File lib/turf/meta.rb, line 68
def coord_reduce(geojson, initial_value: nil, exclude_wrap_coord: false)
  previous_value = initial_value

  coord_each(
    geojson,
    exclude_wrap_coord: exclude_wrap_coord,
  ) do |current_coord, coord_index|
    previous_value =
      if coord_index.zero? && initial_value.nil?
        current_coord
      else
        yield(
          previous_value,
          current_coord,
          coord_index
        )
      end
  end

  previous_value
end
degrees_to_radians(degrees) click to toggle source

Converts an angle in degrees to radians @see turfjs.org/docs/#degreesToRadians @param degrees [number] angle between 0 and 360 degrees @return [number] angle in radians

# File lib/turf/helpers.rb, line 201
def degrees_to_radians(degrees)
  radians = degrees.remainder(360)
  radians * Math::PI / 180
end
destination(origin, distance, bearing, units: "kilometers", properties: {}) click to toggle source

Takes a Point and calculates the location of a destination point given a distance in degrees, radians, miles, or kilometers; and bearing in degrees. This uses the Haversine formula to account for global curvature. @see turfjs.org/docs/#destination @param origin [Coord] starting point @param distance [number] distance from the origin point @param bearing [number] ranging from -180 to 180 @param units [string] miles, kilometers, degrees, or radians @param properties [Hash] Translate properties to Point @return [Feature<Point>] destination point

# File lib/turf/destination.rb, line 16
def destination(origin, distance, bearing, units: "kilometers", properties: {})
  coordinates1 = get_coord origin
  longitude1 = degrees_to_radians coordinates1[0]
  latitude1 = degrees_to_radians coordinates1[1]
  bearing_radians = degrees_to_radians bearing
  radians = length_to_radians distance, units

  latitude2 = Math.asin(Math.sin(latitude1) * Math.cos(radians) +
    Math.cos(latitude1) * Math.sin(radians) * Math.cos(bearing_radians))
  longitude2 = longitude1 + Math.atan2(
    Math.sin(bearing_radians) * Math.sin(radians) * Math.cos(latitude1),
    Math.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2),
  )
  lng = radians_to_degrees(longitude2)
  lat = radians_to_degrees(latitude2)

  point([lng, lat], properties: properties)
end
distance(from, to, units: "kilometers") click to toggle source

Calculates the distance between two points in degrees, radians, miles, or kilometers. This uses the Haversine formula to account for global curvature. @see turfjs.org/docs/#distance @param from [Coord] origin point @param to [Coord] destination point @param units [string] can be degrees, radians, miles, or kilometers @return [number] distance between the two points

# File lib/turf/distance.rb, line 14
def distance(from, to, units: "kilometers")
  coordinates1 = get_coord from
  coordinates2 = get_coord to

  d_lat = degrees_to_radians coordinates2[1] - coordinates1[1]
  d_lon = degrees_to_radians coordinates2[0] - coordinates1[0]
  lat1 = degrees_to_radians coordinates1[1]
  lat2 = degrees_to_radians coordinates2[1]

  a =
    (
      (Math.sin(d_lat / 2)**2) +
      (Math.sin(d_lon / 2)**2) * Math.cos(lat1) * Math.cos(lat2)
    )

  radians_to_length(
    2 * Math.atan2(
      Math.sqrt(a),
      Math.sqrt(1 - a),
    ),
    units,
  )
end
feature(geom, properties: {}, bbox: nil, id: nil) click to toggle source

Wraps a GeoJSON Geometry in a GeoJSON Feature. @see turfjs.org/docs/#feature @param geom [Geometry] input geometry @param properties [Hash] an Object of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string | number] Identifier associated with the Feature @return [Feature] a GeoJSON Feature

# File lib/turf/helpers.rb, line 35
def feature(geom, properties: {}, bbox: nil, id: nil)
  feat = {
    type: "Feature",
    properties: properties,
    geometry: geom
  }
  feat[:id] = options[:id] if id
  feat[:bbox] = options[:bbox] if bbox

  feat
end
feature_collection(features, bbox: nil, id: nil) click to toggle source

Takes one or more Features and creates a FeatureCollection. @see turfjs.org/docs/#featureCollection @param features [Array<Feature>] input features @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string | number] Identifier associated with the Feature @return [FeatureCollection] FeatureCollection of Features

# File lib/turf/helpers.rb, line 53
def feature_collection(features, bbox: nil, id: nil)
  fc = { type: "FeatureCollection" }
  fc[:id] = options[:id] if id
  fc[:bbox] = options[:bbox] if bbox
  fc[:features] = features

  fc
end
feature_each(geojson, &block) click to toggle source

Iterate over features in any GeoJSON object, similar to Array.forEach. @see turfjs.org/docs/#featureEach @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @yield [feature] given any coordinate @yieldparam feature [Feature<any>] currentFeature The current Feature being processed. @yieldparam feature_index [number] The current index of the Feature being processed.

# File lib/turf/meta.rb, line 187
def feature_each(geojson, &block)
  return unless geojson

  features = []
  geojson = deep_symbolize_keys geojson
  case geojson[:type]
  when "Feature"
    features.push geojson
  when "FeatureCollection"
    features.push(*geojson[:features])
  end

  features.each_with_index(&block)
end
feature_reduce(geojson, initial_value: nil) { |previous_value, feature, feature_index| ... } click to toggle source

Reduce features in any GeoJSON object, similar to Array.reduce(). @see turfjs.org/docs/#featureReduce @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @param initial_value [*] Value to use as the first argument to the first call of the callback. @yieldparam previous_value [*] Result of previous reduction @yieldparam feature [Feature<any>] The current Feature being processed. @yieldparam feature_index [number] The current index of the Feature being processed. @return [*] The value that results from the reduction.

# File lib/turf/meta.rb, line 210
def feature_reduce(geojson, initial_value: nil)
  previous_value = initial_value

  feature_each(
    geojson,
  ) do |feature, feature_index|
    previous_value =
      if feature_index.zero? && initial_value.nil?
        feature
      else
        yield(
          previous_value,
          feature,
          feature_index
        )
      end
  end

  previous_value
end
flatten_each(geojson) { |feature(nil, properties: properties, bbox: bbox, id: id), feature_index, 0| ... } click to toggle source

Iterate over flattened features in any GeoJSON object, similar to Array.forEach. @see turfjs.org/docs/#flattenEach @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @yieldparam feature [Feature<any>] The current Feature being processed. @yieldparam feature_index [number] The current index of the Feature being processed. @yieldparam multi_feature_index [number] The current index of the Feature in the multi-Feature

# File lib/turf/meta.rb, line 237
def flatten_each(geojson)
  geom_each(geojson) do |geometry, feature_index, properties, bbox, id|
    if geometry.nil?
      next yield(
        feature(nil, properties: properties, bbox: bbox, id: id),
        feature_index,
        0
      )
    end

    case geometry[:type]
    when "Point", "LineString", "Polygon"
      yield(
        feature(geometry, properties: properties, bbox: bbox, id: id),
        feature_index,
        0
      )
    when "MultiPoint", "MultiLineString", "MultiPolygon"
      geom_type = geometry[:type].sub(/^Multi/, "")
      geometry[:coordinates].each_with_index do |coordinate, multi_feature_index|
        geom = {
          type: geom_type,
          coordinates: coordinate
        }
        yield(
          feature(geom, properties: properties),
          feature_index,
          multi_feature_index
        )
      end
    end
  end
end
flatten_reduce(geojson, initial_value: nil) { |previous_value, feature, feature_index, multi_feature_index| ... } click to toggle source

Reduce flattened features in any GeoJSON object, similar to Array.reduce(). @see turfjs.org/docs/#flattenEach @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @param initial_value [*] Value to use as the first argument to the first call of the callback. @yieldparam previous_value [*] Result of previous reduction @yieldparam feature [Feature<any>] The current Feature being processed. @yieldparam feature_index [number] The current index of the Feature being processed. @yieldparam multi_feature_index [number] The current index of the Feature in the multi-Feature @return [*] The value that results from the reduction.

# File lib/turf/meta.rb, line 280
def flatten_reduce(geojson, initial_value: nil)
  previous_value = initial_value

  flatten_each(
    geojson,
  ) do |feature, feature_index, multi_feature_index|
    previous_value =
      if feature_index.zero? && multi_feature_index.zero? && initial_value.nil?
        feature
      else
        yield(
          previous_value,
          feature,
          feature_index,
          multi_feature_index
        )
      end
  end

  previous_value
end
geom_each(geojson) { |geometry, entry_index, properties, bbox, id| ... } click to toggle source

Iterate over each geometry in any GeoJSON object, similar to Array.forEach() @see turfjs.org/docs/#geomReduce @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @yieldparam geom [Geometry] The current Feature being processed. @yieldparam feature_index [number] The current index of the Feature being processed. @yieldparam properties [Hash] an Object of key-value pairs to add as properties @yieldparam bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @yieldparam id [string|number] Identifier associated with the Feature

# File lib/turf/meta.rb, line 98
def geom_each(geojson)
  return unless geojson

  geojson = deep_symbolize_keys geojson

  # [geometry, properties, bbox, id]
  entries = []

  case geojson[:type]
  when "FeatureCollection"
    geojson[:features].each do |feature|
      entries.push [feature[:geometry], feature[:properties], feature[:bbox], feature[:id]]
    end
  when "Feature"
    entries.push [geojson[:geometry], geojson[:properties], geojson[:bbox], geojson[:id]]
  else
    entries.push [geojson, {}, nil, nil]
  end

  # flatten GeometryCollection
  entries =
    entries.flat_map do |entry|
      geometry, properties, bbox, id = entry
      next [entry] if geometry.nil?
      next [entry] unless geometry[:type] == "GeometryCollection"

      geometry[:geometries].map do |sub_geometry|
        [sub_geometry, properties, bbox, id]
      end
    end

  entries.each_with_index do |entry, entry_index|
    geometry, properties, bbox, id = entry
    yield geometry, entry_index, properties, bbox, id
  end
end
geom_reduce(geojson, initial_value: nil) { |previous_value, geom, geom_index, properties, bbox, id| ... } click to toggle source

Reduce geometry in any GeoJSON object, similar to Array.reduce(). @see turfjs.org/docs/#geomReduce @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @param initial_value [*] Value to use as the first argument to the first call of the callback. @yieldparam previous_value [*] Result of previous reduction @yieldparam geom [Geometry] The current Feature being processed. @yieldparam geom_index [number] The current index of the Feature being processed. @yieldparam properties [Hash] an Object of key-value pairs to add as properties @yieldparam bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @yieldparam id [string|number] Identifier associated with the Feature @return [*] The value that results from the reduction.

# File lib/turf/meta.rb, line 146
def geom_reduce(geojson, initial_value: nil)
  previous_value = initial_value

  geom_each(
    geojson,
  ) do |geom, geom_index, properties, bbox, id|
    previous_value =
      if geom_index.zero? && initial_value.nil?
        geom
      else
        yield(
          previous_value,
          geom,
          geom_index,
          properties,
          bbox,
          id
        )
      end
  end

  previous_value
end
geometries(geojson) click to toggle source

Get all Geometry @param geojson [FeatureCollection|Feature|Geometry] any GeoJSON object @return [Array<Geometry>] list of Geometry

# File lib/turf/meta.rb, line 173
def geometries(geojson)
  [].tap do |geometries|
    geom_each(geojson) do |geometry|
      geometries.push(geometry)
    end
  end
end
geometry_collection(geometries, bbox: nil, id: nil, properties: {}) click to toggle source

Creates a Feature based on a coordinate array. Properties can be added optionally. @see turfjs.org/docs/#geometryCollection @param geometries [Array<Geometry>] an array of GeoJSON Geometries @param properties [Hash] a Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string|number] Identifier associated with the Feature @return [Feature<GeometryCollection>] a GeoJSON GeometryCollection Feature

# File lib/turf/helpers.rb, line 69
def geometry_collection(geometries, bbox: nil, id: nil, properties: {})
  geom = {
    type: "GeometryCollection",
    geometries: geometries
  }

  feature(geom, properties: properties, bbox: bbox, id: id)
end
get_coord(coord) click to toggle source

Unwrap a coordinate from a Point Feature, Geometry or a single coordinate. @see turfjs.org/docs/#getCoord @param coord [Array|Geometry<Point>|Feature<Point>] GeoJSON Point or an Array of numbers @return [Array] coordinates

# File lib/turf/invariant.rb, line 11
def get_coord(coord)
  if !coord
    raise Error, "coord is required"
  end

  is_numeric = ->(i) { i.is_a? Numeric }
  if coord.is_a?(Array) && coord.length >= 2 && coord.all?(&is_numeric)
    return coord
  end

  if coord.is_a? Hash
    coord = deep_symbolize_keys(coord)

    is_feature = coord[:type] == "Feature"
    if is_feature && coord.fetch(:geometry, {})[:type] == "Point"
      return coord[:geometry][:coordinates]
    end

    if coord[:type] == "Point"
      return coord[:coordinates]
    end
  end

  raise Error, "coord must be GeoJSON Point or an Array of numbers"
end
get_geom(geojson) click to toggle source

Get Geometry from Feature or Geometry Object @see turfjs.org/docs/#getGeom @param geojson [Feature|Geometry] GeoJSON Feature or Geometry Object @return [Geometry|null] GeoJSON Geometry Object

# File lib/turf/invariant.rb, line 41
def get_geom(geojson)
  geojson = deep_symbolize_keys geojson
  return geojson[:geometry] if geojson[:type] == "Feature"

  geojson
end
length_to_radians(distance, units = "kilometers") click to toggle source

Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet @see turfjs.org/docs/#lengthToRadians @param distance [number] in real units @param units [string] can be degrees, radians, miles, inches, yards, metres, meters, kilometres, kilometers. @return [number] radians

# File lib/turf/helpers.rb, line 225
def length_to_radians(distance, units = "kilometers")
  factor = FACTORS[units]
  raise Error, "#{units} units is invalid" unless factor

  distance / factor
end
line_string(coordinates, properties: {}, bbox: nil, id: nil) click to toggle source

Creates a LineString Feature from an Array of Positions. @see turfjs.org/docs/#lineString @param coordinates [Array<Array<number>>] an array of Positions @param properties [Hash] an Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string|number] Identifier associated with the Feature @return [Feature<LineString>] LineString Feature

# File lib/turf/helpers.rb, line 100
def line_string(coordinates, properties: {}, bbox: nil, id: nil)
  if coordinates.size < 2
    raise Error, "coordinates must be an array of two or more positions"
  end

  geom = {
    type: "LineString",
    coordinates: coordinates
  }
  feature(geom, properties: properties, bbox: bbox, id: id)
end
multi_line_string(coordinates, properties: {}, bbox: nil, id: nil) click to toggle source

Creates a Feature<MultiLineString> based on a coordinate array. Properties can be added optionally. @see turfjs.org/docs/#multiLineString @param coordinates [Array<Array<Array<number>>>] coordinates an array of LineStrings @param properties [Hash] a Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string|number] Identifier associated with the Feature @return [Feature<MultiLineString>] a MultiLineString feature

# File lib/turf/helpers.rb, line 178
def multi_line_string(coordinates, properties: {}, bbox: nil, id: nil)
  geom = {
    type: "MultiLineString",
    coordinates: coordinates
  }
  feature(geom, properties: properties, id: id, bbox: bbox)
end
multi_point(coordinates, properties: {}, bbox: nil, id: nil) click to toggle source

Creates a Feature based on a coordinate array. Properties can be added optionally. @param coordinates [Array<Array<number>>] an array of Positions @param properties [Hash] a Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string|number] Identifier associated with the Feature @return [Feature<MultiPoint>] a MultiPoint feature

# File lib/turf/helpers.rb, line 84
def multi_point(coordinates, properties: {}, bbox: nil, id: nil)
  geom = {
    type: "MultiPoint",
    coordinates: coordinates
  }

  feature(geom, properties: properties, bbox: bbox, id: id)
end
multi_polygon(coordinates, properties: {}, bbox: nil, id: nil) click to toggle source

Creates a Feature<MultiPolygon> based on a coordinate array. Properties can be added optionally. @see turfjs.org/docs/#multiPolygon @param coordinates [Array<Array<Array<Array<number>>>>] an array of Polygons @param properties [Hash] an Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string|number] Identifier associated with the Feature @return [Feature<MultiPolygon>] a multipolygon feature

# File lib/turf/helpers.rb, line 163
def multi_polygon(coordinates, properties: {}, bbox: nil, id: nil)
  geom = {
    type: "MultiPolygon",
    coordinates: coordinates
  }
  feature(geom, properties: properties, id: id, bbox: bbox)
end
point(coordinates, properties: {}, id: nil, bbox: nil) click to toggle source

Creates a Point Feature from a Position. @see turfjs.org/docs/#point @param coordinates [Array<number>] longitude, latitude position (each in decimal degrees) @param properties [Hash] an Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string | number] Identifier associated with the Feature @return [Feature<Point>] a Point feature

# File lib/turf/helpers.rb, line 119
def point(coordinates, properties: {}, id: nil, bbox: nil)
  geom = {
    type: "Point",
    coordinates: coordinates
  }
  feature(geom, properties: properties, id: id, bbox: bbox)
end
polygon(coordinates, properties: {}, bbox: nil, id: nil) click to toggle source

Creates a Polygon Feature from an Array of LinearRings. @see turfjs.org/docs/#polygon @param coordinates [Array<Array<Array<number>>>] an array of LinearRings @param properties [Hash] an Hash of key-value pairs to add as properties @param bbox [Array<number>] Bounding Box Array [west, south, east, north] associated with the Feature @param id [string | number] Identifier associated with the Feature @return [Feature<Polygon>] Polygon feature

# File lib/turf/helpers.rb, line 134
def polygon(coordinates, properties: {}, bbox: nil, id: nil)
  coordinates.each do |ring|
    if ring.size < 4
      raise(
        Error,
        "Each LinearRing of a Polygon must have 4 or more Positions.",
      )
    end

    ring.last.each_with_index do |number, idx|
      if ring.first[idx] != number
        raise Error, "First and last Position are not equivalent."
      end
    end
  end
  geom = {
    type: "Polygon",
    coordinates: coordinates
  }
  feature(geom, properties: properties, id: id, bbox: bbox)
end
radians_to_degrees(radians) click to toggle source

Converts an angle in radians to degrees @see turfjs.org/docs/#radiansToDegrees @param radians [number] angle in radians @return [number] degrees between 0 and 360 degrees

# File lib/turf/helpers.rb, line 192
def radians_to_degrees(radians)
  degrees = radians.remainder(2 * Math::PI)
  degrees * 180 / Math::PI
end
radians_to_length(radians, units = "kilometers") click to toggle source

Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit. Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet @see turfjs.org/docs/#radiansToLength @param radians [number] in radians across the sphere @param units [string] can be degrees, radians, miles, inches, yards, metres, meters, kilometres, kilometers. @return [number] distance

# File lib/turf/helpers.rb, line 212
def radians_to_length(radians, units = "kilometers")
  factor = FACTORS[units]
  raise Error, "#{units} units is invalid" unless factor

  radians * factor
end

Private Instance Methods

area_calculate_area(geom) click to toggle source
# File lib/turf/area.rb, line 17
def area_calculate_area(geom)
  case geom[:type]
  when "Polygon"
    area_polygon_area(geom[:coordinates])
  when "MultiPolygon"
    geom[:coordinates].map do |coordinate|
      area_polygon_area(coordinate)
    end.sum
  else
    0
  end
end
area_polygon_area(coords) click to toggle source
# File lib/turf/area.rb, line 30
def area_polygon_area(coords)
  outline, *holes = coords
  total = area_ring_area(outline).abs
  holes.each do |hole|
    total -= area_ring_area(hole).abs
  end
  total
end
area_rad(num) click to toggle source
# File lib/turf/area.rb, line 77
def area_rad(num)
  num * Math::PI / 180
end
area_ring_area(coords) click to toggle source
# File lib/turf/area.rb, line 41
def area_ring_area(coords)
  return 0 if coords.size <= 2

  total = 0

  coords.each_with_index do |_coord, index|
    lower_index, middle_index, upper_index =
      case index
      when coords.size - 2
        [
          coords.size - 2,
          coords.size - 1,
          0,
        ]
      when coords.size - 1
        [
          coords.size - 1,
          0,
          1,
        ]
      else
        [
          index,
          index + 1,
          index + 2,
        ]
      end
    p1 = coords[lower_index]
    p2 = coords[middle_index]
    p3 = coords[upper_index]
    total += (area_rad(p3[0]) - area_rad(p1[0])) * Math.sin(area_rad(p2[1]))
  end

  total * AREA_RADIUS * AREA_RADIUS / 2
end
calculate_final_bearing(from, to) click to toggle source
# File lib/turf/bearing.rb, line 33
def calculate_final_bearing(from, to)
  bear = bearing(to, from)
  (bear + 180) % 360
end
deep_symbolize_keys(input) click to toggle source

A non-intrusive implemenation of Rails' Hash#deep_symbolize_keys

# File lib/turf.rb, line 16
def deep_symbolize_keys(input)
  case input
  when Hash
    input.transform_keys(&:to_sym).transform_values do |value|
      deep_symbolize_keys(value)
    end
  when Array
    input.map do |value|
      deep_symbolize_keys value
    end
  else
    input
  end
end
in_bbox(point, bbox) click to toggle source
# File lib/turf/boolean_point_in_polygon.rb, line 52
def in_bbox(point, bbox)
  bbox[0] <= point[0] &&
    bbox[1] <= point[1] &&
    bbox[2] >= point[0] &&
    bbox[3] >= point[1]
end
in_ring(point, ring, ignore_boundary) click to toggle source
# File lib/turf/boolean_point_in_polygon.rb, line 59
def in_ring(point, ring, ignore_boundary)
  is_inside = false
  is_ring_valid = ring[0][0] == ring[ring.size - 1][0]
  is_ring_valid &&= ring[0][1] == ring[ring.size - 1][1]
  if is_ring_valid
    ring = ring.slice(0, ring.size - 1)
  end
  ring.each_with_index do |ring_pt, ring_pt_index|
    ring_pt2 = ring[(ring_pt_index + 1) % ring.size]

    xi = ring_pt[0]
    yi = ring_pt[1]
    xj = ring_pt2[0]
    yj = ring_pt2[1]

    on_boundary = (
      point[1] * (xi - xj) + yi * (xj - point[0]) + yj * (point[0] - xi)
    ).zero?
    on_boundary &&= ((xi - point[0]) * (xj - point[0]) <= 0)
    on_boundary &&= ((yi - point[1]) * (yj - point[1]) <= 0)
    if on_boundary
      return !ignore_boundary
    end

    intersect = ((yi > point[1]) != (yj > point[1])) &&
                (point[0] < (xj - xi) * (point[1] - yi) / (yj - yi) + xi)
    if intersect
      is_inside = !is_inside
    end
  end
  is_inside
end