ffi-geos 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -9,15 +9,21 @@
9
9
 
10
10
  Ruby versions known to work:
11
11
 
12
- * Ruby MRI 1.8.7 and 1.9.2, x86_64, OSX 10.6.5+
12
+ * Ruby MRI 1.8.7, 1.9.2 and 1.9.3 x86_64, OSX 10.6.5+
13
13
  * Ruby MRI 1.8.7 and 1.9.2, i386, linux
14
- * Ruby MRI 1.8.7, x86_64, linux
15
- * JRuby 1.6.3, x86_64 OSX 10.6.5+
14
+ * Ruby MRI 1.8.7, 1.9.2 and 1.9.3, x86_64, linux
15
+ * JRuby 1.6, x86_64 OSX 10.6.5+
16
+
17
+ === JRuby Notes
16
18
 
17
19
  Note that versions of JRuby prior to version 1.6.3 have problems in their ffi
18
20
  implementation when dealing with AutoPointers that can lead to segfaults during
19
21
  garbage collection.
20
22
 
23
+ JRuby 1.7.0 is exhibiting some strange and sporadic memory problems that are
24
+ difficult to lock down. Unit tests show that the errors do not occur 100% of
25
+ the time, so it has been difficult to trace the root cause of the errors.
26
+
21
27
  == Features
22
28
 
23
29
  ffi-geos supports all of the features found in the binary SWIG-based GEOS
@@ -54,6 +60,13 @@ Ruby bindings along with the following enhancements and additions:
54
60
 
55
61
  == New Methods and Additions (not exhaustive)
56
62
 
63
+ * SRIDs can be copied on many operations. GEOS doesn't usually copy SRIDs
64
+ around, but for the sake of convenience, we do. The default behaviour for
65
+ SRID copying can be set via the Geos.srid_copy_policy= method. The default
66
+ behaviour is to use 0 values as before, but you can optionally allow for
67
+ copying in either a lenient or a strict sort of manner. See the documentation
68
+ for Geos.srid_copy_policy= for details.
69
+
57
70
  === Geos
58
71
 
59
72
  * Geos.create_multi_point
@@ -149,3 +162,8 @@ Ruby bindings along with the following enhancements and additions:
149
162
 
150
163
  * Charlie Savage for the original SWIG-based GEOS bindings implementation and
151
164
  some fixes for MinGW.
165
+
166
+ == License
167
+
168
+ This gem is licensed under an MIT-style license. See the +MIT-LICENSE+ file for
169
+ details.
data/ffi-geos.gemspec CHANGED
@@ -23,5 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency("ffi", [">= 1.0.0"])
24
24
  s.add_dependency("rdoc")
25
25
  s.add_dependency("rake", ["~> 0.9"])
26
+ s.add_dependency("minitest")
27
+ s.add_dependency("turn")
26
28
  end
27
29
 
data/lib/ffi-geos.rb CHANGED
@@ -59,15 +59,19 @@ module Geos
59
59
  end
60
60
 
61
61
  def self.find_lib(lib)
62
- Dir.glob(search_paths.map { |path|
63
- File.expand_path(File.join(path, "#{lib}.#{FFI::Platform::LIBSUFFIX}"))
64
- }).first
62
+ if ENV['GEOS_LIBRARY_PATH'] && File.file?(ENV['GEOS_LIBRARY_PATH'])
63
+ ENV['GEOS_LIBRARY_PATH']
64
+ else
65
+ Dir.glob(search_paths.map { |path|
66
+ File.expand_path(File.join(path, "#{lib}.#{FFI::Platform::LIBSUFFIX}"))
67
+ }).first
68
+ end
65
69
  end
66
70
 
67
71
  def self.geos_library_path
68
72
  @geos_library_path ||= begin
69
73
  # On MingW the libraries have version numbers
70
- find_lib('libgeos_c{,-?}')
74
+ find_lib('{lib,}geos_c{,-?}')
71
75
  end
72
76
  end
73
77
 
@@ -79,8 +83,6 @@ module Geos
79
83
 
80
84
  extend ::FFI::Library
81
85
 
