ffi-gdal 1.0.0.beta5 → 1.0.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -3
  3. data/.rubocop.yml +7 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +1 -1
  6. data/History.md +143 -1
  7. data/README.md +5 -11
  8. data/Rakefile +2 -60
  9. data/TODO.md +10 -0
  10. data/examples/geometries.rb +4 -6
  11. data/examples/gridding.rb +99 -98
  12. data/examples/ogr_layer_to_layer.rb +0 -2
  13. data/examples/raster_erasing.rb +47 -0
  14. data/examples/remove_small_polygons.rb +62 -0
  15. data/examples/testing_gdal.rb +0 -3
  16. data/examples/warping.rb +140 -0
  17. data/ffi-gdal.gemspec +5 -2
  18. data/lib/ext/error_symbols.rb +1 -1
  19. data/lib/ext/ffi_library_function_checks.rb +3 -2
  20. data/lib/ext/float_ext.rb +2 -2
  21. data/lib/ext/narray_ext.rb +1 -1
  22. data/lib/ext/numeric_as_data_type.rb +1 -1
  23. data/lib/ext/to_bool.rb +2 -2
  24. data/lib/ffi/cpl/conv.rb +1 -3
  25. data/lib/ffi/cpl/error.rb +0 -3
  26. data/lib/ffi/cpl/minixml.rb +17 -21
  27. data/lib/ffi/cpl/progress.rb +27 -0
  28. data/lib/ffi/cpl/string.rb +0 -8
  29. data/lib/ffi/cpl/vsi.rb +0 -1
  30. data/lib/ffi/cpl/xml_node.rb +0 -1
  31. data/lib/ffi/cpl.rb +15 -0
  32. data/lib/ffi/gdal/alg.rb +72 -54
  33. data/lib/ffi/gdal/gdal.rb +669 -672
  34. data/lib/ffi/gdal/grid.rb +141 -24
  35. data/lib/ffi/gdal/grid_data_metrics_options.rb +1 -1
  36. data/lib/ffi/gdal/grid_moving_average_options.rb +1 -1
  37. data/lib/ffi/gdal/matching.rb +0 -2
  38. data/lib/ffi/gdal/transformer_info.rb +1 -1
  39. data/lib/ffi/gdal/version.rb +1 -1
  40. data/lib/ffi/gdal/vrt.rb +0 -2
  41. data/lib/ffi/gdal/warp_options.rb +12 -14
  42. data/lib/ffi/gdal/warper.rb +61 -6
  43. data/lib/ffi/gdal.rb +18 -3
  44. data/lib/ffi/ogr/api.rb +10 -21
  45. data/lib/ffi/ogr/core.rb +9 -12
  46. data/lib/ffi/ogr/featurestyle.rb +0 -5
  47. data/lib/ffi/ogr/geocoding.rb +0 -1
  48. data/lib/ffi/ogr/srs_api.rb +0 -4
  49. data/lib/ffi/ogr/style_value.rb +1 -2
  50. data/lib/ffi/ogr.rb +15 -12
  51. data/lib/ffi-gdal.rb +5 -3
  52. data/lib/gdal/color_entry.rb +1 -0
  53. data/lib/gdal/color_interpretation.rb +2 -2
  54. data/lib/gdal/color_table.rb +14 -14
  55. data/lib/gdal/color_table_mixins/extensions.rb +4 -4
  56. data/lib/gdal/cpl_error_handler.rb +12 -14
  57. data/lib/gdal/data_type.rb +13 -12
  58. data/lib/gdal/dataset.rb +170 -94
  59. data/lib/gdal/dataset_mixins/algorithm_methods.rb +47 -21
  60. data/lib/gdal/dataset_mixins/extensions.rb +32 -61
  61. data/lib/gdal/dataset_mixins/matching.rb +0 -2
  62. data/lib/gdal/dataset_mixins/warp_methods.rb +42 -0
  63. data/lib/gdal/driver.rb +62 -47
  64. data/lib/gdal/driver_mixins/extensions.rb +2 -7
  65. data/lib/gdal/environment_methods.rb +13 -10
  66. data/lib/gdal/exceptions.rb +24 -2
  67. data/lib/gdal/geo_transform.rb +10 -16
  68. data/lib/gdal/geo_transform_mixins/extensions.rb +58 -3
  69. data/lib/gdal/grid.rb +62 -109
  70. data/lib/gdal/{grid_types → grid_algorithms}/data_metrics_base.rb +1 -3
  71. data/lib/gdal/{grid_types → grid_algorithms}/inverse_distance_to_a_power.rb +2 -4
  72. data/lib/gdal/{grid_types → grid_algorithms}/metric_average_distance.rb +2 -2
  73. data/lib/gdal/{grid_types → grid_algorithms}/metric_average_distance_pts.rb +2 -2
  74. data/lib/gdal/{grid_types → grid_algorithms}/metric_count.rb +2 -2
  75. data/lib/gdal/{grid_types → grid_algorithms}/metric_maximum.rb +2 -2
  76. data/lib/gdal/{grid_types → grid_algorithms}/metric_minimum.rb +2 -2
  77. data/lib/gdal/{grid_types → grid_algorithms}/metric_range.rb +2 -2
  78. data/lib/gdal/{grid_types → grid_algorithms}/moving_average.rb +2 -4
  79. data/lib/gdal/{grid_types → grid_algorithms}/nearest_neighbor.rb +2 -4
  80. data/lib/gdal/grid_algorithms.rb +22 -0
  81. data/lib/gdal/gridder/point_extracting.rb +89 -0
  82. data/lib/gdal/gridder.rb +294 -0
  83. data/lib/gdal/gridder_options.rb +273 -0
  84. data/lib/gdal/internal_helpers.rb +132 -23
  85. data/lib/gdal/major_object.rb +13 -10
  86. data/lib/gdal/merger.rb +130 -0
  87. data/lib/gdal/options.rb +3 -2
  88. data/lib/gdal/raster_attribute_table.rb +74 -51
  89. data/lib/gdal/raster_attribute_table_mixins/extensions.rb +21 -3
  90. data/lib/gdal/raster_band.rb +139 -167
  91. data/lib/gdal/raster_band_classifier.rb +19 -18
  92. data/lib/gdal/raster_band_mixins/algorithm_extensions.rb +107 -0
  93. data/lib/gdal/raster_band_mixins/algorithm_methods.rb +79 -40
  94. data/lib/gdal/raster_band_mixins/coloring_extensions.rb +84 -0
  95. data/lib/gdal/raster_band_mixins/extensions.rb +34 -169
  96. data/lib/gdal/raster_band_mixins/io_extensions.rb +180 -0
  97. data/lib/gdal/rpc_info.rb +1 -2
  98. data/lib/gdal/transformer.rb +1 -6
  99. data/lib/gdal/transformers/approximate_transformer.rb +0 -4
  100. data/lib/gdal/transformers/base_general_image_projection_transformer.rb +0 -6
  101. data/lib/gdal/transformers/gcp_transformer.rb +2 -6
  102. data/lib/gdal/transformers/general_image_projection_transformer.rb +8 -7
  103. data/lib/gdal/transformers/general_image_projection_transformer2.rb +1 -1
  104. data/lib/gdal/transformers/geolocation_transformer.rb +0 -4
  105. data/lib/gdal/transformers/reprojection_transformer.rb +0 -8
  106. data/lib/gdal/transformers/rpc_transformer.rb +0 -4
  107. data/lib/gdal/transformers/tps_transformer.rb +1 -3
  108. data/lib/gdal/version_info.rb +7 -8
  109. data/lib/gdal/virtual_dataset.rb +2 -4
  110. data/lib/gdal/warp_operation.rb +17 -14
  111. data/lib/gdal/warp_options.rb +132 -0
  112. data/lib/gdal.rb +41 -2
  113. data/lib/ogr/coordinate_transformation.rb +79 -32
  114. data/lib/ogr/data_source.rb +17 -14
  115. data/lib/ogr/data_source_extensions.rb +1 -5
  116. data/lib/ogr/driver.rb +11 -14
  117. data/lib/ogr/envelope.rb +1 -1
  118. data/lib/ogr/envelope_extensions.rb +23 -6
  119. data/lib/ogr/error_handling.rb +3 -3
  120. data/lib/ogr/exceptions.rb +6 -0
  121. data/lib/ogr/feature.rb +25 -38
  122. data/lib/ogr/feature_definition.rb +6 -8
  123. data/lib/ogr/feature_definition_extensions.rb +2 -6
  124. data/lib/ogr/feature_extensions.rb +71 -41
  125. data/lib/ogr/field.rb +16 -15
  126. data/lib/ogr/field_definition.rb +4 -4
  127. data/lib/ogr/geocoder.rb +5 -5
  128. data/lib/ogr/geometries/geometry_collection.rb +4 -1
  129. data/lib/ogr/geometries/geometry_collection_25d.rb +12 -0
  130. data/lib/ogr/geometries/line_string.rb +30 -8
  131. data/lib/ogr/geometries/line_string_25d.rb +21 -0
  132. data/lib/ogr/geometries/linear_ring.rb +10 -1
  133. data/lib/ogr/geometries/multi_line_string.rb +2 -1
  134. data/lib/ogr/geometries/multi_line_string_25d.rb +13 -0
  135. data/lib/ogr/geometries/multi_point.rb +2 -1
  136. data/lib/ogr/geometries/multi_point_25d.rb +14 -0
  137. data/lib/ogr/geometries/multi_polygon.rb +3 -2
  138. data/lib/ogr/geometries/multi_polygon_25d.rb +13 -0
  139. data/lib/ogr/geometries/point.rb +20 -23
  140. data/lib/ogr/geometries/point_25d.rb +48 -0
  141. data/lib/ogr/geometries/polygon.rb +4 -1
  142. data/lib/ogr/geometries/polygon_25d.rb +14 -0
  143. data/lib/ogr/geometry.rb +125 -93
  144. data/lib/ogr/geometry_field_definition.rb +7 -5
  145. data/lib/ogr/geometry_mixins/container_mixins.rb +23 -0
  146. data/lib/ogr/geometry_mixins/extensions.rb +111 -0
  147. data/lib/ogr/geometry_types/container.rb +10 -3
  148. data/lib/ogr/geometry_types/curve.rb +68 -23
  149. data/lib/ogr/geometry_types/surface.rb +0 -9
  150. data/lib/ogr/internal_helpers.rb +3 -3
  151. data/lib/ogr/layer.rb +4 -5
  152. data/lib/ogr/layer_mixins/extensions.rb +242 -17
  153. data/lib/ogr/layer_mixins/ogr_feature_methods.rb +11 -11
  154. data/lib/ogr/layer_mixins/ogr_field_methods.rb +6 -11
  155. data/lib/ogr/layer_mixins/ogr_layer_method_methods.rb +18 -18
  156. data/lib/ogr/layer_mixins/ogr_query_filter_methods.rb +0 -2
  157. data/lib/ogr/layer_mixins/ogr_sql_methods.rb +1 -1
  158. data/lib/ogr/spatial_reference.rb +12 -37
  159. data/lib/ogr/spatial_reference_mixins/coordinate_system_getter_setters.rb +53 -55
  160. data/lib/ogr/spatial_reference_mixins/exporters.rb +18 -49
  161. data/lib/ogr/spatial_reference_mixins/parameter_getter_setters.rb +10 -29
  162. data/lib/ogr/style_table.rb +2 -2
  163. data/lib/ogr/style_table_extensions.rb +3 -1
  164. data/lib/ogr/style_tool.rb +8 -14
  165. data/lib/ogr.rb +39 -1
  166. data/spec/ffi-gdal_spec.rb +18 -1
  167. data/spec/integration/gdal/color_table_info_spec.rb +49 -33
  168. data/spec/integration/gdal/dataset_info_spec.rb +294 -45
  169. data/spec/integration/gdal/driver_info_spec.rb +139 -31
  170. data/spec/integration/gdal/geo_transform_info_spec.rb +197 -26
  171. data/spec/integration/gdal/gridder_spec.rb +329 -0
  172. data/spec/integration/gdal/raster_attribute_table_info_spec.rb +216 -11
  173. data/spec/integration/gdal/raster_band_algorithms_spec.rb +33 -0
  174. data/spec/integration/gdal/raster_band_info_spec.rb +240 -271
  175. data/spec/integration/ogr/layer_spec.rb +3 -1
  176. data/spec/spec_helper.rb +15 -6
  177. data/spec/support/images/osgeo/gdal/data/hfa/float-rle.img +0 -0
  178. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.lgo +31 -0
  179. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.tif +0 -0
  180. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.tif.msk +0 -0
  181. data/spec/support/images/osgeo/geotiff/GeogToWGS84GeoKey/GeogToWGS84GeoKey5.txt +10 -0
  182. data/spec/support/images/osgeo/geotiff/gdal_eg/cea.tif +0 -0
  183. data/spec/support/images/osgeo/geotiff/gdal_eg/cea.txt +84 -0
  184. data/spec/support/images/osgeo/geotiff/zi_imaging/image0.lgo +45 -0
  185. data/spec/support/images/osgeo/geotiff/zi_imaging/image0.tif +0 -0
  186. data/spec/support/integration_help.rb +32 -2
  187. data/spec/support/shared_examples/gdal/major_object_examples.rb +0 -6
  188. data/spec/support/shared_examples/ogr/a_geometry.rb +1 -1
  189. data/spec/unit/ffi/gdal_spec.rb +1 -1
  190. data/spec/unit/gdal/color_entry_spec.rb +1 -0
  191. data/spec/unit/gdal/color_interpretation_spec.rb +1 -0
  192. data/spec/unit/gdal/dataset_spec.rb +53 -2
  193. data/spec/unit/gdal/geo_transform_mixins/extensions_spec.rb +67 -0
  194. data/spec/unit/gdal/geo_transform_spec.rb +1 -1
  195. data/spec/unit/gdal/grid_spec.rb +83 -0
  196. data/spec/unit/gdal/gridder/point_extracting_spec.rb +99 -0
  197. data/spec/unit/gdal/gridder_options_spec.rb +183 -0
  198. data/spec/unit/gdal/gridder_spec.rb +140 -0
  199. data/spec/unit/gdal/internal_helpers_spec.rb +166 -2
  200. data/spec/unit/gdal/major_object_spec.rb +2 -0
  201. data/spec/unit/gdal/options_spec.rb +1 -0
  202. data/spec/unit/gdal/raster_band_classifier_spec.rb +70 -12
  203. data/spec/unit/gdal/raster_band_mixins/extensions_spec.rb +71 -0
  204. data/spec/unit/gdal/raster_band_mixins/io_extensions_spec.rb +133 -0
  205. data/spec/unit/gdal/raster_band_spec.rb +1 -0
  206. data/spec/unit/gdal/rpc_info_spec.rb +1 -0
  207. data/spec/unit/gdal/version_info_spec.rb +2 -0
  208. data/spec/unit/gdal/warp_operation_spec.rb +1 -0
  209. data/spec/unit/ogr/coordinate_transformation_spec.rb +102 -0
  210. data/spec/unit/ogr/data_source_spec.rb +12 -0
  211. data/spec/unit/ogr/feature_extensions_spec.rb +88 -0
  212. data/spec/unit/ogr/feature_spec.rb +30 -46
  213. data/spec/unit/ogr/geometries/geometry_collection_25d_spec.rb +23 -0
  214. data/spec/unit/ogr/geometries/geometry_collection_spec.rb +3 -3
  215. data/spec/unit/ogr/geometries/line_string_25d_spec.rb +23 -0
  216. data/spec/unit/ogr/geometries/line_string_spec.rb +2 -2
  217. data/spec/unit/ogr/geometries/linear_ring_spec.rb +2 -2
  218. data/spec/unit/ogr/geometries/multi_line_string_25d_spec.rb +23 -0
  219. data/spec/unit/ogr/geometries/multi_point_25d_spec.rb +23 -0
  220. data/spec/unit/ogr/geometries/multi_polygon_25d_spec.rb +23 -0
  221. data/spec/unit/ogr/geometries/point_25d_spec.rb +23 -0
  222. data/spec/unit/ogr/geometries/point_spec.rb +14 -24
  223. data/spec/unit/ogr/geometries/polygon_25d_spec.rb +23 -0
  224. data/spec/unit/ogr/geometries/polygon_spec.rb +1 -1
  225. data/spec/unit/ogr/geometry_field_definition_spec.rb +1 -1
  226. data/spec/unit/ogr/geometry_spec.rb +196 -30
  227. data/spec/unit/ogr/internal_helpers_spec.rb +20 -9
  228. data/spec/unit/ogr/layer_mixins/ogr_feature_methods_spec.rb +14 -6
  229. data/spec/unit/ogr/spatial_reference_mixins/exporters_spec.rb +9 -1
  230. data/spec/unit/ogr/spatial_reference_mixins/parameter_getter_setters_spec.rb +2 -1
  231. data/spec/unit/ogr/style_table_spec.rb +1 -1
  232. data/tmp/.keep +0 -0
  233. metadata +121 -19
  234. data/examples/points.txt +0 -127
  235. data/lib/gdal/grid_types.rb +0 -22
  236. data/lib/ogr/geometries/point_extensions.rb +0 -32
  237. data/lib/ogr/geometry_extensions.rb +0 -59
