ffi-gdal 1.0.0.beta3 → 1.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +62 -0
  4. data/Gemfile +1 -1
  5. data/History.md +53 -28
  6. data/README.md +6 -0
  7. data/Rakefile +23 -1
  8. data/examples/extract_and_colorize.rb +21 -22
  9. data/examples/geometries.rb +2 -2
  10. data/examples/gridding.rb +106 -0
  11. data/examples/ogr_layer_to_layer.rb +1 -1
  12. data/examples/points.txt +127 -0
  13. data/examples/testing_gdal.rb +3 -4
  14. data/ffi-gdal.gemspec +3 -2
  15. data/lib/ext/error_symbols.rb +2 -57
  16. data/lib/ext/ffi_library_function_checks.rb +26 -0
  17. data/lib/ext/float_ext.rb +2 -2
  18. data/lib/ext/narray_ext.rb +2 -0
  19. data/lib/ext/numeric_as_data_type.rb +19 -0
  20. data/lib/ext/to_bool.rb +4 -4
  21. data/lib/ffi/cpl/conv.rb +132 -0
  22. data/lib/ffi/cpl/error.rb +67 -0
  23. data/lib/ffi/cpl/hash_set.rb +39 -0
  24. data/lib/ffi/cpl/http.rb +25 -0
  25. data/lib/ffi/cpl/http_result.rb +18 -0
  26. data/lib/ffi/cpl/list.rb +38 -0
  27. data/lib/ffi/cpl/mime_part.rb +11 -0
  28. data/lib/ffi/cpl/minixml.rb +47 -0
  29. data/lib/ffi/cpl/port.rb +23 -0
  30. data/lib/ffi/cpl/quad_tree.rb +51 -0
  31. data/lib/ffi/{ogr/ogr_envelope.rb → cpl/rect_obj.rb} +3 -3
  32. data/lib/ffi/cpl/string.rb +95 -0
  33. data/lib/ffi/cpl/vsi.rb +115 -0
  34. data/lib/ffi/cpl/xml_node.rb +6 -6
  35. data/lib/ffi/gdal/alg.rb +385 -0
  36. data/lib/ffi/gdal/{gdal_color_entry.rb → color_entry.rb} +1 -2
  37. data/lib/ffi/gdal/exceptions.rb +6 -0
  38. data/lib/ffi/gdal/{gdal_gcp.rb → gcp.rb} +1 -3
  39. data/lib/ffi/gdal/{gdal_h.rb → gdal.rb} +253 -252
  40. data/lib/ffi/gdal/grid.rb +58 -0
  41. data/lib/ffi/gdal/{gdal_grid_data_metrics_options.rb → grid_data_metrics_options.rb} +1 -2
  42. data/lib/ffi/gdal/{gdal_grid_inverse_distance_to_a_power_options.rb → grid_inverse_distance_to_a_power_options.rb} +1 -2
  43. data/lib/ffi/gdal/{gdal_grid_moving_average_options.rb → grid_moving_average_options.rb} +1 -2
  44. data/lib/ffi/gdal/{gdal_grid_nearest_neighbor_options.rb → grid_nearest_neighbor_options.rb} +1 -2
  45. data/lib/ffi/gdal/matching.rb +20 -0
  46. data/lib/ffi/gdal/{gdal_rpc_info.rb → rpc_info.rb} +1 -2
  47. data/lib/ffi/gdal/{gdal_transformer_info.rb → transformer_info.rb} +1 -2
  48. data/lib/ffi/gdal/version.rb +1 -1
  49. data/lib/ffi/gdal/vrt.rb +92 -0
  50. data/lib/ffi/gdal/{gdal_warp_options.rb → warp_options.rb} +8 -4
  51. data/lib/ffi/gdal/warper.rb +70 -0
  52. data/lib/ffi/gdal.rb +56 -69
  53. data/lib/ffi/ogr/api.rb +567 -0
  54. data/lib/ffi/ogr/{ogr_contour_writer_info.rb → contour_writer_info.rb} +2 -3
  55. data/lib/ffi/ogr/core.rb +181 -0
  56. data/lib/ffi/ogr/envelope.rb +12 -0
  57. data/lib/ffi/ogr/{ogr_envelope_3d.rb → envelope_3d.rb} +2 -2
  58. data/lib/ffi/ogr/featurestyle.rb +29 -0
  59. data/lib/ffi/ogr/field.rb +63 -0
  60. data/lib/ffi/ogr/geocoding.rb +30 -0
  61. data/lib/ffi/ogr/srs_api.rb +407 -0
  62. data/lib/ffi/ogr/style_param.rb +13 -0
  63. data/lib/ffi/ogr/{ogr_style_value.rb → style_value.rb} +4 -3
  64. data/lib/ffi/ogr.rb +7 -7
  65. data/lib/ffi-gdal.rb +7 -145
  66. data/lib/gdal/color_entry.rb +18 -14
  67. data/lib/gdal/color_entry_mixins/extensions.rb +32 -0
  68. data/lib/gdal/color_interpretation.rb +2 -2
  69. data/lib/gdal/color_table.rb +37 -32
  70. data/lib/gdal/color_table_mixins/extensions.rb +48 -0
  71. data/lib/gdal/cpl_error_handler.rb +119 -0
  72. data/lib/gdal/data_type.rb +7 -7
  73. data/lib/gdal/dataset.rb +131 -238
  74. data/lib/gdal/dataset_mixins/algorithm_methods.rb +182 -0
  75. data/lib/gdal/dataset_mixins/extensions.rb +542 -0
  76. data/lib/gdal/dataset_mixins/matching.rb +26 -0
  77. data/lib/gdal/driver.rb +68 -92
  78. data/lib/gdal/driver_mixins/extensions.rb +93 -0
  79. data/lib/gdal/exceptions.rb +32 -4
  80. data/lib/gdal/geo_transform.rb +63 -43
  81. data/lib/gdal/geo_transform_mixins/extensions.rb +57 -0
  82. data/lib/gdal/grid.rb +144 -0
  83. data/lib/gdal/grid_types/data_metrics_base.rb +14 -0
  84. data/lib/gdal/grid_types/inverse_distance_to_a_power.rb +19 -0
  85. data/lib/gdal/grid_types/metric_average_distance.rb +12 -0
  86. data/lib/gdal/grid_types/metric_average_distance_pts.rb +12 -0
  87. data/lib/gdal/grid_types/metric_count.rb +12 -0
  88. data/lib/gdal/grid_types/metric_maximum.rb +12 -0
  89. data/lib/gdal/grid_types/metric_minimum.rb +12 -0
  90. data/lib/gdal/grid_types/metric_range.rb +12 -0
  91. data/lib/gdal/grid_types/moving_average.rb +19 -0
  92. data/lib/gdal/grid_types/nearest_neighbor.rb +19 -0
  93. data/lib/gdal/grid_types.rb +22 -0
  94. data/lib/gdal/internal_helpers.rb +94 -0
  95. data/lib/gdal/major_object.rb +4 -7
  96. data/lib/gdal/options.rb +14 -7
  97. data/lib/gdal/raster_attribute_table.rb +38 -47
  98. data/lib/gdal/raster_attribute_table_mixins/extensions.rb +41 -0
  99. data/lib/gdal/raster_band.rb +193 -227
  100. data/lib/gdal/raster_band_classifier.rb +107 -0
  101. data/lib/gdal/raster_band_mixins/algorithm_methods.rb +292 -0
  102. data/lib/gdal/raster_band_mixins/extensions.rb +238 -0
  103. data/lib/gdal/rpc_info.rb +35 -0
  104. data/lib/gdal/transformer.rb +15 -0
  105. data/lib/gdal/transformers/approximate_transformer.rb +48 -0
  106. data/lib/gdal/transformers/base_general_image_projection_transformer.rb +45 -0
  107. data/lib/gdal/transformers/gcp_transformer.rb +55 -0
  108. data/lib/gdal/transformers/general_image_projection_transformer.rb +31 -0
  109. data/lib/gdal/transformers/general_image_projection_transformer2.rb +52 -0
  110. data/lib/gdal/transformers/general_image_projection_transformer3.rb +25 -0
  111. data/lib/gdal/transformers/geolocation_transformer.rb +42 -0
  112. data/lib/gdal/transformers/reprojection_transformer.rb +39 -0
  113. data/lib/gdal/transformers/rpc_transformer.rb +56 -0
  114. data/lib/gdal/transformers/tps_transformer.rb +40 -0
  115. data/lib/gdal/virtual_dataset.rb +96 -0
  116. data/lib/gdal/warp_operation.rb +20 -23
  117. data/lib/gdal.rb +17 -0
  118. data/lib/ogr/coordinate_transformation.rb +16 -41
  119. data/lib/ogr/data_source.rb +103 -58
  120. data/lib/ogr/data_source_extensions.rb +5 -6
  121. data/lib/ogr/data_source_mixins/capability_methods.rb +27 -0
  122. data/lib/ogr/driver.rb +61 -33
  123. data/lib/ogr/driver_mixins/capability_methods.rb +16 -0
  124. data/lib/ogr/envelope.rb +29 -18
  125. data/lib/ogr/envelope_extensions.rb +70 -49
  126. data/lib/ogr/error_handling.rb +46 -0
  127. data/lib/ogr/exceptions.rb +58 -12
  128. data/lib/ogr/feature.rb +334 -86
  129. data/lib/ogr/feature_definition.rb +94 -51
  130. data/lib/ogr/feature_definition_extensions.rb +36 -13
  131. data/lib/ogr/feature_extensions.rb +62 -11
  132. data/lib/ogr/field.rb +175 -54
  133. data/lib/ogr/field_definition.rb +110 -0
  134. data/lib/ogr/{field_extensions.rb → field_definition_extensions.rb} +4 -5
  135. data/lib/ogr/{geocoding_session.rb → geocoder.rb} +14 -13
  136. data/lib/ogr/geometries/geometry_collection.rb +13 -0
  137. data/lib/ogr/geometries/line_string.rb +35 -0
  138. data/lib/ogr/geometries/linear_ring.rb +11 -0
  139. data/lib/ogr/geometries/multi_line_string.rb +16 -0
  140. data/lib/ogr/geometries/multi_point.rb +14 -0
  141. data/lib/ogr/geometries/multi_polygon.rb +21 -0
  142. data/lib/ogr/geometries/none_geometry.rb +13 -0
  143. data/lib/ogr/geometries/point.rb +65 -0
  144. data/lib/ogr/geometries/point_extensions.rb +32 -0
  145. data/lib/ogr/geometries/polygon.rb +14 -0
  146. data/lib/ogr/geometries/unknown_geometry.rb +10 -0
  147. data/lib/ogr/geometry.rb +270 -242
  148. data/lib/ogr/geometry_extensions.rb +8 -9
  149. data/lib/ogr/geometry_field_definition.rb +99 -0
  150. data/lib/ogr/geometry_field_definition_extensions.rb +19 -0
  151. data/lib/ogr/geometry_types/container.rb +75 -0
  152. data/lib/ogr/geometry_types/curve.rb +25 -28
  153. data/lib/ogr/geometry_types/surface.rb +13 -4
  154. data/lib/ogr/internal_helpers.rb +57 -0
  155. data/lib/ogr/layer.rb +60 -181
  156. data/lib/ogr/layer_mixins/capability_methods.rb +102 -0
  157. data/lib/ogr/layer_mixins/extensions.rb +59 -0
  158. data/lib/ogr/layer_mixins/ogr_feature_methods.rb +127 -0
  159. data/lib/ogr/layer_mixins/ogr_field_methods.rb +143 -0
  160. data/lib/ogr/layer_mixins/ogr_layer_method_methods.rb +163 -0
  161. data/lib/ogr/layer_mixins/ogr_query_filter_methods.rb +89 -0
  162. data/lib/ogr/layer_mixins/ogr_sql_methods.rb +48 -0
  163. data/lib/ogr/spatial_reference.rb +108 -589
  164. data/lib/ogr/spatial_reference_extensions.rb +29 -3
  165. data/lib/ogr/spatial_reference_mixins/coordinate_system_getter_setters.rb +494 -0
  166. data/lib/ogr/spatial_reference_mixins/exporters.rb +134 -0
  167. data/lib/ogr/spatial_reference_mixins/importers.rb +243 -0
  168. data/lib/ogr/spatial_reference_mixins/morphers.rb +25 -0
  169. data/lib/ogr/spatial_reference_mixins/parameter_getter_setters.rb +122 -0
  170. data/lib/ogr/spatial_reference_mixins/type_checks.rb +62 -0
  171. data/lib/ogr/style_table.rb +53 -5
  172. data/lib/ogr/style_table_extensions.rb +21 -5
  173. data/lib/ogr/style_tool.rb +118 -0
  174. data/lib/ogr.rb +8 -0
  175. data/spec/ffi-gdal_spec.rb +1 -2
  176. data/spec/integration/{color_table_info_spec.rb → gdal/color_table_info_spec.rb} +12 -12
  177. data/spec/integration/{dataset_info_spec.rb → gdal/dataset_info_spec.rb} +2 -6
  178. data/spec/integration/{driver_info_spec.rb → gdal/driver_info_spec.rb} +5 -5
  179. data/spec/integration/{geo_transform_info_spec.rb → gdal/geo_transform_info_spec.rb} +1 -14
  180. data/spec/integration/{raster_attribute_table_info_spec.rb → gdal/raster_attribute_table_info_spec.rb} +1 -2
  181. data/spec/integration/{raster_band_info_spec.rb → gdal/raster_band_info_spec.rb} +30 -42
  182. data/spec/integration/ogr/layer_spec.rb +97 -0
  183. data/spec/spec_helper.rb +94 -5
  184. data/spec/support/integration_help.rb +1 -0
  185. data/spec/support/shared_contexts.rb +26 -0
  186. data/spec/support/shared_examples/{major_object_examples.rb → gdal/major_object_examples.rb} +5 -5
  187. data/spec/support/shared_examples/ogr/a_25D_geometry.rb +7 -0
  188. data/spec/support/shared_examples/ogr/a_container_geometry.rb +47 -0
  189. data/spec/support/shared_examples/ogr/a_geometry.rb +404 -0
  190. data/spec/support/shared_examples/ogr/a_line_string.rb +16 -0
  191. data/spec/support/test_style_table.txt +3 -0
  192. data/spec/unit/ext/error_symbols_spec.rb +41 -53
  193. data/spec/unit/ext/numeric_as_data_type_spec.rb +113 -0
  194. data/spec/unit/ffi/gdal_spec.rb +70 -0
  195. data/spec/unit/gdal/color_entry_spec.rb +5 -0
  196. data/spec/unit/gdal/color_interpretation_spec.rb +5 -0
  197. data/spec/unit/gdal/{color_table_extensions_spec.rb → color_table_mixins/extensions_spec.rb} +3 -3
  198. data/spec/unit/gdal/color_table_spec.rb +14 -16
  199. data/spec/unit/gdal/data_type_spec.rb +10 -17
  200. data/spec/unit/gdal/dataset_spec.rb +4 -7
  201. data/spec/unit/gdal/driver_mixins/extensions_spec.rb +22 -0
  202. data/spec/unit/gdal/driver_spec.rb +49 -0
  203. data/spec/unit/gdal/environment_methods_spec.rb +6 -0
  204. data/spec/unit/gdal/geo_transform_spec.rb +276 -0
  205. data/spec/unit/gdal/grid_spec.rb +5 -0
  206. data/spec/unit/gdal/internal_helpers_spec.rb +112 -0
  207. data/spec/unit/gdal/major_object_spec.rb +6 -0
  208. data/spec/unit/gdal/options_spec.rb +5 -0
  209. data/spec/unit/gdal/raster_attribute_table_spec.rb +5 -0
  210. data/spec/unit/gdal/raster_band_classifier_spec.rb +134 -0
  211. data/spec/unit/gdal/raster_band_spec.rb +5 -0
  212. data/spec/unit/gdal/rpc_info_spec.rb +5 -0
  213. data/spec/unit/gdal/version_info_spec.rb +6 -0
  214. data/spec/unit/gdal/virtual_dataset_spec.rb +32 -0
  215. data/spec/unit/gdal/warp_operation_spec.rb +5 -0
  216. data/spec/unit/ogr/data_source_mixins/capability_methods_spec.rb +30 -0
  217. data/spec/unit/ogr/data_source_spec.rb +209 -0
  218. data/spec/unit/ogr/driver_mixins/capability_methods_spec.rb +18 -0
  219. data/spec/unit/ogr/driver_spec.rb +150 -0
  220. data/spec/unit/ogr/envelope_spec.rb +322 -0
  221. data/spec/unit/ogr/feature_definition_spec.rb +313 -0
  222. data/spec/unit/ogr/feature_spec.rb +379 -0
  223. data/spec/unit/ogr/field_definition_spec.rb +135 -0
  224. data/spec/unit/ogr/field_spec.rb +193 -0
  225. data/spec/unit/ogr/geometries/geometry_collection_spec.rb +186 -0
  226. data/spec/unit/ogr/geometries/line_string_spec.rb +105 -0
  227. data/spec/unit/ogr/{linear_ring_spec.rb → geometries/linear_ring_spec.rb} +10 -31
  228. data/spec/unit/ogr/geometries/multi_line_string_spec.rb +14 -0
  229. data/spec/unit/ogr/geometries/multi_point_spec.rb +14 -0
  230. data/spec/unit/ogr/geometries/multi_polygon_spec.rb +41 -0
  231. data/spec/unit/ogr/geometries/none_geometry_spec.rb +12 -0
  232. data/spec/unit/ogr/{point_spec.rb → geometries/point_spec.rb} +19 -25
  233. data/spec/unit/ogr/geometries/polygon_spec.rb +17 -0
  234. data/spec/unit/ogr/geometries/unknown_geometry_spec.rb +10 -0
  235. data/spec/unit/ogr/geometry_field_definition_spec.rb +87 -0
  236. data/spec/unit/ogr/geometry_spec.rb +542 -0
  237. data/spec/unit/ogr/internal_helpers_spec.rb +57 -0
  238. data/spec/unit/ogr/layer_mixins/capability_methods_spec.rb +88 -0
  239. data/spec/unit/ogr/layer_mixins/ogr_feature_methods_spec.rb +145 -0
  240. data/spec/unit/ogr/layer_mixins/ogr_field_methods_spec.rb +432 -0
  241. data/spec/unit/ogr/layer_mixins/ogr_layer_method_methods_spec.rb +20 -0
  242. data/spec/unit/ogr/layer_mixins/ogr_query_filter_methods_spec.rb +42 -0
  243. data/spec/unit/ogr/layer_mixins/ogr_sql_methods_spec.rb +12 -0
  244. data/spec/unit/ogr/layer_spec.rb +66 -67
  245. data/spec/unit/ogr/spatial_reference_mixins/coordinate_system_getter_setters_spec.rb +46 -0
  246. data/spec/unit/ogr/spatial_reference_mixins/exporters_spec.rb +139 -0
  247. data/spec/unit/ogr/spatial_reference_mixins/importers_spec.rb +38 -0
  248. data/spec/unit/ogr/spatial_reference_mixins/morphers_spec.rb +36 -0
  249. data/spec/unit/ogr/spatial_reference_mixins/parameter_getter_setters_spec.rb +102 -0
  250. data/spec/unit/ogr/spatial_reference_mixins/type_checks_spec.rb +157 -0
  251. data/spec/unit/ogr/spatial_reference_spec.rb +42 -0
  252. data/spec/unit/ogr/style_table_spec.rb +132 -0
  253. data/spec/unit/ogr/style_tool_spec.rb +157 -0
  254. data/spec/unit/version_info_spec.rb +1 -1
  255. metadata +285 -75
  256. data/lib/ffi/cpl/conv_h.rb +0 -143
  257. data/lib/ffi/cpl/error_h.rb +0 -63
  258. data/lib/ffi/cpl/minixml_h.rb +0 -14
  259. data/lib/ffi/cpl/string_h.rb +0 -81
  260. data/lib/ffi/cpl/vsi_h.rb +0 -112
  261. data/lib/ffi/gdal/alg_h.rb +0 -127
  262. data/lib/ffi/gdal/grid_h.rb +0 -51
  263. data/lib/ffi/gdal/warper_h.rb +0 -48
  264. data/lib/ffi/ogr/api_h.rb +0 -553
  265. data/lib/ffi/ogr/core_h.rb +0 -148
  266. data/lib/ffi/ogr/featurestyle_h.rb +0 -22
  267. data/lib/ffi/ogr/geocoding_h.rb +0 -21
  268. data/lib/ffi/ogr/ogr_field.rb +0 -50
  269. data/lib/ffi/ogr/ogr_style_param.rb +0 -12
  270. data/lib/ffi/ogr/srs_api_h.rb +0 -325
  271. data/lib/gdal/color_entry_extensions.rb +0 -30
  272. data/lib/gdal/color_table_extensions.rb +0 -47
  273. data/lib/gdal/dataset_extensions.rb +0 -496
  274. data/lib/gdal/driver_extensions.rb +0 -56
  275. data/lib/gdal/geo_transform_extensions.rb +0 -90
  276. data/lib/gdal/raster_attribute_table_extensions.rb +0 -40
  277. data/lib/gdal/raster_band_extensions.rb +0 -198
  278. data/lib/ogr/geometry_types/collection.rb +0 -45
  279. data/lib/ogr/layer_extensions.rb +0 -55
  280. data/lib/ogr/line_string.rb +0 -7
  281. data/lib/ogr/linear_ring.rb +0 -6
  282. data/lib/ogr/multi_line_string.rb +0 -9
  283. data/lib/ogr/multi_point.rb +0 -7
  284. data/lib/ogr/multi_polygon.rb +0 -14
  285. data/lib/ogr/point.rb +0 -89
  286. data/lib/ogr/polygon.rb +0 -9