82
- ffi_lib(geos_library_path)
83
-
84
86
  Geos::DimensionTypes = enum(:dimension_type, [
85
87
  :dontcare, -3,
86
88
  :non_empty, -2,
@@ -626,6 +628,11 @@ module Geos
626
628
  :int, :pointer, :pointer, :pointer
627
629
  ],
628
630
 
631
+ :GEOSGeomGetZ_r => [
632
+ # -1 on exception, *handle, *geom, *point
633
+ :int, :pointer, :pointer, :pointer
634
+ ],
635
+
629
636
  :GEOSGeomGetPointN_r => [
630
637
  # *point, *handle, *geom, n
631
638
  :pointer, :pointer, :pointer, :int
@@ -940,15 +947,25 @@ module Geos
940
947
  #### /Algorithms ####
941
948
  }
942
949
 
943
- FFI_LAYOUT.each do |fun, ary|
944
- ret = ary.shift
945
- begin
946
- self.class_eval do
947
- attach_function(fun, ary, ret)
950
+ begin
951
+ ffi_lib(geos_library_path)
952
+
953
+ FFI_LAYOUT.each do |fun, ary|
954
+ ret = ary.shift
955
+ begin
956
+ self.class_eval do
957
+ attach_function(fun, ary, ret)
958
+ end
959
+ rescue FFI::NotFoundError
960
+ # that's okay
948
961
  end
949
- rescue FFI::NotFoundError
950
- # that's okay
951
962
  end
963
+
964
+ # Checks to see if we actually have the GEOS library loaded.
965
+ FFIGeos.GEOSversion
966
+
967
+ rescue LoadError, NoMethodError
968
+ raise LoadError.new("Couldn't load the GEOS CAPI library.")
952
969
  end
953
970
  end
954
971
 
@@ -989,6 +1006,54 @@ module Geos
989
1006
  Thread.current[:ffi_geos_handle].ptr
990
1007
  end
991
1008
 
1009
+ def srid_copy_policy
1010
+ Thread.current[:ffi_geos_srid_copy_policy] ||= srid_copy_policy_default
1011
+ end
1012
+
1013
+ # Sets the SRID copying behaviour. This value can be one of the values
1014
+ # found in Geos::Constants::SRID_COPY_POLICIES and are local to the
1015
+ # current thread. A special value of +:default+ can also be used, which
1016
+ # will use a global default that can be set with srid_copy_policy_default=.
1017
+ # Setting this value will cause all future threads to use this global
1018
+ # default rather than the true default value which is set to +:zero+ for
1019
+ # the sake of backwards compatibility with
1020
+ #
1021
+ # The available values for +policy+ are:
1022
+ #
1023
+ # * +:default+ - use the value set with srid_copy_policy_default=,
1024
+ # which itself is +:zero+.
1025
+ # * +:zero+ - set all SRIDs to 0. The only exception to this is when
1026
+ # cloning a Geometry, in which the SRID is always copied as per the
1027
+ # previous behaviour.
1028
+ # * +:lenient+ - when copying SRIDs, use the SRID of the object that the
1029
+ # operation is being performed on, even if operation involves multiple
1030
+ # Geometry objects that may have different SRIDs.
1031
+ # * +:strict+ - when copying SRIDs, raise a Geos::MixedSRIDsError exception
1032
+ # if an operation is performed on mixed SRIDs. This setting
1033
+ def srid_copy_policy=(policy)
1034
+ if policy == :default
1035
+ Thread.current[:ffi_geos_srid_copy_policy] = srid_copy_policy_default
1036
+ elsif Geos::Constants::SRID_COPY_POLICIES.include?(policy)
1037
+ Thread.current[:ffi_geos_srid_copy_policy] = policy
1038
+ else
1039
+ raise ArgumentError.new("Invalid SRID policy #{policy} (must be one of #{Geos::Constants::SRID_COPY_POLICIES})")
1040
+ end
1041
+ end
1042
+
1043
+ def srid_copy_policy_default
1044
+ @srid_copy_policy_default ||= :zero
1045
+ end
1046
+
1047
+ def srid_copy_policy_default=(policy)
1048
+ if policy == :default
1049
+ @srid_copy_policy_default = :zero
1050
+ elsif Geos::Constants::SRID_COPY_POLICIES.include?(policy)
1051
+ @srid_copy_policy_default = policy
1052
+ else
1053
+ raise ArgumentError.new("Invalid SRID policy #{policy} (must be one of #{Geos::Constants::SRID_COPY_POLICIES})")
1054
+ end
1055
+ end
1056
+
992
1057
  %w{
993
1058
  create_point
994
1059
  create_line_string
@@ -1070,6 +1135,18 @@ module Geos
1070
1135
  :join => :round,
1071
1136
  :mitre_limit => 5.0
1072
1137
  }.freeze
1138
+
1139
+ SRID_COPY_POLICIES = [
1140
+ :zero,
1141
+ :lenient,
1142
+ :strict
1143
+ ].freeze
1144
+ end
1145
+
1146
+ class MixedSRIDsError < RuntimeError
1147
+ def initialize(srid_a, srid_b)
1148
+ super("Operation on mixed SRIDs (#{srid_a} vs. #{srid_b})")
1149
+ end
1073
1150
  end
1074
1151
 
1075
1152
  include GeomTypes
@@ -95,12 +95,10 @@ module Geos
95
95
 
96
96
  @ptr = FFI::AutoPointer.new(
97
97
  ptr,
98
- auto_free ? self.class.method(:release) : self.class.method(:no_release)
98
+ self.class.method(:release)
99
99
  )
100
100
 
101
- if !auto_free
102
- @ptr.autorelease = false
103
- end
101
+ @ptr.autorelease = auto_free
104
102
 
105
103
  @x = CoordinateAccessor.new(self, 0)
106
104
  @y = CoordinateAccessor.new(self, 1)
@@ -120,9 +118,10 @@ module Geos
120
118
  FFIGeos.GEOSCoordSeq_clone_r(Geos.current_handle, source.ptr),
121
119
  self.class.method(:release)
122
120
  )
