Class: OGR::Feature

Inherits:
Object
  • Object
show all
Includes:
Extensions
Defined in:
lib/ogr/feature.rb,
lib/ogr/extensions/feature/extensions.rb

Defined Under Namespace

Modules: Extensions

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Extensions

#each_field, #each_geometry_field, #each_geometry_field_definition, #field, #fields, #geometry_field_definitions, #geometry_fields

Constructor Details

#initialize(fd_or_pointer) ⇒ Feature

Returns a new instance of Feature.

Parameters:

  • fd_or_pointer (OGR::FeatureDefinition, FFI::Pointer)

    Must either be a FeatureDefinition (i.e. normal Feature creation) or a Pointer (in the case a handle to a C OGR Feature needs to be wrapped with this object).



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/ogr/feature.rb', line 22

def initialize(fd_or_pointer)
  pointer = case fd_or_pointer
            when OGR::FeatureDefinition then FFI::OGR::API.OGR_F_Create(fd_or_pointer.c_pointer)
            when FFI::Pointer
              fd_or_pointer.autorelease = false
              fd_or_pointer
            else
              raise OGR::InvalidFeature, "OGR::Feature must be instantiated with valid feature"
            end

  if !pointer.is_a?(FFI::Pointer) || pointer.null?
    raise OGR::InvalidFeature, "Unable to create Feature with #{fd_or_pointer}"
  end

  # pointer.autorelease = false

  # @c_pointer = FFI::AutoPointer.new(pointer, Feature.method(:release))
  @c_pointer = pointer
end

Instance Attribute Details

#c_pointerFFI::Pointer (readonly)

Returns C pointer of the C Feature.

Returns:

  • (FFI::Pointer)

    C pointer of the C Feature.



17
18
19
# File 'lib/ogr/feature.rb', line 17

def c_pointer
  @c_pointer
end

Class Method Details

.release(pointer) ⇒ Object

Parameters:

  • pointer (FFI::Pointer)


10
11
12
13
14
# File 'lib/ogr/feature.rb', line 10

def self.release(pointer)
  return unless pointer && !pointer.null?

  FFI::OGR::API.OGR_F_Destroy(pointer)
end

Instance Method Details

#cloneOGR::Feature

Returns:

Raises:



50
51
52
53
54
55
56
# File 'lib/ogr/feature.rb', line 50

def clone
  # This new feature is owned by the caller and must be released accordingly.
  feature_ptr = FFI::OGR::API.OGR_F_Clone(@c_pointer)
  raise OGR::Failure, "Unable to clone feature" if feature_ptr.nil?

  OGR::Feature.new(feature_ptr)
end

#definitionOGR::FeatureDefinition?

Returns:



225
226
227
228
229
230
231
232
# File 'lib/ogr/feature.rb', line 225

def definition
  feature_defn_ptr = FFI::OGR::API.OGR_F_GetDefnRef(@c_pointer)
  feature_defn_ptr.autorelease = false

  return nil if feature_defn_ptr.null?

  OGR::FeatureDefinition.new(feature_defn_ptr)
end

#destroy!Object



42
43
44
45
46
# File 'lib/ogr/feature.rb', line 42

def destroy!
  Feature.release(@c_pointer)

  @c_pointer = nil
end

#dump_readable(file_path = nil) ⇒ Object

Dumps the feature out to the file in human-readable form.

Parameters:

  • file_path (String) (defaults to: nil)


61
62
63
64
65
# File 'lib/ogr/feature.rb', line 61

def dump_readable(file_path = nil)
  file_ptr = file_path ? FFI::CPL::Conv.CPLOpenShared(file_path, "w", false) : nil
  FFI::OGR::API.OGR_F_DumpReadable(@c_pointer, file_ptr)
  FFI::CPL::Conv.CPLCloseShared(file_ptr) if file_ptr
end

#equal?(other) ⇒ Boolean Also known as: equals?

Returns:

  • (Boolean)


372
373
374
# File 'lib/ogr/feature.rb', line 372

def equal?(other)
  FFI::OGR::API.OGR_F_Equal(@c_pointer, c_pointer_from(other))
end

#fidInteger

Returns:



281
282
283
# File 'lib/ogr/feature.rb', line 281

def fid
  FFI::OGR::API.OGR_F_GetFID(@c_pointer)
end

#fid=(new_fid) ⇒ Object

Parameters:

Raises:



287
288
289
290
291
# File 'lib/ogr/feature.rb', line 287