data/lib/ogr/geometry.rb CHANGED
@@ -1,221 +1,231 @@
1
1
  require_relative 'envelope'
2
2
  require_relative 'geometry_extensions'
3
+ require_relative '../gdal'
4
+ require_relative '../gdal/options'
5
+ require_relative '../gdal/logger'
3
6
 
4
7
  module OGR
5
- class Geometry
6
- include GDAL::Logger
7
- include GeometryExtensions
8
+ module Geometry
9
+ module ClassMethods
10
+ def create(type)
11
+ geometry_pointer = FFI::OGR::API.OGR_G_CreateGeometry(type)
12
+ return nil if geometry_pointer.null?
13
+ geometry_pointer.autorelease = false
14
+
15
+ factory(geometry_pointer)
16
+ end
8
17
 
9
- # @param type [FFI::GDAL::OGRwkbGeometryType]
10
- # @return [OGR::Geometry]
11
- def self.create(type)
12
- geometry_pointer = FFI::GDAL.OGR_G_CreateGeometry(type)
13
- return nil if geometry_pointer.null?
14
- geometry_pointer.autorelease = false
18
+ # Creates a new Geometry using the class of the geometry that the type
19
+ # represents.
20
+ #
21
+ # @param geometry [OGR::Geometry, FFI::Pointer]
22
+ # @return [OGR::Geometry]
23
+ def factory(geometry)
24
+ geometry =
25
+ if geometry.is_a?(OGR::Geometry)
26
+ geometry
27
+ else
28
+ OGR::UnknownGeometry.new(geometry)
29
+ end
30
+
31
+ new_pointer = geometry.c_pointer
32
+ # geometry.c_pointer.autorelease = true
33
+
34
+ case geometry.type
35
+ when :wkbPoint, :wkbPoint25D then OGR::Point.new(new_pointer)
36
+ when :wkbLineString, :wkbLineString25D then OGR::LineString.new(new_pointer)
37
+ when :wkbLinearRing then OGR::LinearRing.new(new_pointer)
38
+ when :wkbPolygon, :wkbPolygon25D then OGR::Polygon.new(new_pointer)
39
+ when :wkbMultiPoint, :wkbMultiPoint25D then OGR::MultiPoint.new(new_pointer)
40
+ when :wkbMultiLineString, :wkbMultiLineString25D then OGR::MultiLineString.new(new_pointer)
41
+ when :wkbMultiPolygon, :wkbMultiPolygon25D then OGR::MultiPolygon.new(new_pointer)
42
+ when :wkbGeometryCollection then OGR::GeometryCollection.new(new_pointer)
43
+ when :wkbNone then OGR::NoneGeometry.new(new_pointer)
44
+ else
45
+ geometry
46
+ end
47
+ end
15
48
 
