Class: GeoRuby::SimpleFeatures::Point

Inherits:
Geometry
  • Object
show all
Defined in:
lib/geo_ruby/simple_features/point.rb

Overview

Represents a point. It is in 3D if the Z coordinate is not nil.

Instance Attribute Summary collapse

Attributes inherited from Geometry

#srid, #with_m, #with_z

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Geometry

#as_ewkb, #as_ewkt, #as_georss, #as_hex_ewkb, #as_hex_wkb, #as_kml, #as_wkb, #as_wkt, #envelope, from_ewkb, from_ewkt, from_georss, from_georss_with_tags, from_hex_ewkb, from_kml, kml_to_wkt

Constructor Details

#initialize(srid = DEFAULT_SRID, with_z = false, with_m = false) ⇒ Point

Returns a new instance of Point.



14
15
16
17
18
19
20
# File 'lib/geo_ruby/simple_features/point.rb', line 14

def initialize(srid=DEFAULT_SRID,with_z=false,with_m=false)
  super(srid,with_z,with_m)
  @x=0.0
  @y=0.0
  @z=0.0 #default value : meaningful if with_z

  @m=0.0 #default value : meaningful if with_m

end

Instance Attribute Details

#mObject

Returns the value of attribute m.



8
9
10
# File 'lib/geo_ruby/simple_features/point.rb', line 8

def m
  @m
end

#xObject Also known as: lon, lng

Returns the value of attribute x.



8
9
10
# File 'lib/geo_ruby/simple_features/point.rb', line 8

def x
  @x
end

#yObject Also known as: lat

Returns the value of attribute y.



8
9
10
# File 'lib/geo_ruby/simple_features/point.rb', line 8

def y
  @y
end

#zObject

Returns the value of attribute z.



8
9
10
# File 'lib/geo_ruby/simple_features/point.rb', line 8

def z
  @z
end

Class Method Details

.from_coordinates(coords, srid = DEFAULT_SRID, with_z = false, with_m = false) ⇒ Object

creates a point from an array of coordinates



188
189
190
191
192
193
194
195
196
197
198
# File 'lib/geo_ruby/simple_features/point.rb', line 188

def self.from_coordinates(coords,srid=DEFAULT_SRID,with_z=false,with_m=false)
  if ! (with_z or with_m)
    from_x_y(coords[0],coords[1],srid)
  elsif with_z and with_m
    from_x_y_z_m(coords[0],coords[1],coords[2],coords[3],srid)
  elsif with_z
    from_x_y_z(coords[0],coords[1],coords[2],srid)
  else
    from_x_y_m(coords[0],coords[1],coords[2],srid) 
  end
end

.from_x_y(x, y, srid = DEFAULT_SRID) ⇒ Object Also known as: from_lon_lat

creates a point from the X and Y coordinates



201
202
203
204
# File 'lib/geo_ruby/simple_features/point.rb', line 201

def self.from_x_y(x,y,srid=DEFAULT_SRID)
  point= new(srid)
  point.set_x_y(x,y)
end

.from_x_y_m(x, y, m, srid = DEFAULT_SRID) ⇒ Object Also known as: from_lon_lat_m

creates a point from the X, Y and M coordinates



214
215
216
217
218
# File 'lib/geo_ruby/simple_features/point.rb', line 214

def self.from_x_y_m(x,y,m,srid=DEFAULT_SRID)
  point= new(srid,false,true)
  point.m=m
  point.set_x_y(x,y)
end

.from_x_y_z(x, y, z, srid = DEFAULT_SRID) ⇒ Object Also known as: from_lon_lat_z

creates a point from the X, Y and Z coordinates



207
208
209
210
# File 'lib/geo_ruby/simple_features/point.rb', line 207

def self.from_x_y_z(x,y,z,srid=DEFAULT_SRID)
  point= new(srid,true)
  point.set_x_y_z(x,y,z)
end

.from_x_y_z_m(x, y, z, m, srid = DEFAULT_SRID) ⇒ Object Also known as: from_lon_lat_z_m

creates a point from the X, Y, Z and M coordinates



221
222
223
224
225
# File 'lib/geo_ruby/simple_features/point.rb', line 221

def self.from_x_y_z_m(x,y,z,m,srid=DEFAULT_SRID)
  point= new(srid,true,true)
  point.m=m
  point.set_x_y_z(x,y,z)
end

Instance Method Details

#==(other_point) ⇒ Object

tests the equality of the position of points + m



