rgeo-dschee 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +29 -0
  3. data/ext/geos_c_impl/coordinates.c +65 -0
  4. data/ext/geos_c_impl/coordinates.h +2 -0
  5. data/ext/geos_c_impl/extconf.rb +43 -0
  6. data/ext/geos_c_impl/factory.c +995 -0
  7. data/ext/geos_c_impl/factory.h +238 -0
  8. data/ext/geos_c_impl/geometry.c +1093 -0
  9. data/ext/geos_c_impl/geometry.h +23 -0
  10. data/ext/geos_c_impl/geometry_collection.c +757 -0
  11. data/ext/geos_c_impl/geometry_collection.h +46 -0
  12. data/ext/geos_c_impl/line_string.c +675 -0
  13. data/ext/geos_c_impl/line_string.h +32 -0
  14. data/ext/geos_c_impl/main.c +40 -0
  15. data/ext/geos_c_impl/point.c +236 -0
  16. data/ext/geos_c_impl/point.h +30 -0
  17. data/ext/geos_c_impl/polygon.c +359 -0
  18. data/ext/geos_c_impl/polygon.h +43 -0
  19. data/ext/geos_c_impl/preface.h +38 -0
  20. data/ext/proj4_c_impl/extconf.rb +62 -0
  21. data/ext/proj4_c_impl/main.c +315 -0
  22. data/lib/rgeo.rb +89 -0
  23. data/lib/rgeo/cartesian.rb +25 -0
  24. data/lib/rgeo/cartesian/analysis.rb +77 -0
  25. data/lib/rgeo/cartesian/bounding_box.rb +398 -0
  26. data/lib/rgeo/cartesian/calculations.rb +113 -0
  27. data/lib/rgeo/cartesian/factory.rb +347 -0
  28. data/lib/rgeo/cartesian/feature_classes.rb +100 -0
  29. data/lib/rgeo/cartesian/feature_methods.rb +88 -0
  30. data/lib/rgeo/cartesian/interface.rb +135 -0
  31. data/lib/rgeo/coord_sys.rb +43 -0
  32. data/lib/rgeo/coord_sys/cs/entities.rb +1315 -0
  33. data/lib/rgeo/coord_sys/cs/factories.rb +148 -0
  34. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +272 -0
  35. data/lib/rgeo/coord_sys/proj4.rb +293 -0
  36. data/lib/rgeo/coord_sys/srs_database/interface.rb +115 -0
  37. data/lib/rgeo/coord_sys/srs_database/proj4_data.rb +140 -0
  38. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +62 -0
  39. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +63 -0
  40. data/lib/rgeo/error.rb +27 -0
  41. data/lib/rgeo/feature.rb +54 -0
  42. data/lib/rgeo/feature/curve.rb +111 -0
  43. data/lib/rgeo/feature/factory.rb +278 -0
  44. data/lib/rgeo/feature/factory_generator.rb +96 -0
  45. data/lib/rgeo/feature/geometry.rb +624 -0
  46. data/lib/rgeo/feature/geometry_collection.rb +95 -0
  47. data/lib/rgeo/feature/line.rb +26 -0
  48. data/lib/rgeo/feature/line_string.rb +60 -0
  49. data/lib/rgeo/feature/linear_ring.rb +26 -0
  50. data/lib/rgeo/feature/mixins.rb +143 -0
  51. data/lib/rgeo/feature/multi_curve.rb +71 -0
  52. data/lib/rgeo/feature/multi_line_string.rb +26 -0
  53. data/lib/rgeo/feature/multi_point.rb +33 -0
  54. data/lib/rgeo/feature/multi_polygon.rb +57 -0
  55. data/lib/rgeo/feature/multi_surface.rb +73 -0
  56. data/lib/rgeo/feature/point.rb +84 -0
  57. data/lib/rgeo/feature/polygon.rb +97 -0
  58. data/lib/rgeo/feature/surface.rb +79 -0
  59. data/lib/rgeo/feature/types.rb +284 -0
  60. data/lib/rgeo/geographic.rb +40 -0
  61. data/lib/rgeo/geographic/factory.rb +450 -0
  62. data/lib/rgeo/geographic/interface.rb +489 -0
  63. data/lib/rgeo/geographic/proj4_projector.rb +58 -0
  64. data/lib/rgeo/geographic/projected_feature_classes.rb +107 -0
  65. data/lib/rgeo/geographic/projected_feature_methods.rb +212 -0
  66. data/lib/rgeo/geographic/projected_window.rb +383 -0
  67. data/lib/rgeo/geographic/simple_mercator_projector.rb +110 -0
  68. data/lib/rgeo/geographic/spherical_feature_classes.rb +100 -0
  69. data/lib/rgeo/geographic/spherical_feature_methods.rb +134 -0
  70. data/lib/rgeo/geographic/spherical_math.rb +188 -0
  71. data/lib/rgeo/geos.rb +89 -0
  72. data/lib/rgeo/geos/capi_factory.rb +470 -0
  73. data/lib/rgeo/geos/capi_feature_classes.rb +129 -0
  74. data/lib/rgeo/geos/ffi_factory.rb +592 -0
  75. data/lib/rgeo/geos/ffi_feature_classes.rb +83 -0
  76. data/lib/rgeo/geos/ffi_feature_methods.rb +574 -0
  77. data/lib/rgeo/geos/interface.rb +202 -0
  78. data/lib/rgeo/geos/utils.rb +74 -0
  79. data/lib/rgeo/geos/zm_factory.rb +405 -0
  80. data/lib/rgeo/geos/zm_feature_classes.rb +80 -0
  81. data/lib/rgeo/geos/zm_feature_methods.rb +344 -0
  82. data/lib/rgeo/impl_helper.rb +19 -0
  83. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +185 -0
  84. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +61 -0
  85. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +146 -0
  86. data/lib/rgeo/impl_helper/basic_point_methods.rb +104 -0
  87. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +87 -0
  88. data/lib/rgeo/impl_helper/math.rb +14 -0
  89. data/lib/rgeo/impl_helper/utils.rb +29 -0
  90. data/lib/rgeo/version.rb +3 -0
  91. data/lib/rgeo/wkrep.rb +37 -0
  92. data/lib/rgeo/wkrep/wkb_generator.rb +201 -0
  93. data/lib/rgeo/wkrep/wkb_parser.rb +251 -0
  94. data/lib/rgeo/wkrep/wkt_generator.rb +207 -0
  95. data/lib/rgeo/wkrep/wkt_parser.rb +415 -0
  96. data/lib/rgeo/yaml.rb +23 -0
  97. data/test/cartesian_analysis_test.rb +65 -0
  98. data/test/cartesian_bbox_test.rb +123 -0
  99. data/test/common/factory_tests.rb +78 -0
  100. data/test/common/geometry_collection_tests.rb +237 -0
  101. data/test/common/line_string_tests.rb +330 -0
  102. data/test/common/multi_line_string_tests.rb +182 -0
  103. data/test/common/multi_point_tests.rb +200 -0
  104. data/test/common/multi_polygon_tests.rb +191 -0
  105. data/test/common/point_tests.rb +370 -0
  106. data/test/common/polygon_tests.rb +261 -0
  107. data/test/coord_sys/ogc_cs_test.rb +342 -0
  108. data/test/coord_sys/proj4_srs_data_test.rb +41 -0
  109. data/test/coord_sys/proj4_test.rb +150 -0
  110. data/test/coord_sys/sr_org_test.rb +32 -0
  111. data/test/coord_sys/url_reader_test.rb +42 -0
  112. data/test/geos_capi/factory_test.rb +31 -0
  113. data/test/geos_capi/geometry_collection_test.rb +24 -0
  114. data/test/geos_capi/line_string_test.rb +24 -0
  115. data/test/geos_capi/misc_test.rb +116 -0
  116. data/test/geos_capi/multi_line_string_test.rb +24 -0
  117. data/test/geos_capi/multi_point_test.rb +24 -0
  118. data/test/geos_capi/multi_polygon_test.rb +39 -0
  119. data/test/geos_capi/parsing_unparsing_test.rb +40 -0
  120. data/test/geos_capi/point_test.rb +72 -0
  121. data/test/geos_capi/polygon_test.rb +154 -0
  122. data/test/geos_capi/zmfactory_test.rb +57 -0
  123. data/test/geos_ffi/factory_test.rb +31 -0
  124. data/test/geos_ffi/geometry_collection_test.rb +24 -0
  125. data/test/geos_ffi/line_string_test.rb +24 -0
  126. data/test/geos_ffi/misc_test.rb +63 -0
  127. data/test/geos_ffi/multi_line_string_test.rb +24 -0
  128. data/test/geos_ffi/multi_point_test.rb +24 -0
  129. data/test/geos_ffi/multi_polygon_test.rb +33 -0
  130. data/test/geos_ffi/parsing_unparsing_test.rb +41 -0
  131. data/test/geos_ffi/point_test.rb +77 -0
  132. data/test/geos_ffi/polygon_test.rb +46 -0
  133. data/test/geos_ffi/zmfactory_test.rb +58 -0
  134. data/test/mixins_test.rb +141 -0
  135. data/test/oneoff_test.rb +26 -0
  136. data/test/projected_geographic/factory_test.rb +25 -0
  137. data/test/projected_geographic/geometry_collection_test.rb +24 -0
  138. data/test/projected_geographic/line_string_test.rb +24 -0
  139. data/test/projected_geographic/multi_line_string_test.rb +26 -0
  140. data/test/projected_geographic/multi_point_test.rb +30 -0
  141. data/test/projected_geographic/multi_polygon_test.rb +25 -0
  142. data/test/projected_geographic/point_test.rb +51 -0
  143. data/test/projected_geographic/polygon_test.rb +24 -0
  144. data/test/simple_cartesian/calculations_test.rb +99 -0
  145. data/test/simple_cartesian/factory_test.rb +27 -0
  146. data/test/simple_cartesian/geometry_collection_test.rb +30 -0
  147. data/test/simple_cartesian/line_string_test.rb +31 -0
  148. data/test/simple_cartesian/multi_line_string_test.rb +28 -0
  149. data/test/simple_cartesian/multi_point_test.rb +31 -0
  150. data/test/simple_cartesian/multi_polygon_test.rb +31 -0
  151. data/test/simple_cartesian/point_test.rb +50 -0
  152. data/test/simple_cartesian/polygon_test.rb +28 -0
  153. data/test/simple_mercator/factory_test.rb +25 -0
  154. data/test/simple_mercator/geometry_collection_test.rb +24 -0
  155. data/test/simple_mercator/line_string_test.rb +24 -0
  156. data/test/simple_mercator/multi_line_string_test.rb +26 -0
  157. data/test/simple_mercator/multi_point_test.rb +29 -0
  158. data/test/simple_mercator/multi_polygon_test.rb +25 -0
  159. data/test/simple_mercator/point_test.rb +55 -0
  160. data/test/simple_mercator/polygon_test.rb +24 -0
  161. data/test/simple_mercator/window_test.rb +173 -0
  162. data/test/spherical_geographic/calculations_test.rb +167 -0
  163. data/test/spherical_geographic/factory_test.rb +27 -0
  164. data/test/spherical_geographic/geometry_collection_test.rb +31 -0
  165. data/test/spherical_geographic/line_string_test.rb +31 -0
  166. data/test/spherical_geographic/multi_line_string_test.rb +29 -0
  167. data/test/spherical_geographic/multi_point_test.rb +31 -0
  168. data/test/spherical_geographic/multi_polygon_test.rb +31 -0
  169. data/test/spherical_geographic/point_test.rb +78 -0
  170. data/test/spherical_geographic/polygon_test.rb +28 -0
  171. data/test/types_test.rb +42 -0
  172. data/test/wkrep/wkb_generator_test.rb +185 -0
  173. data/test/wkrep/wkb_parser_test.rb +293 -0
  174. data/test/wkrep/wkt_generator_test.rb +294 -0
  175. data/test/wkrep/wkt_parser_test.rb +412 -0
  176. metadata +386 -0