def fid=(new_fid)
  OGR::ErrorHandling.handle_ogr_err("Unable to set FID") do
    FFI::OGR::API.OGR_F_SetFID(@c_pointer, new_fid)
  end
end

#field_as_binary(index) ⇒ String

Parameters:

Returns:



438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/ogr/feature.rb', line 438

def field_as_binary(index)
  byte_count_ptr = FFI::MemoryPointer.new(:int)

  # This list is internal, and should not be modified, or freed. Its lifetime may be very brief.
  binary_data_ptr = FFI::OGR::API.OGR_F_GetFieldAsBinary(@c_pointer, index, byte_count_ptr)
  binary_data_ptr.autorelease = false

  byte_count = byte_count_ptr.read_int
  string = byte_count.positive? ? binary_data_ptr.read_bytes(byte_count) : ""

  string.unpack("C*")
end

#field_as_date_time(index) ⇒ Object



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
# File 'lib/ogr/feature.rb', line 451

def field_as_date_time(index)
  year_ptr = FFI::MemoryPointer.new(:int)
  month_ptr = FFI::MemoryPointer.new(:int)
  day_ptr = FFI::MemoryPointer.new(:int)
  hour_ptr = FFI::MemoryPointer.new(:int)
  minute_ptr = FFI::MemoryPointer.new(:int)
  second_ptr = FFI::MemoryPointer.new(:int)
  time_zone_flag_ptr = FFI::MemoryPointer.new(:int)

  success = FFI::OGR::API.OGR_F_GetFieldAsDateTime(
    @c_pointer,
    index,
    year_ptr,
    month_ptr,
    day_ptr,
    hour_ptr,
    minute_ptr,
    second_ptr,
    time_zone_flag_ptr
  )
  return nil unless success

  formatted_tz = OGR._format_time_zone_for_ruby(time_zone_flag_ptr.read_int)

  if formatted_tz
    DateTime.new(
      year_ptr.read_int,
      month_ptr.read_int,
      day_ptr.read_int,
      hour_ptr.read_int,
      minute_ptr.read_int,
      second_ptr.read_int,
      formatted_tz
    )
  else
    DateTime.new(
      year_ptr.read_int,
      month_ptr.read_int,
      day_ptr.read_int,
      hour_ptr.read_int,
      minute_ptr.read_int,
      second_ptr.read_int
    )
  end
end

#field_as_double(index) ⇒ Float

Parameters:

Returns:



398
399
400
# File 'lib/ogr/feature.rb', line 398

def field_as_double(index)
  FFI::OGR::API.OGR_F_GetFieldAsDouble(@c_pointer, index)
end

#field_as_double_list(index) ⇒ Array<Float>

Parameters:

Returns:



404
405
406
407
408
409
410
411
412
413
# File 'lib/ogr/feature.rb', line 404

def field_as_double_list(index)
  list_size_ptr = FFI::MemoryPointer.new(:int)
  # This list is internal, and should not be modified, or freed. Its lifetime may be very brief.
  list_ptr = FFI::OGR::API.OGR_F_GetFieldAsDoubleList(@c_pointer, index, list_size_ptr)
  list_ptr.autorelease = false

  return [] if list_ptr.null?

  list_ptr.read_array_of_double(list_size_ptr.read_int)
end

#field_as_integer(index) ⇒ Integer

Parameters:

Returns:



379
380
381
# File 'lib/ogr/feature.rb', line 379

def field_as_integer(index)
  FFI::OGR::API.OGR_F_GetFieldAsInteger(@c_pointer, index)
end

#field_as_integer_list(index) ⇒ Array<Integer>

Parameters:

Returns:



385
386
387
388
389
390
391
392
393
394
# File 'lib/ogr/feature.rb', line 385

def field_as_integer_list(index)
  list_size_ptr = FFI::MemoryPointer.new(:int)
  #  This list is internal, and should not be modified, or freed. Its lifetime may be very brief.
  list_ptr = FFI::OGR::API.OGR_F_GetFieldAsIntegerList(@c_pointer, index, list_size_ptr)
  list_ptr.autorelease = false

  return [] if list_ptr.null?

  list_ptr.read_array_of_int(list_size_ptr.read_int)
end

#field_as_string(index) ⇒ String

Parameters:

Returns:



417
418
419
420
421
422
# File 'lib/ogr/feature.rb', line 417