@@ -6,9 +6,10 @@ module OGR
6
6
  include GeometryTypes::Container
7
7
 
8
8
  # @param [FFI::Pointer] geometry_ptr
9
- def initialize(geometry_ptr = nil)
9
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
10
10
  geometry_ptr ||= OGR::Geometry.create(:wkbMultiPoint)
11
11
  initialize_from_pointer(geometry_ptr)
12
+ self.spatial_reference = spatial_reference if spatial_reference
12
13
  end
13
14
  end
14
15
  end
@@ -0,0 +1,14 @@
1
+ require_relative 'multi_point'
2
+
3
+ module OGR
4
+ # NOTE: {{#type}} will return :wkbMultiPoint (read: 2D instead of 2.5D) until
5
+ # a Z value is set.
6
+ class MultiPoint25D < MultiPoint
7
+ # @param geometry_ptr [FFI::Pointer]
8
+ # @param spatial_reference [OGR::SpatialReference]
9
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
10
+ geometry_ptr ||= OGR::Geometry.create(:wkbMultiPoint25D)
11
+ super(geometry_ptr, spatial_reference: spatial_reference)
12
+ end
13
+ end
14
+ end
@@ -8,14 +8,15 @@ module OGR
8
8
  include GeometryTypes::Surface
9
9
 
