Class: Geos::CoordinateSequence

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ffi-geos/coordinate_sequence.rb

Overview

A CoordinateSequence is a list of coordinates in a Geometry.

Defined Under Namespace

Classes: CoordinateAccessor, ParseError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ CoordinateSequence

:call-seq:

new(ptr, auto_free = true, parent = nil)
new(size = 0, dimensions = 0)
new(options)
new(points)

The ptr version of the initializer is for internal use.

new(points) will try to glean the size and dimensions of your CoordinateSequence from an Array of points. The Array should contain uniform-sized Arrays which represent the [ x, y, z ] values of your coordinates.



58
59
60
61
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
107
108
109
110
111
112
113
114
115
116
# File 'lib/ffi-geos/coordinate_sequence.rb', line 58

def initialize(*args)
  points = nil # forward declaration we can use later

  ptr, auto_free, parent = if args.first.is_a?(FFI::Pointer)
    args.first(3)
  else
    size, dimensions = if args.first.is_a?(Array)
      points = if args.first.first.is_a?(Array)
        args.first
      else
        args
      end
      lengths = points.collect(&:length).uniq

      if lengths.empty?
        [ 0, 0 ]
      elsif lengths.length != 1
        raise ParseError.new("Different sized points found in Array")
      elsif !lengths.first.between?(1, 3)
        raise ParseError.new("Expected points to contain 1-3 elements")
      else
        [ points.length, points.first.length ]
      end
    elsif args.first.is_a?(Hash)
      args.first.values_at(:size, :dimensions)
    else
      if !args.length.between?(0, 2)
        raise ArgumentError.new("wrong number of arguments (#{args.length} for 0-2)")
      else
        [ args[0], args[1] ]
      end
    end

    size ||= 0
    dimensions ||= 0

    [ FFIGeos.GEOSCoordSeq_create_r(Geos.current_handle, size, dimensions), true ]
  end

  @ptr = FFI::AutoPointer.new(
    ptr,
    self.class.method(:release)
  )

  @ptr.autorelease = auto_free
  @parent = parent if parent

  @x = CoordinateAccessor.new(self, 0)
  @y = CoordinateAccessor.new(self, 1)
  @z = CoordinateAccessor.new(self, 2)

  if points
    points.each_with_index do |point, idx|
      point.each_with_index do |val, dim|
        self.set_ordinate(idx, dim, val)
      end
    end
  end
end

Instance Attribute Details

#ptrObject (readonly)

Returns the value of attribute ptr.



44
45
46
# File 'lib/ffi-geos/coordinate_sequence.rb', line 44

def ptr
  @ptr
end

#xObject (readonly)

Returns the value of attribute x.



44
45
46
# File 'lib/ffi-geos/coordinate_sequence.rb', line 44

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



44
45
46
# File 'lib/ffi-geos/coordinate_sequence.rb', line 44

def y
  @y
end

#zObject (readonly)

Returns the value of attribute z.



44
45
46
# File 'lib/ffi-geos/coordinate_sequence.rb', line 44

def z
  @z
end

Class Method Details

.release(ptr) ⇒ Object

:nodoc:



129
130
131
# File 'lib/ffi-geos/coordinate_sequence.rb', line 129

def self.release(ptr) #:nodoc:
  FFIGeos.GEOSCoordSeq_destroy_r(Geos.current_handle, ptr)
end

Instance Method Details

#[](*args) ⇒ Object Also known as: slice



148
149
150
151
152
153
154
155
156
157
# File 'lib/ffi-geos/coordinate_sequence.rb', line 148

def [](*args)
  if args.length == 1 && args.first.is_a?(Numeric) && args.first >= 0
    i = args.first
    ary = [ self.get_x(i), self.get_y(i) ]
    ary << self.get_z(i) if self.has_z?
    ary
  else
    self.to_a[*args]
  end
end

#dimensionsObject



229
230
231
232
233
234
235
236
237
# File 'lib/ffi-geos/coordinate_sequence.rb', line 229

def dimensions
  if defined?(@dimensions)
    @dimensions
  else
    int_ptr = FFI::MemoryPointer.new(:int)
    FFIGeos.GEOSCoordSeq_getDimensions_r(Geos.current_handle, self.ptr, int_ptr)
    @dimensions = int_ptr.read_int
  end
end

#eachObject

Yields coordinates as [ x, y, z ]. The z coordinate may be omitted for 2-dimensional CoordinateSequences.



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ffi-geos/coordinate_sequence.rb', line 135

def each
  if block_given?
    self.length.times do |n|
      yield self.build_coordinate(n)
    end
    self
  else
    self.length.times.collect { |n|
      self.build_coordinate(n)
    }.to_enum
  end
end

#empty?Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/ffi-geos/coordinate_sequence.rb', line 225

def empty?
  self.length == 0
end