@@ -0,0 +1,129 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # GEOS implementation additions written in Ruby
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+
7
+ module RGeo
8
+ module Geos
9
+ module CAPIGeometryMethods # :nodoc:
10
+ include Feature::Instance
11
+
12
+ def inspect
13
+ "#<#{self.class}:0x#{object_id.to_s(16)} #{as_text.inspect}>"
14
+ end
15
+
16
+ # Marshal support
17
+
18
+ def marshal_dump # :nodoc:
19
+ factory_ = factory
20
+ [factory_, factory_._write_for_marshal(self)]
21
+ end
22
+
23
+ def marshal_load(data_) # :nodoc:
24
+ obj_ = data_[0]._read_for_marshal(data_[1])
25
+ _steal(obj_)
26
+ end
27
+
28
+ # Psych support
29
+
30
+ def encode_with(coder_) # :nodoc:
31
+ factory_ = factory
32
+ coder_["factory"] = factory_
33
+ str_ = factory_._write_for_psych(self)
34
+ str_ = str_.encode("US-ASCII") if str_.respond_to?(:encode)
35
+ coder_["wkt"] = str_
36
+ end
37
+
38
+ def init_with(coder_) # :nodoc:
39
+ obj_ = coder_["factory"]._read_for_psych(coder_["wkt"])
40
+ _steal(obj_)
41
+ end
42
+
43
+ def as_text
44
+ str_ = _as_text
45
+ str_.force_encoding("US-ASCII") if str_.respond_to?(:force_encoding)
46
+ str_
47
+ end
48
+ alias_method :to_s, :as_text
49
+ end
50
+
51
+ module CAPIGeometryCollectionMethods # :nodoc:
52
+ include ::Enumerable
53
+ end
54
+
55
+ class CAPIGeometryImpl # :nodoc:
56
+ include CAPIGeometryMethods
57
+
58
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Geometry).include_in_class(self, true)
59
+ end
60
+
61
+ class CAPIPointImpl # :nodoc:
62
+ include CAPIGeometryMethods
63
+ include CAPIPointMethods
64
+
65
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Point).include_in_class(self, true)
66
+ end
67
+
68
+ class CAPILineStringImpl # :nodoc:
69
+ include CAPIGeometryMethods
70
+ include CAPILineStringMethods
71
+
72
+ Feature::MixinCollection::GLOBAL.for_type(Feature::LineString).include_in_class(self, true)
73
+ end
74
+
75
+ class CAPILinearRingImpl # :nodoc:
76
+ include CAPIGeometryMethods
77
+ include CAPILineStringMethods
78
+ include CAPILinearRingMethods
79
+
80
+ Feature::MixinCollection::GLOBAL.for_type(Feature::LinearRing).include_in_class(self, true)
81
+ end
82
+
83
+ class CAPILineImpl # :nodoc:
84
+ include CAPIGeometryMethods
85
+ include CAPILineStringMethods
86
+ include CAPILineMethods
87
+
88
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Line).include_in_class(self, true)
89
+ end
90
+
91
+ class CAPIPolygonImpl # :nodoc:
92
+ include CAPIGeometryMethods
93
+ include CAPIPolygonMethods
94
+
95
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Polygon).include_in_class(self, true)
96
+ end
97
+
98
+ class CAPIGeometryCollectionImpl # :nodoc:
99
+ include CAPIGeometryMethods
100
+ include CAPIGeometryCollectionMethods
101
+
102
+ Feature::MixinCollection::GLOBAL.for_type(Feature::GeometryCollection).include_in_class(self, true)
103
+ end
104
+
105
+ class CAPIMultiPointImpl # :nodoc:
106
+ include CAPIGeometryMethods
107
+ include CAPIGeometryCollectionMethods
108
+ include CAPIMultiPointMethods
109
+
110
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPoint).include_in_class(self, true)
111
+ end
112
+
113
+ class CAPIMultiLineStringImpl # :nodoc:
114
+ include CAPIGeometryMethods
115
+ include CAPIGeometryCollectionMethods
116
+ include CAPIMultiLineStringMethods
117
+
118
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self, true)
119
+ end
120
+
121
+ class CAPIMultiPolygonImpl # :nodoc:
122
+ include CAPIGeometryMethods
123
+ include CAPIGeometryCollectionMethods
124
+ include CAPIMultiPolygonMethods
125
+
126
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPolygon).include_in_class(self, true)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,592 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # FFI-GEOS factory implementation
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+
7
+ module RGeo
8
+ module Geos
9
+ # This the FFI-GEOS implementation of ::RGeo::Feature::Factory.
10
+
11
+ class FFIFactory
12
+ include Feature::Factory::Instance
13
+
14
+ # Create a new factory. Returns nil if the FFI-GEOS implementation
15
+ # is not supported.
16
+ #
17
+ # See ::RGeo::Geos.factory for a list of supported options.
18
+
19
+ def initialize(opts_ = {})
20
+ # Main flags
21
+ @uses_lenient_multi_polygon_assertions = opts_[:uses_lenient_assertions] ||
22
+ opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
23
+ @has_z = opts_[:has_z_coordinate] ? true : false
24
+ @has_m = opts_[:has_m_coordinate] ? true : false
25
+ if @has_z && @has_m
26
+ raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
27
+ end
28
+ @_has_3d = @has_z || @has_m
29
+ @buffer_resolution = opts_[:buffer_resolution].to_i
30
+ @buffer_resolution = 1 if @buffer_resolution < 1
31
+ @_auto_prepare = opts_[:auto_prepare] == :disabled ? false : true
32
+
33
+ # Interpret the generator options
34
+ wkt_generator_ = opts_[:wkt_generator]
35
+ case wkt_generator_
36
+ when :geos
37
+ @wkt_writer = ::Geos::WktWriter.new
38
+ @wkt_generator = nil
39
+ when ::Hash
40
+ @wkt_generator = WKRep::WKTGenerator.new(wkt_generator_)
41
+ @wkt_writer = nil
42
+ else
43
+ @wkt_generator = WKRep::WKTGenerator.new(convert_case: :upper)
44
+ @wkt_writer = nil
45
+ end
46
+ wkb_generator_ = opts_[:wkb_generator]
47
+ case wkb_generator_
48
+ when :geos
49
+ @wkb_writer = ::Geos::WkbWriter.new
50
+ @wkb_generator = nil
51
+ when ::Hash
52
+ @wkb_generator = WKRep::WKBGenerator.new(wkb_generator_)
53
+ @wkb_writer = nil
54
+ else
55
+ @wkb_generator = WKRep::WKBGenerator.new
56
+ @wkb_writer = nil
57
+ end
58
+
59
+ # Coordinate system (srid, proj4, and coord_sys)
60
+ @srid = opts_[:srid]
61
+ @proj4 = opts_[:proj4]
62
+ if CoordSys::Proj4.supported?
63
+ if @proj4.is_a?(::String) || @proj4.is_a?(::Hash)
64
+ @proj4 = CoordSys::Proj4.create(@proj4)
65
+ end
66
+ else
67
+ @proj4 = nil
68
+ end
69
+ @coord_sys = opts_[:coord_sys]
70
+ if @coord_sys.is_a?(::String)
71
+ @coord_sys = begin
72
+ CoordSys::CS.create_from_wkt(@coord_sys)
73
+ rescue
74
+ nil
75
+ end
76
+ end
77
+ if (!@proj4 || !@coord_sys) && @srid && (db_ = opts_[:srs_database])
78
+ entry_ = db_.get(@srid.to_i)
79
+ if entry_
80
+ @proj4 ||= entry_.proj4
81
+ @coord_sys ||= entry_.coord_sys
82
+ end
83
+ end
84
+ @srid ||= @coord_sys.authority_code if @coord_sys
85
+ @srid = @srid.to_i
86
+
87
+ # Interpret parser options
88
+ wkt_parser_ = opts_[:wkt_parser]
89
+ case wkt_parser_
90
+ when :geos
91
+ @wkt_reader = ::Geos::WktReader.new
92
+ @wkt_parser = nil
93
+ when ::Hash
94
+ @wkt_parser = WKRep::WKTParser.new(self, wkt_parser_)
95
+ @wkt_reader = nil
96
+ else
97
+ @wkt_parser = WKRep::WKTParser.new(self)
98
+ @wkt_reader = nil
99
+ end
100
+ wkb_parser_ = opts_[:wkb_parser]
101
+ case wkb_parser_
102
+ when :geos
103
+ @wkb_reader = ::Geos::WkbReader.new
104
+ @wkb_parser = nil
105
+ when ::Hash
106
+ @wkb_parser = WKRep::WKBParser.new(self, wkb_parser_)
107
+ @wkb_reader = nil
108
+ else
109
+ @wkb_parser = WKRep::WKBParser.new(self)
110
+ @wkb_reader = nil
111
+ end
112
+ end
113
+
114
+ # Standard object inspection output
115
+
116
+ def inspect
117
+ "#<#{self.class}:0x#{object_id.to_s(16)} srid=#{srid}>"
118
+ end
119
+
120
+ # Factory equivalence test.
121
+
122
+ def eql?(rhs_)
123
+ rhs_.is_a?(self.class) && @srid == rhs_.srid &&
124
+ @has_z == rhs_.property(:has_z_coordinate) &&
125
+ @has_m == rhs_.property(:has_m_coordinate) &&
126
+ @buffer_resolution == rhs_.property(:buffer_resolution) &&
127
+ @proj4.eql?(rhs_.proj4)
128
+ end
129
+ alias_method :==, :eql?
130
+
131
+ # Standard hash code
132
+
133
+ def hash
134
+ @hash ||= [@srid, @has_z, @has_m, @buffer_resolution, @proj4].hash
135
+ end
136
+
137
+ # Marshal support
138
+
139
+ def marshal_dump # :nodoc:
140
+ hash_ = {
141
+ "hasz" => @has_z,
142
+ "hasm" => @has_m,
143
+ "srid" => @srid,
144
+ "bufr" => @buffer_resolution,
145
+ "wktg" => @wkt_generator._properties,
146
+ "wkbg" => @wkb_generator._properties,
147
+ "wktp" => @wkt_parser._properties,
148
+ "wkbp" => @wkb_parser._properties,
149
+ "lmpa" => @uses_lenient_multi_polygon_assertions,
150
+ "apre" => @_auto_prepare
151
+ }
152
+ hash_["proj4"] = @proj4.marshal_dump if @proj4
153
+ hash_["cs"] = @coord_sys.to_wkt if @coord_sys
154
+ hash_
155
+ end
156
+
157
+ def marshal_load(data_) # :nodoc:
158
+ if CoordSys::Proj4.supported? && (proj4_data_ = data_["proj4"])
159
+ proj4_ = CoordSys::Proj4.allocate
160
+ proj4_.marshal_load(proj4_data_)
161
+ else
162
+ proj4_ = nil
163
+ end
164
+ if (coord_sys_data_ = data_["cs"])
165
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_)
166
+ else
167
+ coord_sys_ = nil
168
+ end
169
+ initialize(
170
+ has_z_coordinate: data_["hasz"],
171
+ has_m_coordinate: data_["hasm"],
172
+ srid: data_["srid"],
173
+ buffer_resolution: data_["bufr"],
174
+ wkt_generator: ImplHelper::Utils.symbolize_hash(data_["wktg"]),
175
+ wkb_generator: ImplHelper::Utils.symbolize_hash(data_["wkbg"]),
176
+ wkt_parser: ImplHelper::Utils.symbolize_hash(data_["wktp"]),
177
+ wkb_parser: ImplHelper::Utils.symbolize_hash(data_["wkbp"]),
178
+ uses_lenient_multi_polygon_assertions: data_["lmpa"],
179
+ auto_prepare: (data_["apre"] ? :simple : :disabled),
180
+ proj4: proj4_,
181
+ coord_sys: coord_sys_
182
+ )
183
+ end
184
+
185
+ # Psych support
186
+
187
+ def encode_with(coder_) # :nodoc:
188
+ coder_["has_z_coordinate"] = @has_z
189
+ coder_["has_m_coordinate"] = @has_m
190
+ coder_["srid"] = @srid
191
+ coder_["buffer_resolution"] = @buffer_resolution
192
+ coder_["lenient_multi_polygon_assertions"] = @uses_lenient_multi_polygon_assertions
193
+ coder_["wkt_generator"] = @wkt_generator._properties
194
+ coder_["wkb_generator"] = @wkb_generator._properties
195
+ coder_["wkt_parser"] = @wkt_parser._properties
196
+ coder_["wkb_parser"] = @wkb_parser._properties
197
+ coder_["auto_prepare"] = @_auto_prepare ? "simple" : "disabled"
198
+ if @proj4
199
+ str_ = @proj4.original_str || @proj4.canonical_str
200
+ coder_["proj4"] = @proj4.radians? ? { "proj4" => str_, "radians" => true } : str_
201
+ end
202
+ coder_["coord_sys"] = @coord_sys.to_wkt if @coord_sys
203
+ end
204
+
205
+ def init_with(coder_) # :nodoc:
206
+ if (proj4_data_ = coder_["proj4"])
207
+ if proj4_data_.is_a?(::Hash)
208
+ proj4_ = CoordSys::Proj4.create(proj4_data_["proj4"], radians: proj4_data_["radians"])
209
+ else
210
+ proj4_ = CoordSys::Proj4.create(proj4_data_.to_s)
211
+ end
212
+ else
213
+ proj4_ = nil
214
+ end
215
+ if (coord_sys_data_ = coder_["cs"])
216
+ coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_.to_s)
217
+ else
218
+ coord_sys_ = nil
219
+ end
220
+ initialize(
221
+ has_z_coordinate: coder_["has_z_coordinate"],
222
+ has_m_coordinate: coder_["has_m_coordinate"],
223
+ srid: coder_["srid"],
224
+ buffer_resolution: coder_["buffer_resolution"],
225
+ wkt_generator: ImplHelper::Utils.symbolize_hash(coder_["wkt_generator"]),
226
+ wkb_generator: ImplHelper::Utils.symbolize_hash(coder_["wkb_generator"]),
227
+ wkt_parser: ImplHelper::Utils.symbolize_hash(coder_["wkt_parser"]),
228
+ wkb_parser: ImplHelper::Utils.symbolize_hash(coder_["wkb_parser"]),
229
+ auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
230
+ uses_lenient_multi_polygon_assertions: coder_["lenient_multi_polygon_assertions"],
231
+ proj4: proj4_,
232
+ coord_sys: coord_sys_
233
+ )
234
+ end
235
+
236
+ # Returns the SRID of geometries created by this factory.
237
+
238
+ attr_reader :srid
239
+
240
+ # Returns the resolution used by buffer calculations on geometries
241
+ # created by this factory
242
+
243
+ attr_reader :buffer_resolution
244
+
245
+ # Returns true if this factory is lenient with MultiPolygon assertions
246
+
247
+ def lenient_multi_polygon_assertions?
248
+ @uses_lenient_multi_polygon_assertions
249
+ end
250
+
251
+ # See ::RGeo::Feature::Factory#property
252
+
253
+ def property(name_)
254
+ case name_
255
+ when :has_z_coordinate
256
+ @has_z
257
+ when :has_m_coordinate
258
+ @has_m
259
+ when :is_cartesian
260
+ true
261
+ when :buffer_resolution
262
+ @buffer_resolution
263
+ when :uses_lenient_multi_polygon_assertions
264
+ @uses_lenient_multi_polygon_assertions
265
+ when :auto_prepare
266
+ @_auto_prepare ? :simple : :disabled
267
+ end
268
+ end
269
+
270
+ # Create a feature that wraps the given ffi-geos geometry object
271
+
272
+ def wrap_fg_geom(fg_geom_)
273
+ _wrap_fg_geom(fg_geom_, nil)
274
+ end
275
+
276
+ # See ::RGeo::Feature::Factory#parse_wkt
277
+
278
+ def parse_wkt(str_)
279
+ if @wkt_reader
280
+ _wrap_fg_geom(@wkt_reader.read(str_), nil)
281
+ else
282
+ @wkt_parser.parse(str_)
283
+ end
284
+ end
285
+
286
+ # See ::RGeo::Feature::Factory#parse_wkb
287
+
288
+ def parse_wkb(str_)
289
+ if @wkb_reader
290
+ _wrap_fg_geom(@wkb_reader.read(str_), nil)
291
+ else
292
+ @wkb_parser.parse(str_)
293
+ end
294
+ end
295
+
296
+ # See ::RGeo::Feature::Factory#point
297
+
298
+ def point(x_, y_, z_ = 0)
299
+ cs_ = ::Geos::CoordinateSequence.new(1, 3)
300
+ cs_.set_x(0, x_)
301
+ cs_.set_y(0, y_)
302
+ cs_.set_z(0, z_)
303
+ FFIPointImpl.new(self, ::Geos::Utils.create_point(cs_), nil)
304
+ end
305
+
306
+ # See ::RGeo::Feature::Factory#line_string
307
+
308
+ def line_string(points_)
309
+ points_ = points_.to_a unless points_.is_a?(::Array)
310
+ size_ = points_.size
311
+ return nil if size_ == 1
312
+ cs_ = ::Geos::CoordinateSequence.new(size_, 3)
313
+ points_.each_with_index do |p_, i_|
314
+ return nil unless ::RGeo::Feature::Point.check_type(p_)
315
+ cs_.set_x(i_, p_.x)
316
+ cs_.set_y(i_, p_.y)
317
+ if @has_z
318
+ cs_.set_z(i_, p_.z)
319
+ elsif @has_m
320
+ cs_.set_z(i_, p_.m)
321
+ end
322
+ end
323
+ FFILineStringImpl.new(self, ::Geos::Utils.create_line_string(cs_), nil)
324
+ end
325
+
326
+ # See ::RGeo::Feature::Factory#line
327
+
328
+ def line(start_, end_)
329
+ return nil unless ::RGeo::Feature::Point.check_type(start_) &&
330
+ ::RGeo::Feature::Point.check_type(end_)
331
+ cs_ = ::Geos::CoordinateSequence.new(2, 3)
332
+ cs_.set_x(0, start_.x)
333
+ cs_.set_x(1, end_.x)
334
+ cs_.set_y(0, start_.y)
335
+ cs_.set_y(1, end_.y)
336
+ if @has_z
337
+ cs_.set_z(0, start_.z)
338
+ cs_.set_z(1, end_.z)
339
+ elsif @has_m
340
+ cs_.set_z(0, start_.m)
341
+ cs_.set_z(1, end_.m)
342
+ end
343
+ FFILineImpl.new(self, ::Geos::Utils.create_line_string(cs_), nil)
344
+ end
345
+
346
+ # See ::RGeo::Feature::Factory#linear_ring
347
+
348
+ def linear_ring(points_)
349
+ points_ = points_.to_a unless points_.is_a?(::Array)
350
+ fg_geom_ = _create_fg_linear_ring(points_)
351
+ fg_geom_ ? FFILinearRingImpl.new(self, fg_geom_, nil) : nil
352
+ end
353
+
354
+ # See ::RGeo::Feature::Factory#polygon
355
+
356
+ def polygon(outer_ring_, inner_rings_ = nil)
357
+ inner_rings_ = inner_rings_.to_a unless inner_rings_.is_a?(::Array)
358
+ return nil unless ::RGeo::Feature::LineString.check_type(outer_ring_)
359
+ outer_ring_ = _create_fg_linear_ring(outer_ring_.points)
360
+ inner_rings_ = inner_rings_.map do |r_|
361
+ return nil unless ::RGeo::Feature::LineString.check_type(r_)
362
+ _create_fg_linear_ring(r_.points)
363
+ end
364
+ inner_rings_.compact!
365
+ fg_geom_ = ::Geos::Utils.create_polygon(outer_ring_, *inner_rings_)
366
+ fg_geom_ ? FFIPolygonImpl.new(self, fg_geom_, nil) : nil
367
+ end
368
+
369
+ # See ::RGeo::Feature::Factory#collection
370
+
371
+ def collection(elems_)
372
+ elems_ = elems_.to_a unless elems_.is_a?(::Array)
373
+ klasses_ = []
374
+ fg_geoms_ = []
375
+ elems_.each do |elem_|
376
+ k_ = elem_._klasses if elem_.factory.is_a?(FFIFactory)
377
+ elem_ = ::RGeo::Feature.cast(elem_, self, :force_new, :keep_subtype)
378
+ if elem_
379
+ klasses_ << (k_ || elem_.class)
380
+ fg_geoms_ << elem_._detach_fg_geom
381
+ end
382
+ end
383
+ fg_geom_ = ::Geos::Utils.create_collection(
384
+ ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION, fg_geoms_)
385
+ fg_geom_ ? FFIGeometryCollectionImpl.new(self, fg_geom_, klasses_) : nil
386
+ end
387
+
388
+ # See ::RGeo::Feature::Factory#multi_point
389
+
390
+ def multi_point(elems_)
391
+ elems_ = elems_.to_a unless elems_.is_a?(::Array)
392
+ elems_ = elems_.map do |elem_|
393
+ elem_ = ::RGeo::Feature.cast(elem_, self, ::RGeo::Feature::Point,
394
+ :force_new, :keep_subtype)
395
+ return nil unless elem_
396
+ elem_._detach_fg_geom
397
+ end
398
+ klasses_ = ::Array.new(elems_.size, FFIPointImpl)
399
+ fg_geom_ = ::Geos::Utils.create_collection(
400
+ ::Geos::GeomTypes::GEOS_MULTIPOINT, elems_)
401
+ fg_geom_ ? FFIMultiPointImpl.new(self, fg_geom_, klasses_) : nil
402
+ end
403
+
404
+ # See ::RGeo::Feature::Factory#multi_line_string
405
+
406
+ def multi_line_string(elems_)
407
+ elems_ = elems_.to_a unless elems_.is_a?(::Array)
408
+ klasses_ = []
409
+ elems_ = elems_.map do |elem_|
410
+ elem_ = ::RGeo::Feature.cast(elem_, self, ::RGeo::Feature::LineString,
411
+ :force_new, :keep_subtype)
412
+ return nil unless elem_
413
+ klasses_ << elem_.class
414
+ elem_._detach_fg_geom
415
+ end
416
+ fg_geom_ = ::Geos::Utils.create_collection(
417
+ ::Geos::GeomTypes::GEOS_MULTILINESTRING, elems_)
418
+ fg_geom_ ? FFIMultiLineStringImpl.new(self, fg_geom_, klasses_) : nil
419
+ end
420
+
421
+ # See ::RGeo::Feature::Factory#multi_polygon
422
+
423
+ def multi_polygon(elems_)
424
+ elems_ = elems_.to_a unless elems_.is_a?(::Array)
425
+ elems_ = elems_.map do |elem_|
426
+ elem_ = ::RGeo::Feature.cast(elem_, self, ::RGeo::Feature::Polygon,
427
+ :force_new, :keep_subtype)
428
+ return nil unless elem_
429
+ elem_._detach_fg_geom
430
+ end
431
+ unless @uses_lenient_multi_polygon_assertions
432
+ (1...elems_.size).each do |i_|
433
+ (0...i_).each do |j_|
434
+ igeom_ = elems_[i_]
435
+ jgeom_ = elems_[j_]
436
+ return nil if igeom_.relate_pattern(jgeom_, "2********") ||
437
+ igeom_.relate_pattern(jgeom_, "****1****")
438
+ end
439
+ end
440
+ end
441
+ klasses_ = ::Array.new(elems_.size, FFIPolygonImpl)
442
+ fg_geom_ = ::Geos::Utils.create_collection(
443
+ ::Geos::GeomTypes::GEOS_MULTIPOLYGON, elems_)
444
+ fg_geom_ ? FFIMultiPolygonImpl.new(self, fg_geom_, klasses_) : nil
445
+ end
446
+
447
+ # See ::RGeo::Feature::Factory#proj4
448
+
449
+ attr_reader :proj4
450
+
451
+ # See ::RGeo::Feature::Factory#coord_sys
452
+
453
+ attr_reader :coord_sys
454
+
455
+ # See ::RGeo::Feature::Factory#override_cast
456
+
457
+ def override_cast(_original_, _ntype_, _flags_)
458
+ false
459
+ # TODO
460
+ end
461
+
462
+ attr_reader :_has_3d # :nodoc:
463
+ attr_reader :_auto_prepare # :nodoc:
464
+
465
+ def _wrap_fg_geom(fg_geom_, klass_) # :nodoc:
466
+ klasses_ = nil
467
+
468
+ # We don't allow "empty" points, so replace such objects with
469
+ # an empty collection.
470
+ if fg_geom_.type_id == ::Geos::GeomTypes::GEOS_POINT && fg_geom_.empty?
471
+ fg_geom_ = ::Geos::Utils.create_geometry_collection
472
+ klass_ = FFIGeometryCollectionImpl
473
+ end
474
+
475
+ unless klass_.is_a?(::Class)
476
+ is_collection_ = false
477
+ case fg_geom_.type_id
478
+ when ::Geos::GeomTypes::GEOS_POINT
479
+ inferred_klass_ = FFIPointImpl
480
+ when ::Geos::GeomTypes::GEOS_MULTIPOINT
481
+ inferred_klass_ = FFIMultiPointImpl
482
+ is_collection_ = true
483
+ when ::Geos::GeomTypes::GEOS_LINESTRING
484
+ inferred_klass_ = FFILineStringImpl
485
+ when ::Geos::GeomTypes::GEOS_LINEARRING
486
+ inferred_klass_ = FFILinearRingImpl
487
+ when ::Geos::GeomTypes::GEOS_MULTILINESTRING
488
+ inferred_klass_ = FFIMultiLineStringImpl
489
+ is_collection_ = true
490
+ when ::Geos::GeomTypes::GEOS_POLYGON
491
+ inferred_klass_ = FFIPolygonImpl
492
+ when ::Geos::GeomTypes::GEOS_MULTIPOLYGON
493
+ inferred_klass_ = FFIMultiPolygonImpl
494
+ is_collection_ = true
495
+ when ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION
496
+ inferred_klass_ = FFIGeometryCollectionImpl
497
+ is_collection_ = true
498
+ else
499
+ inferred_klass_ = FFIGeometryImpl
500
+ end
501
+ klasses_ = klass_ if is_collection_ && klass_.is_a?(::Array)
502
+ klass_ = inferred_klass_
503
+ end
504
+ klass_.new(self, fg_geom_, klasses_)
505
+ end
506
+
507
+ def _convert_to_fg_geometry(obj_, type_ = nil) # :nodoc:
508
+ if type_.nil? && obj_.factory == self
509
+ obj_
510
+ else
511
+ obj_ = Feature.cast(obj_, self, type_)
512
+ end
513
+ obj_ ? obj_.fg_geom : nil
514
+ end
515
+
516
+ def _create_fg_linear_ring(points_) # :nodoc:
517
+ size_ = points_.size
518
+ return nil if size_ == 1 || size_ == 2
519
+ if size_ > 0 && points_.first != points_.last
520
+ points_ += [points_.first]
521
+ size_ += 1
522
+ end
523
+ cs_ = ::Geos::CoordinateSequence.new(size_, 3)
524
+ points_.each_with_index do |p_, i_|
525
+ return nil unless ::RGeo::Feature::Point.check_type(p_)
526
+ cs_.set_x(i_, p_.x)
527
+ cs_.set_y(i_, p_.y)
528
+ if @has_z
529
+ cs_.set_z(i_, p_.z)
530
+ elsif @has_m
531
+ cs_.set_z(i_, p_.m)
532
+ end
533
+ end
534
+ ::Geos::Utils.create_linear_ring(cs_)
535
+ end
536
+
537
+ def _generate_wkt(geom_) # :nodoc:
538
+ if @wkt_writer
539
+ @wkt_writer.write(geom_.fg_geom)
540
+ else
541
+ @wkt_generator.generate(geom_)
542
+ end
543
+ end
544
+
545
+ def _generate_wkb(geom_) # :nodoc:
546
+ if @wkb_writer
547
+ @wkb_writer.write(geom_.fg_geom)
548
+ else
549
+ @wkb_generator.generate(geom_)
550
+ end
551
+ end
552
+
553
+ def _write_for_marshal(geom_) # :nodoc:
554
+ if Utils.ffi_supports_set_output_dimension || !@_has_3d
555
+ unless defined?(@marshal_wkb_writer)
556
+ @marshal_wkb_writer = ::Geos::WkbWriter.new
557
+ @marshal_wkb_writer.output_dimensions = 3 if @_has_3d
558
+ end
559
+ @marshal_wkb_writer.write(geom_.fg_geom)
560
+ else
561
+ Utils.marshal_wkb_generator.generate(geom_)
562
+ end
563
+ end
564
+
565
+ def _read_for_marshal(str_) # :nodoc:
566
+ unless defined?(@marshal_wkb_reader)
567
+ @marshal_wkb_reader = ::Geos::WkbReader.new
568
+ end
569
+ @marshal_wkb_reader.read(str_)
570
+ end
571
+
572
+ def _write_for_psych(geom_) # :nodoc:
573
+ if Utils.ffi_supports_set_output_dimension || !@_has_3d
574
+ unless defined?(@psych_wkt_writer)
575
+ @psych_wkt_writer = ::Geos::WktWriter.new
576
+ @psych_wkt_writer.output_dimensions = 3 if @_has_3d
577
+ end
578
+ @psych_wkt_writer.write(geom_.fg_geom)
579
+ else
580
+ Utils.psych_wkt_generator.generate(geom_)
581
+ end
582
+ end
583
+
584
+ def _read_for_psych(str_) # :nodoc:
585
+ unless defined?(@psych_wkt_reader)
586
+ @psych_wkt_reader = ::Geos::WktReader.new
587
+ end
588
+ @psych_wkt_reader.read(str_)
589
+ end
590
+ end
591
+ end
592
+ end