Class: GeoRuby::SimpleFeatures::LineString

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

Overview

Represents a line string as an array of points (see Point).

Direct Known Subclasses

LinearRing

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_geojson, from_georss, from_georss_with_tags, from_hex_ewkb, from_kml, #to_json

Constructor Details

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


10
11
12
13
# File 'lib/geo_ruby/simple_features/line_string.rb', line 10

def initialize(srid = DEFAULT_SRID, with_z = false, with_m = false)
  super(srid, with_z, with_m)
  @points = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &b) ⇒ Object

Delegate the unknown methods to the points array


16
17
18
# File 'lib/geo_ruby/simple_features/line_string.rb', line 16

def method_missing(method_name, *args, &b)
  @points.send(method_name, *args, &b)
end

Instance Attribute Details

#pointsObject (readonly)

the list of points forming the line string


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

def points
  @points
end

Class Method Details

.from_coordinates(points, srid = DEFAULT_SRID, z = false, m = false) ⇒ Object

Creates a new line string. Accept a sequence of points as argument:

((x,y)...(x,y))

217
218
219
220
221
# File 'lib/geo_ruby/simple_features/line_string.rb', line 217

def self.from_coordinates(points, srid = DEFAULT_SRID, z = false, m = false)
  line_string = new(srid, z, m)
  line_string.concat(points.map { |p| Point.from_coordinates(p, srid, z, m) })
  line_string
end

.from_points(points, srid = DEFAULT_SRID, z = false, m = false) ⇒ Object

Creates a new line string. Accept an array of points as argument


209
210
211
212
213
# File 'lib/geo_ruby/simple_features/line_string.rb', line 209

def self.from_points(points, srid = DEFAULT_SRID, z = false, m = false)
  line_string = new(srid, z, m)
  line_string.concat(points)
  line_string
end

Instance Method Details

#==(other) ⇒ Object

Tests the equality of line strings


95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/geo_ruby/simple_features/line_string.rb', line 95

def ==(other)
  if other.class != self.class ||
     other.length != length
    false
  else
    index = 0
    while index < length
      return false if self[index] != other[index]
      index += 1
    end
    true
  end
end

#as_json(_options = {}) ⇒ Object


204
205
206
# File 'lib/geo_ruby/simple_features/line_string.rb', line 204

def as_json(_options = {})
  { type: 'LineString', coordinates: to_coordinates }
end

#binary_geometry_typeObject

WKB geometry type


117
118
119
# File 'lib/geo_ruby/simple_features/line_string.rb', line 117

def binary_geometry_type #:nodoc:
  2
end

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

Binary representation of a line string


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

def binary_representation(allow_z = true, allow_m = true) #:nodoc:
  rep = [length].pack('V')
  each { |point| rep << point.binary_representation(allow_z, allow_m) }
  rep
end

#bounding_boxObject

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


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/geo_ruby/simple_features/line_string.rb', line 36

def bounding_box
  max_x = max_y = -Float::MAX
  min_x = min_y = Float::MAX
  if with_z
    max_z, min_z = -Float::MAX, Float::MAX
    each do |point|
      max_y = point.y if point.y > max_y
      min_y = point.y if point.y < min_y
      max_x = point.x if point.x > max_x
      min_x = point.x if point.x < min_x
      max_z = point.z if point.z > max_z
      min_z = point.z if point.z < min_z
    end
    [Point.from_x_y_z(min_x, min_y, min_z), Point.from_x_y_z(max_x, max_y, max_z)]
  else
    each do |point|
      max_y = point.y if point.y > max_y
      min_y = point.y if point.y < min_y
      max_x = point.x if point.x > max_x
      min_x = point.x if point.x < min_x
    end
    [Point.from_x_y(min_x, min_y), Point.from_x_y(max_x, max_y)]
  end
end

#clockwise?Boolean


26
27
28
29
30
31
32
33
# File 'lib/geo_ruby/simple_features/line_string.rb', line 26

def clockwise?
  tuples = @points.zip(
    @points[1..-1] + [@points[0]],
    @points[2..-1] + [@points[0], @points[1]])
  tuples.map! { |a, b, c| b.x * (c.y - a.y)  }
  sum = tuples.reduce(0.0) { |a, e| a + e }
  sum < 0.0
end

#closed?Boolean

tests if the line string is closed


21
22
23
24
# File 'lib/geo_ruby/simple_features/line_string.rb', line 21

def closed?  # a bit naive...

  @points.first == @points.last
end

#do_simplify(list, epsilon) ⇒ Object


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

def do_simplify(list, epsilon)
  index = dmax = 0
  2.upto(list.length - 1) do |i|
    d = list[i].orthogonal_distance(list[0], list[-1])
    index, dmax = i, d if d > dmax
  end
  return [list[0], list[-1]] if dmax < epsilon
  res1 = do_simplify(list[0..index], epsilon)
  res2 = do_simplify(list[index..-1], epsilon)
  res1[0..-2] + res2[0..-1]
end

#euclidian_distanceObject