#get_ordinate(idx, dim) ⇒ Object



211
212
213
214
215
216
# File 'lib/ffi-geos/coordinate_sequence.rb', line 211

def get_ordinate(idx, dim)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getOrdinate_r(Geos.current_handle, self.ptr, idx, dim, double_ptr)
  double_ptr.read_double
end

#get_x(idx) ⇒ Object

Gets the x value of a coordinate. Can also be retrieved via #x[].



188
189
190
191
192
193
# File 'lib/ffi-geos/coordinate_sequence.rb', line 188

def get_x(idx)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getX_r(Geos.current_handle, self.ptr, idx, double_ptr)
  double_ptr.read_double
end

#get_y(idx) ⇒ Object

Gets the y value of a coordinate. Can also be retrieved via #y[].



196
197
198
199
200
201
# File 'lib/ffi-geos/coordinate_sequence.rb', line 196

def get_y(idx)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getY_r(Geos.current_handle, self.ptr, idx, double_ptr)
  double_ptr.read_double
end

#get_z(idx) ⇒ Object

Gets the z value of a coordinate. Can also be retrieved via #z[].



204
205
206
207
208
209
# File 'lib/ffi-geos/coordinate_sequence.rb', line 204

def get_z(idx)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getZ_r(Geos.current_handle, self.ptr, idx, double_ptr)
  double_ptr.read_double
end

#has_z?Boolean

Returns:

  • (Boolean)


160
161
162
# File 'lib/ffi-geos/coordinate_sequence.rb', line 160

def has_z?
  self.dimensions == 3
end

#initialize_copy(source) ⇒ Object



118
119
120
121
122
123
124
125
126
127
# File 'lib/ffi-geos/coordinate_sequence.rb', line 118

def initialize_copy(source)
  @ptr = FFI::AutoPointer.new(
    FFIGeos.GEOSCoordSeq_clone_r(Geos.current_handle, source.ptr),
    self.class.method(:release)
  )

  @x = CoordinateAccessor.new(self, 0)
  @y = CoordinateAccessor.new(self, 1)
  @z = CoordinateAccessor.new(self, 2)
end

#lengthObject Also known as: size



218
219
220
221
222
# File 'lib/ffi-geos/coordinate_sequence.rb', line 218

def length
  int_ptr = FFI::MemoryPointer.new(:int)
  FFIGeos.GEOSCoordSeq_getSize_r(Geos.current_handle, self.ptr, int_ptr)
  int_ptr.read_int
end

#set_ordinate(idx, dim, val) ⇒ Object



182
183
184
185
# File 'lib/ffi-geos/coordinate_sequence.rb', line 182

def set_ordinate(idx, dim, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setOrdinate_r(Geos.current_handle, self.ptr, idx, dim, val.to_f)
end

#set_x(idx, val) ⇒ Object

Sets the x value of a coordinate. Can also be set via #x[]=.



165
166
167
168
# File 'lib/ffi-geos/coordinate_sequence.rb', line 165

def set_x(idx, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setX_r(Geos.current_handle, self.ptr, idx, val.to_f)
end

#set_y(idx, val) ⇒ Object

Sets the y value of a coordinate. Can also be set via #y[]=.



171
172
173
174
# File 'lib/ffi-geos/coordinate_sequence.rb', line 171

def set_y(idx, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setY_r(Geos.current_handle, self.ptr, idx, val.to_f)
end

#set_z(idx, val) ⇒ Object

Sets the z value of a coordinate. Can also be set via #z[]=.



177
178
179
180
# File 'lib/ffi-geos/coordinate_sequence.rb', line 177

def set_z(idx, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setZ_r(Geos.current_handle, self.ptr, idx, val.to_f)
end

#to_line_string(options = {}) ⇒ Object



247
248
249
# File 'lib/ffi-geos/coordinate_sequence.rb', line 247

def to_line_string(options = {})
  Geos.create_line_string(self, :srid => options[:srid])
end

#to_linear_ring(options = {}) ⇒ Object



243
244
245
# File 'lib/ffi-geos/coordinate_sequence.rb', line 243

def to_linear_ring(options = {})
  Geos.create_linear_ring(self, :srid => options[:srid])
end

#to_point(options = {}) ⇒ Object



239
240
241
# File 'lib/ffi-geos/coordinate_sequence.rb', line 239

def to_point(options = {})
  Geos.create_point(self, :srid => options[:srid])
end

#to_polygon(options = {}) ⇒ Object



251
252
253
# File 'lib/ffi-geos/coordinate_sequence.rb', line 251

def to_polygon(options = {})
  Geos.create_polygon(self, :srid => options[:srid])
end

#to_sObject



255
256
257
258
259
# File 'lib/ffi-geos/coordinate_sequence.rb', line 255

def to_s
  self.entries.collect { |entry|
    entry.join(' ')
  }.join(', ')
end