16
- _to_geometry_type(geometry_pointer)
17
- end
49
+ # @return [OGR::Geometry]
50
+ # @param wkt_data [String]
51
+ # @param spatial_ref [FFI::Pointer] Optional spatial reference
52
+ # to assign to the new geometry.
53
+ # @return [OGR::Geometry]
54
+ def create_from_wkt(wkt_data, spatial_ref = nil)
55
+ wkt_data_pointer = FFI::MemoryPointer.from_string(wkt_data)
56
+ wkt_pointer_pointer = FFI::MemoryPointer.new(:pointer)
57
+ wkt_pointer_pointer.write_pointer(wkt_data_pointer)
58
+
59
+ spatial_ref_pointer =
60
+ if spatial_ref
61
+ GDAL._pointer(OGR::SpatialReference, spatial_ref)
62
+ else
63
+ nil
64
+ end
65
+
66
+ geometry_ptr = FFI::MemoryPointer.new(:pointer)
67
+ geometry_ptr_ptr = FFI::MemoryPointer.new(:pointer)
68
+ geometry_ptr_ptr.write_pointer(geometry_ptr)
69
+
70
+ FFI::OGR::API.OGR_G_CreateFromWkt(wkt_pointer_pointer,
71
+ spatial_ref_pointer, geometry_ptr_ptr)
72
+
73
+ return nil if geometry_ptr_ptr.null? ||
74
+ geometry_ptr_ptr.read_pointer.null?
75
+ geometry_ptr_ptr.read_pointer.nil?
18
76
 