86
87
88
89
90
91
92
# File 'lib/geo_ruby/simple_features/line_string.rb', line 86

def euclidian_distance
  total = 0
  @points.each_with_index do |p, i|
    total += p.euclidian_distance(@points[i + 1]) if @points[i + 1]
  end
  total
end

#georss_gml_representation(options) ⇒ Object

georss gml representation


145
146
147
148
149
150
151
152
# File 'lib/geo_ruby/simple_features/line_string.rb', line 145

def georss_gml_representation(options) #:nodoc:
  georss_ns = options[:georss_ns] || 'georss'
  gml_ns = options[:gml_ns] || 'gml'

  "<#{georss_ns}:where>\n<#{gml_ns}:LineString>\n<#{gml_ns}:posList>\n" \
  "#{georss_poslist}\n</#{gml_ns}:posList>\n</#{gml_ns}:LineString>\n" \
  "</#{georss_ns}:where>\n"
end

#georss_poslistObject

:nodoc:


154
155
156
# File 'lib/geo_ruby/simple_features/line_string.rb', line 154

def georss_poslist #:nodoc:
  map { |point| "#{point.y} #{point.x}" }.join(' ')
end

#georss_simple_representation(options) ⇒ Object

georss simple representation


131
132
133
134
135
# File 'lib/geo_ruby/simple_features/line_string.rb', line 131

def georss_simple_representation(options) #:nodoc:
  georss_ns = options[:georss_ns] || 'georss'
  geom_attr = options[:geom_attr]
  "<#{georss_ns}:line#{geom_attr}>#{georss_poslist}</#{georss_ns}:line>\n"
end

#georss_w3cgeo_representation(options) ⇒ Object

georss w3c representation : outputs the first point of the line


138
139
140
141
142
# File 'lib/geo_ruby/simple_features/line_string.rb', line 138

def georss_w3cgeo_representation(options) #:nodoc:
  w3cgeo_ns = options[:w3cgeo_ns] || 'geo'
  "<#{w3cgeo_ns}:lat>#{self[0].y}</#{w3cgeo_ns}:lat>\n"\
  "<#{w3cgeo_ns}:long>#{self[0].x}</#{w3cgeo_ns}:long>\n"
end

#intersects?(_other_line_string) ⇒ Boolean

call to native Geo intersect, return true or false


75
76
# File 'lib/geo_ruby/simple_features/line_string.rb', line 75

def intersects?(_other_line_string)
end

#kml_poslist(options) ⇒ Object

:nodoc:


171
172
173
174
175
176
177
178
179
180
# File 'lib/geo_ruby/simple_features/line_string.rb', line 171

def kml_poslist(options) #:nodoc:
  pos_list = \
  if options[:allow_z]
    map { |point| "#{point.x},#{point.y},#{options[:fixed_z] || point.z || 0}" }
  else
    map { |point| "#{point.x},#{point.y}" }
  end
  pos_list.reverse! if options[:reverse]
  pos_list.join(' ')
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: clampToGround is the default)


162
163
164
165
166
167
168
169
# File 'lib/geo_ruby/simple_features/line_string.rb', line 162

def kml_representation(options = {}) #:nodoc:
  result = "<LineString#{options[:id_attr]}>\n"
  result += options[:geom_data] if options[:geom_data]
  result += '<coordinates>'
  result += kml_poslist(options)
  result += "</coordinates>\n"
  result + "</LineString>\n"
end

#m_rangeObject


61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/geo_ruby/simple_features/line_string.rb', line 61

def m_range
  if with_m
    max_m, min_m = -Float::MAX, Float::MAX
    each do |point|
      max_m = point.m if point.m.to_f > max_m
      min_m = point.m if point.m.to_f < min_m
    end
    [min_m, max_m]
  else
    [0, 0]
  end
end

#simplify(epsilon = 1) ⇒ Object

Simplify linestring (Douglas Peucker Algorithm) en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm


184
185
186
# File 'lib/geo_ruby/simple_features/line_string.rb', line 184

def simplify(epsilon = 1)
  LineString.from_points(do_simplify(@points, epsilon))
end

#spherical_distanceObject


78
79
80
81
82
83
84
# File 'lib/geo_ruby/simple_features/line_string.rb', line 78

def spherical_distance
  total = 0
  @points.each_with_index do |p, i|
    total += p.spherical_distance(@points[i + 1]) if @points[i + 1]
  end
  total
end

#text_geometry_typeObject

WKT geometry type


126
127
128
# File 'lib/geo_ruby/simple_features/line_string.rb', line 126

def text_geometry_type #:nodoc:
  'LINESTRING'
end

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

Text representation of a line string


122
123
124
# File 'lib/geo_ruby/simple_features/line_string.rb', line 122

def text_representation(allow_z = true, allow_m = true) #:nodoc:
  @points.collect { |point| point.text_representation(allow_z, allow_m) }.join(',')
end

#to_coordinatesObject


200
201
202
# File 'lib/geo_ruby/simple_features/line_string.rb', line 200

def to_coordinates
  points.map(&:to_coordinates)
end