ffi-geos 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3954 -4
- data/.travis.yml +23 -11
- data/Gemfile +7 -9
- data/Guardfile +3 -4
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -20
- data/Rakefile +3 -2
- data/ffi-geos.gemspec +2 -2
- data/lib/ffi-geos.rb +93 -44
- data/lib/ffi-geos/coordinate_sequence.rb +147 -145
- data/lib/ffi-geos/geometry.rb +68 -17
- data/lib/ffi-geos/geometry_collection.rb +22 -8
- data/lib/ffi-geos/interrupt.rb +11 -14
- data/lib/ffi-geos/line_string.rb +57 -42
- data/lib/ffi-geos/point.rb +16 -16
- data/lib/ffi-geos/polygon.rb +42 -28
- data/lib/ffi-geos/strtree.rb +3 -5
- data/lib/ffi-geos/tools.rb +1 -1
- data/lib/ffi-geos/utils.rb +4 -12
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkb_writer.rb +2 -3
- data/lib/ffi-geos/wkt_writer.rb +4 -7
- data/sonar-project.properties +16 -0
- data/test/coordinate_sequence_tests.rb +144 -122
- data/test/geometry_collection_tests.rb +38 -65
- data/test/geometry_tests.rb +106 -17
- data/test/interrupt_tests.rb +7 -7
- data/test/line_string_tests.rb +10 -10
- data/test/point_tests.rb +2 -2
- data/test/polygon_tests.rb +3 -4
- data/test/prepared_geometry_tests.rb +8 -8
- data/test/strtree_tests.rb +5 -5
- data/test/test_helper.rb +20 -35
- 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 +4 -4
data/.travis.yml
CHANGED
@@ -1,21 +1,33 @@
|
|
1
1
|
cache: bundler
|
2
2
|
sudo: false
|
3
3
|
language: ruby
|
4
|
+
dist: trusty
|
5
|
+
|
4
6
|
rvm:
|
5
|
-
- 2.
|
6
|
-
- 2.
|
7
|
-
- 2.
|
8
|
-
- 2.
|
9
|
-
- rbx-3
|
7
|
+
- 2.7.0
|
8
|
+
- 2.6.5
|
9
|
+
- 2.5.7
|
10
|
+
- 2.4.9
|
10
11
|
- jruby-head
|
11
|
-
|
12
|
-
allow_failures:
|
13
|
-
- rvm: rbx-3
|
14
|
-
- rvm: jruby-head
|
12
|
+
|
15
13
|
addons:
|
16
14
|
apt:
|
17
15
|
packages:
|
18
16
|
- libgeos-c1
|
17
|
+
sonarcloud:
|
18
|
+
organization: "dark-panda"
|
19
|
+
token:
|
20
|
+
secure: UiS3BU1SUSbIynvaup+3w9NNa85mH3lXSa+iCQx9luhp5Nc5Zg4xedycfGylCzpr6D6vRRH3gYefafitcvjS8LbhtNd2Z4oezp2T4fRt8W387HJ3wIcRkyOwBhmQqt/SiPiQr/rkDE9VomelLe7RSkelfAQQvpka5TMzc4wKYd4=
|
21
|
+
|
22
|
+
git:
|
23
|
+
depth: false
|
24
|
+
|
19
25
|
before_install:
|
20
|
-
- gem
|
21
|
-
|
26
|
+
- gem install bundler
|
27
|
+
|
28
|
+
before_script:
|
29
|
+
- bundle exec rubocop --format=json > rubocop-report.json || true
|
30
|
+
|
31
|
+
script:
|
32
|
+
- bundle exec rake test
|
33
|
+
- sonar-scanner
|
data/Gemfile
CHANGED
@@ -1,23 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
7
|
+
gem 'guard'
|
8
|
+
gem 'guard-minitest'
|
5
9
|
gem 'minitest'
|
6
10
|
gem 'minitest-reporters'
|
7
11
|
gem 'rake', '~> 10.0'
|
8
12
|
gem 'rdoc', '~> 3.12'
|
13
|
+
gem 'rubocop', require: false
|
14
|
+
gem 'simplecov', '~> 0.17.0', require: false
|
9
15
|
|
10
16
|
platforms :rbx do
|
11
17
|
gem 'rubinius-developer_tools'
|
12
18
|
gem 'rubysl', '~> 2.0'
|
13
19
|
end
|
14
20
|
|
15
|
-
|
16
|
-
gem 'guard'
|
17
|
-
gem 'guard-minitest'
|
18
|
-
gem 'simplecov'
|
19
|
-
end
|
20
|
-
|
21
|
-
if File.exist?('Gemfile.local')
|
22
|
-
instance_eval File.read('Gemfile.local')
|
23
|
-
end
|
21
|
+
instance_eval File.read('Gemfile.local') if File.exist?('Gemfile.local')
|
data/Guardfile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
guard 'minitest', test_folders: 'test', test_file_patterns: '*_tests.rb' do
|
3
|
-
watch(%r
|
4
|
+
watch(%r{^test/(.+)_tests\.rb})
|
4
5
|
|
5
6
|
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) do |m|
|
6
7
|
"test/#{m[2]}_tests.rb"
|
@@ -11,6 +12,4 @@ guard 'minitest', test_folders: 'test', test_file_patterns: '*_tests.rb' do
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
if File.exist?('Guardfile.local')
|
15
|
-
instance_eval File.read('Guardfile.local')
|
16
|
-
end
|
15
|
+
instance_eval File.read('Guardfile.local') if File.exist?('Guardfile.local')
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -7,15 +7,8 @@
|
|
7
7
|
* GEOS version 3.3.0 or greater. GEOS 3.2.2 and below will work to an extent,
|
8
8
|
but some features and methods will be disabled or missing.
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
* Ruby MRI 1.9.3, 2.0+, 2.1+, 2.2+
|
13
|
-
* Ruby MRI 1.8.7 works but as Ruby 1.8 is no longer being maintained, there's
|
14
|
-
no guarantee this will continue in the future and is therefore no longer
|
15
|
-
being tested with the same rigour as more modern versions of Ruby.
|
16
|
-
* Rubinius 2
|
17
|
-
* JRuby 1.6+, with the exception of versions of JRuby prior to 1.6.3 as per
|
18
|
-
below. This includes both 1.8 and 1.9 modes.
|
10
|
+
We currently test on Travis CI using the current releases of MRI that are
|
11
|
+
maintained. See `.travis.yml` for a list. We also test against jruby-head.
|
19
12
|
|
20
13
|
=== JRuby Notes
|
21
14
|
|
@@ -74,17 +67,6 @@ Ruby bindings along with the following enhancements and additions:
|
|
74
67
|
entire GEOS C API is represented in ffi-geos along with all sorts of useful
|
75
68
|
convenience methods and geometry conversion and manipulation methods.
|
76
69
|
|
77
|
-
* *NEW IN ffi-geos 1.0.0* -- all errors thrown by ffi-geos are now instances of
|
78
|
-
Geos::Error or subclasses thereof. Geos::Error itself is a descendant
|
79
|
-
of RuntimeError as is the case with the native Geos extension. This means
|
80
|
-
that code like rescue RuntimeError should still work but you can now
|
81
|
-
further capture more precise error types by capturing errors like
|
82
|
-
Geos::Error, Geos::ParseError, etc.
|
83
|
-
|
84
|
-
* *NEW IN ffi-geos 1.0.0* -- new methods for Geom::Geometry#voronoi_diagram,
|
85
|
-
Geos::MultiLineString#closed? and Geos::Geometry#clip_by_rect when using
|
86
|
-
GEOS 3.5.0+.
|
87
|
-
|
88
70
|
== Thanks
|
89
71
|
|
90
72
|
* Daniel Azuma for the testing and JRuby help.
|
data/Rakefile
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
# -*- ruby -*-
|
3
4
|
|
@@ -7,7 +8,7 @@ require 'rake/testtask'
|
|
7
8
|
require 'rdoc/task'
|
8
9
|
require 'bundler/gem_tasks'
|
9
10
|
|
10
|
-
|
11
|
+
$LOAD_PATH.push File.expand_path(File.dirname(__FILE__), 'lib')
|
11
12
|
|
12
13
|
version = Geos::VERSION
|
13
14
|
|
@@ -19,7 +20,7 @@ Rake::TestTask.new(:test) do |t|
|
|
19
20
|
t.warning = !!ENV['WARNINGS']
|
20
21
|
end
|
21
22
|
|
22
|
-
task :
|
23
|
+
task default: :test
|
23
24
|
|
24
25
|
begin
|
25
26
|
desc 'Build docs'
|
data/ffi-geos.gemspec
CHANGED
data/lib/ffi-geos.rb
CHANGED
@@ -52,11 +52,11 @@ module Geos
|
|
52
52
|
def self.search_paths
|
53
53
|
@search_paths ||= begin
|
54
54
|
if ENV['GEOS_LIBRARY_PATH']
|
55
|
-
[
|
55
|
+
[ENV['GEOS_LIBRARY_PATH']]
|
56
56
|
elsif FFI::Platform::IS_WINDOWS
|
57
57
|
ENV['PATH'].split(File::PATH_SEPARATOR)
|
58
58
|
else
|
59
|
-
[
|
59
|
+
['/usr/local/{lib64,lib}', '/opt/local/{lib64,lib}', '/usr/{lib64,lib}', '/usr/lib/{x86_64,i386}-linux-gnu']
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -65,9 +65,9 @@ module Geos
|
|
65
65
|
if ENV['GEOS_LIBRARY_PATH'] && File.file?(ENV['GEOS_LIBRARY_PATH'])
|
66
66
|
ENV['GEOS_LIBRARY_PATH']
|
67
67
|
else
|
68
|
-
Dir.glob(search_paths.map
|
68
|
+
Dir.glob(search_paths.map do |path|
|
69
69
|
File.expand_path(File.join(path, "#{lib}.#{FFI::Platform::LIBSUFFIX}{,.?}"))
|
70
|
-
|
70
|
+
end).first
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -81,7 +81,7 @@ module Geos
|
|
81
81
|
# For backwards compatibility with older ffi-geos versions where this
|
82
82
|
# used to return an Array.
|
83
83
|
def self.geos_library_paths
|
84
|
-
[
|
84
|
+
[geos_library_path]
|
85
85
|
end
|
86
86
|
|
87
87
|
extend ::FFI::Library
|
@@ -150,10 +150,10 @@ module Geos
|
|
150
150
|
:pointer,
|
151
151
|
|
152
152
|
# notice callback
|
153
|
-
callback([
|
153
|
+
callback([:string, :string], :void),
|
154
154
|
|
155
155
|
# error callback
|
156
|
-
callback([
|
156
|
+
callback([:string, :string], :void)
|
157
157
|
],
|
158
158
|
|
159
159
|
finishGEOS_r: [
|
@@ -163,16 +163,16 @@ module Geos
|
|
163
163
|
# / deprecated in GEOS 3.5.0+
|
164
164
|
|
165
165
|
# GEOS 3.5.0+
|
166
|
-
GEOS_init_r: [
|
166
|
+
GEOS_init_r: [:pointer],
|
167
167
|
|
168
168
|
GEOSContext_setNoticeMessageHandler_r: [
|
169
169
|
# void, *handle, callback, *void
|
170
|
-
:void, :pointer, callback([
|
170
|
+
:void, :pointer, callback([:string, :string], :void), :pointer
|
171
171
|
],
|
172
172
|
|
173
173
|
GEOSContext_setErrorMessageHandler_r: [
|
174
174
|
# void, *handle, callback, *void
|
175
|
-
:void, :pointer, callback([
|
175
|
+
:void, :pointer, callback([:string, :string], :void), :pointer
|
176
176
|
],
|
177
177
|
|
178
178
|
GEOS_finish_r: [
|
@@ -207,6 +207,21 @@ module Geos
|
|
207
207
|
:pointer, :pointer, :pointer, :uint
|
208
208
|
],
|
209
209
|
|
210
|
+
GEOSPolygonize_valid_r: [
|
211
|
+
# *geom, *handle, **geoms, ngeoms
|
212
|
+
:pointer, :pointer, :pointer, :uint
|
213
|
+
],
|
214
|
+
|
215
|
+
GEOSBuildArea_r: [
|
216
|
+
# *geom, *handle, *geom
|
217
|
+
:pointer, :pointer, :pointer
|
218
|
+
],
|
219
|
+
|
220
|
+
GEOSMakeValid_r: [
|
221
|
+
# *geom, *handle, *geom
|
222
|
+
:pointer, :pointer, :pointer
|
223
|
+
],
|
224
|
+
|
210
225
|
GEOSPolygonizer_getCutEdges_r: [
|
211
226
|
# *geom, *handle, **geoms, ngeoms
|
212
227
|
:pointer, :pointer, :pointer, :uint
|
@@ -328,6 +343,11 @@ module Geos
|
|
328
343
|
# 0 on exception, *handle, *coord_seq, (uint *) size
|
329
344
|
:int, :pointer, :pointer, :pointer
|
330
345
|
],
|
346
|
+
|
347
|
+
GEOSCoordSeq_isCCW_r: [
|
348
|
+
# 0 on exception, *handle, *coord_seq, (char *) value
|
349
|
+
:int, :pointer, :pointer, :pointer
|
350
|
+
],
|
331
351
|
#### /CoordinateSequence functions ####
|
332
352
|
|
333
353
|
#### Geometry functions ####
|
@@ -437,6 +457,11 @@ module Geos
|
|
437
457
|
:pointer, :pointer, :pointer, :pointer
|
438
458
|
],
|
439
459
|
|
460
|
+
GEOSCoverageUnion_r: [
|
461
|
+
# *geom, *handle, *geom
|
462
|
+
:pointer, :pointer, :pointer
|
463
|
+
],
|
464
|
+
|
440
465
|
GEOSUnaryUnion_r: [
|
441
466
|
# *geom, *handle, *geom
|
442
467
|
:pointer, :pointer, :pointer
|
@@ -468,6 +493,11 @@ module Geos
|
|
468
493
|
:pointer, :pointer, :pointer
|
469
494
|
],
|
470
495
|
|
496
|
+
GEOSMinimumBoundingCircle_r: [
|
497
|
+
# *geom, *handle, *geom, *double radius, **geom center
|
498
|
+
:pointer, :pointer, :pointer, :pointer, :pointer
|
499
|
+
],
|
500
|
+
|
471
501
|
GEOSEnvelope_r: [
|
472
502
|
# *geom, *handle, *geom
|
473
503
|
:pointer, :pointer, :pointer
|
@@ -478,6 +508,26 @@ module Geos
|
|
478
508
|
:pointer, :pointer, :pointer
|
479
509
|
],
|
480
510
|
|
511
|
+
GEOSGeom_getXMin_r: [
|
512
|
+
# 0 on exception, *handle, (double *) value
|
513
|
+
:int, :pointer, :pointer, :pointer
|
514
|
+
],
|
515
|
+
|
516
|
+
GEOSGeom_getXMax_r: [
|
517
|
+
# 0 on exception, *handle, (double *) value
|
518
|
+
:int, :pointer, :pointer, :pointer
|
519
|
+
],
|
520
|
+
|
521
|
+
GEOSGeom_getYMin_r: [
|
522
|
+
# 0 on exception, *handle, (double *) value
|
523
|
+
:int, :pointer, :pointer, :pointer
|
524
|
+
],
|
525
|
+
|
526
|
+
GEOSGeom_getYMax_r: [
|
527
|
+
# 0 on exception, *handle, (double *) value
|
528
|
+
:int, :pointer, :pointer, :pointer
|
529
|
+
],
|
530
|
+
|
481
531
|
GEOSSimplify_r: [
|
482
532
|
# *geom, *handle, *geom, tolerance
|
483
533
|
:pointer, :pointer, :pointer, :double
|
@@ -643,6 +693,11 @@ module Geos
|
|
643
693
|
:int, :pointer, :pointer, :pointer, :pointer
|
644
694
|
],
|
645
695
|
|
696
|
+
GEOSDistanceIndexed_r: [
|
697
|
+
# (0 on exception, 1 otherwise), *handle, *geom_a, *geom_b, (double *) distance
|
698
|
+
:int, :pointer, :pointer, :pointer, :pointer
|
699
|
+
],
|
700
|
+
|
646
701
|
GEOSHausdorffDistance_r: [
|
647
702
|
# (0 on exception, 1 otherwise), *handle, *geom_a, *geom_b, (double *) distance
|
648
703
|
:int, :pointer, :pointer, :pointer, :pointer
|
@@ -777,12 +832,12 @@ module Geos
|
|
777
832
|
|
778
833
|
GEOSSTRtree_query_r: [
|
779
834
|
# void, *handle, *tree, *geom, void query_callback((void *) item, (void *) user_data), (void *) user_data
|
780
|
-
:void, :pointer, :pointer, :pointer, callback([
|
835
|
+
:void, :pointer, :pointer, :pointer, callback([:pointer, :pointer], :void), :pointer
|
781
836
|
],
|
782
837
|
|
783
838
|
GEOSSTRtree_iterate_r: [
|
784
839
|
# void, *handle, *tree, void query_callback((void *) item, (void *) user_data), (void *) user_data
|
785
|
-
:void, :pointer, :pointer, callback([
|
840
|
+
:void, :pointer, :pointer, callback([:pointer, :pointer], :void), :pointer
|
786
841
|
],
|
787
842
|
|
788
843
|
GEOSSTRtree_remove_r: [
|
@@ -797,7 +852,7 @@ module Geos
|
|
797
852
|
|
798
853
|
GEOSSTRtree_nearest_generic_r: [
|
799
854
|
# *void, *handle, *tree, *item, *item_envelope, int distance_callback(*item_1, *item_2, *double, void *user_data), *user_data
|
800
|
-
:pointer, :pointer, :pointer, :pointer, :pointer, callback([
|
855
|
+
:pointer, :pointer, :pointer, :pointer, :pointer, callback([:pointer, :pointer, :pointer, :pointer], :int), :pointer
|
801
856
|
],
|
802
857
|
#### /STRtree functions ####
|
803
858
|
|
@@ -1105,13 +1160,11 @@ module Geos
|
|
1105
1160
|
def notice_handler=(method_or_block)
|
1106
1161
|
@notice_handler = method_or_block
|
1107
1162
|
FFIGeos.GEOSContext_setNoticeMessageHandler_r(@ptr, @notice_handler, nil)
|
1108
|
-
@notice_handler
|
1109
1163
|
end
|
1110
1164
|
|
1111
1165
|
def error_handler=(method_or_block)
|
1112
1166
|
@error_handler = method_or_block
|
1113
1167
|
FFIGeos.GEOSContext_setErrorMessageHandler_r(@ptr, @error_handler, nil)
|
1114
|
-
@error_handler
|
1115
1168
|
end
|
1116
1169
|
|
1117
1170
|
def notice_handler(&block)
|
@@ -1148,13 +1201,9 @@ module Geos
|
|
1148
1201
|
FFIGeos.finishGEOS_r(ptr)
|
1149
1202
|
end
|
1150
1203
|
|
1151
|
-
|
1152
|
-
@notice_handler
|
1153
|
-
end
|
1204
|
+
attr_reader :notice_handler
|
1154
1205
|
|
1155
|
-
|
1156
|
-
@error_handler
|
1157
|
-
end
|
1206
|
+
attr_reader :error_handler
|
1158
1207
|
end
|
1159
1208
|
|
1160
1209
|
private
|
@@ -1170,7 +1219,7 @@ module Geos
|
|
1170
1219
|
|
1171
1220
|
class << self
|
1172
1221
|
def version
|
1173
|
-
@version ||= FFIGeos.GEOSversion
|
1222
|
+
@version ||= FFIGeos.GEOSversion.strip
|
1174
1223
|
end
|
1175
1224
|
|
1176
1225
|
def jts_port
|
@@ -1281,28 +1330,28 @@ module Geos
|
|
1281
1330
|
GEOS_CAPI_VERSION,
|
1282
1331
|
GEOS_CAPI_VERSION_MAJOR, GEOS_CAPI_VERSION_MINOR, GEOS_CAPI_VERSION_PATCH,
|
1283
1332
|
GEOS_SVN_REVISION =
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1333
|
+
if !(versions = Geos.version.scan(/^
|
1334
|
+
((\d+)\.(\d+)\.(\d+)((?:dev|rc|beta|alpha)\d*)?)
|
1335
|
+
-CAPI-
|
1336
|
+
((\d+)\.(\d+)\.(\d+))
|
1337
|
+
(?:\s+r?(\h+))?
|
1338
|
+
$/x)).empty?
|
1339
|
+
versions = versions[0]
|
1340
|
+
[
|
1341
|
+
versions[0],
|
1342
|
+
versions[1].to_i,
|
1343
|
+
versions[2].to_i,
|
1344
|
+
versions[3].to_i,
|
1345
|
+
versions[4],
|
1346
|
+
versions[5],
|
1347
|
+
versions[6].to_i,
|
1348
|
+
versions[7].to_i,
|
1349
|
+
versions[8].to_i,
|
1350
|
+
versions[9]&.to_i
|
1351
|
+
]
|
1352
|
+
else
|
1353
|
+
['0.0.0', 0, 0, 0, nil, '0.0.0', 0, 0, 0]
|
1354
|
+
end
|
1306
1355
|
GEOS_CAPI_FIRST_INTERFACE = GEOS_CAPI_VERSION_MAJOR.to_i
|
1307
1356
|
GEOS_CAPI_LAST_INTERFACE = GEOS_CAPI_VERSION_MAJOR.to_i + GEOS_CAPI_VERSION_MINOR.to_i
|
1308
1357
|
end
|
@@ -69,28 +69,26 @@ module Geos
|
|
69
69
|
lengths = points.collect(&:length).uniq
|
70
70
|
|
71
71
|
if lengths.empty?
|
72
|
-
[
|
72
|
+
[0, 0]
|
73
73
|
elsif lengths.length != 1
|
74
74
|
raise ParseError, 'Different sized points found in Array'
|
75
75
|
elsif !lengths.first.between?(1, 3)
|
76
76
|
raise ParseError, 'Expected points to contain 1-3 elements'
|
77
77
|
else
|
78
|
-
[
|
78
|
+
[points.length, points.first.length]
|
79
79
|
end
|
80
80
|
elsif args.first.is_a?(Hash)
|
81
81
|
args.first.values_at(:size, :dimensions)
|
82
|
+
elsif !args.length.between?(0, 2)
|
83
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0-2)"
|
82
84
|
else
|
83
|
-
|
84
|
-
raise ArgumentError, "wrong number of arguments (#{args.length} for 0-2)"
|
85
|
-
else
|
86
|
-
[ args[0], args[1] ]
|
87
|
-
end
|
85
|
+
[args[0], args[1]]
|
88
86
|
end
|
89
87
|
|
90
88
|
size ||= 0
|
91
89
|
dimensions ||= 0
|
92
90
|
|
93
|
-
[
|
91
|
+
[FFIGeos.GEOSCoordSeq_create_r(Geos.current_handle_pointer, size, dimensions), true]
|
94
92
|
end
|
95
93
|
|
96
94
|
@ptr = FFI::AutoPointer.new(
|
@@ -147,7 +145,7 @@ module Geos
|
|
147
145
|
def [](*args)
|
148
146
|
if args.length == 1 && args.first.is_a?(Numeric) && args.first >= 0
|
149
147
|
i = args.first
|
150
|
-
ary = [
|
148
|
+
ary = [get_x(i), get_y(i)]
|
151
149
|
ary << get_z(i) if has_z?
|
152
150
|
ary
|
153
151
|
else
|
@@ -235,6 +233,16 @@ module Geos
|
|
235
233
|
end
|
236
234
|
end
|
237
235
|
|
236
|
+
if FFIGeos.respond_to?(:GEOSCoordSeq_isCCW_r)
|
237
|
+
# Available in GEOS 3.7+.
|
238
|
+
def counter_clockwise?
|
239
|
+
char_ptr = FFI::MemoryPointer.new(:char)
|
240
|
+
FFIGeos.GEOSCoordSeq_isCCW_r(Geos.current_handle_pointer, ptr, char_ptr)
|
241
|
+
Tools.bool_result(char_ptr.read_char)
|
242
|
+
end
|
243
|
+
alias ccw? counter_clockwise?
|
244
|
+
end
|
245
|
+
|
238
246
|
def to_point(options = {})
|
239
247
|
Geos.create_point(self, srid: options[:srid])
|
240
248
|
end
|
@@ -258,11 +266,11 @@ module Geos
|
|
258
266
|
end
|
259
267
|
|
260
268
|
%w{ x y z }.each do |m|
|
261
|
-
class_eval(<<-
|
269
|
+
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
262
270
|
def #{m}_max
|
263
271
|
ret = nil
|
264
|
-
|
265
|
-
value =
|
272
|
+
length.times do |i|
|
273
|
+
value = get_#{m}(i)
|
266
274
|
ret = value if !ret || value >= ret
|
267
275
|
end
|
268
276
|
ret
|
@@ -270,23 +278,23 @@ module Geos
|
|
270
278
|
|
271
279
|
def #{m}_min
|
272
280
|
ret = nil
|
273
|
-
|
274
|
-
value =
|
281
|
+
length.times do |i|
|
282
|
+
value = get_#{m}(i)
|
275
283
|
ret = value if !ret || value <= ret
|
276
284
|
end
|
277
285
|
ret
|
278
286
|
end
|
279
|
-
|
287
|
+
RUBY
|
280
288
|
end
|
281
289
|
|
282
290
|
def snap_to_grid!(*args)
|
283
291
|
grid = {
|
284
|
-
:
|
285
|
-
:
|
286
|
-
:
|
287
|
-
:
|
288
|
-
:
|
289
|
-
:
|
292
|
+
offset_x: 0, # 1
|
293
|
+
offset_y: 0, # 2
|
294
|
+
offset_z: 0, # -
|
295
|
+
size_x: 0, # 3
|
296
|
+
size_y: 0, # 4
|
297
|
+
size_z: 0 # -
|
290
298
|
}
|
291
299
|
|
292
300
|
if args.length == 1 && args[0].is_a?(Numeric)
|
@@ -295,9 +303,7 @@ module Geos
|
|
295
303
|
grid.merge!(args[0])
|
296
304
|
end
|
297
305
|
|
298
|
-
if grid[:size]
|
299
|
-
grid[:size_x] = grid[:size_y] = grid[:size_z] = grid[:size]
|
300
|
-
end
|
306
|
+
grid[:size_x] = grid[:size_y] = grid[:size_z] = grid[:size] if grid[:size]
|
301
307
|
|
302
308
|
if grid[:offset]
|
303
309
|
case grid[:offset]
|
@@ -310,55 +316,51 @@ module Geos
|
|
310
316
|
when Array
|
311
317
|
grid[:offset_x], grid[:offset_y], grid[:offset_z] = grid[:offset]
|
312
318
|
else
|
313
|
-
raise ArgumentError
|
319
|
+
raise ArgumentError, 'Expected :offset option to be a Geos::Point'
|
314
320
|
end
|
315
321
|
end
|
316
322
|
|
317
|
-
|
318
|
-
if grid[:size_x] != 0
|
319
|
-
self.x[i] = ((self.x[i] - grid[:offset_x]) / grid[:size_x]).round * grid[:size_x] + grid[:offset_x]
|
320
|
-
end
|
323
|
+
length.times do |i|
|
324
|
+
x[i] = ((x[i] - grid[:offset_x]) / grid[:size_x]).round * grid[:size_x] + grid[:offset_x] if grid[:size_x] != 0
|
321
325
|
|
322
|
-
if grid[:size_y] != 0
|
323
|
-
self.y[i] = ((self.y[i] - grid[:offset_y]) / grid[:size_y]).round * grid[:size_y] + grid[:offset_y]
|
324
|
-
end
|
326
|
+
y[i] = ((y[i] - grid[:offset_y]) / grid[:size_y]).round * grid[:size_y] + grid[:offset_y] if grid[:size_y] != 0
|
325
327
|
|
326
|
-
if
|
327
|
-
self.z[i] = ((self.z[i] - grid[:offset_z]) / grid[:size_z]).round * grid[:size_z] + grid[:offset_z]
|
328
|
-
end
|
328
|
+
z[i] = ((z[i] - grid[:offset_z]) / grid[:size_z]).round * grid[:size_z] + grid[:offset_z] if has_z? && grid[:size_z] != 0
|
329
329
|
end
|
330
330
|
|
331
|
-
cs =
|
331
|
+
cs = remove_duplicate_coords
|
332
332
|
@ptr = cs.ptr
|
333
333
|
|
334
334
|
self
|
335
335
|
end
|
336
336
|
|
337
337
|
def snap_to_grid(*args)
|
338
|
-
|
338
|
+
dup.snap_to_grid!(*args)
|
339
339
|
end
|
340
340
|
|
341
341
|
def remove_duplicate_coords
|
342
|
-
Geos::CoordinateSequence.new(
|
342
|
+
Geos::CoordinateSequence.new(to_a.each_with_object([]) do |v, memo|
|
343
343
|
memo << v unless memo.last == v
|
344
|
-
|
345
|
-
})
|
344
|
+
end)
|
346
345
|
end
|
347
346
|
|
348
347
|
def affine!(options)
|
349
348
|
options.default = 0.0
|
350
349
|
|
351
|
-
if
|
352
|
-
|
353
|
-
x
|
350
|
+
if has_z?
|
351
|
+
length.times do |i|
|
352
|
+
x = self.x[i]
|
353
|
+
y = self.y[i]
|
354
|
+
z = self.z[i]
|
354
355
|
|
355
356
|
self.x[i] = options[:afac] * x + options[:bfac] * y + options[:cfac] * z + options[:xoff]
|
356
357
|
self.y[i] = options[:dfac] * x + options[:efac] * y + options[:ffac] * z + options[:yoff]
|
357
358
|
self.z[i] = options[:gfac] * x + options[:hfac] * y + options[:ifac] * z + options[:zoff]
|
358
359
|
end
|
359
360
|
else
|
360
|
-
|
361
|
-
x
|
361
|
+
length.times do |i|
|
362
|
+
x = self.x[i]
|
363
|
+
y = self.y[i]
|
362
364
|
|
363
365
|
self.x[i] = options[:afac] * x + options[:bfac] * y + options[:xoff]
|
364
366
|
self.y[i] = options[:dfac] * x + options[:efac] * y + options[:yoff]
|
@@ -369,88 +371,88 @@ module Geos
|
|
369
371
|
end
|
370
372
|
|
371
373
|
def affine(options)
|
372
|
-
|
374
|
+
dup.affine!(options)
|
373
375
|
end
|
374
376
|
|
375
|
-
def rotate!(radians, origin = [
|
377
|
+
def rotate!(radians, origin = [0.0, 0.0])
|
376
378
|
origin = case origin
|
377
379
|
when Array
|
378
380
|
origin
|
379
381
|
when Geos::Geometry
|
380
382
|
center = origin.centroid
|
381
|
-
[
|
383
|
+
[center.x, center.y]
|
382
384
|
else
|
383
|
-
raise ArgumentError
|
385
|
+
raise ArgumentError, 'Expected an Array or a Geos::Geometry for the origin'
|
384
386
|
end
|
385
387
|
|
386
|
-
|
387
|
-
:
|
388
|
-
:
|
389
|
-
:
|
390
|
-
:
|
391
|
-
:
|
392
|
-
:
|
393
|
-
:
|
394
|
-
:
|
395
|
-
:
|
396
|
-
:
|
397
|
-
:
|
398
|
-
:
|
399
|
-
|
388
|
+
affine!(
|
389
|
+
afac: Math.cos(radians),
|
390
|
+
bfac: -Math.sin(radians),
|
391
|
+
cfac: 0,
|
392
|
+
dfac: Math.sin(radians),
|
393
|
+
efac: Math.cos(radians),
|
394
|
+
ffac: 0,
|
395
|
+
gfac: 0,
|
396
|
+
hfac: 0,
|
397
|
+
ifac: 1,
|
398
|
+
xoff: origin[0] - Math.cos(radians) * origin[0] + Math.sin(radians) * origin[1],
|
399
|
+
yoff: origin[1] - Math.sin(radians) * origin[0] - Math.cos(radians) * origin[1],
|
400
|
+
zoff: 0
|
401
|
+
)
|
400
402
|
end
|
401
403
|
|
402
|
-
def rotate(radians, origin = [
|
403
|
-
|
404
|
+
def rotate(radians, origin = [0.0, 0.0])
|
405
|
+
dup.rotate!(radians, origin)
|
404
406
|
end
|
405
407
|
|
406
408
|
def rotate_x!(radians)
|
407
|
-
|
408
|
-
:
|
409
|
-
:
|
410
|
-
:
|
411
|
-
:
|
412
|
-
:
|
413
|
-
:
|
414
|
-
:
|
415
|
-
:
|
416
|
-
:
|
417
|
-
:
|
418
|
-
:
|
419
|
-
:
|
420
|
-
|
409
|
+
affine!(
|
410
|
+
afac: 1,
|
411
|
+
bfac: 0,
|
412
|
+
cfac: 0,
|
413
|
+
dfac: 0,
|
414
|
+
efac: Math.cos(radians),
|
415
|
+
ffac: -Math.sin(radians),
|
416
|
+
gfac: 0,
|
417
|
+
hfac: Math.sin(radians),
|
418
|
+
ifac: Math.cos(radians),
|
419
|
+
xoff: 0,
|
420
|
+
yoff: 0,
|
421
|
+
zoff: 0
|
422
|
+
)
|
421
423
|
end
|
422
424
|
|
423
425
|
def rotate_x(radians)
|
424
|
-
|
426
|
+
dup.rotate_x!(radians)
|
425
427
|
end
|
426
428
|
|
427
429
|
def rotate_y!(radians)
|
428
|
-
|
429
|
-
:
|
430
|
-
:
|
431
|
-
:
|
432
|
-
:
|
433
|
-
:
|
434
|
-
:
|
435
|
-
:
|
436
|
-
:
|
437
|
-
:
|
438
|
-
:
|
439
|
-
:
|
440
|
-
:
|
441
|
-
|
430
|
+
affine!(
|
431
|
+
afac: Math.cos(radians),
|
432
|
+
bfac: 0,
|
433
|
+
cfac: Math.sin(radians),
|
434
|
+
dfac: 0,
|
435
|
+
efac: 1,
|
436
|
+
ffac: 0,
|
437
|
+
gfac: -Math.sin(radians),
|
438
|
+
hfac: 0,
|
439
|
+
ifac: Math.cos(radians),
|
440
|
+
xoff: 0,
|
441
|
+
yoff: 0,
|
442
|
+
zoff: 0
|
443
|
+
)
|
442
444
|
end
|
443
445
|
|
444
446
|
def rotate_y(radians)
|
445
|
-
|
447
|
+
dup.rotate_y!(radians)
|
446
448
|
end
|
447
449
|
|
448
450
|
def rotate_z!(radians)
|
449
|
-
|
451
|
+
rotate!(radians)
|
450
452
|
end
|
451
453
|
|
452
454
|
def rotate_z(radians)
|
453
|
-
|
455
|
+
dup.rotate!(radians)
|
454
456
|
end
|
455
457
|
|
456
458
|
def scale!(*args)
|
@@ -459,27 +461,27 @@ module Geos
|
|
459
461
|
elsif args.length.between?(1, 3)
|
460
462
|
args.values_at(0...3)
|
461
463
|
else
|
462
|
-
raise ArgumentError
|
464
|
+
raise ArgumentError, "Wrong number of arguments #{args.length} for 1-3"
|
463
465
|
end
|
464
466
|
|
465
|
-
|
466
|
-
:
|
467
|
-
:
|
468
|
-
:
|
469
|
-
:
|
470
|
-
:
|
471
|
-
:
|
472
|
-
:
|
473
|
-
:
|
474
|
-
:
|
475
|
-
:
|
476
|
-
:
|
477
|
-
:
|
478
|
-
|
467
|
+
affine!(
|
468
|
+
afac: x || 1,
|
469
|
+
bfac: 0,
|
470
|
+
cfac: 0,
|
471
|
+
dfac: 0,
|
472
|
+
efac: y || 1,
|
473
|
+
ffac: 0,
|
474
|
+
gfac: 0,
|
475
|
+
hfac: 0,
|
476
|
+
ifac: z || 1,
|
477
|
+
xoff: 0,
|
478
|
+
yoff: 0,
|
479
|
+
zoff: 0
|
480
|
+
)
|
479
481
|
end
|
480
482
|
|
481
483
|
def scale(*args)
|
482
|
-
|
484
|
+
dup.scale!(*args)
|
483
485
|
end
|
484
486
|
|
485
487
|
def trans_scale!(*args)
|
@@ -488,7 +490,7 @@ module Geos
|
|
488
490
|
elsif args.length.between?(1, 4)
|
489
491
|
args.values_at(0...4)
|
490
492
|
else
|
491
|
-
raise ArgumentError
|
493
|
+
raise ArgumentError, "Wrong number of arguments #{args.length} for 1-4"
|
492
494
|
end
|
493
495
|
|
494
496
|
x_factor ||= 1
|
@@ -496,24 +498,24 @@ module Geos
|
|
496
498
|
delta_x ||= 0
|
497
499
|
delta_y ||= 0
|
498
500
|
|
499
|
-
|
500
|
-
:
|
501
|
-
:
|
502
|
-
:
|
503
|
-
:
|
504
|
-
:
|
505
|
-
:
|
506
|
-
:
|
507
|
-
:
|
508
|
-
:
|
509
|
-
:
|
510
|
-
:
|
511
|
-
:
|
512
|
-
|
501
|
+
affine!(
|
502
|
+
afac: x_factor,
|
503
|
+
bfac: 0,
|
504
|
+
cfac: 0,
|
505
|
+
dfac: 0,
|
506
|
+
efac: y_factor,
|
507
|
+
ffac: 0,
|
508
|
+
gfac: 0,
|
509
|
+
hfac: 0,
|
510
|
+
ifac: 1,
|
511
|
+
xoff: delta_x * x_factor,
|
512
|
+
yoff: delta_y * y_factor,
|
513
|
+
zoff: 0
|
514
|
+
)
|
513
515
|
end
|
514
516
|
|
515
517
|
def trans_scale(*args)
|
516
|
-
|
518
|
+
dup.trans_scale!(*args)
|
517
519
|
end
|
518
520
|
|
519
521
|
def translate!(*args)
|
@@ -522,27 +524,27 @@ module Geos
|
|
522
524
|
elsif args.length.between?(1, 3)
|
523
525
|
args.values_at(0...3)
|
524
526
|
else
|
525
|
-
raise ArgumentError
|
527
|
+
raise ArgumentError, "Wrong number of arguments #{args.length} for 1-3"
|
526
528
|
end
|
527
529
|
|
528
|
-
|
529
|
-
:
|
530
|
-
:
|
531
|
-
:
|
532
|
-
:
|
533
|
-
:
|
534
|
-
:
|
535
|
-
:
|
536
|
-
:
|
537
|
-
:
|
538
|
-
:
|
539
|
-
:
|
540
|
-
:
|
541
|
-
|
530
|
+
affine!(
|
531
|
+
afac: 1,
|
532
|
+
bfac: 0,
|
533
|
+
cfac: 0,
|
534
|
+
dfac: 0,
|
535
|
+
efac: 1,
|
536
|
+
ffac: 0,
|
537
|
+
gfac: 0,
|
538
|
+
hfac: 0,
|
539
|
+
ifac: 1,
|
540
|
+
xoff: x || 0,
|
541
|
+
yoff: y || 0,
|
542
|
+
zoff: z || 1
|
543
|
+
)
|
542
544
|
end
|
543
545
|
|
544
546
|
def translate(*args)
|
545
|
-
|
547
|
+
dup.translate!(*args)
|
546
548
|
end
|
547
549
|
|
548
550
|
protected
|