ffi-geos 1.2.2 → 2.3.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +49 -0
- data/.rubocop.yml +5117 -4
- data/FUNDING.yml +2 -0
- data/Gemfile +9 -16
- data/Guardfile +3 -4
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -20
- data/Rakefile +3 -2
- data/ffi-geos.gemspec +7 -2
- data/lib/ffi-geos/buffer_params.rb +1 -1
- data/lib/ffi-geos/coordinate_sequence.rb +179 -177
- data/lib/ffi-geos/geometry.rb +118 -31
- data/lib/ffi-geos/geometry_collection.rb +26 -12
- data/lib/ffi-geos/interrupt.rb +11 -14
- data/lib/ffi-geos/line_string.rb +64 -49
- data/lib/ffi-geos/multi_line_string.rb +1 -1
- data/lib/ffi-geos/point.rb +18 -18
- data/lib/ffi-geos/polygon.rb +44 -30
- data/lib/ffi-geos/prepared_geometry.rb +1 -1
- data/lib/ffi-geos/strtree.rb +28 -30
- data/lib/ffi-geos/tools.rb +1 -1
- data/lib/ffi-geos/utils.rb +16 -23
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkb_reader.rb +1 -1
- data/lib/ffi-geos/wkb_writer.rb +4 -5
- data/lib/ffi-geos/wkt_reader.rb +1 -1
- data/lib/ffi-geos/wkt_writer.rb +7 -13
- data/lib/ffi-geos.rb +134 -48
- data/sonar-project.properties +16 -0
- data/test/coordinate_sequence_tests.rb +148 -126
- data/test/geometry_collection_tests.rb +41 -67
- data/test/geometry_tests.rb +341 -40
- data/test/interrupt_tests.rb +7 -7
- data/test/line_string_tests.rb +23 -15
- data/test/point_tests.rb +5 -5
- data/test/polygon_tests.rb +6 -7
- data/test/prepared_geometry_tests.rb +8 -8
- data/test/strtree_tests.rb +13 -12
- data/test/test_helper.rb +74 -56
- data/test/utils_tests.rb +69 -59
- data/test/wkb_reader_tests.rb +9 -9
- data/test/wkb_writer_tests.rb +14 -12
- data/test/wkt_reader_tests.rb +0 -1
- data/test/wkt_writer_tests.rb +2 -5
- metadata +12 -10
- data/.travis.yml +0 -21
data/lib/ffi-geos/polygon.rb
CHANGED
@@ -34,7 +34,7 @@ module Geos
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def dump_points(cur_path = [])
|
37
|
-
points = [
|
37
|
+
points = [exterior_ring.dump_points]
|
38
38
|
|
39
39
|
interior_rings.each do |ring|
|
40
40
|
points.push(ring.dump_points)
|
@@ -44,25 +44,25 @@ module Geos
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def snap_to_grid!(*args)
|
47
|
-
|
47
|
+
unless empty?
|
48
48
|
exterior_ring = self.exterior_ring.coord_seq.snap_to_grid!(*args)
|
49
49
|
|
50
|
-
if exterior_ring.
|
51
|
-
@ptr = Geos.create_empty_polygon(:
|
50
|
+
if exterior_ring.empty?
|
51
|
+
@ptr = Geos.create_empty_polygon(srid: srid).ptr
|
52
52
|
elsif exterior_ring.length < 4
|
53
|
-
raise Geos::InvalidGeometryError
|
53
|
+
raise Geos::InvalidGeometryError, "snap_to_grid! produced an invalid number of points in exterior ring - found #{exterior_ring.length} - must be 0 or >= 4"
|
54
54
|
else
|
55
55
|
interior_rings = []
|
56
56
|
|
57
|
-
|
58
|
-
interior_ring =
|
57
|
+
num_interior_rings.times do |i|
|
58
|
+
interior_ring = interior_ring_n(i).coord_seq.snap_to_grid!(*args)
|
59
59
|
|
60
60
|
interior_rings << interior_ring unless interior_ring.length < 4
|
61
|
-
|
61
|
+
end
|
62
62
|
|
63
63
|
interior_rings.compact!
|
64
64
|
|
65
|
-
polygon = Geos.create_polygon(exterior_ring, interior_rings, :
|
65
|
+
polygon = Geos.create_polygon(exterior_ring, interior_rings, srid: srid)
|
66
66
|
@ptr = polygon.ptr
|
67
67
|
end
|
68
68
|
end
|
@@ -71,33 +71,47 @@ module Geos
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def snap_to_grid(*args)
|
74
|
-
ret =
|
75
|
-
ret.srid = pick_srid_according_to_policy(
|
74
|
+
ret = dup.snap_to_grid!(*args)
|
75
|
+
ret.srid = pick_srid_according_to_policy(srid)
|
76
76
|
ret
|
77
77
|
end
|
78
78
|
|
79
79
|
%w{ max min }.each do |op|
|
80
80
|
%w{ x y }.each do |dimension|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
native_method = "GEOSGeom_get#{dimension.upcase}#{op[0].upcase}#{op[1..-1]}_r"
|
82
|
+
|
83
|
+
if FFIGeos.respond_to?(native_method)
|
84
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
85
|
+
def #{dimension}_#{op}
|
86
|
+
return if empty?
|
87
|
+
|
88
|
+
double_ptr = FFI::MemoryPointer.new(:double)
|
89
|
+
FFIGeos.#{native_method}(Geos.current_handle_pointer, ptr, double_ptr)
|
90
|
+
double_ptr.read_double
|
85
91
|
end
|
86
|
-
|
87
|
-
|
92
|
+
RUBY
|
93
|
+
else
|
94
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
95
|
+
def #{dimension}_#{op}
|
96
|
+
unless empty?
|
97
|
+
envelope.exterior_ring.#{dimension}_#{op}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
RUBY
|
101
|
+
end
|
88
102
|
end
|
89
103
|
|
90
|
-
|
104
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
91
105
|
def z_#{op}
|
92
|
-
unless
|
93
|
-
if
|
94
|
-
|
106
|
+
unless empty?
|
107
|
+
if has_z?
|
108
|
+
exterior_ring.z_#{op}
|
95
109
|
else
|
96
110
|
0
|
97
111
|
end
|
98
112
|
end
|
99
113
|
end
|
100
|
-
|
114
|
+
RUBY
|
101
115
|
end
|
102
116
|
|
103
117
|
%w{
|
@@ -110,21 +124,21 @@ module Geos
|
|
110
124
|
trans_scale
|
111
125
|
translate
|
112
126
|
}.each do |m|
|
113
|
-
|
114
|
-
def #{m}!(*args)
|
115
|
-
|
116
|
-
|
127
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
128
|
+
def #{m}!(*args, **kwargs)
|
129
|
+
exterior_ring.coord_seq.#{m}!(*args, **kwargs)
|
130
|
+
interior_rings.each do |ring|
|
117
131
|
ring.coord_seq.#{m}!(*args)
|
118
132
|
end
|
119
133
|
self
|
120
134
|
end
|
121
135
|
|
122
|
-
def #{m}(*args)
|
123
|
-
ret =
|
124
|
-
ret.srid = pick_srid_according_to_policy(
|
136
|
+
def #{m}(*args, **kwargs)
|
137
|
+
ret = dup.#{m}!(*args, **kwargs)
|
138
|
+
ret.srid = pick_srid_according_to_policy(srid)
|
125
139
|
ret
|
126
140
|
end
|
127
|
-
|
141
|
+
RUBY
|
128
142
|
end
|
129
143
|
end
|
130
144
|
end
|
data/lib/ffi-geos/strtree.rb
CHANGED
@@ -23,23 +23,22 @@ module Geos
|
|
23
23
|
geoms_and_objects = nil # forward declaration
|
24
24
|
capacity = 10
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
args.first
|
31
|
-
|
32
|
-
|
33
|
-
|
26
|
+
case args.first
|
27
|
+
when Integer
|
28
|
+
capacity = args.first
|
29
|
+
when Array
|
30
|
+
geoms_and_objects = if args.first.first.is_a?(Array)
|
31
|
+
args.first
|
32
|
+
else
|
33
|
+
args
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
geoms_and_objects.each do |geom, _obj|
|
37
|
+
check_geometry(geom)
|
38
|
+
end
|
38
39
|
end
|
39
40
|
|
40
|
-
if capacity <= 0
|
41
|
-
raise ArgumentError, 'STRtree capacity must be greater than 0'
|
42
|
-
end
|
41
|
+
raise ArgumentError, 'STRtree capacity must be greater than 0' if capacity <= 0
|
43
42
|
|
44
43
|
ptr = FFIGeos.GEOSSTRtree_create_r(Geos.current_handle_pointer, capacity)
|
45
44
|
|
@@ -61,7 +60,7 @@ module Geos
|
|
61
60
|
end
|
62
61
|
end
|
63
62
|
|
64
|
-
def self.release(ptr)
|
63
|
+
def self.release(ptr) # :nodoc:
|
65
64
|
FFIGeos.GEOSSTRtree_destroy_r(Geos.current_handle_pointer, ptr)
|
66
65
|
end
|
67
66
|
|
@@ -99,7 +98,7 @@ module Geos
|
|
99
98
|
def remove(geom, item)
|
100
99
|
check_geometry(geom)
|
101
100
|
|
102
|
-
key = if storage = @storage.detect { |
|
101
|
+
key = if (storage = @storage.detect { |_k, v| v[:item] == item })
|
103
102
|
storage[0]
|
104
103
|
end
|
105
104
|
|
@@ -139,16 +138,17 @@ module Geos
|
|
139
138
|
|
140
139
|
def query(geom, ret = :item)
|
141
140
|
query_all(geom).collect { |storage|
|
142
|
-
item =
|
143
|
-
|
144
|
-
|
145
|
-
memo
|
141
|
+
item = case ret
|
142
|
+
when Array
|
143
|
+
storage.inject({}) do |memo, k|
|
144
|
+
memo.tap do
|
145
|
+
memo[k] = storage[k]
|
146
|
+
end
|
146
147
|
end
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
storage[ret]
|
148
|
+
when :all
|
149
|
+
storage
|
150
|
+
else
|
151
|
+
storage[ret]
|
152
152
|
end
|
153
153
|
|
154
154
|
item.tap do
|
@@ -166,10 +166,8 @@ module Geos
|
|
166
166
|
end
|
167
167
|
alias query_geoms query_geometries
|
168
168
|
|
169
|
-
def iterate
|
170
|
-
@storage.each_value
|
171
|
-
yield(v)
|
172
|
-
end
|
169
|
+
def iterate(&block)
|
170
|
+
@storage.each_value(&block)
|
173
171
|
end
|
174
172
|
|
175
173
|
if FFIGeos.respond_to?(:GEOSSTRtree_nearest_generic_r)
|
@@ -180,7 +178,7 @@ module Geos
|
|
180
178
|
|
181
179
|
return nil if @storage.empty?
|
182
180
|
|
183
|
-
callback = proc { |item,
|
181
|
+
callback = proc { |item, _item_2, distance_ptr|
|
184
182
|
key = item.read_int
|
185
183
|
geom_from_storage = @storage[key][:geometry]
|
186
184
|
|
data/lib/ffi-geos/tools.rb
CHANGED
data/lib/ffi-geos/utils.rb
CHANGED
@@ -30,22 +30,21 @@ module Geos
|
|
30
30
|
def create_point(*args)
|
31
31
|
options = extract_options!(args)
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
case args.length
|
34
|
+
when 1
|
35
|
+
cs = args.first
|
36
|
+
when 2
|
37
|
+
cs = CoordinateSequence.new(1, 2)
|
38
|
+
cs.x[0] = args[0].to_f
|
39
|
+
cs.y[0] = args[1].to_f
|
40
|
+
when 3
|
41
|
+
cs = CoordinateSequence.new(1, 3)
|
42
|
+
cs.x[0], cs.y[0], cs.z[0] = args.map(&:to_f)
|
43
|
+
else
|
44
|
+
raise ArgumentError, "Wrong number of arguments (#{args.length} for 1-3)"
|
44
45
|
end
|
45
46
|
|
46
|
-
if cs.length != 1
|
47
|
-
raise ArgumentError, 'IllegalArgumentException: Point coordinate list must contain a single element'
|
48
|
-
end
|
47
|
+
raise ArgumentError, 'IllegalArgumentException: Point coordinate list must contain a single element' if cs.length != 1
|
49
48
|
|
50
49
|
cs_dup = cs.dup
|
51
50
|
cs_dup.ptr.autorelease = false
|
@@ -56,9 +55,7 @@ module Geos
|
|
56
55
|
def create_line_string(cs, options = {})
|
57
56
|
cs = cs_from_cs_or_geom(cs)
|
58
57
|
|
59
|
-
if cs.length <= 1 && cs.
|
60
|
-
raise ArgumentError, 'IllegalArgumentException: point array must contain 0 or >1 elements'
|
61
|
-
end
|
58
|
+
raise ArgumentError, 'IllegalArgumentException: point array must contain 0 or >1 elements' if cs.length <= 1 && !cs.empty?
|
62
59
|
|
63
60
|
cs_dup = cs.dup
|
64
61
|
cs_dup.ptr.autorelease = false
|
@@ -69,9 +66,7 @@ module Geos
|
|
69
66
|
def create_linear_ring(cs, options = {})
|
70
67
|
cs = cs_from_cs_or_geom(cs)
|
71
68
|
|
72
|
-
if cs.length <= 1 && cs.
|
73
|
-
raise ArgumentError, 'IllegalArgumentException: point array must contain 0 or >1 elements'
|
74
|
-
end
|
69
|
+
raise ArgumentError, 'IllegalArgumentException: point array must contain 0 or >1 elements' if cs.length <= 1 && !cs.empty?
|
75
70
|
|
76
71
|
cs.ptr.autorelease = false
|
77
72
|
|
@@ -154,9 +149,7 @@ module Geos
|
|
154
149
|
options = extract_options!(args)
|
155
150
|
|
156
151
|
geoms = Array(args).flatten.tap do |i|
|
157
|
-
if i.detect { |g| !g.is_a?(klass) }
|
158
|
-
raise TypeError, "Expected geoms Array to contain #{klass} objects"
|
159
|
-
end
|
152
|
+
raise TypeError, "Expected geoms Array to contain #{klass} objects" if i.detect { |g| !g.is_a?(klass) }
|
160
153
|
end
|
161
154
|
|
162
155
|
geoms_dups = geoms.map(&:dup)
|
data/lib/ffi-geos/version.rb
CHANGED
data/lib/ffi-geos/wkb_reader.rb
CHANGED
data/lib/ffi-geos/wkb_writer.rb
CHANGED
@@ -20,7 +20,7 @@ module Geos
|
|
20
20
|
set_options(options)
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.release(ptr)
|
23
|
+
def self.release(ptr) # :nodoc:
|
24
24
|
FFIGeos.GEOSWKBWriter_destroy_r(Geos.current_handle_pointer, ptr)
|
25
25
|
end
|
26
26
|
|
@@ -57,9 +57,8 @@ module Geos
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def output_dimensions=(dim)
|
60
|
-
if dim < 2 || dim > 3
|
61
|
-
|
62
|
-
end
|
60
|
+
raise ArgumentError, 'Output dimensions must be either 2 or 3' if dim < 2 || dim > 3
|
61
|
+
|
63
62
|
FFIGeos.GEOSWKBWriter_setOutputDimension_r(Geos.current_handle_pointer, ptr, dim)
|
64
63
|
end
|
65
64
|
|
@@ -86,7 +85,7 @@ module Geos
|
|
86
85
|
|
87
86
|
private
|
88
87
|
|
89
|
-
def set_options(options)
|
88
|
+
def set_options(options) # :nodoc:
|
90
89
|
self.include_srid = options[:include_srid] if options.key?(:include_srid)
|
91
90
|
end
|
92
91
|
end
|
data/lib/ffi-geos/wkt_reader.rb
CHANGED
data/lib/ffi-geos/wkt_writer.rb
CHANGED
@@ -2,10 +2,7 @@
|
|
2
2
|
|
3
3
|
module Geos
|
4
4
|
class WktWriter
|
5
|
-
attr_reader :ptr
|
6
|
-
attr_reader :old_3d
|
7
|
-
attr_reader :rounding_precision
|
8
|
-
attr_reader :trim
|
5
|
+
attr_reader :ptr, :old_3d, :rounding_precision, :trim
|
9
6
|
|
10
7
|
def initialize(options = {})
|
11
8
|
options = {
|
@@ -24,12 +21,12 @@ module Geos
|
|
24
21
|
set_options(options)
|
25
22
|
end
|
26
23
|
|
27
|
-
def self.release(ptr)
|
24
|
+
def self.release(ptr) # :nodoc:
|
28
25
|
FFIGeos.GEOSWKTWriter_destroy_r(Geos.current_handle_pointer, ptr)
|
29
26
|
end
|
30
27
|
|
31
|
-
def set_options(options)
|
32
|
-
[
|
28
|
+
def set_options(options) # :nodoc:
|
29
|
+
[:trim, :old_3d, :rounding_precision, :output_dimensions].each do |k|
|
33
30
|
send("#{k}=", options[k]) if respond_to?("#{k}=") && options.key?(k)
|
34
31
|
end
|
35
32
|
end
|
@@ -67,9 +64,7 @@ module Geos
|
|
67
64
|
# Available in GEOS 3.3+.
|
68
65
|
def rounding_precision=(r)
|
69
66
|
r = r.to_i
|
70
|
-
if r > 255
|
71
|
-
raise ArgumentError, 'Rounding precision cannot be greater than 255'
|
72
|
-
end
|
67
|
+
raise ArgumentError, 'Rounding precision cannot be greater than 255' if r > 255
|
73
68
|
|
74
69
|
@rounding_precision = r
|
75
70
|
FFIGeos.GEOSWKTWriter_setRoundingPrecision_r(Geos.current_handle_pointer, ptr, @rounding_precision)
|
@@ -88,9 +83,8 @@ module Geos
|
|
88
83
|
# Available in GEOS 3.3+.
|
89
84
|
def output_dimensions=(dim)
|
90
85
|
dim = dim.to_i
|
91
|
-
if dim < 2 || dim > 3
|
92
|
-
|
93
|
-
end
|
86
|
+
raise ArgumentError, 'Output dimensions must be either 2 or 3' if dim < 2 || dim > 3
|
87
|
+
|
94
88
|
FFIGeos.GEOSWKTWriter_setOutputDimension_r(Geos.current_handle_pointer, ptr, dim)
|
95
89
|
end
|
96
90
|
end
|