123
124
125
126
127
128
129
# File 'lib/geo_ruby/simple_features/point.rb', line 123

def ==(other_point)
  if other_point.class != self.class
    false
  else
    @x == other_point.x and @y == other_point.y and @z == other_point.z and @m == other_point.m
  end
end

#binary_geometry_typeObject

WKB geometry type of a point



139
140
141
# File 'lib/geo_ruby/simple_features/point.rb', line 139

def binary_geometry_type#:nodoc:

  1
end

#binary_representation(allow_z = true, allow_m = true) ⇒ Object

binary representation of a point. It lacks some headers to be a valid EWKB representation.



132
133
134
135
136
137
# File 'lib/geo_ruby/simple_features/point.rb', line 132

def binary_representation(allow_z=true,allow_m=true) #:nodoc:

  bin_rep = [@x,@y].pack("EE")
  bin_rep += [@z].pack("E") if @with_z and allow_z #Default value so no crash

  bin_rep += [@m].pack("E") if @with_m and allow_m #idem

  bin_rep
end

#bounding_boxObject

Bounding box in 2D/3D. Returns an array of 2 points



110
111
112
113
114
115
116
# File 'lib/geo_ruby/simple_features/point.rb', line 110

def bounding_box
  unless with_z
    [Point.from_x_y(@x,@y),Point.from_x_y(@x,@y)]
  else
    [Point.from_x_y_z(@x,@y,@z),Point.from_x_y_z(@x,@y,@z)]
  end
end

#ellipsoidal_distance(point, a = 6378137.0, b = 6356752.3142) ⇒ Object

Ellipsoidal distance in m using Vincenty’s formula. Lifted entirely from Chris Veness’s code at www.movable-type.co.uk/scripts/LatLongVincenty.html and adapted for Ruby. Assumes the x and y are the lon and lat in degrees. a is the semi-major axis (equatorial radius) of the ellipsoid b is the semi-minor axis (polar radius) of the ellipsoid Their values by default are set to the ones of the WGS84 ellipsoid



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/geo_ruby/simple_features/point.rb', line 62

def ellipsoidal_distance(point, a = 6378137.0, b = 6356752.3142)
  deg_to_rad = 0.0174532925199433
  
  f = (a-b) / a
  l = (point.lon - lon) * deg_to_rad
  
  u1 = Math.atan((1-f) * Math.tan(lat * deg_to_rad ))
  u2 = Math.atan((1-f) * Math.tan(point.lat * deg_to_rad))
  sinU1 = Math.sin(u1)
  cosU1 = Math.cos(u1)
  sinU2 = Math.sin(u2)
  cosU2 = Math.cos(u2)
  
  lambda = l
  lambdaP = 2 * Math::PI
  iterLimit = 20
  
  while (lambda-lambdaP).abs > 1e-12 && --iterLimit>0
    sinLambda = Math.sin(lambda)
    cosLambda = Math.cos(lambda)
    sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda))
    
    return 0 if sinSigma == 0 #coincident points

    
    cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda
    sigma = Math.atan2(sinSigma, cosSigma)
    sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma
    cosSqAlpha = 1 - sinAlpha*sinAlpha
    cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha
    
    cos2SigmaM = 0 if (cos2SigmaM.nan?) #equatorial line: cosSqAlpha=0


    c = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha))
    lambdaP = lambda
    lambda = l + (1-c) * f * sinAlpha * (sigma + c * sinSigma * (cos2SigmaM + c * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))
  end
  return NaN if iterLimit==0 #formula failed to converge


  uSq = cosSqAlpha * (a*a - b*b) / (b*b)
  a_bis = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)))
  b_bis = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)))
  deltaSigma = b_bis * sinSigma*(cos2SigmaM + b_bis/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- b_bis/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)))

  b*a_bis*(sigma-deltaSigma)
end

#euclidian_distance(point) ⇒ Object

Return the distance between the 2D points (ie taking care only of the x and y coordinates), assuming the points are in projected coordinates. Euclidian distance in whatever unit the x and y ordinates are.



39
40
41
# File 'lib/geo_ruby/simple_features/point.rb', line 39

def euclidian_distance(point)
  Math.sqrt((point.x - x)**2 + (point.y - y)**2)
end

#georss_gml_representation(options) ⇒ Object

georss gml representation



167
168
169
170
171
172
173
# File 'lib/geo_ruby/simple_features/point.rb', line 167

