Module: Turf

Extended by:
Turf
Included in:
Turf
Defined in:
lib/turf.rb,
lib/turf/area.rb,
lib/turf/meta.rb,
lib/turf/along.rb,
lib/turf/circle.rb,
lib/turf/length.rb,
lib/turf/bearing.rb,
lib/turf/helpers.rb,
lib/turf/version.rb,
lib/turf/centroid.rb,
lib/turf/distance.rb,
lib/turf/truncate.rb,
lib/turf/invariant.rb,
lib/turf/destination.rb,
lib/turf/boolean_point_in_polygon.rb

Overview

:nodoc:

Defined Under Namespace

Classes: Error

Constant Summary collapse

AREA_RADIUS =
6_378_137.0
VERSION =

Version of turf-ruby

"0.8.1"

Meta collapse

Measurement collapse

Helper collapse

Unit Conversion collapse

Booleans collapse

Instance Method Summary collapse

Instance Method Details

#along(line, distance, units: "kilometers") ⇒ Feature<Point>

Takes a LineString and returns a Point at a specified distance along the line.

Parameters:

  • line (Feature<LineString>)

    input line

  • distance (number)

    distance along the line

  • units (string) (defaults to: "kilometers")

    can be degrees, radians, miles, or kilometers (optional, default “kilometers”)

Returns:

  • (Feature<Point>)

    Point distance units along the line

See Also:



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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) ⇒ number

Takes one or more features and returns their area in square meters.

Parameters:

  • geojson (GeoJSON)

    input GeoJSON feature(s)

Returns:

  • (number)

    aria in square meters

See Also:



9
10
11
12
13
# 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) ⇒ number

Takes two points and finds the geographic bearing between them, i.e. the angle measured in degrees from the north line (0 degrees)

Parameters:

  • from (Coord)

    starting Point

  • to (Coord)

    ending Point

  • final (defaults to: false)

    boolean calculates the final bearing if true

Returns:

  • (number)

    bearing in decimal degrees, between -180 and 180 degrees (positive clockwise)

See Also:



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 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) ⇒ boolean

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. inside the polygon otherwise false.

Parameters:

  • point (Coord)

    input point

  • polygon (Feature<(Polygon | MultiPolygon)>)

    input polygon or multipolygon

  • ignore_boundary (boolean) (defaults to: false)

    True if polygon boundary should be ignored when determining if the point is

Returns:

  • (boolean)

    true if the Point is inside the Polygon; false if the Point is not inside the Polygon

See Also:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 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: {}) ⇒ Feature<Point>

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.

Parameters:

  • geojson (GeoJSON)

    GeoJSON to be centered

  • properties (Hash) (defaults to: {})

    a [Hash] that is used as the Feature’s properties

Returns:

  • (Feature<Point>)

    the centroid of the input features

See Also:



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/turf/centroid.rb', line 13

def centroid(geojson, properties: {})
  x_sum = 0.0
  y_sum = 0.0
  len = 0.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

#circle(center, radius, options = {}) ⇒ Object

Takes a Point and calculates the circle polygon given a radius in degrees, radians, miles, or kilometers; and steps for precision.

Parameters:

  • center (Feature<Point>|number[])

    center point

  • radius (number)

    radius of the circle

  • [options={}] (hash)

    Optional parameters

  • [options.steps=64] (number)

    number of steps

  • [options.units='kilometers'] (string)

    miles, kilometers, degrees, or radians

  • [options.properties={}] (hash)

    properties



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/turf/circle.rb', line 14

def circle(center, radius, options = {})
  center = deep_symbolize_keys(center)
  # default params
  steps = options[:steps] || 64
  properties = options[:properties]
  properties ||= !center.is_a?(Array) && center[:type] == "Feature" && center[:properties]
  properties ||= {}

  # main
  coordinates = []
  steps.times do |i|
    coordinates.push(destination(center, radius, (i * -360.0) / steps, **options).dig(:geometry, :coordinates))
  end
  coordinates.push(coordinates[0])

  polygon([coordinates], properties: properties)
end

#coord_all(geojson, exclude_wrap_coord: false, &block) ⇒ Array<Array<number>>

Get all coordinates from any GeoJSON object. ring in its iteration

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

  • exclude_wrap_coord (boolean) (defaults to: false)

    whether or not to include the final coordinate of LinearRings that wraps the

Returns:

  • (Array<Array<number>>)

    coordinate position array

See Also:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/turf/meta.rb', line 25

