Class: Parse::GeoPoint

Inherits:
Model
  • Object
show all
Defined in:
lib/parse/model/geopoint.rb

Overview

This class manages the GeoPoint data type that Parse provides to support geo-queries. To define a GeoPoint property, use the ‘:geopoint` data type. Please note that latitudes should not be between -90.0 and 90.0, and longitudes should be between -180.0 and 180.0.

Examples:

class PlaceObject < Parse::Object
  property :location, :geopoint
end

san_diego = Parse::GeoPoint.new(32.8233, -117.6542)
los_angeles = Parse::GeoPoint.new [34.0192341, -118.970792]
san_diego == los_angeles # false

place = PlaceObject.new
place.location = san_diego
place.save

Constant Summary collapse

ATTRIBUTES =

The default attributes in a Parse GeoPoint hash.

{ __type: :string, latitude: :float, longitude: :float }.freeze
FIELD_LAT =

The key field for latitude

"latitude".freeze
FIELD_LNG =

The key field for longitude

"longitude".freeze
LAT_MIN =

The minimum latitude value.

-90.0
# The maximum latitude value.
LAT_MAX =

The maximum latitude value.

90.0
LNG_MIN =

The minimum longitude value.

-180.0
# The maximum longitude value.
LNG_MAX =

The maximum longitude value.

180.0

Constants inherited from Model

Model::CLASS_AUDIENCE, Model::CLASS_INSTALLATION, Model::CLASS_JOB_SCHEDULE, Model::CLASS_JOB_STATUS, Model::CLASS_PRODUCT, Model::CLASS_PUSH_STATUS, Model::CLASS_ROLE, Model::CLASS_SCHEMA, Model::CLASS_SESSION, Model::CLASS_USER, Model::ID, Model::KEY_CLASS_NAME, Model::KEY_CREATED_AT, Model::KEY_OBJECT_ID, Model::KEY_UPDATED_AT, Model::OBJECT_ID, Model::TYPE_ACL, Model::TYPE_BYTES, Model::TYPE_DATE, Model::TYPE_FIELD, Model::TYPE_FILE, Model::TYPE_GEOPOINT, Model::TYPE_NUMBER, Model::TYPE_OBJECT, Model::TYPE_POINTER, Model::TYPE_POLYGON, Model::TYPE_RELATION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Model

#dirty?, find_class

Methods included from Client::Connectable

#client

Constructor Details

#initialize(latitude = nil, longitude = nil) ⇒ GeoPoint

The initializer can create a GeoPoint with a hash, array or values.

Examples:

san_diego = Parse::GeoPoint.new(32.8233, -117.6542)
san_diego = Parse::GeoPoint.new [32.8233, -117.6542]
san_diego = Parse::GeoPoint.new { latitude: 32.8233, longitude: -117.6542}

Parameters:

  • latitude (Numeric) (defaults to: nil)

    The latitude value between LAT_MIN and LAT_MAX.

  • longitude (Numeric) (defaults to: nil)

    The longitude value between LNG_MIN and LNG_MAX.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/parse/model/geopoint.rb', line 64

def initialize(latitude = nil, longitude = nil)
  @latitude = @longitude = 0.0
  if latitude.is_a?(Hash) || latitude.is_a?(Array)
    self.attributes = latitude
  elsif latitude.is_a?(Numeric) && longitude.is_a?(Numeric)
    @latitude = latitude
    @longitude = longitude
  elsif latitude.is_a?(GeoPoint)
    @latitude = latitude.latitude
    @longitude = latitude.longitude
  end

  _validate_point
end

Instance Attribute Details

#latitudeFloat Also known as: lat

Returns latitude value between -90.0 and 90.0.

Returns:

  • (Float)

    latitude value between -90.0 and 90.0



30
31
32
# File 'lib/parse/model/geopoint.rb', line 30

def latitude
  @latitude
end

#longitudeFloat Also known as: lng

Returns longitude value between -180.0 and 180.0.

Returns:

  • (Float)

    longitude value between -180.0 and 180.0



32
33
34
# File 'lib/parse/model/geopoint.rb', line 32

def longitude
  @longitude
end

Class Method Details

.from_geojson(geojson) ⇒ Parse::GeoPoint

Build a Parse::GeoPoint from a GeoJSON ‘Point` geometry object. Accepts either symbol or string keys and the standard `[longitude, latitude]` axis order; performs the swap to Parse’s ‘[latitude, longitude]` internal storage.

Examples:

Parse::GeoPoint.from_geojson("type" => "Point", "coordinates" => [-117.6542, 32.8233])

Parameters:

  • geojson (Hash)

    a GeoJSON Point geometry object.

Returns:

Raises:

  • (ArgumentError)

    if the input is not a valid GeoJSON Point.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/parse/model/geopoint.rb', line 190

def self.from_geojson(geojson)
  raise ArgumentError, "[Parse::GeoPoint] from_geojson expects a Hash." unless geojson.is_a?(Hash)
  hash = geojson.respond_to?(:symbolize_keys) ? geojson.symbolize_keys : geojson
  type = hash[:type] || hash["type"]
  coords = hash[:coordinates] || hash["coordinates"]
  # Mirror Parse::Polygon.from_geojson: require both coordinates to
  # be finite Numerics. Without this check, non-numeric entries
  # (`"evil"`, `{"$where": "..."}`, `nil`) silently coerce to 0.0
  # via `.to_f`, producing a null-island point that matches
  # ACL-relevant proximity queries unintentionally. NaN / Infinity
  # similarly produce silent geo bugs and 2dsphere index errors.
  unless type.to_s == "Point" && coords.is_a?(Array) && coords.length == 2 &&
         coords[0].is_a?(Numeric) && coords[1].is_a?(Numeric) &&
         coords[0].finite? && coords[1].finite?
    raise ArgumentError, "[Parse::GeoPoint] from_geojson expects a GeoJSON Point with " \
                         "two finite numeric coordinates."
  end
  Parse::GeoPoint.new(coords[1].to_f, coords[0].to_f)
end

.parse_classModel::TYPE_GEOPOINT



50
# File 'lib/parse/model/geopoint.rb', line 50

def self.parse_class; TYPE_GEOPOINT; end

Instance Method Details

#==(g) ⇒ Boolean

Returns true if two geopoints are equal based on lat and lng.

Returns:

  • (Boolean)

    true if two geopoints are equal based on lat and lng.



150
151
152
153
# File 'lib/parse/model/geopoint.rb', line 150

def ==(g)
  return false unless g.is_a?(GeoPoint)
  @latitude == g.latitude && @longitude == g.longitude
end

#attributesHash

Returns attributes for a Parse GeoPoint.

Returns:

  • (Hash)

    attributes for a Parse GeoPoint.



93
94
95
# File 'lib/parse/model/geopoint.rb', line 93

def attributes
  ATTRIBUTES
end

#attributes=(h) ⇒ Object

Setting lat and lng for an GeoPoint can be done using a hash with the attributes set or with an array of two items where the first is the lat and the second is the lng (ex. [32.22,-118.81])



137
138
139
140
141
142
143
144
145
146
147
# File 'lib/parse/model/geopoint.rb', line 137

def attributes=(h)
  if h.is_a?(Hash)
    h = h.symbolize_keys
    @latitude = h[:latitude].to_f || h[:lat].to_f || @latitude
    @longitude = h[:longitude].to_f || h[:lng].to_f || @longitude
  elsif h.is_a?(Array) && h.count == 2
    @latitude = h.first.to_f
    @longitude = h.last.to_f
  end
  _validate_point
end

#distance_in_km(geopoint, lng = nil) ⇒ Float

Calculate the distance in kilometers to another GeoPoint using Haversine method. You may also call this method with a latitude and longitude.

Examples:

point.distance_in_km(geotpoint)
point.distance_in_km(lat, lng)

Parameters:

  • geopoint (GeoPoint)
  • lng (Float) (defaults to: nil)

    Longitude assuming that the first parameter is a latitude instead of a GeoPoint.

Returns:

  • (Float)

    number of miles between geopoints.

See Also:



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/parse/model/geopoint.rb', line 240

def distance_in_km(geopoint, lng = nil)
  unless geopoint.is_a?(Parse::GeoPoint)
    geopoint = Parse::GeoPoint.new(geopoint, lng)
  end

  dtor = Math::PI / 180
  r = 6378.14
  r_lat1 = self.latitude * dtor
  r_lng1 = self.longitude * dtor
  r_lat2 = geopoint.latitude * dtor
  r_lng2 = geopoint.longitude * dtor

  delta_lat = r_lat1 - r_lat2
  delta_lng = r_lng1 - r_lng2

  a = (Math::sin(delta_lat / 2.0) ** 2).to_f + (Math::cos(r_lat1) * Math::cos(r_lat2) * (Math::sin(delta_lng / 2.0) ** 2))
  c = 2.0 * Math::atan2(Math::sqrt(a), Math::sqrt(1.0 - a))
  d = r * c
  d
end

#distance_in_miles(geopoint, lng = nil) ⇒ Float

Calculate the distance in miles to another GeoPoint using Haversine. You may also call this method with a latitude and longitude. is longitude instead of a GeoPoint.

Examples:

point.distance_in_miles(geotpoint)
point.distance_in_miles(lat, lng)

Parameters:

  • geopoint (GeoPoint)
  • lng (Float) (defaults to: nil)

    Longitude assuming that the first parameter

Returns:

  • (Float)

    number of miles between geopoints.

See Also:



226
227
228
# File 'lib/parse/model/geopoint.rb', line 226

def distance_in_miles(geopoint, lng = nil)
  distance_in_km(geopoint, lng) * 0.621371
end

#estimated(precision = 2) ⇒ GeoPoint

Helper method for reducing the precision of a geopoint.

Parameters:

  • precision (Integer) (defaults to: 2)

    The number of floating digits to keep.

Returns:

  • (GeoPoint)

    Reduces the precision of a geopoint.



158
159
160
# File 'lib/parse/model/geopoint.rb', line 158

def estimated(precision = 2)
  Parse::GeoPoint.new(@latitude.to_f.round(precision), @longitude.round(precision))
end

#max_kilometers(km) ⇒ Array Also known as: max_km

Helper method for performing geo-queries with a radial kilometer constraint. Used with ‘:field.near => gp.max_kilometers(N)` to compile a `$nearSphere` + `$maxDistanceInKilometers` query against Parse Server.