123
- end
124
121
 
125
- def self.no_release(ptr) #:nodoc:
122
+ @x = CoordinateAccessor.new(self, 0)
123
+ @y = CoordinateAccessor.new(self, 1)
124
+ @z = CoordinateAccessor.new(self, 2)
126
125
  end
127
126
 
128
127
  def self.release(ptr) #:nodoc:
@@ -144,6 +143,22 @@ module Geos
144
143
  end
145
144
  end
146
145
 
146
+ def [](*args)
147
+ if args.length == 1 && args.first.is_a?(Numeric) && args.first >= 0
148
+ i = args.first
149
+ ary = [ self.get_x(i), self.get_y(i) ]
150
+ ary << self.get_z(i) if self.has_z?
151
+ ary
152
+ else
153
+ self.to_a[*args]
154
+ end
155
+ end
156
+ alias :slice :[]
157
+
158
+ def has_z?
159
+ self.dimensions == 3
160
+ end
161
+
147
162
  # Sets the x value of a coordinate. Can also be set via #x[]=.
148
163
  def set_x(idx, val)
149
164
  self.check_bounds(idx)
@@ -215,20 +230,20 @@ module Geos
215
230
  }.read_int
216
231
  end
217
232
 
218
- def to_point
219
- Geos.create_point(self)
233
+ def to_point(options = {})
234
+ Geos.create_point(self, :srid => options[:srid])
220
235
  end
221
236
 
222
- def to_linear_ring
223
- Geos.create_linear_ring(self)
237
+ def to_linear_ring(options = {})
238
+ Geos.create_linear_ring(self, :srid => options[:srid])
224
239
  end
225
240
 
226
- def to_line_string
227
- Geos.create_line_string(self)
241
+ def to_line_string(options = {})
242
+ Geos.create_line_string(self, :srid => options[:srid])
228
243
  end
229
244
 
230
- def to_polygon
231
- Geos.create_polygon(self)
245
+ def to_polygon(options = {})
246
+ Geos.create_polygon(self, :srid => options[:srid])
232
247
  end
233
248
 
234
249
  def to_s
@@ -10,12 +10,10 @@ module Geos
10
10
  def initialize(ptr, auto_free = true)
11
11
  @ptr = FFI::AutoPointer.new(
12
12
  ptr,
13
- auto_free ? self.class.method(:release) : self.class.method(:no_release)
13
+ self.class.method(:release)
14
14
  )
15
15
 
16
- if !auto_free
17
- @ptr.autorelease = false
18
- end
16
+ @ptr.autorelease = auto_free
19
17
  end
20
18
 
21
19
  def initialize_copy(source)
@@ -28,9 +26,6 @@ module Geos
28
26
  self.srid = source.srid
29
27
  end
30
28
 
31
- def self.no_release(ptr) #:nodoc:
32
- end
33
-
34
29
  def self.release(ptr) #:nodoc:
35
30
  FFIGeos.GEOSGeom_destroy_r(Geos.current_handle, ptr)
36
31
  end
@@ -80,7 +75,9 @@ module Geos
80
75
 
81
76
  def intersection(geom)
82
77
  check_geometry(geom)
83
- cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle, self.ptr, geom.ptr))
78
+ cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle, self.ptr, geom.ptr), {
79
+ :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
80
+ })
84
81
  end