19
- def self._to_geometry_type(geometry)
20
- geometry = if geometry.kind_of?(OGR::Geometry)
21
- geometry
22
- else
23
- new(geometry)
24
- end
77
+ geometry = factory(geometry_ptr_ptr.read_pointer)
78
+ ObjectSpace.define_finalizer(geometry) { destroy! }
25
79
 
26
- case geometry.name
27
- when 'POINT' then OGR::Point.new(geometry.c_pointer)
28
- when 'LINESTRING' then OGR::LineString.new(geometry.c_pointer)
29
- when 'LINEARRING' then OGR::LinearRing.new(geometry.c_pointer)
30
- when 'POLYGON' then OGR::Polygon.new(geometry.c_pointer)
31
- when 'MULTIPOINT' then OGR::MultiPoint.new(geometry.c_pointer)
32
- when 'MULTILINESTRING' then OGR::MultiLineString.new(geometry.c_pointer)
33
- when 'MULTIPOLYGON' then OGR::MultiPolygon.new(geometry.c_pointer)
34
- else
35
80
  geometry
36
81
  end
37
- end
38
82
 
39
- # @param wkt_data [String]
40
- # @param spatial_reference [FFI::Pointer] Optional spatial reference
41
- # to assign to the new geometry.
42
- # @return [OGR::Geometry]
43
- def self.create_from_wkt(wkt_data, spatial_reference=nil)
44
- wkt_data_pointer = FFI::MemoryPointer.from_string(wkt_data)
45
- wkt_pointer_pointer = FFI::MemoryPointer.new(:pointer)
46
- wkt_pointer_pointer.write_pointer(wkt_data_pointer)
83
+ # @param gml_data [String]
84
+ # @return [OGR::Geometry]
85
+ def create_from_gml(gml_data)
86
+ geometry_pointer = FFI::OGR::API.OGR_G_CreateFromGML(gml_data)
47
87
 
48
- spatial_ref_pointer = if spatial_reference
49
- GDAL._pointer(OGR::SpatialReference, spatial_reference)
50
- else
51
- FFI::MemoryPointer.new(:pointer)
88
+ _ = factory(geometry_pointer)
52
89
  end
53
90
 
54
- geometry_ptr = FFI::MemoryPointer.new(:pointer)
55
- geometry_ptr_ptr = FFI::MemoryPointer.new(:pointer)
56
- geometry_ptr_ptr.write_pointer(geometry_ptr)
57
-
58
- FFI::GDAL.OGR_G_CreateFromWkt(wkt_pointer_pointer,
59
- spatial_ref_pointer, geometry_ptr_ptr)
60
-
61
- return nil if geometry_ptr_ptr.null? ||
62
- geometry_ptr_ptr.read_pointer.null?
63
- geometry_ptr_ptr.read_pointer.nil?
64
-
65
- # Not assigning here makes tests crash when using a #let.
66
- geometry = _to_geometry_type(geometry_ptr_ptr.read_pointer)
67
- end
68
-
69
- # @param gml_data [String]
70
- # @return [OGR::Geometry]
71
- def self.create_from_gml(gml_data)
72
- geometry_pointer = FFI::GDAL.OGR_G_CreateFromGML(gml_data)
73
-
74
- new(geometry_pointer)
75
- end
91
+ # @param json_data [String]
92
+ # @return [OGR::Geometry]
93
+ def create_from_json(json_data)
94
+ geometry_pointer = FFI::OGR::API.OGR_G_CreateGeometryFromJson(json_data)
76
95
 
77
- # @param json_data [String]
78
- # @return [OGR::Geometry]
79
- def self.create_from_json(json_data)
80
- geometry_pointer = FFI::GDAL.OGR_G_CreateGeometryFromJson(json_data)
96
+ factory(geometry_pointer)
97
+ end
81
98
 
82
- new(geometry_pointer)
83
- end
99
+ # The human-readable string for the geometry type.
100
+ #
101
+ # @param type [FFI::OGR::WKBGeometryType]
102
+ # @return [String]
103
+ def type_to_name(type)
104
+ FFI::OGR::Core.OGRGeometryTypeToName(type)
105
+ end
84
106
 
85
- # @return [String]
86
- def self.type_to_name(type)
87
- FFI::GDAL.OGRGeometryTypeToName(type)
107
+ # Finds the most specific common geometry type from the two given types.
108
+ # Useful when trying to figure out what geometry type to report for an
109
+ # entire layer, when the layer uses multiple types.
110
+ #
111
+ # @param main [FFI::OGR::WKBGeometryType]
112
+ # @param extra [FFI::OGR::WKBGeometryType]
113
+ # @return [FFI::OGR::WKBGeometryType] Returns :wkbUnknown when there is
114
+ # no type in common.
115
+ def merge_geometry_types(main, extra)
116
+ FFI::OGR::Core.OGRMergeGeometryTypes(main, extra)
117
+ end
88
118
  end
89
119
 
90
- # @param geometry [OGR::Geometry, FFI::Pointer]
91
- def initialize(geometry)
92
- @geometry_pointer = GDAL._pointer(OGR::Geometry, geometry)
93
- @geometry_pointer.autorelease = false
94
-
95
- close_me = -> {
96
- if @geometry_pointer && !@geometry_pointer.null?
97
- FFI::GDAL.OGR_G_DestroyGeometry(@geometry_pointer)
98
- end
99
- }
100
- ObjectSpace.define_finalizer self, close_me
101
- end
120
+ extend ClassMethods
102
121
 