def field_as_string(index)
  field, ptr = FFI::OGR::API.OGR_F_GetFieldAsString(@c_pointer, index)
  ptr.autorelease = false

  field.force_encoding(Encoding::UTF_8)
end

#field_as_string_list(index) ⇒ Array<String>

Parameters:

Returns:



426
427
428
429
430
431
432
433
434
# File 'lib/ogr/feature.rb', line 426

def field_as_string_list(index)
  # This list is internal, and should not be modified, or freed. Its lifetime may be very brief.
  list_ptr = FFI::OGR::API.OGR_F_GetFieldAsStringList(@c_pointer, index)
  list_ptr.autorelease = false

  return [] if list_ptr.null?

  list_ptr.get_array_of_string(0)
end

#field_countInteger

This will always be the same as the field count for the feature definition.

Returns:



88
89
90
# File 'lib/ogr/feature.rb', line 88

def field_count
  FFI::OGR::API.OGR_F_GetFieldCount(@c_pointer)
end

#field_definition(index) ⇒ OGR::FieldDefinition

NOTE: Do not modify the FieldDefinition that’s returned here.

Parameters:

Returns:



195
196
197
198
199
200
201
202
203
# File 'lib/ogr/feature.rb', line 195

def field_definition(index)
  # This returns an internal reference and should not be deleted or modified
  field_pointer = FFI::OGR::API.OGR_F_GetFieldDefnRef(@c_pointer, index)
  field_pointer.autorelease = false

  return nil if field_pointer.null?

  OGR::FieldDefinition.new(field_pointer, nil)
end

#field_index(name) ⇒ Integer?

Parameters:

Returns:



207
208
209
210
211
# File 'lib/ogr/feature.rb', line 207

def field_index(name)
  result = FFI::OGR::API.OGR_F_GetFieldIndex(@c_pointer, name)

  result.negative? ? nil : result
end

#field_set?(index) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


215
216
217
# File 'lib/ogr/feature.rb', line 215

def field_set?(index)
  FFI::OGR::API.OGR_F_IsFieldSet(@c_pointer, index)
end

#geometryOGR::Geometry

NOTE: Do not modify the Geometry that’s returned here.

Returns:



237
238
239
240
241
242
243
244
245
# File 'lib/ogr/feature.rb', line 237

def geometry
  # This returns an internal reference and should not be deleted or modified
  geometry_ptr = FFI::OGR::API.OGR_F_GetGeometryRef(@c_pointer)
  geometry_ptr.autorelease = false

  return nil if geometry_ptr.null?

  OGR::Geometry.factory(geometry_ptr)
end

#geometry_field(index) ⇒ OGR::Geometry?

NOTE: Do not modify the Geometry that’s returned here.

Parameters:

Returns:



330
331
332
333
334
335
336
337
338
# File 'lib/ogr/feature.rb', line 330

def geometry_field(index)
  # This returns an internal reference and should not be deleted or modified
  geometry_ptr = FFI::OGR::API.OGR_F_GetGeomFieldRef(@c_pointer, index)
  geometry_ptr.autorelease = false

  return nil if geometry_ptr.nil? || geometry_ptr.null?

  OGR::Geometry.factory(geometry_ptr)
end

#geometry_field_countInteger

The number of Geometries in this feature.

Returns:



296
297
298
# File 'lib/ogr/feature.rb', line 296

def geometry_field_count
  FFI::OGR::API.OGR_F_GetGeomFieldCount(@c_pointer)
end

#geometry_field_definition(index) ⇒ OGR::GeometryFieldDefinition

NOTE: Do not modify the GeometryFieldDefinition that’s returned here.

Parameters:

Returns:

Raises:



307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/ogr/feature.rb', line 307

def geometry_field_definition(index)
  # This returns an internal reference and should not be deleted or modified
  gfd_ptr = FFI::OGR::API.OGR_F_GetGeomFieldDefnRef(@c_pointer, index)
  gfd_ptr.autorelease = false

  return nil if gfd_ptr.nil?

  gfd = OGR::GeometryFieldDefinition.new(gfd_ptr)
  gfd.read_only = true

  gfd
end

#geometry_field_index(name) ⇒ Integer

Parameters:

Returns:



322
323
324
# File 'lib/ogr/feature.rb', line 322

def geometry_field_index(name)
  FFI::OGR::API.OGR_F_GetGeomFieldIndex(@c_pointer, name)
end

#set_field_binary(index, value) ⇒ Object

Parameters:

Raises:

  • (TypeError)