85
82
 
86
83
  if FFIGeos.respond_to?(:GEOSBufferWithParams_r)
@@ -110,7 +107,7 @@ module Geos
110
107
  raise ArgumentError.new("Expected Geos::BufferParams, a Hash or a Numeric")
111
108
  end
112
109
 
113
- cast_geometry_ptr(FFIGeos.GEOSBufferWithParams_r(Geos.current_handle, self.ptr, params.ptr, width))
110
+ cast_geometry_ptr(FFIGeos.GEOSBufferWithParams_r(Geos.current_handle, self.ptr, params.ptr, width), :srid_copy => self.srid)
114
111
  end
115
112
  else
116
113
  def buffer(width, options = nil)
@@ -126,26 +123,31 @@ module Geos
126
123
  raise ArgumentError.new("Expected Geos::BufferParams, a Hash or a Numeric")
127
124
  end
128
125
 
129
- cast_geometry_ptr(FFIGeos.GEOSBuffer_r(Geos.current_handle, self.ptr, width, quad_segs))
126
+ cast_geometry_ptr(FFIGeos.GEOSBuffer_r(Geos.current_handle, self.ptr, width, quad_segs), :srid_copy => self.srid)
130
127
  end
131
128
  end
132
129
 
133
130
  def convex_hull
134
- cast_geometry_ptr(FFIGeos.GEOSConvexHull_r(Geos.current_handle, self.ptr))
131
+ cast_geometry_ptr(FFIGeos.GEOSConvexHull_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
135
132
  end
136
133
 
137
134
  def difference(geom)
138
135
  check_geometry(geom)
139
- cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle, self.ptr, geom.ptr))
136
+ cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle, self.ptr, geom.ptr), {
137
+ :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
138
+ })
140
139
  end
141
140
 
142
141
  def sym_difference(geom)
143
142
  check_geometry(geom)
144
- cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle, self.ptr, geom.ptr))
143
+ cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle, self.ptr, geom.ptr), {
144
+ :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
145
+ })
145
146
  end
147
+ alias :symmetric_difference :sym_difference
146
148
 
147
149
  def boundary
148
- cast_geometry_ptr(FFIGeos.GEOSBoundary_r(Geos.current_handle, self.ptr))
150
+ cast_geometry_ptr(FFIGeos.GEOSBoundary_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
149
151
  end
150
152
 
151
153
  # Calling without a geom argument is equivalent to calling unary_union when
@@ -154,7 +156,9 @@ module Geos
154
156
  def union(geom = nil)
155
157
  if geom
156
158
  check_geometry(geom)
157
- cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle, self.ptr, geom.ptr))
159
+ cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle, self.ptr, geom.ptr), {
160
+ :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
161
+ })
158
162
  else
159
163
  if self.respond_to?(:unary_union)
160
164
  self.unary_union
@@ -165,27 +169,32 @@ module Geos
165
169
  end
166
170
 
167
171
  def union_cascaded
168
- cast_geometry_ptr(FFIGeos.GEOSUnionCascaded_r(Geos.current_handle, self.ptr))
172
+ cast_geometry_ptr(FFIGeos.GEOSUnionCascaded_r(Geos.current_handle, self.ptr), {
173
+ :srid_copy => self.srid
174
+ })
169
175
  end
170
176
 
171
177
  if FFIGeos.respond_to?(:GEOSUnaryUnion_r)
172
178
  # Available in GEOS 3.3+
173
179
  def unary_union
174
- cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle, self.ptr))
180
+ cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle, self.ptr), {
181
+ :srid_copy => self.srid
182
+ })
175
183
  end
176
184
  end
177
185
 
178
186
  def point_on_surface