def coord_all(geojson, exclude_wrap_coord: false, &block)
  geometry_index = -1
  geom_each(geojson) do |geometry, _idx, _properties|
    if geometry.nil?
      next
    end

    case geometry[:type]
    when "Point"
      geometry_index += 1
      block.call(geometry[:coordinates], geometry_index)
    when "LineString", "MultiPoint"
      geometry[:coordinates].each do |coords|
        geometry_index += 1
        block.call(coords, geometry_index)
      end
    when "Polygon", "MultiLineString"
      geometry[:coordinates].each do |line_coords|
        if exclude_wrap_coord
          line_coords = line_coords[0...-1]
        end
        line_coords.each do |coords|
          geometry_index += 1
          block.call(coords, geometry_index)
        end
      end
    when "MultiPolygon"
      geometry[:coordinates].each do |polygon_coords|
        polygon_coords.each do |line_coords|
          if exclude_wrap_coord
            line_coords = line_coords[0...-1]
          end
          line_coords.each do |coords|
            geometry_index += 1
            block.call(coords, geometry_index)
          end
        end
      end
    when "Feature"
      coord_each(geometry, exclude_wrap_coord: exclude_wrap_coord, &block)
    else
      raise Error, "Unknown Geometry Type: #{geometry[:type]}"
    end
  end
  geojson
end

#coord_each(geojson, exclude_wrap_coord: false) {|current_coord, coord_index| ... } ⇒ Object

Iterate over coordinates in any GeoJSON object, similar to Array.forEach() ring in its iteration

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

  • exclude_wrap_coord (boolean) (defaults to: false)

    whether or not to include the final coordinate of LinearRings that wraps the

Yields:

  • (current_coord, coord_index)

    given any coordinate

Yield Parameters:

  • current_coord (Array<number>)

    The current coordinate being processed.

  • coord_index (number)

    The current index of the coordinate being processed.

See Also:



15
16
17
# 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, &block)
end

#coord_reduce(geojson, initial_value: nil, exclude_wrap_coord: false) ⇒ *

Reduce coordinates in any GeoJSON object, similar to Array.reduce() ring in its iteration.

Parameters:

  • geojson (FeatureCollection|Geometry|Feature)

    any GeoJSON object

  • initial_value (*) (defaults to: nil)

    Value to use as the first argument to the first call of the callback.

  • exclude_wrap_coord (Boolean) (defaults to: false)

    whether or not to include the final coordinate of LinearRings that wraps the

Returns:

  • (*)

    The value that results from the reduction.

See Also:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/turf/meta.rb', line 79

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) ⇒ number

Converts an angle in degrees to radians

Parameters:

  • degrees (number)

    angle between 0 and 360 degrees

Returns:

  • (number)

    angle in radians

See Also:



201
202
203
204
# 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, options = {}) ⇒ Feature<Point>

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.

Parameters:

  • origin (Coord)

    starting point

  • distance (number)

    distance from the origin point

  • bearing (number)

    ranging from -180 to 180

  • units (string)

    miles, kilometers, degrees, or radians

  • properties (Hash)

    Translate properties to Point

Returns:

  • (Feature<Point>)

    destination point

See Also:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/turf/destination.rb', line 16

def destination(origin, distance, bearing, options = {})
  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, options[: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: options[:properties])
end

#distance(from, to, units: "kilometers") ⇒ number

Calculates the distance between two points in degrees, radians, miles, or kilometers. This uses the Haversine formula to account for global curvature.

Parameters:

  • from (Coord)

    origin point

  • to (Coord)

    destination point

  • units (string) (defaults to: "kilometers")

    can be degrees, radians, miles, or kilometers

Returns:

  • (number)

    distance between the two points

See Also:



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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.0)**2) +
      ((Math.sin(d_lon / 2.0)**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) ⇒ Feature

Wraps a GeoJSON Geometry in a GeoJSON Feature.

Parameters:

  • geom (Geometry)

    input geometry

  • properties (Hash) (defaults to: {})

    an Object of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string | number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature)

    a GeoJSON Feature

See Also:



35
36
37
38
39
40
41
42
43
44
45
# 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) ⇒ FeatureCollection

Takes one or more Features and creates a FeatureCollection.

Parameters:

  • features (Array<Feature>)

    input features

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string | number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (FeatureCollection)

    FeatureCollection of Features

See Also:



53
54
55
56
57
58
59
60
# 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) {|feature| ... } ⇒ Object

Iterate over features in any GeoJSON object, similar to Array.forEach.

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

