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.



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
117
# File 'lib/ffi-geos/coordinate_sequence.rb', line 59

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_pointer, 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.



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

def ptr
  @ptr
end

#xObject (readonly)

Returns the value of attribute x.



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

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



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

def y
  @y
end

#zObject (readonly)

Returns the value of attribute z.



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

def z
  @z
end

Class Method Details

.release(ptr) ⇒ Object

:nodoc:



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

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

Instance Method Details

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



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

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



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

def dimensions
  if defined?(@dimensions)
    @dimensions
  else
    int_ptr = FFI::MemoryPointer.new(:int)
    FFIGeos.GEOSCoordSeq_getDimensions_r(Geos.current_handle_pointer, 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.



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

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)


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

def empty?
  self.length == 0
end

#get_ordinate(idx, dim) ⇒ Object



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

def get_ordinate(idx, dim)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getOrdinate_r(Geos.current_handle_pointer, 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[].



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

def get_x(idx)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getX_r(Geos.current_handle_pointer, 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[].



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

def get_y(idx)
  self.check_bounds(idx)
  double_ptr = FFI::MemoryPointer.new(:double)
  FFIGeos.GEOSCoordSeq_getY_r(Geos.current_handle_pointer, 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[].



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

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

#has_z?Boolean

Returns:

  • (Boolean)


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

def has_z?
  self.dimensions == 3
end

#initialize_copy(source) ⇒ Object



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

def initialize_copy(source)
  @ptr = FFI::AutoPointer.new(
    FFIGeos.GEOSCoordSeq_clone_r(Geos.current_handle_pointer, 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



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

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

#set_ordinate(idx, dim, val) ⇒ Object



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

def set_ordinate(idx, dim, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setOrdinate_r(Geos.current_handle_pointer, 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[]=.



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

def set_x(idx, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setX_r(Geos.current_handle_pointer, 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[]=.



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

def set_y(idx, val)
  self.check_bounds(idx)
  FFIGeos.GEOSCoordSeq_setY_r(Geos.current_handle_pointer, 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[]=.



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

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

#to_line_string(options = {}) ⇒ Object



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

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

#to_linear_ring(options = {}) ⇒ Object



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

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

#to_point(options = {}) ⇒ Object



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

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

#to_polygon(options = {}) ⇒ Object



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

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

#to_sObject



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

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