161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/ogr/feature.rb', line 161

def set_field_binary(index, value)
  raise TypeError, "value must be a binary string" unless value.is_a? String

  value_ptr = FFI::MemoryPointer.new(:uchar, value.length)
  value_ptr.put_bytes(0, value)

  FFI::OGR::API.OGR_F_SetFieldBinary(
    @c_pointer,
    index,
    value.length,
    value_ptr
  )
end

#set_field_date_time(index, value) ⇒ Object

Parameters:

  • index (Integer)
  • value (Date, Time, DateTime)


177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/ogr/feature.rb', line 177

def set_field_date_time(index, value)
  time = value.to_time
  zone = OGR._format_time_zone_for_ogr(value.zone)

  FFI::OGR::API.OGR_F_SetFieldDateTime(@c_pointer, index,
                                       time.year,
                                       time.month,
                                       time.day,
                                       time.hour,
                                       time.min,
                                       time.sec,
                                       zone)
end

#set_field_double(index, value) ⇒ Object

Parameters:



106
107
108
# File 'lib/ogr/feature.rb', line 106

def set_field_double(index, value)
  FFI::OGR::API.OGR_F_SetFieldDouble(@c_pointer, index, value)
end

#set_field_double_list(index, values) ⇒ Object

Parameters:



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ogr/feature.rb', line 139

def set_field_double_list(index, values)
  values_ptr = FFI::MemoryPointer.new(:double, values.size)
  values_ptr.write_array_of_double(values)

  FFI::OGR::API.OGR_F_SetFieldDoubleList(
    @c_pointer,
    index,
    values.size,
    values_ptr
  )
end

#set_field_integer(index, value) ⇒ Object

Parameters:



100
101
102
# File 'lib/ogr/feature.rb', line 100

def set_field_integer(index, value)
  FFI::OGR::API.OGR_F_SetFieldInteger(@c_pointer, index, value)
end

#set_field_integer_list(index, values) ⇒ Object

Parameters:



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/ogr/feature.rb', line 125

def set_field_integer_list(index, values)
  values_ptr = FFI::MemoryPointer.new(:int, values.size)
  values_ptr.write_array_of_int(values)

  FFI::OGR::API.OGR_F_SetFieldIntegerList(
    @c_pointer,
    index,
    values.size,
    values_ptr
  )
end

#set_field_raw(index, field) ⇒ Object

Parameters:



153
154
155
156
157
# File 'lib/ogr/feature.rb', line 153

def set_field_raw(index, field)
  usable_raw_field = field.c_struct

  FFI::OGR::API.OGR_F_SetFieldRaw(@c_pointer, index, usable_raw_field)
end

#set_field_string(index, value) ⇒ Object

Parameters:



94
95
96
# File 'lib/ogr/feature.rb', line 94

def set_field_string(index, value)
  FFI::OGR::API.OGR_F_SetFieldString(@c_pointer, index, value)
end

#set_field_string_list(index, values) ⇒ Object

Parameters:

Raises:



113
114
115
116
117
118
119
120
121
# File 'lib/ogr/feature.rb', line 113

def set_field_string_list(index, values)
  values_ptr = GDAL._string_array_to_pointer(values)

  FFI::OGR::API.OGR_F_SetFieldStringList(
    @c_pointer,
    index,
    values_ptr
  )
end

#set_from!(_other_feature, _be_forgiving: false, with_map: nil) ⇒ Object

Overwrites the contents of this feature from the geometry and attributes of the other_feature.

TODO: Implement with_map

Parameters:

  • _other_feature (OGR::Feature)
  • _be_forgiving (Boolean) (defaults to: false)

    true if the operation should continue despite lacking output fields matching some of the source fields.

  • with_map (Array<Integer>) (defaults to: nil)

Raises:



76
77
78
79
80
81
82
# File 'lib/ogr/feature.rb', line 76

def set_from!(_other_feature, _be_forgiving: false, with_map: nil)
  raise NotImplementedError, "with_map: is not yet supported" if with_map

  OGR::ErrorHandling.handle_ogr_err("Unable to set from other feature") do
    FFI::OGR::API.OGR_F_SetFrom(@c_pointer, other_feature_ptr)
  end
end

#set_geometry(new_geometry) ⇒ Object

Sets the geometry of the feature by making a copy of new_geometry.

Parameters:

Raises:



251
252
253
254
255
# File 'lib/ogr/feature.rb', line 251