103
- def c_pointer
104
- @geometry_pointer
122
+ def self.included(base)
123
+ base.send(:include, GDAL::Logger)
124
+ base.send(:include, GeometryExtensions)
105
125
  end
106
126
 
107
- # If this geometry is a container, this adds +geometry+ to the container.
108
- # If this is a Polygon, +geometry+ must be a LinearRing. If the Polygon is
109
- # empty, the first added +geometry+ will be the exterior ring. Subsequent
110
- # geometries added will be interior rings.
111
- #
112
- # @param sub_geometry [OGR::Geometry, FFI::Pointer]
113
- # @return +true+ if successful, otherwise raises an OGR exception.
114
- def add_geometry(sub_geometry)
115
- ogr_err = FFI::GDAL.OGR_G_AddGeometry(@geometry_pointer, pointer_from(sub_geometry))
127
+ #--------------------------------------------------------------------------
128
+ # Instance Methods
129
+ #--------------------------------------------------------------------------
116
130
 
117
- ogr_err.to_ruby
118
- end
131
+ # @return [FFI::Pointer]
132
+ attr_reader :c_pointer
119
133
 
120
- # @param sub_geometry [OGR::Geometry, FFI::Pointer]
121
- # @return +true+ if successful, otherwise raises an OGR exception.
122
- def add_directly(sub_geometry)
123
- ogr_err = FFI::GDAL.OGR_G_AddGeometryDirectly(@geometry_pointer, pointer_from(sub_geometry))
134
+ # @param value [Boolean]
135
+ attr_writer :read_only
124
136
 
125
- ogr_err.to_ruby
137
+ def read_only?
138
+ @read_only || false
126
139
  end
127
140
 
128
- # @param geometry_index [Fixnum]
129
- # @param delete [Boolean]
130
- # @return +true+ if successful, otherwise raises an OGR exception.
131
- def remove!(geometry_index, delete=true)
132
- ogr_err = FFI::GDAL.OGR_G_RemoveGeometry(@geometry_pointer, geometry_index, delete)
141
+ def destroy!
142
+ return unless @c_pointer
133
143
 
134
- ogr_err.to_ruby
144
+ FFI::OGR::API.OGR_G_DestroyGeometry(@c_pointer)
145
+ @c_pointer = nil
135
146
  end
136
147
 
137
148
  # Clears all information from the geometry.
149
+ #
150
+ # @return nil
138
151
  def empty!
139
- FFI::GDAL.OGR_G_Empty(@geometry_pointer)
152
+ FFI::OGR::API.OGR_G_Empty(@c_pointer)
140
153
  end
141
154
 
142
155
  # @return [Fixnum] 0 for points, 1 for lines, 2 for surfaces.
143
156
  def dimension
144
- FFI::GDAL.OGR_G_GetDimension(@geometry_pointer)
157
+ FFI::OGR::API.OGR_G_GetDimension(@c_pointer)
145
158
  end
146
159
 
147
160
  # The dimension of coordinates in this geometry (i.e. 2d vs 3d).
148
161
  #
149
162
  # @return [Fixnum] 2 or 3, but 0 in the case of an empty point.
150
163
  def coordinate_dimension
151
- FFI::GDAL.OGR_G_GetCoordinateDimension(@geometry_pointer)
164
+ FFI::OGR::API.OGR_G_GetCoordinateDimension(@c_pointer)
152
165
  end
153
166
 
154
167
  # @param new_coordinate_dimension [Fixnum]
155
168
  def coordinate_dimension=(new_coordinate_dimension)
156
169
  unless [2, 3].include?(new_coordinate_dimension)
157
- raise "Can't set coordinate to #{new_coordinate_dimension}. Must be 2 or 3."
170
+ fail "Can't set coordinate to #{new_coordinate_dimension}. Must be 2 or 3."
158
171
  end
159
172
 
160
- FFI::GDAL.OGR_G_SetCoordinateDimension(@geometry_pointer, new_coordinate_dimension)
173
+ FFI::OGR::API.OGR_G_SetCoordinateDimension(@c_pointer, new_coordinate_dimension)
161
174
  end
162
175
 
163
176
  # @return [OGR::Envelope]
164
177
  def envelope
165
- return @envelope if @envelope
166
-
167
178
  case coordinate_dimension
168
179
  when 2
169
- envelope = FFI::GDAL::OGREnvelope.new
170
- FFI::GDAL.OGR_G_GetEnvelope(@geometry_pointer, envelope)
180
+ envelope = FFI::OGR::Envelope.new
181
+ FFI::OGR::API.OGR_G_GetEnvelope(@c_pointer, envelope)
171
182
  when 3
172
- envelope = FFI::GDAL::OGREnvelope3D.new
173
- FFI::GDAL.OGR_G_GetEnvelope3D(@geometry_pointer, envelope)
174
- when 0
175
- return nil
183
+ envelope = FFI::OGR::Envelope3D.new
184
+ FFI::OGR::API.OGR_G_GetEnvelope3D(@c_pointer, envelope)
185
+ when 0 then return nil
176
186
  else
177
- raise 'Unknown envelope dimension.'
187
+ fail 'Unknown envelope dimension.'
178
188
  end
179
189
 
180
190
  return nil if envelope.null?
181
191
 
182
- @envelope = OGR::Envelope.new(envelope)
192
+ OGR::Envelope.new(envelope)
183
193
  end
184
194
 
185
- # @return [FFI::GDAL::OGRwkbGeometryType]
195
+ # @return [FFI::OGR::API::WKBGeometryType]
186
196
  def type
187
- FFI::GDAL.OGR_G_GetGeometryType(@geometry_pointer)
197
+ FFI::OGR::API.OGR_G_GetGeometryType(@c_pointer)
188
198
  end
189
199
 
190
200
  # @return [String]
191
201
  def type_to_name
192
- FFI::GDAL.OGRGeometryTypeToName(type)
202
+ FFI::OGR::Core.OGRGeometryTypeToName(type)
193
203
  end
194
204
 
195
205
  # @return [String]
196
206
  def name
197
- FFI::GDAL.OGR_G_GetGeometryName(@geometry_pointer)
207
+ FFI::OGR::API.OGR_G_GetGeometryName(@c_pointer)
198
208
  end
199
209
 
200
210
  # @return [Fixnum]
201
- def count
202
- FFI::GDAL.OGR_G_GetGeometryCount(@geometry_pointer)
211
+ def geometry_count
212
+ FFI::OGR::API.OGR_G_GetGeometryCount(@c_pointer)
203
213
  end
204
214
 
205
215
  # @return [Fixnum]
206
216
  def point_count
207
217
  return 0 if empty?
208
218
 
209
- FFI::GDAL.OGR_G_GetPointCount(@geometry_pointer)
219
+ FFI::OGR::API.OGR_G_GetPointCount(@c_pointer)
210
220
  end
211
221
 
212
222
  # @return [Fixnum]
213
223
  # @todo This regularly crashes, so disabling it.
214
224
  def centroid
215
- raise NotImplementedError, '#centroid not yet implemented.'
225
+ fail NotImplementedError, '#centroid not yet implemented.'
216
226
 
217
227
  point = OGR::Geometry.create(:wkbPoint)
218
- FFI::GDAL.OGR_G_Centroid(@geometry_pointer, point.c_pointer)
228
+ FFI::OGR::API.OGR_G_Centroid(@c_pointer, point.c_pointer)
219
229
  return nil if point.c_pointer.null?
220
230
 
221
231
  point
@@ -226,72 +236,82 @@ module OGR
226
236
  # @param file [String] The text file to write to.
227
237
  # @param prefix [String] The prefix to put on each line of output.
228
238
  # @return [String]
229
- def dump_readable(file, prefix=nil)
230
- FFI::GDAL.OGR_G_DumpReadable(@geometry_pointer, file, prefix)
239
+ def dump_readable(file, prefix = nil)
240
+ FFI::OGR::API.OGR_G_DumpReadable(@c_pointer, file, prefix)
231
241
  end
232
242
 
233
243
  # Converts this geometry to a 2D geometry.