10
10
  # @param [FFI::Pointer] geometry_ptr
11
- def initialize(geometry_ptr = nil)
11
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
12
12
  geometry_ptr ||= OGR::Geometry.create(:wkbMultiPolygon)
13
13
  initialize_from_pointer(geometry_ptr)
14
+ self.spatial_reference = spatial_reference if spatial_reference
14
15
  end
15
16
 
16
17
  # @return [OGR::Geometry]
17
18
  def union_cascaded
18
- build_geometry { |ptr| FFI::OGR::API.OGR_G_UnionCascaded(ptr) }
19
+ build_geometry { FFI::OGR::API.OGR_G_UnionCascaded(@c_pointer) }
19
20
  end
20
21
  end
21
22
  end
@@ -0,0 +1,13 @@
1
+ require_relative 'multi_polygon'
2
+
3
+ module OGR
4
+ # NOTE: {{#type}} will return :wkbMultiPolygon (read: 2D instead of 2.5D)
5
+ # until a Z value is set.
6
+ class MultiPolygon25D < MultiPolygon
7
+ # @param [FFI::Pointer] geometry_ptr
8
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
9
+ geometry_ptr ||= OGR::Geometry.create(:wkbMultiPolygon25D)
10
+ super(geometry_ptr, spatial_reference: spatial_reference)
11
+ end
12
+ end
13
+ end
@@ -1,14 +1,12 @@
1
- require_relative 'point_extensions'
2
-
3
1
  module OGR