def set_geometry(new_geometry) # rubocop:disable Naming/AccessorMethodName
  OGR::ErrorHandling.handle_ogr_err("Unable to set geometry on feature") do
    FFI::OGR::API.OGR_F_SetGeometry(@c_pointer, new_geometry.c_pointer)
  end
end

#set_geometry_directly(new_geometry) ⇒ Object Also known as: geometry=

Sets the geometry of the feature by taking ownership of +new_geometry.

Parameters:

Raises:



261
262
263
264
265
266
267
# File 'lib/ogr/feature.rb', line 261

def set_geometry_directly(new_geometry) # rubocop:disable Naming/AccessorMethodName
  new_geometry.c_pointer.autorelease = false

  OGR::ErrorHandling.handle_ogr_err("Unable to set geometry directly on feature") do
    FFI::OGR::API.OGR_F_SetGeometryDirectly(@c_pointer, new_geometry.c_pointer)
  end
end

#set_geometry_field(index, geometry) ⇒ Object

Sets the feature geometry of a specified geometry field by making a copy of geometry.

Parameters:

Raises:



346
347
348
349
350
351
352
353
# File 'lib/ogr/feature.rb', line 346

def set_geometry_field(index, geometry)
  geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
  raise OGR::InvalidGeometry if geometry_ptr.nil?

  OGR::ErrorHandling.handle_ogr_err("Unable to set geometry field at index #{index}") do
    FFI::OGR::API.OGR_F_SetGeomField(@c_pointer, index, geometry_ptr)
  end
end

#set_geometry_field_directly(index, geometry) ⇒ Object

Sets the feature geometry of a specified geometry field by taking ownership of geometry.

Parameters:

Raises:



361
362
363
364
365
366
367
368
369
# File 'lib/ogr/feature.rb', line 361

def set_geometry_field_directly(index, geometry)
  geometry_ptr = GDAL._pointer(OGR::Geometry, geometry, autorelease: false)

  raise OGR::InvalidGeometry if geometry_ptr.nil?

  OGR::ErrorHandling.handle_ogr_err("Unable to set geometry field directly at index #{index}") do
    FFI::OGR::API.OGR_F_SetGeomFieldDirectly(@c_pointer, index, geometry_ptr)
  end
end

#steal_geometryOGR::Geometry

Takes away ownership of the Feature’s Geometry and returns it to the caller.

Returns:

Raises:



273
274
275
276
277
278
# File 'lib/ogr/feature.rb', line 273

def steal_geometry
  geometry_ptr = FFI::OGR::API.OGR_F_StealGeometry(@c_pointer)
  raise OGR::Failure, "Unable to steal geometry." if geometry_ptr.nil? || geometry_ptr.null?

  OGR::Geometry.factory(geometry_ptr)
end

#style_stringString

Returns:



498
499
500
501
502
503
# File 'lib/ogr/feature.rb', line 498

def style_string
  style, ptr = FFI::OGR::API.OGR_F_GetStyleString(@c_pointer)
  ptr.autorelease = false

  style
end

#style_string=(new_style) ⇒ Object

Parameters:



506
507
508
# File 'lib/ogr/feature.rb', line 506

def style_string=(new_style)
  FFI::OGR::API.OGR_F_SetStyleString(@c_pointer, new_style)
end

#style_tableOGR::StyleTable

Returns:



511
512
513
514
515
516
517
518
# File 'lib/ogr/feature.rb', line 511

def style_table
  style_table_ptr = FFI::OGR::API.OGR_F_GetStyleTable(@c_pointer)
  style_table_ptr.autorelease = false

  return nil if style_table_ptr.nil? || style_table_ptr.null?

  OGR::StyleTable.new(style_table_ptr)
end

#style_table=(new_style_table) ⇒ Object

Parameters:

Raises:



521
522
523
524
525
526
527
# File 'lib/ogr/feature.rb', line 521

def style_table=(new_style_table)
  new_style_table_ptr = GDAL._pointer(OGR::StyleTable, new_style_table, autorelease: false)

  raise OGR::InvalidStyleTable unless new_style_table_ptr

  FFI::OGR::API.OGR_F_SetStyleTableDirectly(@c_pointer, new_style_table_ptr)
end

#unset_field(index) ⇒ Object

Parameters:



220
221
222
# File 'lib/ogr/feature.rb', line 220

def unset_field(index)
  FFI::OGR::API.OGR_F_UnsetField(@c_pointer, index)
end