Yields:

  • (feature)

    given any coordinate

Yield Parameters:

  • feature (Feature<any>)

    currentFeature The current Feature being processed.

  • feature_index (number)

    The current index of the Feature being processed.

See Also:



194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/turf/meta.rb', line 194

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| ... } ⇒ *

Reduce features in any GeoJSON object, similar to Array.reduce().

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

  • initial_value (*) (defaults to: nil)

    Value to use as the first argument to the first call of the callback.

Yield Parameters:

  • previous_value (*)

    Result of previous reduction

  • feature (Feature<any>)

    The current Feature being processed.

  • feature_index (number)

    The current index of the Feature being processed.

Returns:

  • (*)

    The value that results from the reduction.

See Also:



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/turf/meta.rb', line 217

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, feature_index, multi_feature_index| ... } ⇒ Object

Iterate over flattened features in any GeoJSON object, similar to Array.forEach.

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

Yield Parameters:

  • feature (Feature<any>)

    The current Feature being processed.

  • feature_index (number)

    The current index of the Feature being processed.

  • multi_feature_index (number)

    The current index of the Feature in the multi-Feature

See Also:



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/turf/meta.rb', line 244

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| ... } ⇒ *

Reduce flattened features in any GeoJSON object, similar to Array.reduce().

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

  • initial_value (*) (defaults to: nil)

    Value to use as the first argument to the first call of the callback.

Yield Parameters:

  • previous_value (*)

    Result of previous reduction

  • feature (Feature<any>)

    The current Feature being processed.

  • feature_index (number)

    The current index of the Feature being processed.

  • multi_feature_index (number)

    The current index of the Feature in the multi-Feature

Returns:

  • (*)

    The value that results from the reduction.

See Also:



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/turf/meta.rb', line 287

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) {|geom, feature_index, properties, bbox, id| ... } ⇒ Object

Iterate over each geometry in any GeoJSON object, similar to Array.forEach()

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

Yield Parameters:

  • geom (Geometry)

    The current Feature being processed.

  • feature_index (number)

    The current index of the Feature being processed.

  • properties (Hash)

    an Object of key-value pairs to add as properties

  • bbox (Array<number>)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number)

    Identifier associated with the Feature

See Also:



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/turf/meta.rb', line 109

def geom_each(geojson)
  return unless geojson

  geojson = deep_symbolize_keys! geojson

  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

  entry_index = -1

  # flatten GeometryCollection
  entries.each do |entry|
    geometry, properties, bbox, id = entry
    if geometry.nil? || geometry[:type] != "GeometryCollection"
      yield(geometry, (entry_index += 1), properties, bbox, id)
    else
      geometry[:geometries].each do |sub_geometry|
        yield(sub_geometry, (entry_index += 1), properties, bbox, id)
      end
    end
  end
end

#geom_reduce(geojson, initial_value: nil) {|previous_value, geom, geom_index, properties, bbox, id| ... } ⇒ *

Reduce geometry in any GeoJSON object, similar to Array.reduce().

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

  • initial_value (*) (defaults to: nil)

    Value to use as the first argument to the first call of the callback.

Yield Parameters:

  • previous_value (*)

    Result of previous reduction

  • geom (Geometry)

    The current Feature being processed.

  • geom_index (number)

    The current index of the Feature being processed.

  • properties (Hash)

    an Object of key-value pairs to add as properties

  • bbox (Array<number>)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number)

    Identifier associated with the Feature

Returns:

  • (*)

    The value that results from the reduction.

See Also:



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/turf/meta.rb', line 153

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) ⇒ Array<Geometry>

Get all Geometry

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

Returns:

  • (Array<Geometry>)

    list of Geometry



180
181
182
183
184
185
186
# File 'lib/turf/meta.rb', line 180

def geometries(geojson)
  geometries = []
  geom_each(geojson) do |geometry|
    geometries.push(geometry)
  end
  geometries
end

#geometry_collection(geometries, bbox: nil, id: nil, properties: {}) ⇒ Feature<GeometryCollection>

Creates a Feature based on a coordinate array. Properties can be added optionally.

Parameters:

  • geometries (Array<Geometry>)

    an array of GeoJSON Geometries

  • properties (Hash) (defaults to: {})

    a Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<GeometryCollection>)

    a GeoJSON GeometryCollection Feature

See Also:



69
70
71
72
73
74
75
76
# 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) ⇒ Array

Unwrap a coordinate from a Point Feature, Geometry or a single coordinate.