179
- cast_geometry_ptr(FFIGeos.GEOSPointOnSurface_r(Geos.current_handle, self.ptr))
187
+ cast_geometry_ptr(FFIGeos.GEOSPointOnSurface_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
180
188
  end
189
+ alias :representative_point :point_on_surface
181
190
 
182
191
  def centroid
183
- cast_geometry_ptr(FFIGeos.GEOSGetCentroid_r(Geos.current_handle, self.ptr))
192
+ cast_geometry_ptr(FFIGeos.GEOSGetCentroid_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
184
193
  end
185
194
  alias :center :centroid
186
195
 
187
196
  def envelope
188
- cast_geometry_ptr(FFIGeos.GEOSEnvelope_r(Geos.current_handle, self.ptr))
197
+ cast_geometry_ptr(FFIGeos.GEOSEnvelope_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
189
198
  end
190
199
 
191
200
  # Returns the Dimensionally Extended Nine-Intersection Model (DE-9IM)
@@ -211,19 +220,19 @@ module Geos
211
220
  end
212
221
 
213
222
  def line_merge
214
- cast_geometry_ptr(FFIGeos.GEOSLineMerge_r(Geos.current_handle, self.ptr))
223
+ cast_geometry_ptr(FFIGeos.GEOSLineMerge_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
215
224
  end
216
225
 
217
226
  def simplify(tolerance)
218
- cast_geometry_ptr(FFIGeos.GEOSSimplify_r(Geos.current_handle, self.ptr, tolerance))
227
+ cast_geometry_ptr(FFIGeos.GEOSSimplify_r(Geos.current_handle, self.ptr, tolerance), :srid_copy => self.srid)
219
228
  end
220
229
 
221
230
  def topology_preserve_simplify(tolerance)
222
- cast_geometry_ptr(FFIGeos.GEOSTopologyPreserveSimplify_r(Geos.current_handle, self.ptr, tolerance))
231
+ cast_geometry_ptr(FFIGeos.GEOSTopologyPreserveSimplify_r(Geos.current_handle, self.ptr, tolerance), :srid_copy => self.srid)
223
232
  end
224
233
 
225
234
  def extract_unique_points
226
- cast_geometry_ptr(FFIGeos.GEOSGeom_extractUniquePoints_r(Geos.current_handle, self.ptr))
235
+ cast_geometry_ptr(FFIGeos.GEOSGeom_extractUniquePoints_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
227
236
  end
228
237
  alias :unique_points :extract_unique_points
229
238
 
@@ -311,11 +320,21 @@ module Geos
311
320
  bool_result(FFIGeos.GEOSEquals_r(Geos.current_handle, self.ptr, geom.ptr))
312
321
  end
313
322
  alias :== :eql?
323
+ alias :equals? :eql?
314
324
 
315
325
  def eql_exact?(geom, tolerance)
316
326
  check_geometry(geom)
317
327
  bool_result(FFIGeos.GEOSEqualsExact_r(Geos.current_handle, self.ptr, geom.ptr, tolerance))
318
328
  end
329
+ alias :equals_exact? :eql_exact?
330
+ alias :exactly_equals? :eql_exact?
331
+
332
+ def eql_almost?(geom, decimal = 6)
333
+ check_geometry(geom)
334
+ bool_result(FFIGeos.GEOSEqualsExact_r(Geos.current_handle, self.ptr, geom.ptr, 0.5 * 10 ** (-decimal)))
335
+ end
336
+ alias :equals_almost? :eql_almost?
337
+ alias :almost_equals? :eql_almost?
319
338
 
320
339
  def empty?
321
340
  bool_result(FFIGeos.GEOSisEmpty_r(Geos.current_handle, self.ptr))
@@ -348,7 +367,9 @@ module Geos
348
367
  if !valid
349
368
  {
350
369
  :detail => detail.read_pointer.read_string,
351
- :location => cast_geometry_ptr(location.read_pointer)
370
+ :location => cast_geometry_ptr(location.read_pointer, {
371
+ :srid_copy => self.srid
372
+ })
352
373
  }
353
374
  end
354
375
  end
@@ -390,7 +411,7 @@ module Geos
390
411
  FFIGeos.GEOSInterpolate_r(Geos.current_handle, self.ptr, d)
391
412
  end
392
413
 
393
- cast_geometry_ptr(ret)
414
+ cast_geometry_ptr(ret, :srid_copy => self.srid)
394
415
  end
395
416
 
396
417
  def interpolate_normalized(d)
@@ -398,23 +419,31 @@ module Geos
398
419
  end
399
420
 
400
421
  def start_point
401
- cast_geometry_ptr(FFIGeos.GEOSGeomGetStartPoint_r(Geos.current_handle, self.ptr))
422
+ cast_geometry_ptr(FFIGeos.GEOSGeomGetStartPoint_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
402
423
  end
403
424
 
404
425
  def end_point
405
- cast_geometry_ptr(FFIGeos.GEOSGeomGetEndPoint_r(Geos.current_handle, self.ptr))
426
+ cast_geometry_ptr(FFIGeos.GEOSGeomGetEndPoint_r(Geos.current_handle, self.ptr), :srid_copy => self.srid)
406
427
  end
407
428
 
408
429
  def area
409
- FFI::MemoryPointer.new(:double).tap { |ret|
410
- FFIGeos.GEOSArea_r(Geos.current_handle, self.ptr, ret)
411
- }.read_double
430
+ if self.empty?
431
+ 0
432
+ else
433
+ FFI::MemoryPointer.new(:double).tap { |ret|
434
+ FFIGeos.GEOSArea_r(Geos.current_handle, self.ptr, ret)
435
+ }.read_double
436
+ end
412
437
  end
413
438
 
414
439
  def length
415
- FFI::MemoryPointer.new(:double).tap { |ret|
416
- FFIGeos.GEOSLength_r(Geos.current_handle, self.ptr, ret)
417
- }.read_double
440
+ if self.empty?
441
+ 0
442
+ else
443
+ FFI::MemoryPointer.new(:double).tap { |ret|
444
+ FFIGeos.GEOSLength_r(Geos.current_handle, self.ptr, ret)
445
+ }.read_double
446
+ end
418
447
  end
419
448
 
420
449
  def distance(geom)
@@ -437,13 +466,17 @@ module Geos
437
466
 
438
467
  def snap(geom, tolerance)
439
468
  check_geometry(geom)
440
- cast_geometry_ptr(FFIGeos.GEOSSnap_r(Geos.current_handle, self.ptr, geom.ptr, tolerance))
469
+ cast_geometry_ptr(FFIGeos.GEOSSnap_r(Geos.current_handle, self.ptr, geom.ptr, tolerance), {
470
+ :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
471
+ })
441
472
  end
442
473
  alias :snap_to :snap
443
474
 
444
475
  def shared_paths(geom)
445
476
  check_geometry(geom)
446
- cast_geometry_ptr(FFIGeos.GEOSSharedPaths_r(Geos.current_handle, self.ptr, geom.ptr)).to_a
477
+ cast_geometry_ptr(FFIGeos.GEOSSharedPaths_r(Geos.current_handle, self.ptr, geom.ptr), {
478
+ :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
479
+ }).to_a
447
480
  end
448
481
 
449
482
  # Returns a Hash with the following structure:
@@ -460,12 +493,14 @@ module Geos
460
493
  invalid_rings = FFI::MemoryPointer.new(:pointer)
461
494
 
462
495
  rings = cast_geometry_ptr(
463
- FFIGeos.GEOSPolygonize_full_r(Geos.current_handle, self.ptr, cuts, dangles, invalid_rings)
496
+ FFIGeos.GEOSPolygonize_full_r(Geos.current_handle, self.ptr, cuts, dangles, invalid_rings), {
497
+ :srid_copy => self.srid
498
+ }
464
499
  )
465
500
 
466
- cuts = cast_geometry_ptr(cuts.read_pointer)
467
- dangles = cast_geometry_ptr(dangles.read_pointer)
468
- invalid_rings = cast_geometry_ptr(invalid_rings.read_pointer)
501
+ cuts = cast_geometry_ptr(cuts.read_pointer, :srid_copy => self.srid)
502
+ dangles = cast_geometry_ptr(dangles.read_pointer, :srid_copy => self.srid)
503
+ invalid_rings = cast_geometry_ptr(invalid_rings.read_pointer, :srid_copy => self.srid)
469
504
 
470
505
  {
471
506
  :rings => rings.to_a,
@@ -479,14 +514,14 @@ module Geos
479
514
  ary = FFI::MemoryPointer.new(:pointer)
480
515
  ary.write_array_of_pointer([ self.ptr ])
481
516
 
482
- cast_geometry_ptr(FFIGeos.GEOSPolygonize_r(Geos.current_handle, ary, 1)).to_a
517
+ cast_geometry_ptr(FFIGeos.GEOSPolygonize_r(Geos.current_handle, ary, 1), :srid_copy => self.srid).to_a
483
518
  end
484
519
 
485
520
  def polygonize_cut_edges
486
521
  ary = FFI::MemoryPointer.new(:pointer)
487
522
  ary.write_array_of_pointer([ self.ptr ])
488
523
 
489
- cast_geometry_ptr(FFIGeos.GEOSPolygonizer_getCutEdges_r(Geos.current_handle, ary, 1)).to_a
524
+ cast_geometry_ptr(FFIGeos.GEOSPolygonizer_getCutEdges_r(Geos.current_handle, ary, 1), :srid_copy => self.srid).to_a
490
525
  end
491
526
 
492
527
  def to_prepared