4
2
  class Point
5
3
  include OGR::Geometry
6
- include PointExtensions
7
4
 
8
5
  # @param [FFI::Pointer] geometry_ptr
9
- def initialize(geometry_ptr = nil)
6
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
10
7
  geometry_ptr ||= OGR::Geometry.create(:wkbPoint)
11
8
  initialize_from_pointer(geometry_ptr)
9
+ self.spatial_reference = spatial_reference if spatial_reference
12
10
  end
13
11
 
14
12
  # @return [Float]
@@ -25,41 +23,40 @@ module OGR
25
23
  FFI::OGR::API.OGR_G_GetY(@c_pointer, 0)
26
24
  end
27
25
 
28
- # @return [Float]
29
- def z
30
- return nil if empty?
31
-
32
- FFI::OGR::API.OGR_G_GetZ(@c_pointer, 0)
33
- end
34
-
35
- # @return [Array<Float, Float, Float>] [x, y] if 2d or [x, y, z] if 3d.
26
+ # @return [<Array<Float, Float>] [x, y].
36
27
  def point
37
28
  return [] if empty?
38
29
 
39
30
  x_ptr = FFI::MemoryPointer.new(:double)
40
31
  y_ptr = FFI::MemoryPointer.new(:double)
41
32
  z_ptr = FFI::MemoryPointer.new(:double)
42
-
43
33
  FFI::OGR::API.OGR_G_GetPoint(@c_pointer, 0, x_ptr, y_ptr, z_ptr)
44
34
 
45
- if coordinate_dimension == 2
46
- [x_ptr.read_double, y_ptr.read_double]
47
- else
48
- [x_ptr.read_double, y_ptr.read_double, z_ptr.read_double]
49
- end
35
+ [x_ptr.read_double, y_ptr.read_double]
36
+ end
37
+ alias point_value point
38
+
39
+ # Wrapper around {#point_value} to provide API parity with other geometries
40
+ # that can have multiple points.
41
+ #
42
+ # @return [Array<Array<Float, Float>>]
43
+ # TODO: move to an extension
44
+ def point_values
45
+ [point]
50
46
  end
51
47
 
52
- def set_point(x, y, z = 0)
53
- FFI::OGR::API.OGR_G_SetPoint(@c_pointer, 0, x, y, z)
48
+ # @param x [Number]
49
+ # @param y [Number]
50
+ def set_point(x, y)
51
+ FFI::OGR::API.OGR_G_SetPoint_2D(@c_pointer, 0, x, y)
54
52
  end
55
53
 
56
54
  # Adds a point to a LineString or Point geometry.
57
55
  #
58
56
  # @param x [Float]
59
57
  # @param y [Float]
60
- # @param z [Float]
61
- def add_point(x, y, z = 0)
62
- FFI::OGR::API.OGR_G_AddPoint(@c_pointer, x, y, z)
58
+ def add_point(x, y)
59
+ FFI::OGR::API.OGR_G_AddPoint_2D(@c_pointer, x, y)
63
60
  end
64
61
  end
65
62
  end
@@ -0,0 +1,48 @@
1
+ require_relative 'point'
2
+
3
+ module OGR
4
+ # NOTE: {{#type}} will return :wkbPoint (read: 2D instead of 2.5D) until a Z
5
+ # value is set.
6
+ class Point25D < Point
7
+ # @param [FFI::Pointer] geometry_ptr
8
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
9
+ geometry_ptr ||= OGR::Geometry.create(:wkbPoint25D)
10
+ super(geometry_ptr, spatial_reference: spatial_reference)
11
+ end
12
+
13
+ # @return [Float]
14
+ def z
15
+ return if empty?
16
+
17
+ FFI::OGR::API.OGR_G_GetZ(@c_pointer, 0)
18
+ end
19
+
20
+ # @return [Array<Float, Float, Float>] [x, y, z].
21
+ def point
22
+ return [] if empty?
23
+
24
+ x_ptr = FFI::MemoryPointer.new(:double)
25
+ y_ptr = FFI::MemoryPointer.new(:double)
26
+ z_ptr = FFI::MemoryPointer.new(:double)
27
+ FFI::OGR::API.OGR_G_GetPoint(@c_pointer, 0, x_ptr, y_ptr, z_ptr)
28
+
29
+ [x_ptr.read_double, y_ptr.read_double, z_ptr.read_double]
30
+ end
31
+
32
+ # @param x [Number]
33
+ # @param y [Number]
34
+ # @param z [Number]
35
+ def set_point(x, y, z)
36
+ FFI::OGR::API.OGR_G_SetPoint(@c_pointer, 0, x, y, z)
37
+ end
38
+
39
+ # Adds a point to a LineString or Point geometry.
40
+ #
41
+ # @param x [Float]
42
+ # @param y [Float]
43
+ # @param z [Float]
44
+ def add_point(x, y, z)
45
+ FFI::OGR::API.OGR_G_AddPoint(@c_pointer, x, y, z)
46
+ end
47
+ end
48
+ end
@@ -1,14 +1,17 @@
1
+ require_relative '../geometry_types/container'
1
2
  require_relative '../geometry_types/surface'