234
244
  def flatten_to_2d!
235
- FFI::GDAL.OGR_G_FlattenTo2D(@geometry_pointer)
245
+ FFI::OGR::API.OGR_G_FlattenTo2D(@c_pointer)
236
246
  end
237
247
 
238
248
  # @param geometry [OGR::Geometry, FFI::Pointer]
239
249
  # @return [Boolean]
240
250
  def intersects?(geometry)
241
- FFI::GDAL.OGR_G_Intersects(@geometry_pointer, pointer_from(geometry))
251
+ geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
252
+ FFI::OGR::API.OGR_G_Intersects(@c_pointer, geometry_ptr)
242
253
  end
243
254
 
244
255
  # @param geometry [OGR::Geometry, FFI::Pointer]
245
256
  # @return [Boolean]
246
257
  def equals?(geometry)
247
- FFI::GDAL.OGR_G_Equals(@geometry_pointer, pointer_from(geometry))
258
+ return false unless geometry.is_a? OGR::Geometry
259
+
260
+ FFI::OGR::API.OGR_G_Equals(@c_pointer, geometry.c_pointer)
248
261
  end
249
262
  alias_method :==, :equals?
250
263
 
251
264
  # @param geometry [OGR::Geometry, FFI::Pointer]
252
265
  # @return [Boolean]
253
266
  def disjoint?(geometry)
254
- FFI::GDAL.OGR_G_Disjoint(@geometry_pointer, pointer_from(geometry))
267
+ geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
268
+ FFI::OGR::API.OGR_G_Disjoint(@c_pointer, geometry_ptr)
255
269
  end
256
270
 
257
271
  # @param geometry [OGR::Geometry, FFI::Pointer]
258
272
  # @return [Boolean]
259
273
  def touches?(geometry)
260
- FFI::GDAL.OGR_G_Touches(@geometry_pointer, geometry.c_pointer)
274
+ FFI::OGR::API.OGR_G_Touches(@c_pointer, geometry.c_pointer)
261
275
  end
262
276
 
263
277
  # @param geometry [OGR::Geometry, FFI::Pointer]
264
278
  # @return [Boolean]
265
279
  def crosses?(geometry)
266
- FFI::GDAL.OGR_G_Crosses(@geometry_pointer, pointer_from(geometry))
280
+ geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
281
+ FFI::OGR::API.OGR_G_Crosses(@c_pointer, geometry_ptr)
267
282
  end
268
283
 
269
284
  # @param geometry [OGR::Geometry, FFI::Pointer]
270
285
  # @return [Boolean]
271
286
  def within?(geometry)
272
- FFI::GDAL.OGR_G_Within(@geometry_pointer, pointer_from(geometry))
287
+ geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
288
+ FFI::OGR::API.OGR_G_Within(@c_pointer, geometry_ptr)
273
289
  end
274
290
 
275
291
  # @param geometry [OGR::Geometry, FFI::Pointer]
276
292
  # @return [Boolean]
277
293
  def contains?(geometry)
278
- FFI::GDAL.OGR_G_Contains(@geometry_pointer, pointer_from(geometry))
294
+ geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
295
+ FFI::OGR::API.OGR_G_Contains(@c_pointer, geometry_ptr)
279
296
  end
280
297
 
281
298
  # @param geometry [OGR::Geometry, FFI::Pointer]
282
299
  # @return [Boolean]
283
300
  def overlaps?(geometry)
284
- FFI::GDAL.OGR_G_Overlaps(@geometry_pointer, pointer_from(geometry))
301
+ geometry_ptr = GDAL._pointer(OGR::Geometry, geometry)
302
+ FFI::OGR::API.OGR_G_Overlaps(@c_pointer, geometry_ptr)
285
303
  end
286
304
 
287
305
  # @return [Boolean]
288
306
  def empty?
289
- FFI::GDAL.OGR_G_IsEmpty(@geometry_pointer)
307
+ FFI::OGR::API.OGR_G_IsEmpty(@c_pointer)
290
308
  end
291
309
 
292
310
  # @return [Boolean]
293
311
  def valid?
294
- FFI::GDAL.OGR_G_IsValid(@geometry_pointer)
312
+ FFI::OGR::API.OGR_G_IsValid(@c_pointer)
313
+ rescue GDAL::Error
314
+ false
295
315
  end
296
316
 
297
317
  # Returns TRUE if the geometry has no anomalous geometric points, such as
@@ -301,26 +321,32 @@ module OGR
301
321
  #
302
322
  # @return [Boolean]
303
323
  def simple?
304
- FFI::GDAL.OGR_G_IsSimple(@geometry_pointer)
324
+ FFI::OGR::API.OGR_G_IsSimple(@c_pointer)
305
325
  end
306
326
 
307
327
  # TRUE if the geometry has no points, otherwise FALSE.
308
328
  #
309
329
  # @return [Boolean]
310
330
  def ring?
311
- FFI::GDAL.OGR_G_IsRing(@geometry_pointer)
331
+ FFI::OGR::API.OGR_G_IsRing(@c_pointer)
332
+ rescue GDAL::Error => ex
333
+ if ex.message.include? 'IllegalArgumentException'
334
+ false
335
+ else
336
+ raise
337
+ end
312
338
  end
313
339
 
314
340
  # @param other_geometry [OGR::Geometry]
315
341
  # @return [OGR::Geometry]
316
342
  # @todo This regularly crashes, so disabling it.
317
343
  def intersection(other_geometry)
318
- raise NotImplementedError, '#intersection not yet implemented.'
344
+ fail NotImplementedError, '#intersection not yet implemented.'
319
345
 
320
346
  return nil unless intersects?(other_geometry)
321
347
 
322
348
  build_geometry do |ptr|
323
- FFI::GDAL.OGR_G_Intersection(ptr, other_geometry.c_pointer)
349
+ FFI::OGR::API.OGR_G_Intersection(ptr, other_geometry.c_pointer)
324
350
  end
325
351
  end
326
352
 
@@ -328,14 +354,14 @@ module OGR
328
354
  # @return [OGR::Geometry]
329
355
  def union(other_geometry)
330
356
  build_geometry do |ptr|
331
- FFI::GDAL.OGR_G_Union(ptr, other_geometry.c_pointer)
357
+ FFI::OGR::API.OGR_G_Union(ptr, other_geometry.c_pointer)
332
358
  end
333
359
  end
334
360
 
335
361
  # If this or any contained geometries has polygon rings that aren't closed,
336
362
  # this closes them by adding the starting point at the end.
337
363
  def close_rings!
338
- FFI::GDAL.OGR_G_CloseRings(@geometry_pointer)
364
+ FFI::OGR::API.OGR_G_CloseRings(@c_pointer)
339
365
  end
340
366
 
341
367
  # Creates a polygon from a set of sparse edges. The newly created geometry
@@ -345,26 +371,26 @@ module OGR
345
371
  # MultiLineString or if it's impossible to reassemble due to topological
346
372
  # inconsistencies.
347
373
  def polygonize
348
- build_geometry { |ptr| FFI::GDAL.OGR_G_Polygonize(ptr) }
374
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_Polygonize(ptr) }
349
375
  end
350
376
 
351
377
  # @param geometry [OGR::Geometry]
352
378
  # @return [OGR::Geometry]
353
379
  def difference(geometry)
354
- new_geometry_ptr = FFI::GDAL.OGR_G_Difference(@geometry_pointer, geometry.c_pointer)
380
+ new_geometry_ptr = FFI::OGR::API.OGR_G_Difference(@c_pointer, geometry.c_pointer)
355
381
  return nil if new_geometry_ptr.null?
356
382
 
357
- self.class._to_geometry_type(new_geometry_ptr)
383
+ self.class.factory(new_geometry_ptr)
358
384
  end
359
385
  alias_method :-, :difference
360
386
 
361
387
  # @param geometry [OGR::Geometry]
362
388
  # @return [OGR::Geometry]
363
389
  def symmetric_difference(geometry)
