Module: OGR::Layer::Extensions
- Included in:
- OGR::Layer
- Defined in:
- lib/ogr/extensions/layer/extensions.rb
Overview
Methods not part of the C Layer API.
Instance Method Summary collapse
-
#any_geometries_with_z? ⇒ Boolean
Iterates through features to see if any of them are 3d.
-
#each_feature {|| ... } ⇒ Enumerator
Enumerates through all associated features.
- #each_feature_pointer {|A| ... } ⇒ Enumerator
-
#features ⇒ Array<OGR::Feature>
Returns all features as an Array.
-
#geometry_from_extent ⇒ OGR::Polygon
A polygon derived from a LinearRing that connects the 4 bounding box points (from the extent).
-
#point_values(with_attributes = {}) ⇒ Array<Array>
Iterates through all geometries in the Layer and extracts the point values to an Array.
Instance Method Details
#any_geometries_with_z? ⇒ Boolean
Iterates through features to see if any of them are 3d.
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/ogr/extensions/layer/extensions.rb', line 224 def any_geometries_with_z? found_z_geom = false each_feature_pointer do |feature_ptr| break if found_z_geom geom_ptr = FFI::OGR::API.OGR_F_GetGeometryRef(feature_ptr) geom_ptr.autorelease = false coordinate_dimension = FFI::OGR::API.OGR_G_GetCoordinateDimension(geom_ptr) found_z_geom = coordinate_dimension == 3 end feature.destroy! if feature.c_pointer found_z_geom end |
#each_feature {|| ... } ⇒ Enumerator
Enumerates through all associated features. Beware: it calls OGR::LayerMixins::OGRFeatureMethods#reset_reading both before and after it’s called. If you’re using OGR::LayerMixins::OGRFeatureMethods#next_feature for iterating through features somewhere in your code, this will reset that reading.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/ogr/extensions/layer/extensions.rb', line 16 def each_feature return enum_for(:each_feature) unless block_given? FFI::OGR::API.OGR_L_ResetReading(@c_pointer) loop do feature = next_feature break unless feature begin yield feature rescue StandardError feature.destroy! raise end feature.destroy! end FFI::OGR::API.OGR_L_ResetReading(@c_pointer) end |
#each_feature_pointer {|A| ... } ⇒ Enumerator
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/ogr/extensions/layer/extensions.rb', line 40 def each_feature_pointer return enum_for(:each_feature_pointer) unless block_given? FFI::OGR::API.OGR_L_ResetReading(@c_pointer) loop do feature_ptr = FFI::OGR::API.OGR_L_GetNextFeature(@c_pointer) if feature_ptr.null? FFI::OGR::API.OGR_F_Destroy(feature_ptr) break end begin yield feature_ptr rescue StandardError FFI::OGR::API.OGR_F_Destroy(feature_ptr) raise end FFI::OGR::API.OGR_F_Destroy(feature_ptr) end FFI::OGR::API.OGR_L_ResetReading(@c_pointer) end |
#features ⇒ Array<OGR::Feature>
Returns all features as an Array. Note that if you just want to iterate through features, OGR::Layer::Extensions.{{#each_feature} will perform better.
70 71 72 |
# File 'lib/ogr/extensions/layer/extensions.rb', line 70 def features each_feature.map(&:clone) end |
#geometry_from_extent ⇒ OGR::Polygon
Returns A polygon derived from a LinearRing that connects the 4 bounding box points (from the extent).
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/ogr/extensions/layer/extensions.rb', line 76 def geometry_from_extent ring = OGR::LinearRing.new ring.point_count = 5 ring.set_point(0, extent.x_min, extent.y_min) ring.set_point(1, extent.x_min, extent.y_max) ring.set_point(2, extent.x_max, extent.y_max) ring.set_point(3, extent.x_max, extent.y_min) ring.set_point(4, extent.x_min, extent.y_min) polygon = OGR::Polygon.new spatial_reference: spatial_reference.dup polygon.add_geometry(ring) polygon end |
#point_values(with_attributes = {}) ⇒ Array<Array>
Iterates through all geometries in the Layer and extracts the point values to an Array. The result will be an Array of Arrays where the inner Array is the point values. If with_attributes
is given, it will extract the field values for each given field names.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/ogr/extensions/layer/extensions.rb', line 114 def point_values(with_attributes = {}) return [] if feature_count.zero? field_indices = with_attributes.keys.map { |field_name| find_field_index(field_name) } values = Array.new(feature_count) { Array.new(with_attributes.size + 2) } start = Time.now i = 0 # Initing these once and only once in the case the geom type is _not_ # wkbPoint. x_ptr = FFI::MemoryPointer.new(:double) y_ptr = FFI::MemoryPointer.new(:double) # This block is intentionally long simply for the sake of performance. # I've tried refactoring chunks of this out to separate methods and # performance suffers greatly. Since this is a key part of gridding (at # least at this point), it needs to be as fast as possible. each_feature_pointer do |feature_ptr| # rubocop:todo Metrics/BlockLength field_values = field_indices.map.with_index do |j, attribute_index| FFI::OGR::API.send(:"OGR_F_GetFieldAs#{with_attributes.values[attribute_index].capitalize}", feature_ptr, j) end geom_ptr = FFI::OGR::API.OGR_F_GetGeometryRef(feature_ptr) geom_ptr.autorelease = false FFI::OGR::API.OGR_G_FlattenTo2D(geom_ptr) geom_type = FFI::OGR::API.OGR_G_GetGeometryType(geom_ptr) case geom_type when :wkbPoint values[i] = collect_point_values(geom_ptr, field_values) i += 1 when :wkbLineString, :wkbLinearRing extract_ring_points(geom_ptr, x_ptr, y_ptr) do |points| values[i] = points.push(*field_values) i += 1 end when :wkbPolygon exterior_ring_ptr = FFI::OGR::API.OGR_G_GetGeometryRef(geom_ptr, 0) extract_ring_points(exterior_ring_ptr, x_ptr, y_ptr) do |points| values[i] = points.push(*field_values) i += 1 end count = FFI::OGR::API.OGR_G_GetGeometryCount(geom_ptr) next if count > 1 count.times do |ring_num| next if ring_num.zero? ring_ptr = FFI::OGR::API.OGR_G_GetGeometryRef(geom_ptr, ring_num) extract_ring_points(ring_ptr, x_ptr, y_ptr) do |points| values[i] = points.push(*field_values) i += 1 end end when :wkbMultiPoint, :wkbMultiLineString count = FFI::OGR::API.OGR_G_GetGeometryCount(geom_ptr) count.times do |geom_num| ring_ptr = FFI::OGR::API.OGR_G_GetGeometryRef(geom_ptr, geom_num) extract_ring_points(ring_ptr, x_ptr, y_ptr) do |points| values[i] = points.push(*field_values) i += 1 end end when :wkbMultiPolygon polygon_count = FFI::OGR::API.OGR_G_GetGeometryCount(geom_ptr) polygon_count.times do |polygon_num| polygon_ptr = FFI::OGR::API.OGR_G_GetGeometryRef(geom_ptr, polygon_num) polygon_ptr.autorelease = false exterior_ring_ptr = FFI::OGR::API.OGR_G_GetGeometryRef(polygon_ptr, 0) exterior_ring_ptr.autorelease = false extract_ring_points(exterior_ring_ptr, x_ptr, y_ptr) do |points| values[i] = points.push(*field_values) i += 1 end count = FFI::OGR::API.OGR_G_GetGeometryCount(polygon_ptr) next if count > 1 count.times do |ring_num| next if ring_num.zero? ring_ptr = FFI::OGR::API.OGR_G_GetGeometryRef(polygon_ptr, ring_num) ring_ptr.autorelease = false extract_ring_points(ring_ptr, x_ptr, y_ptr) do |points| values[i] = points.push(*field_values) i += 1 end end end else raise OGR::UnsupportedGeometryType, "Not sure how to extract point_values for a #{geom_type}" end end log "#point_values took #{Time.now - start}s" values end |