2
3
 
3
4
  module OGR
4
5
  class Polygon
5
6
  include OGR::Geometry
6
7
  include GeometryTypes::Surface
8
+ include GeometryTypes::Container
7
9
 
8
10
  # @param [FFI::Pointer] geometry_ptr
9
- def initialize(geometry_ptr = nil)
11
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
10
12
  geometry_ptr ||= OGR::Geometry.create(:wkbPolygon)
11
13
  initialize_from_pointer(geometry_ptr)
14
+ self.spatial_reference = spatial_reference if spatial_reference
12
15
  end
13
16
  end
14
17
  end
@@ -0,0 +1,14 @@
1
+ require_relative 'polygon'
2
+
3
+ module OGR
4
+ # NOTE: {{#type}} will return :wkbPolygon (read: 2D instead of 2.5D) until a Z
5
+ # value is set.
6
+ class Polygon25D < Polygon
7
+ # @param geometry_ptr [FFI::Pointer]
8
+ # @param spatial_reference [OGR::SpatialReference]
9
+ def initialize(geometry_ptr = nil, spatial_reference: nil)
10
+ geometry_ptr ||= OGR::Geometry.create(:wkbPolygon25D)
11
+ super(geometry_ptr, spatial_reference: spatial_reference)
12
+ end
13
+ end
14
+ end
data/lib/ogr/geometry.rb CHANGED
@@ -1,15 +1,13 @@
1
- require_relative 'envelope'
2
- require_relative 'geometry_extensions'
1
+ require_relative '../ogr'
2
+ require_relative 'geometry_mixins/extensions'
3
3
  require_relative '../gdal'
4
- require_relative '../gdal/options'
5
- require_relative '../gdal/logger'
6
4
 
7
5
  module OGR
8
6
  module Geometry
9
7
  module ClassMethods
10
8
  def create(type)
11
9
  geometry_pointer = FFI::OGR::API.OGR_G_CreateGeometry(type)
12
- return nil if geometry_pointer.null?
10
+ return if geometry_pointer.null?
13
11
  geometry_pointer.autorelease = false
14
12
 
15
13
  factory(geometry_pointer)
@@ -29,23 +27,35 @@ module OGR
29
27
  end
30
28
 
31
29
  new_pointer = geometry.c_pointer
30
+ return if new_pointer.nil? || new_pointer.null?
32
31
 
33
32
  case geometry.type
34
- when :wkbPoint, :wkbPoint25D then OGR::Point.new(new_pointer)
35
- when :wkbLineString, :wkbLineString25D then OGR::LineString.new(new_pointer)
33
+ when :wkbPoint then OGR::Point.new(new_pointer)
34
+ when :wkbPoint25D then OGR::Point25D.new(new_pointer)
35
+ when :wkbLineString
36
+ if geometry.to_wkt =~ /^LINEARRING/
37
+ OGR::LinearRing.new(new_pointer)
38
+ else
39
+ OGR::LineString.new(new_pointer)
40
+ end
41
+ when :wkbLineString25D then OGR::LineString25D.new(new_pointer)
36
42
  when :wkbLinearRing then OGR::LinearRing.new(new_pointer)
37
- when :wkbPolygon, :wkbPolygon25D then OGR::Polygon.new(new_pointer)
38
- when :wkbMultiPoint, :wkbMultiPoint25D then OGR::MultiPoint.new(new_pointer)
39
- when :wkbMultiLineString, :wkbMultiLineString25D then OGR::MultiLineString.new(new_pointer)
40
- when :wkbMultiPolygon, :wkbMultiPolygon25D then OGR::MultiPolygon.new(new_pointer)
43
+ when :wkbPolygon then OGR::Polygon.new(new_pointer)
44
+ when :wkbPolygon25D then OGR::Polygon25D.new(new_pointer)
45
+ when :wkbMultiPoint then OGR::MultiPoint.new(new_pointer)
46
+ when :wkbMultiPoint25D then OGR::MultiPoint25D.new(new_pointer)
47
+ when :wkbMultiLineString then OGR::MultiLineString.new(new_pointer)
48
+ when :wkbMultiLineString25D then OGR::MultiLineString25D.new(new_pointer)
49
+ when :wkbMultiPolygon then OGR::MultiPolygon.new(new_pointer)
50
+ when :wkbMultiPolygon25D then OGR::MultiPolygon25D.new(new_pointer)
41
51
  when :wkbGeometryCollection then OGR::GeometryCollection.new(new_pointer)
52
+ when :wkbGeometryCollection25D then OGR::GeometryCollection25D.new(new_pointer)
42
53
  when :wkbNone then OGR::NoneGeometry.new(new_pointer)
43
54
  else
44
55
  geometry
45
56
  end
46
57
  end
47
58
 
48
- # @return [OGR::Geometry]
49
59
  # @param wkt_data [String]
50
60
  # @param spatial_ref [FFI::Pointer] Optional spatial reference
51
61
  # to assign to the new geometry.
@@ -55,12 +65,7 @@ module OGR
55
65
  wkt_pointer_pointer = FFI::MemoryPointer.new(:pointer)
56
66
  wkt_pointer_pointer.write_pointer(wkt_data_pointer)
57
67
 
58
- spatial_ref_pointer =
59
- if spatial_ref
60
- GDAL._pointer(OGR::SpatialReference, spatial_ref)
61
- else
62
- nil
63
- end
68
+ spatial_ref_pointer = GDAL._pointer(OGR::SpatialReference, spatial_ref) if spatial_ref
64
69
 