Returns:

  • (Array)

    containing ‘[lat, lng, kilometers, :km]`



108
109
110
111
# File 'lib/parse/model/geopoint.rb', line 108

def max_kilometers(km)
  km = 0 if km.nil?
  [@latitude, @longitude, km, :km]
end

#max_miles(m) ⇒ Array

Helper method for performing geo-queries with radial miles constraints

Returns:

  • (Array)

    containing [lat,lng,miles]



99
100
101
102
# File 'lib/parse/model/geopoint.rb', line 99

def max_miles(m)
  m = 0 if m.nil?
  [@latitude, @longitude, m]
end

#max_radians(rad) ⇒ Array

Helper method for performing geo-queries with a radial radians constraint. Used with ‘:field.near => gp.max_radians®` to compile a `$nearSphere` + `$maxDistance` query against Parse Server (raw `$maxDistance` is measured in radians). Convert from miles/km by dividing by mean-Earth-radius (~3958.8 miles or ~6371 km).

Returns:

  • (Array)

    containing ‘[lat, lng, radians, :radians]`



120
121
122
123
# File 'lib/parse/model/geopoint.rb', line 120

def max_radians(rad)
  rad = 0 if rad.nil?
  [@latitude, @longitude, rad, :radians]
end

#parse_classModel::TYPE_GEOPOINT Also known as: __type



52
# File 'lib/parse/model/geopoint.rb', line 52

def parse_class; self.class.parse_class; end

#to_aArray

Returns a tuple containing latitude and longitude

Returns:



164
165
166
# File 'lib/parse/model/geopoint.rb', line 164

def to_a
  [@latitude, @longitude]
end

#to_geojsonHash

GeoJSON (RFC 7946) representation of this point. GeoJSON requires ‘[longitude, latitude]` axis order — the inverse of Parse’s wire format — so this method performs the swap. Useful when handing the value to Leaflet/Mapbox/PostGIS, or when constructing literals for MongoDB-direct geo queries (which use GeoJSON internally).

Examples:

geopoint.to_geojson
# => {"type" => "Point", "coordinates" => [-117.6542, 32.8233]}

Returns:

  • (Hash)

    a GeoJSON ‘Point` geometry object.



177
178
179
# File 'lib/parse/model/geopoint.rb', line 177

def to_geojson
  { "type" => "Point", "coordinates" => [@longitude, @latitude] }
end