def georss_gml_representation(options) #:nodoc:

  georss_ns = options[:georss_ns] || "georss"
  gml_ns = options[:gml_ns] || "gml"
  result = "<#{georss_ns}:where>\n<#{gml_ns}:Point>\n<#{gml_ns}:pos>"
  result += "#{y} #{x}"
  result += "</#{gml_ns}:pos>\n</#{gml_ns}:Point>\n</#{georss_ns}:where>\n"
end

#georss_simple_representation(options) ⇒ Object

georss simple representation



156
157
158
159
160
# File 'lib/geo_ruby/simple_features/point.rb', line 156

def georss_simple_representation(options) #:nodoc:

  georss_ns = options[:georss_ns] || "georss"
  geom_attr = options[:geom_attr]
  "<#{georss_ns}:point#{geom_attr}>#{y} #{x}</#{georss_ns}:point>\n"
end

#georss_w3cgeo_representation(options) ⇒ Object

georss w3c representation



162
163
164
165
# File 'lib/geo_ruby/simple_features/point.rb', line 162

def georss_w3cgeo_representation(options) #:nodoc:

  w3cgeo_ns = options[:w3cgeo_ns] || "geo"
  "<#{w3cgeo_ns}:lat>#{y}</#{w3cgeo_ns}:lat>\n<#{w3cgeo_ns}:long>#{x}</#{w3cgeo_ns}:long>\n"
end

#kml_representation(options = {}) ⇒ Object

outputs the geometry in kml format : options are :id, :tesselate, :extrude, :altitude_mode. If the altitude_mode option is not present, the Z (if present) will not be output (since it won’t be used by GE anyway: clampToGround is the default)



178
179
180
181
182
183
184
185
# File 'lib/geo_ruby/simple_features/point.rb', line 178

def kml_representation(options = {}) #:nodoc: 

  result = "<Point#{options[:id_attr]}>\n"
  result += options[:geom_data] if options[:geom_data]
  result += "<coordinates>#{x},#{y}"
  result += ",#{options[:fixed_z] || z ||0}" if options[:allow_z]
  result += "</coordinates>\n"
  result += "</Point>\n"
end

#m_rangeObject



118
119
120
# File 'lib/geo_ruby/simple_features/point.rb', line 118

def m_range
  [@m,@m]
end

#set_x_y(x, y) ⇒ Object Also known as: set_lon_lat

sets all coordinates of a 2D point in one call



31
32
33
34
35
# File 'lib/geo_ruby/simple_features/point.rb', line 31

def set_x_y(x,y)
  @x=x
  @y=y
  self
end

#set_x_y_z(x, y, z) ⇒ Object Also known as: set_lon_lat_z

sets all coordinates in one call. Use the m accessor to set the m.



22
23
24
25
26
27
# File 'lib/geo_ruby/simple_features/point.rb', line 22

def set_x_y_z(x,y,z)
  @x=x
  @y=y
  @z=z
  self
end

#spherical_distance(point, radius = 6370997.0) ⇒ Object

Returns the sperical distance in m, with a radius of 6471000m, with the haversine law. Assumes x is the lon and y the lat, in degrees (Changed in version 1.1). The user has to make sure using this distance makes sense (ie she should be in latlon coordinates)



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/geo_ruby/simple_features/point.rb', line 44

def spherical_distance(point,radius=6370997.0)
  deg_to_rad = 0.0174532925199433
  
  radlat_from = lat * deg_to_rad
  radlat_to = point.lat * deg_to_rad
  
  dlat = (point.lat - lat) * deg_to_rad
  dlon = (point.lon - lon) * deg_to_rad
 
  a = Math.sin(dlat/2)**2 + Math.cos(radlat_from) * Math.cos(radlat_to) * Math.sin(dlon/2)**2
  c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
  radius * c
end

#text_geometry_typeObject

WKT geometry type of a point



151
152
153
# File 'lib/geo_ruby/simple_features/point.rb', line 151

def text_geometry_type #:nodoc:

  "POINT"
end

#text_representation(allow_z = true, allow_m = true) ⇒ Object

text representation of a point



144
145
146
147
148
149
# File 'lib/geo_ruby/simple_features/point.rb', line 144

def text_representation(allow_z=true,allow_m=true) #:nodoc:

  tex_rep = "#{@x} #{@y}"
  tex_rep += " #{@z}" if @with_z and allow_z
  tex_rep += " #{@m}" if @with_m and allow_m
  tex_rep
end