65
70
  geometry_ptr = FFI::MemoryPointer.new(:pointer)
66
71
  geometry_ptr_ptr = FFI::MemoryPointer.new(:pointer)
@@ -69,14 +74,28 @@ module OGR
69
74
  FFI::OGR::API.OGR_G_CreateFromWkt(wkt_pointer_pointer,
70
75
  spatial_ref_pointer, geometry_ptr_ptr)
71
76
 
72
- return nil if geometry_ptr_ptr.null? ||
73
- geometry_ptr_ptr.read_pointer.null?
74
- geometry_ptr_ptr.read_pointer.nil?
77
+ return if geometry_ptr_ptr.null? || geometry_ptr_ptr.read_pointer.null?
78
+
79
+ factory(geometry_ptr_ptr.read_pointer)
80
+ end
81
+
82
+ # @param wkb_data [String] Binary string of WKB.
83
+ # @param spatial_ref [OGR::SpatialReference]
84
+ # @return [OGR::Geometry]
85
+ def create_from_wkb(wkb_data, spatial_ref = nil)
86
+ wkb_data_pointer = FFI::MemoryPointer.new(:char, wkb_data.length)
87
+ wkb_data_pointer.put_bytes(0, wkb_data)
88
+
89
+ spatial_ref_pointer = GDAL._pointer(OGR::SpatialReference, spatial_ref) if spatial_ref
75
90
 
76
- geometry = factory(geometry_ptr_ptr.read_pointer)
77
- ObjectSpace.define_finalizer(geometry) { destroy! }
91
+ geometry_ptr_ptr = GDAL._pointer_pointer(:pointer)
78
92
 
79
- geometry
93
+ byte_count = wkb_data.length
94
+ FFI::OGR::API.OGR_G_CreateFromWkb(wkb_data_pointer, spatial_ref_pointer, geometry_ptr_ptr, byte_count)
95
+
96
+ return if geometry_ptr_ptr.null? || geometry_ptr_ptr.read_pointer.null?
97
+
98
+ factory(geometry_ptr_ptr.read_pointer)
80
99
  end
81
100
 
82
101
  # @param gml_data [String]
@@ -120,7 +139,7 @@ module OGR
120
139
 
121
140
  def self.included(base)
122
141
  base.send(:include, GDAL::Logger)
123
- base.send(:include, GeometryExtensions)
142
+ base.send(:include, OGR::GeometryMixins::Extensions)
124
143
  base.send(:extend, ClassMethods)
125
144
  end
126
145
 
@@ -131,13 +150,6 @@ module OGR
131
150
  # @return [FFI::Pointer]
132
151
  attr_reader :c_pointer
133
152
 
134
- # @param value [Boolean]
135
- attr_writer :read_only
136
-
137
- def read_only?
138
- @read_only || false
139
- end
140
-
141
153
  def destroy!
142
154
  return unless @c_pointer
143
155
 
@@ -145,6 +157,13 @@ module OGR
145
157
  @c_pointer = nil
146
158
  end
147
159
 
160
+ # @return [OGR::Geometry]
161
+ def clone
162
+ new_geometry_ptr = FFI::OGR::API.OGR_G_Clone(@c_pointer)
163
+
164
+ OGR::Geometry.factory(new_geometry_ptr)
165
+ end
166
+
148
167
  # Clears all information from the geometry.
149
168
  #
150
169
  # @return nil
@@ -167,7 +186,7 @@ module OGR
167
186
  # @param new_coordinate_dimension [Fixnum]
168
187
  def coordinate_dimension=(new_coordinate_dimension)
169
188
  unless [2, 3].include?(new_coordinate_dimension)
170
- fail "Can't set coordinate to #{new_coordinate_dimension}. Must be 2 or 3."
189
+ raise "Can't set coordinate to #{new_coordinate_dimension}. Must be 2 or 3."
171
190
  end
172
191
 
173
192
  FFI::OGR::API.OGR_G_SetCoordinateDimension(@c_pointer, new_coordinate_dimension)
@@ -184,10 +203,10 @@ module OGR
184
203
  FFI::OGR::API.OGR_G_GetEnvelope3D(@c_pointer, envelope)
185
204
  when 0 then return nil
186
205
  else
187
- fail 'Unknown envelope dimension.'
206
+ raise 'Unknown envelope dimension.'
188
207
  end
189
208
 
190
- return nil if envelope.null?
209
+ return if envelope.null?
191
210
 
192
211
  OGR::Envelope.new(envelope)
193
212
  end
@@ -211,6 +230,7 @@ module OGR
211
230
  def geometry_count
212
231
  FFI::OGR::API.OGR_G_GetGeometryCount(@c_pointer)
213
232
  end
233
+ alias count geometry_count
214
234
 
215
235
  # @return [Fixnum]
216
236
  def point_count
@@ -222,22 +242,22 @@ module OGR
222
242
  # @return [Fixnum]
223
243
  # @todo This regularly crashes, so disabling it.
224
244
  def centroid
225
- fail NotImplementedError, '#centroid not yet implemented.'
245
+ point = is_3d? ? OGR::Point25D.new : OGR::Point.new
226
246
 
227
- point = OGR::Geometry.create(:wkbPoint)
228
- FFI::OGR::API.OGR_G_Centroid(@c_pointer, point.c_pointer)
229
- return nil if point.c_pointer.null?
247
+ ogr_err = FFI::OGR::API.OGR_G_Centroid(@c_pointer, point.c_pointer)
248
+ return if point.c_pointer.null? || ogr_err > 0
230
249
 
231
250
  point
232
251
  end
233
252
 
234
- # # Dump as WKT to the give +file+.
253
+ # Dump as WKT to the given +file_path+; dumps to STDOUT if none is given.
235
254
  #
236
- # @param file [String] The text file to write to.
255
+ # @param file_path [String] The text file to write to.
237
256
  # @param prefix [String] The prefix to put on each line of output.