364
- new_geometry_ptr = FFI::GDAL.OGR_G_SymDifference(@geometry_pointer, geometry.c_pointer)
390
+ new_geometry_ptr = FFI::OGR::API.OGR_G_SymDifference(@c_pointer, geometry.c_pointer)
365
391
  return nil if new_geometry_ptr.null?
366
392
 
367
- self.class._to_geometry_type(new_geometry_ptr)
393
+ self.class.factory(new_geometry_ptr)
368
394
  end
369
395
 
370
396
  # The shortest distance between the two geometries.
@@ -372,27 +398,25 @@ module OGR
372
398
  # @param geometry [OGR::Geometry]
373
399
  # @return [Float] -1 if an error occurs.
374
400
  def distance_to(geometry)
375
- FFI::GDAL.OGR_G_Distance(@geometry_pointer, geometry.c_pointer)
401
+ FFI::OGR::API.OGR_G_Distance(@c_pointer, geometry.c_pointer)
376
402
  end
377
403
 
378
404
  # @return [OGR::SpatialReference]
379
405
  def spatial_reference
380
- return @spatial_reference if @spatial_reference
381
-
382
- spatial_ref_ptr = FFI::GDAL.OGR_G_GetSpatialReference(@geometry_pointer)
406
+ spatial_ref_ptr = FFI::OGR::API.OGR_G_GetSpatialReference(@c_pointer)
383
407
  return nil if spatial_ref_ptr.null?
384
408
 
385
- @spatial_reference = OGR::SpatialReference.new(spatial_ref_ptr)
409
+ OGR::SpatialReference.new(spatial_ref_ptr)
386
410
  end
387
411
 
388
412
  # Assigns a spatial reference to this geometry. Any existing spatial
389
- # reference is replace, but this does not reproject the geometry.
413
+ # reference is replaced, but this does not reproject the geometry.
390
414
  #
391
415
  # @param new_spatial_ref [OGR::SpatialReference, FFI::Pointer]
392
416
  def spatial_reference=(new_spatial_ref)
393
417
  new_spatial_ref_ptr = GDAL._pointer(OGR::SpatialReference, new_spatial_ref)
394
418
 
395
- FFI::GDAL.OGR_G_AssignSpatialReference(@geometry_pointer, new_spatial_ref_ptr)
419
+ FFI::OGR::API.OGR_G_AssignSpatialReference(@c_pointer, new_spatial_ref_ptr)
396
420
  end
397
421
 
398
422
  # Transforms the coordinates of this geometry in its current spatial
@@ -410,11 +434,11 @@ module OGR
410
434
  coord_trans_ptr = GDAL._pointer(OGR::CoordinateTransformation,
411
435
  coordinate_transformation)
412
436
 
413
- return if coord_trans_ptr.nil? or coord_trans_ptr.null?
437
+ return if coord_trans_ptr.nil? || coord_trans_ptr.null?
414
438
 
415
- ogr_err = FFI::GDAL.OGR_G_Transform(@geometry_pointer, coord_trans_ptr)
439
+ ogr_err = FFI::OGR::API.OGR_G_Transform(@c_pointer, coord_trans_ptr)
416
440
 
417
- ogr_err.to_ruby
441
+ ogr_err.handle_result
418
442
  end
419
443
 
420
444
  # Similar to +#transform+, but this only works if the geometry already has an
@@ -427,31 +451,23 @@ module OGR
427
451
  new_spatial_ref_ptr = GDAL._pointer(OGR::SpatialReference, new_spatial_ref)
428
452
  return nil if new_spatial_ref_ptr.null?
429
453
 
430
- ogr_err = FFI::GDAL.OGR_G_TransformTo(@geometry_pointer, new_spatial_ref_ptr)
454
+ ogr_err = FFI::OGR::API.OGR_G_TransformTo(@c_pointer, new_spatial_ref_ptr)
431
455
 
432
- ogr_err.to_ruby
456
+ ogr_err.handle_result
433
457
  end
434
458
 
435
459
  # Computes and returns a new, simplified geometry.
436
460
  #
437
- # NOTE: this relies on GDAL having been built against GEOS. If it wasn't,
438
- # this will fail.
439
- #
440
- # @param distance_tolerance [Float]
441
- # @return [OGR::Geometry]
442
- def simplify(distance_tolerance)
443
- build_geometry do |ptr|
444
- FFI::GDAL.OGR_G_Simplify(ptr, distance_tolerance)
445
- end
446
- end
447
-
448
- # Like +#simplify+, but preserves the geometry's topology.
449
- #
450
461
  # @param distance_tolerance [Float]
462
+ # @param preserve_topology [Boolean]
451
463
  # @return [OGR::Geometry]
452
- def simplify_preserve_topology(distance_tolerance)
464
+ def simplify(distance_tolerance, preserve_topology: false)
453
465
  build_geometry do |ptr|
454
- FFI::GDAL.OGR_G_SimplifyPreserveTopology(ptr, distance_tolerance)
466
+ if preserve_topology
467
+ FFI::OGR::API.OGR_G_SimplifyPreserveTopology(ptr, distance_tolerance)
468
+ else
469
+ FFI::OGR::API.OGR_G_Simplify(ptr, distance_tolerance)
470
+ end
455
471
  end
456
472
  end
457
473
 
@@ -459,99 +475,104 @@ module OGR
459
475
  #
460
476
  # @param max_length [Float]
461
477
  def segmentize!(max_length)
462
- FFI::GDAL.OGR_G_Segmentize(@geometry_pointer, max_length)
478
+ FFI::OGR::API.OGR_G_Segmentize(@c_pointer, max_length)
463
479
  end
464
480
 
465
481
  # @return [OGR::Geometry]
466
482
  def boundary
467
- build_geometry { |ptr| FFI::GDAL.OGR_G_Boundary(ptr) }
483
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_Boundary(ptr) }
468
484
  end
469
485
 
486
+ # Computes the buffer of the geometry by building a new geometry that
487
+ # contains the buffer region around the geometry that this was called on.
488
+ #
470
489
  # @param distance [Float] The buffer distance to be applied.
471
490
  # @param quad_segments [Fixnum] The number of segments to use to approximate
472
491
  # a 90 degree (quadrant) of curvature.
473
- # @return [OGR::Geometry]
492
+ # @return [OGR::Polygon]
474
493
  def buffer(distance, quad_segments)
475
494
  build_geometry do |ptr|
476
- FFI::GDAL.OGR_G_Buffer(ptr, distance, quad_segments)
495
+ FFI::OGR::API.OGR_G_Buffer(ptr, distance, quad_segments)
477
496
  end
478
497
  end
479
498
 
480
499
  # @return [OGR::Geometry]
481
500
  def convex_hull
482
- build_geometry { |ptr| FFI::GDAL.OGR_G_ConvexHull(ptr) }
501
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_ConvexHull(ptr) }
483
502
  end
484
503
 
485
- # TODO: should this be a class method?
486
504
  # @param wkb_data [String] Binary WKB data.
487
505
  # @return +true+ if successful, otherwise raises an OGR exception.
488
- def from_wkb(wkb_data)
489
- ogr_err = FFI::GDAL.OGR_G_ImportFromWkb(@geometry_pointer, wkb_data, wkb_data.length)
506
+ def import_from_wkb(wkb_data)
507
+ ogr_err = FFI::OGR::API.OGR_G_ImportFromWkb(@c_pointer, wkb_data, wkb_data.length)
490
508
 
491
- ogr_err.to_ruby
509
+ ogr_err.handle_result
492
510
  end
493
511
 
494
512
  # The exact number of bytes required to hold the WKB of this object.
495
513
  #
496
514
  # @return [Fixnum]
497
515
  def wkb_size
498
- FFI::GDAL.OGR_G_WkbSize(@geometry_pointer)
516
+ FFI::OGR::API.OGR_G_WkbSize(@c_pointer)
499
517
  end
500
518
 
501
519
  # @return [String]