Parameters:

  • coord (Array|Geometry<Point>|Feature<Point>)

    GeoJSON Point or an Array of numbers

Returns:

  • (Array)

    coordinates

Raises:

See Also:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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) ⇒ Geometry|null

Get Geometry from Feature or Geometry Object

Parameters:

  • geojson (Feature|Geometry)

    GeoJSON Feature or Geometry Object

Returns:

  • (Geometry|null)

    GeoJSON Geometry Object

See Also:



41
42
43
44
45
46
# 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(geojson, units: "kilometers") ⇒ number

Takes a GeoJSON and measures its length in the specified units, (Multi)Point ‘s distance are ignored.

Parameters:

  • geojson (Feature<LineString|MultiLinestring>)

    GeoJSON to measure

  • units (string) (defaults to: "kilometers")

    can be degrees, radians, miles, or kilometers (optional, default “kilometers”)

Returns:

  • (number)

    length of GeoJSON

See Also:



12
13
14
15
16
17
18
19
20
# File 'lib/turf/length.rb', line 12

def length(geojson, units: "kilometers")
  geojson = deep_symbolize_keys(geojson)
  geojson = feature(geojson) if geojson[:geometry].nil?
  segment_reduce(geojson, initial_value: 0) do |previous_value, segment|
    previous_value ||= 0
    coords = segment.dig(:geometry, :coordinates)
    previous_value + Turf.distance(coords[0], coords[1], units: units)
  end
end

#length_to_radians(distance, units = nil) ⇒ number

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

Parameters:

  • distance (number)

    in real units

  • units (string) (defaults to: nil)

    can be degrees, radians, miles, inches, yards, metres, meters, kilometres, kilometers.

Returns:

  • (number)

    radians

Raises:

See Also:



226
227
228
229
230
231
232
# File 'lib/turf/helpers.rb', line 226

def length_to_radians(distance, units = nil)
  units ||= "kilometers"
  factor = FACTORS[units]
  raise Error, "#{units} units is invalid" unless factor

  distance / factor
end

#line_string(coordinates, properties: {}, bbox: nil, id: nil) ⇒ Feature<LineString>

Creates a LineString Feature from an Array of Positions.

Parameters:

  • coordinates (Array<Array<number>>)

    an array of Positions

  • properties (Hash) (defaults to: {})

    an Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<LineString>)

    LineString Feature

See Also:



100
101
102
103
104
105
106
107
108
109
110
# 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) ⇒ Feature<MultiLineString>

Creates a Feature<MultiLineString> based on a coordinate array. Properties can be added optionally.

Parameters:

  • coordinates (Array<Array<Array<number>>>)

    coordinates an array of LineStrings

  • properties (Hash) (defaults to: {})

    a Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<MultiLineString>)

    a MultiLineString feature

See Also:



178
179
180
181
182
183
184
# 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) ⇒ Feature<MultiPoint>

Creates a Feature based on a coordinate array. Properties can be added optionally.

Parameters:

  • coordinates (Array<Array<number>>)

    an array of Positions

  • properties (Hash) (defaults to: {})

    a Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<MultiPoint>)

    a MultiPoint feature



84
85
86
87
88
89
90
91
# 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) ⇒ Feature<MultiPolygon>

Creates a Feature<MultiPolygon> based on a coordinate array. Properties can be added optionally.

Parameters:

  • coordinates (Array<Array<Array<Array<number>>>>)

    an array of Polygons

  • properties (Hash) (defaults to: {})

    an Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string|number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<MultiPolygon>)

    a multipolygon feature

See Also:



163
164
165
166
167
168
169
# 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) ⇒ Feature<Point>

Creates a Point Feature from a Position.

Parameters:

  • coordinates (Array<number>)

    longitude, latitude position (each in decimal degrees)

  • properties (Hash) (defaults to: {})

    an Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string | number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<Point>)

    a Point feature

See Also:



119
120
121
122
123
124
125
# 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) ⇒ Feature<Polygon>

Creates a Polygon Feature from an Array of LinearRings.

Parameters:

  • coordinates (Array<Array<Array<number>>>)

    an array of LinearRings

  • properties (Hash) (defaults to: {})

    an Hash of key-value pairs to add as properties

  • bbox (Array<number>) (defaults to: nil)

    Bounding Box Array [west, south, east, north] associated with the Feature

  • id (string | number) (defaults to: nil)

    Identifier associated with the Feature

Returns:

  • (Feature<Polygon>)

    Polygon feature

See Also:



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# 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) ⇒ number