238
- # @return [String]
239
- def dump_readable(file, prefix = nil)
240
- FFI::OGR::API.OGR_G_DumpReadable(@c_pointer, file, prefix)
257
+ def dump_readable(file_path = nil, prefix: nil)
258
+ file_ptr = file_path ? FFI::CPL::Conv.CPLOpenShared(file_path, 'w', false) : nil
259
+ FFI::OGR::API.OGR_G_DumpReadable(@c_pointer, file_ptr, prefix)
260
+ FFI::CPL::Conv.CPLCloseShared(file_ptr) if file_ptr
241
261
  end
242
262
 
243
263
  # Converts this geometry to a 2D geometry.
@@ -259,7 +279,7 @@ module OGR
259
279
 
260
280
  FFI::OGR::API.OGR_G_Equals(@c_pointer, geometry.c_pointer)
261
281
  end
262
- alias_method :==, :equals?
282
+ alias == equals?
263
283
 
264
284
  # @param geometry [OGR::Geometry, FFI::Pointer]
265
285
  # @return [Boolean]
@@ -330,31 +350,25 @@ module OGR
330
350
  def ring?
331
351
  FFI::OGR::API.OGR_G_IsRing(@c_pointer)
332
352
  rescue GDAL::Error => ex
333
- if ex.message.include? 'IllegalArgumentException'
334
- false
335
- else
336
- raise
337
- end
353
+ return false if ex.message.include? 'IllegalArgumentException'
354
+
355
+ raise
338
356
  end
339
357
 
340
358
  # @param other_geometry [OGR::Geometry]
341
359
  # @return [OGR::Geometry]
342
360
  # @todo This regularly crashes, so disabling it.
343
361
  def intersection(other_geometry)
344
- fail NotImplementedError, '#intersection not yet implemented.'
345
-
346
- return nil unless intersects?(other_geometry)
347
-
348
- build_geometry do |ptr|
349
- FFI::OGR::API.OGR_G_Intersection(ptr, other_geometry.c_pointer)
362
+ build_geometry do
363
+ FFI::OGR::API.OGR_G_Intersection(@c_pointer, other_geometry.c_pointer)
350
364
  end
351
365
  end
352
366
 
353
367
  # @param other_geometry [OGR::Geometry]
354
368
  # @return [OGR::Geometry]
355
369
  def union(other_geometry)
356
- build_geometry do |ptr|
357
- FFI::OGR::API.OGR_G_Union(ptr, other_geometry.c_pointer)
370
+ build_geometry do
371
+ FFI::OGR::API.OGR_G_Union(@c_pointer, other_geometry.c_pointer)
358
372
  end
359
373
  end
360
374
 
@@ -371,24 +385,24 @@ module OGR
371
385
  # MultiLineString or if it's impossible to reassemble due to topological
372
386
  # inconsistencies.
373
387
  def polygonize
374
- build_geometry { |ptr| FFI::OGR::API.OGR_G_Polygonize(ptr) }
388
+ build_geometry { FFI::OGR::API.OGR_G_Polygonize(@c_pointer) }
375
389
  end
376
390
 
377
391
  # @param geometry [OGR::Geometry]
378
392
  # @return [OGR::Geometry]
379
393
  def difference(geometry)
380
394
  new_geometry_ptr = FFI::OGR::API.OGR_G_Difference(@c_pointer, geometry.c_pointer)
381
- return nil if new_geometry_ptr.null?
395
+ return if new_geometry_ptr.null?
382
396
 
383
397
  self.class.factory(new_geometry_ptr)
384
398
  end
385
- alias_method :-, :difference
399
+ alias - difference
386
400
 
387
401
  # @param geometry [OGR::Geometry]
388
402
  # @return [OGR::Geometry]
389
403
  def symmetric_difference(geometry)
390
404
  new_geometry_ptr = FFI::OGR::API.OGR_G_SymDifference(@c_pointer, geometry.c_pointer)
391
- return nil if new_geometry_ptr.null?
405
+ return if new_geometry_ptr.null?
392
406
 
393
407
  self.class.factory(new_geometry_ptr)
394
408
  end
@@ -404,7 +418,7 @@ module OGR
404
418
  # @return [OGR::SpatialReference]
405
419
  def spatial_reference
406
420
  spatial_ref_ptr = FFI::OGR::API.OGR_G_GetSpatialReference(@c_pointer)
407
- return nil if spatial_ref_ptr.null?
421
+ return if spatial_ref_ptr.null?
408
422
 
409
423
  OGR::SpatialReference.new(spatial_ref_ptr)
410
424
  end
@@ -449,7 +463,7 @@ module OGR
449
463
  # @return [Boolean]
450
464
  def transform_to!(new_spatial_ref)
451
465
  new_spatial_ref_ptr = GDAL._pointer(OGR::SpatialReference, new_spatial_ref)
452
- return nil if new_spatial_ref_ptr.null?
466
+ return if new_spatial_ref_ptr.null?
453
467
 
454
468
  ogr_err = FFI::OGR::API.OGR_G_TransformTo(@c_pointer, new_spatial_ref_ptr)
455
469
 
@@ -462,11 +476,11 @@ module OGR
462
476
  # @param preserve_topology [Boolean]
463
477
  # @return [OGR::Geometry]
464
478
  def simplify(distance_tolerance, preserve_topology: false)
465
- build_geometry do |ptr|
479
+ build_geometry do
466
480
  if preserve_topology
467
- FFI::OGR::API.OGR_G_SimplifyPreserveTopology(ptr, distance_tolerance)
481
+ FFI::OGR::API.OGR_G_SimplifyPreserveTopology(@c_pointer, distance_tolerance)
468
482
  else
469
- FFI::OGR::API.OGR_G_Simplify(ptr, distance_tolerance)
483
+ FFI::OGR::API.OGR_G_Simplify(@c_pointer, distance_tolerance)
470
484
  end
471
485
  end
472
486
  end
@@ -474,13 +488,16 @@ module OGR
474
488
  # Modify the geometry so that it has no segments longer than +max_length+.
475
489
  #
476
490
  # @param max_length [Float]
491
+ # @return [OGR::Geometry] Returns self that's been segmentized.
477
492
  def segmentize!(max_length)
478
493
  FFI::OGR::API.OGR_G_Segmentize(@c_pointer, max_length)
494
+
495
+ self
479
496
  end
480
497
 