502
- def to_wkb(byte_order=:wkbXDR)
520
+ def to_wkb(byte_order = :wkbXDR)
503
521
  output = FFI::MemoryPointer.new(:uchar, wkb_size)
504
- ogr_err = FFI::GDAL.OGR_G_ExportToWkb(@geometry_pointer, byte_order, output)
505
- ogr_err.to_ruby
522
+ ogr_err = FFI::OGR::API.OGR_G_ExportToWkb(@c_pointer, byte_order, output)
523
+ ogr_err.handle_result 'Unable to export geometry to WKB'
506
524
 
507
525
  output.read_bytes(wkb_size)
508
526
  end
509
527
 
510
- # TODO: should this be a class method?
511
528
  # @param wkt_data [String]
512
- def from_wkt(wkt_data)
529
+ def import_from_wkt(wkt_data)
513
530
  wkt_data_pointer = FFI::MemoryPointer.from_string(wkt_data)
514
531
  wkt_pointer_pointer = FFI::MemoryPointer.new(:pointer)
515
532
  wkt_pointer_pointer.write_pointer(wkt_data_pointer)
516
- ogr_err = FFI::GDAL.OGR_G_ImportFromWkt(@geometry_pointer, wkt_pointer_pointer)
533
+ ogr_err = FFI::OGR::API.OGR_G_ImportFromWkt(@c_pointer, wkt_pointer_pointer)
517
534
 
518
- ogr_err.to_ruby
535
+ ogr_err.handle_result "Unable to import: #{wkt_data}"
519
536
  end
520
537
 
521
538
  # @return [String]
522
539
  def to_wkt
523
540
  output = FFI::MemoryPointer.new(:string)
524
- ogr_err = FFI::GDAL.OGR_G_ExportToWkt(@geometry_pointer, output)
525
- ogr_err.to_ruby
541
+ ogr_err = FFI::OGR::API.OGR_G_ExportToWkt(@c_pointer, output)
542
+ ogr_err.handle_result
526
543
 
527
544
  output.read_pointer.read_string
528
545
  end
529
546
 
530
547
  # This geometry expressed as GML in GML basic data types.
531
548
  #
549
+ # @param [Hash] options
550
+ # @option options [String] :format "GML3" is really the only "option" here,
551
+ # since without passing this in, GDAL defaults to "GML2.1.2" (as of 1.8.0).
552
+ # @option options [String] :gml3_linestring_element "curve" is the only
553
+ # option here, which only pertains a) to LineString geometries, and b)
554
+ # when +:format+ is set to GML3.
555
+ # @option options [String] :gml3_longsrs Defaults to "YES", which prefixes
556
+ # the EPSG authority with "urn:ogc:def:crs:EPSG::". If "NO", the EPSG
557
+ # authority is prefixed with "EPSG:".
558
+ # @option options [String] :gmlid Use this to write a gml:id attribute at
559
+ # the top level of the geometry.
532
560
  # @return [String]
533
- def to_gml
534
- FFI::GDAL.OGR_G_ExportToGML(@geometry_pointer)
561
+ def to_gml(**options)
562
+ options_ptr = GDAL::Options.pointer(options)
563
+ FFI::OGR::API.OGR_G_ExportToGMLEx(@c_pointer, options_ptr)
535
564
  end
536
565
 
537
566
  # @param altitude_mode [String] Value to write in the +altitudeMode+
538
567
  # element.
539
568
  # @return [String]
540
- def to_kml(altitude_mode=nil)
541
- FFI::GDAL.OGR_G_ExportToKML(@geometry_pointer, altitude_mode)
569
+ def to_kml(altitude_mode = nil)
570
+ FFI::OGR::API.OGR_G_ExportToKML(@c_pointer, altitude_mode)
542
571
  end
543
572
 
544
573
  # @return [String]
545
574
  def to_geo_json
546
- FFI::GDAL.OGR_G_ExportToJson(@geometry_pointer)
547
- end
548
-
549
- # Converts the current geometry to a Polygon geometry. The returned object
550
- # is a new OGR::Geometry instance.
551
- #
552
- # @return [OGR::Geometry]
553
- def to_polygon
554
- build_geometry { |ptr| FFI::GDAL.OGR_G_ForceToPolygon(ptr) }
575
+ FFI::OGR::API.OGR_G_ExportToJson(@c_pointer)
555
576
  end
556
577
 
557
578
  # Converts the current geometry to a LineString geometry. The returned
@@ -559,15 +580,15 @@ module OGR
559
580
  #
560
581
  # @return [OGR::Geometry]
561
582
  def to_line_string
562
- build_geometry { |ptr| FFI::GDAL.OGR_G_ForceToLineString(ptr) }
583
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToLineString(ptr) }
563
584
  end
564
585
 
565
- # Converts the current geometry to a MultiPolygon geometry. The returned
566
- # object is a new OGR::Geometry instance.
586
+ # Converts the current geometry to a Polygon geometry. The returned object
587
+ # is a new OGR::Geometry instance.
567
588
  #
568
589
  # @return [OGR::Geometry]
569
- def to_multi_polygon
570
- build_geometry { |ptr| FFI::GDAL.OGR_G_ForceToMultiPolygon(ptr) }
590
+ def to_polygon
591
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToPolygon(ptr) }
571
592
  end
572
593
 
573
594
  # Converts the current geometry to a MultiPoint geometry. The returned
@@ -575,7 +596,7 @@ module OGR
575
596
  #
576
597
  # @return [OGR::Geometry]
577
598
  def to_multi_point
578
- build_geometry { |ptr| FFI::GDAL.OGR_G_ForceToMultiPoint(ptr) }
599
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToMultiPoint(ptr) }
579
600
  end
580
601
 
581
602
  # Converts the current geometry to a MultiLineString geometry. The returned
@@ -583,36 +604,43 @@ module OGR
583
604
  #
584
605
  # @return [OGR::Geometry]
585
606
  def to_multi_line_string
586
- build_geometry { |ptr| FFI::GDAL.OGR_G_ForceToMultiLineString(ptr) }
607
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToMultiLineString(ptr) }
587
608
  end
588
609
 
589
- private
590
-
591
- def build_geometry
592
- geometry_ptr = yield(@geometry_pointer)
593
- return nil if geometry_ptr.null?
610
+ # Converts the current geometry to a MultiPolygon geometry. The returned
611
+ # object is a new OGR::Geometry instance.
612
+ #
613
+ # @return [OGR::MultiPolygon]
614
+ def to_multi_polygon
615
+ build_geometry { |ptr| FFI::OGR::API.OGR_G_ForceToMultiPolygon(ptr) }
616
+ end
594
617
 
595
- if geometry_ptr == @geometry_pointer
596
- log 'Newly created geometry and current geometry are the same.'
597
- end
618
+ private
598
619
 
599
- self.class._to_geometry_type(geometry_ptr)
620
+ # @param geometry_ptr [OGR::Geometry, FFI::Pointer]
621
+ def initialize_from_pointer(geometry_ptr)
622
+ fail OGR::InvalidHandle, "Must initialize with a valid pointer: #{geometry_ptr}" if geometry_ptr.nil?
623
+ @c_pointer = GDAL._pointer(OGR::Geometry, geometry_ptr)
624
+ @read_only = false
625
+ @spatial_reference = nil
600
626
  end
601
627
 
602
- def pointer_from(geometry)
603
- if geometry.is_a? OGR::Geometry
604
- geometry.c_pointer
605
- elsif geometry.kind_of? FFI::Pointer
606
- geometry
607
- end
608
- end
628
+ def build_geometry
629
+ new_geometry_ptr = yield(@c_pointer)
630
+ return nil if new_geometry_ptr.nil? || new_geometry_ptr.null?
609
631
 
610
- def object_from(geometry)
611
- if geometry.is_a? OGR::Geometry
612
- geometry
613
- elsif geometry.kind_of? FFI::Pointer
614
- geometry.c_pointer
615
- end
632
+ OGR::Geometry.factory(new_geometry_ptr)
616
633
  end
617
634
  end
618
635
  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'