Converts an angle in radians to degrees

Parameters:

  • radians (number)

    angle in radians

Returns:

  • (number)

    degrees between 0 and 360 degrees

See Also:



192
193
194
195
# 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 = nil) ⇒ number

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

Parameters:

  • radians (number)

    in radians across the sphere

  • units (string) (defaults to: nil)

    can be degrees, radians, miles, inches, yards, metres, meters, kilometres, kilometers.

Returns:

  • (number)

    distance

Raises:

See Also:



212
213
214
215
216
217
218
# File 'lib/turf/helpers.rb', line 212

def radians_to_length(radians, units = nil)
  units ||= "kilometers"
  factor = FACTORS[units]
  raise Error, "#{units} units is invalid" unless factor

  radians * factor
end

#segment_each(geojson) ⇒ Object

Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach() (Multi)Point geometries do not contain segments therefore they are ignored during this operation.

Parameters:

  • geojson (FeatureCollection|Feature|Geometry)

    any GeoJSON object

See Also:



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/turf/meta.rb', line 313

def segment_each(geojson)
  flatten_each(geojson) do |feature, feature_index|
    # Exclude null Geometries
    return if feature[:geometry].nil?

    # (Multi)Point geometries do not contain segments therefore they are ignored during this operation.
    type = feature[:geometry][:type]
    return if %w[Point MultiPoint].include?(type)

    segment_index = 0

    # Generate 2-vertex line segments
    previous_coords = nil
    previous_feature_index = 0
    coord_each(feature) do |current_coord|
      # Simulating a meta.coord_reduce() since `reduce` operations cannot be stopped by returning `false`
      if previous_coords.nil? || feature_index > previous_feature_index
        previous_coords = current_coord
        previous_feature_index = feature_index
        segment_index = 0
        next
      end

      segment = Turf.line_string([previous_coords, current_coord], properties: feature[:properties])
      next unless yield(segment, feature_index)

      segment_index += 1
      previous_coords = current_coord
    end
  end
end

#segment_reduce(geojson, initial_value: nil) ⇒ Object



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/turf/meta.rb', line 345

def segment_reduce(geojson, initial_value: nil)
  previous_value = initial_value
  started = false

  segment_each(geojson) do |segment, feature_index, multifeature_index, geometry_index, segment_index|
    previous_value =
      if !started && initial_value.nil?
        segment
      else
        yield(
          previous_value,
          segment,
          feature_index,
          multifeature_index,
          geometry_index,
          segment_index
        )
      end
    started = true
  end

  previous_value
end

#truncate(geojson, options = {}) ⇒ Object

Takes a GeoJSON Feature or FeatureCollection and truncates the precision of the geometry. (significant performance increase if true (note statement from js port. not checked in ruby)) var point = turf.point([

70.46923055566859,
58.11088890802906,
1508

]) var options = 3, coordinates: 2 var truncated = turf.truncate(point, options) //=truncated.geometry.coordinates => [70.469, 58.111]

//addToMap var addToMap = [truncated] /

Parameters:

  • geojson (GeoJSON)

    any GeoJSON Feature, FeatureCollection, Geometry or GeometryCollection.

  • [options={}] (hash)

    Optional parameters

  • [options.precision=6] (number)

    coordinate decimal precision

  • [options.coordinates=3] (number)

    maximum number of coordinates (primarly used to remove z coordinates)

  • [options.mutate=false] (boolean)

    allows GeoJSON input to be mutated



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/turf/truncate.rb', line 26

def truncate(geojson, options = {})
  precision = options[:precision] || 6
  coordinates = options[:coordinates] || 3
  mutate = options[:mutate]

  if !geojson
    raise("geojson is required")
  end

  if !mutate
    geojson = deep_dup(geojson)
  end

  # factor = Math.pow(10, precision)
  # geojson[:properties][:truncate] = "done"
  # Truncate Coordinates
  coord_each(geojson) do |coords|
    truncate_coords(coords, precision, coordinates)
  end
  geojson
end

#truncate_coords(coords, precision, coordinates) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/turf/truncate.rb', line 48

def truncate_coords(coords, precision, coordinates)
  # Remove extra coordinates (usually elevation coordinates and more)
  if coords.length > coordinates
    coords.slice!(coordinates..-1)
  end

  # coords.map do |coord|
  #   coord.round(precision)
  # end

  # Truncate coordinate decimals
  (0...coords.length).each do |idx|
    coords[idx] = coords[idx].round(precision)
  end
  coords
end