481
498
  # @return [OGR::Geometry]
482
499
  def boundary
483
- build_geometry { |ptr| FFI::OGR::API.OGR_G_Boundary(ptr) }
500
+ build_geometry { FFI::OGR::API.OGR_G_Boundary(@c_pointer) }
484
501
  end
485
502
 
486
503
  # Computes the buffer of the geometry by building a new geometry that
@@ -490,15 +507,22 @@ module OGR
490
507
  # @param quad_segments [Fixnum] The number of segments to use to approximate
491
508
  # a 90 degree (quadrant) of curvature.
492
509
  # @return [OGR::Polygon]
493
- def buffer(distance, quad_segments)
494
- build_geometry do |ptr|
495
- FFI::OGR::API.OGR_G_Buffer(ptr, distance, quad_segments)
510
+ def buffer(distance, quad_segments = 30)
511
+ build_geometry do
512
+ FFI::OGR::API.OGR_G_Buffer(@c_pointer, distance, quad_segments)
496
513
  end
497
514
  end
498
515
 
499
516
  # @return [OGR::Geometry]
500
517
  def convex_hull
501
- build_geometry { |ptr| FFI::OGR::API.OGR_G_ConvexHull(ptr) }
518
+ build_geometry { FFI::OGR::API.OGR_G_ConvexHull(@c_pointer) }
519
+ end
520
+
521
+ # Returns a point that's guaranteed to lie on the surface.
522
+ #
523
+ # @return [OGR::Point]
524
+ def point_on_surface
525
+ build_geometry { FFI::OGR::API.OGR_G_PointOnSurface(@c_pointer) }
502
526
  end
503
527
 
504
528
  # @param wkb_data [String] Binary WKB data.
@@ -580,7 +604,28 @@ module OGR
580
604
  #
581
605
  # @return [OGR::Geometry]
582
606
  def to_line_string
583
- build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToLineString(ptr) }
607
+ build_geometry { FFI::OGR::API.OGR_G_ForceToLineString(clone.c_pointer) }
608
+ end
609
+
610
+ # Since GDAL doesn't provide converting to a LinearRing, this is a hackish
611
+ # method for doing so.
612
+ #
613
+ # @return [OGR::LinearRing]
614
+ def to_linear_ring(close_rings = false)
615
+ line_string = to_line_string
616
+
617
+ return line_string unless line_string.is_a?(OGR::LineString)
618
+
619
+ linear_ring = OGR::LinearRing.new
620
+
621
+ if line_string.spatial_reference
622
+ linear_ring.spatial_reference = line_string.spatial_reference.clone
623
+ end
624
+
625
+ linear_ring.import_from_wkt(line_string.to_wkt.tr('LINESTRING', 'LINEARRING'))
626
+ linear_ring.close_rings! if close_rings
627
+
628
+ linear_ring
584
629
  end
585
630
 
586
631
  # Converts the current geometry to a Polygon geometry. The returned object
@@ -588,7 +633,7 @@ module OGR
588
633
  #
589
634
  # @return [OGR::Geometry]
590
635
  def to_polygon
591
- build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToPolygon(ptr) }
636
+ build_geometry { FFI::OGR::API.OGR_G_ForceToPolygon(clone.c_pointer) }
592
637
  end
593
638
 
594
639
  # Converts the current geometry to a MultiPoint geometry. The returned
@@ -596,7 +641,7 @@ module OGR
596
641
  #
597
642
  # @return [OGR::Geometry]
598
643
  def to_multi_point
599
- build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToMultiPoint(ptr) }
644
+ build_geometry { FFI::OGR::API.OGR_G_ForceToMultiPoint(clone.c_pointer) }
600
645
  end
601
646
 
602
647
  # Converts the current geometry to a MultiLineString geometry. The returned
@@ -604,7 +649,7 @@ module OGR
604
649
  #
605
650
  # @return [OGR::Geometry]
606
651
  def to_multi_line_string
607
- build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToMultiLineString(ptr) }
652
+ build_geometry { FFI::OGR::API.OGR_G_ForceToMultiLineString(clone.c_pointer) }
608
653
  end
609
654
 
610
655
  # Converts the current geometry to a MultiPolygon geometry. The returned
@@ -612,35 +657,22 @@ module OGR
612
657
  #
613
658
  # @return [OGR::MultiPolygon]
614
659
  def to_multi_polygon
615
- build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToMultiPolygon(ptr) }
660
+ build_geometry { FFI::OGR::API.OGR_G_ForceToMultiPolygon(@c_pointer) }
616
661
  end
617
662
 
618
663
  private
619
664
 
620
665
  # @param geometry_ptr [OGR::Geometry, FFI::Pointer]
621
666
  def initialize_from_pointer(geometry_ptr)
622
- fail OGR::InvalidHandle, "Must initialize with a valid pointer: #{geometry_ptr}" if geometry_ptr.nil?
667
+ raise OGR::InvalidHandle, "Must initialize with a valid pointer: #{geometry_ptr}" if geometry_ptr.nil?
623
668
  @c_pointer = GDAL._pointer(OGR::Geometry, geometry_ptr)
624
- @read_only = false
625
- @spatial_reference = nil
626
669
  end
627
670
 
628
671
  def build_geometry
629
- new_geometry_ptr = yield(@c_pointer)
630
- return nil if new_geometry_ptr.nil? || new_geometry_ptr.null?
672
+ new_geometry_ptr = yield
673
+ return if new_geometry_ptr.nil? || new_geometry_ptr.null? || new_geometry_ptr == @c_pointer
631
674
 
632
675
  OGR::Geometry.factory(new_geometry_ptr)
633
676
  end
634
677
  end
635
678
  end
636
-
637
- require_relative 'geometries/geometry_collection'
638
- require_relative 'geometries/line_string'
639
- require_relative 'geometries/linear_ring'
640
- require_relative 'geometries/multi_line_string'
641
- require_relative 'geometries/multi_point'
642
- require_relative 'geometries/multi_polygon'
643
- require_relative 'geometries/none_geometry'
644
- require_relative 'geometries/point'
645
- require_relative 'geometries/polygon'
646
- require_relative 'geometries/unknown_geometry'