ffi-geos 0.5.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.rdoc +14 -100
- data/lib/ffi-geos.rb +18 -3
- data/lib/ffi-geos/coordinate_sequence.rb +2 -2
- data/lib/ffi-geos/geometry.rb +7 -1
- data/lib/ffi-geos/interrupt.rb +7 -7
- data/lib/ffi-geos/line_string.rb +16 -1
- data/lib/ffi-geos/point.rb +1 -1
- data/lib/ffi-geos/polygon.rb +1 -1
- data/lib/ffi-geos/strtree.rb +7 -1
- data/lib/ffi-geos/tools.rb +31 -5
- data/lib/ffi-geos/utils.rb +6 -18
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkb_reader.rb +7 -0
- data/lib/ffi-geos/wkb_writer.rb +1 -1
- data/lib/ffi-geos/wkt_reader.rb +5 -0
- data/lib/ffi-geos/wkt_writer.rb +2 -2
- data/test/coordinate_sequence_tests.rb +23 -23
- data/test/geometry_collection_tests.rb +6 -1
- data/test/geometry_tests.rb +356 -554
- data/test/interrupt_tests.rb +1 -1
- data/test/line_string_tests.rb +65 -37
- data/test/linear_ring_tests.rb +10 -3
- data/test/misc_tests.rb +1 -1
- data/test/point_tests.rb +6 -1
- data/test/polygon_tests.rb +2 -2
- data/test/prepared_geometry_tests.rb +1 -1
- data/test/strtree_tests.rb +2 -2
- data/test/test_helper.rb +56 -3
- data/test/tools_tests.rb +2 -2
- data/test/utils_tests.rb +35 -43
- data/test/wkb_reader_tests.rb +13 -1
- data/test/wkb_writer_tests.rb +29 -3
- data/test/wkt_reader_tests.rb +2 -2
- data/test/wkt_writer_tests.rb +4 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bc526266d55420dc48080bdd5e692892c7dbb2a
|
4
|
+
data.tar.gz: f7677af86f57eb3d0a9be0b8b1755b3ddc423ffb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 203cff10e29ac37807026ddc9a2d70965fe368df68ca2a03ea3fa74c28f5604ac86a03e33f5430461e0d0b109194bec66036c24d32058285ce6b03a6a815b33e
|
7
|
+
data.tar.gz: 35a98846b51df19ab97ccc39f610ee442b59a5f1c423b9b58870cda443d66476dff0dccad0340909a8906da1eacb86611eabbc287412ae0456f6bdcd8d92d4c8
|
data/.travis.yml
CHANGED
data/README.rdoc
CHANGED
@@ -9,10 +9,10 @@
|
|
9
9
|
|
10
10
|
Ruby versions known to work:
|
11
11
|
|
12
|
-
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0
|
13
|
-
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0
|
14
|
-
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0
|
15
|
-
* JRuby 1.6
|
12
|
+
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0+ x86_64, OSX 10.6.5+
|
13
|
+
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0+ i386, linux
|
14
|
+
* Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0+ x86_64, linux
|
15
|
+
* JRuby 1.6+, x86_64 OSX 10.6.5+
|
16
16
|
|
17
17
|
=== JRuby Notes
|
18
18
|
|
@@ -67,102 +67,16 @@ Ruby bindings along with the following enhancements and additions:
|
|
67
67
|
copying in either a lenient or a strict sort of manner. See the documentation
|
68
68
|
for Geos.srid_copy_policy= for details.
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
*
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
* Geos::coord_seq
|
81
|
-
* Geos::covered_by?
|
82
|
-
* Geos::covers?
|
83
|
-
* Geos::delaunay_triangulation
|
84
|
-
* Geos::end_point
|
85
|
-
* Geos::eql_almost?
|
86
|
-
* Geos::equals?
|
87
|
-
* Geos::equals_almost?
|
88
|
-
* Geos::equals_exact?
|
89
|
-
* Geos::exactly_equals?
|
90
|
-
* Geos::extract_unique_points - Geos::Geometry#unique_points
|
91
|
-
* Geos::hausdorff_distance
|
92
|
-
* Geos::interpolate
|
93
|
-
* Geos::interpolate_normalized
|
94
|
-
* Geos::nearest_points
|
95
|
-
* Geos::node
|
96
|
-
* Geos::normalize!
|
97
|
-
* Geos::num_coordinates
|
98
|
-
* Geos::polygonize
|
99
|
-
* Geos::polygonize_cut_edges
|
100
|
-
* Geos::polygonize_full
|
101
|
-
* Geos::project
|
102
|
-
* Geos::project_normalized
|
103
|
-
* Geos::relate_boundary_node_rule
|
104
|
-
* Geos::representative_point
|
105
|
-
* Geos::shared_paths
|
106
|
-
* Geos::snap
|
107
|
-
* Geos::snap_to
|
108
|
-
* Geos::start_point
|
109
|
-
* Geos::symmetric_difference
|
110
|
-
* Geos::to_prepared
|
111
|
-
* Geos::unary_union
|
112
|
-
* Geos::union_cascaded - Geos::Geometry#union can also be called
|
113
|
-
without a geometry argument to produce the same effect.
|
114
|
-
* Geos::unique_points - Geos::Geometry#extract_unique_points
|
115
|
-
* Geos::valid_detail
|
116
|
-
* Geos::valid_reason
|
117
|
-
|
118
|
-
=== Geos::LineString and Geos::LinearRing
|
119
|
-
|
120
|
-
* Geos::LineString#[]
|
121
|
-
* Geos::LineString#closed?
|
122
|
-
* Geos::LineString#each
|
123
|
-
* Geos::LineString#num_points
|
124
|
-
* Geos::LineString#offset_curve
|
125
|
-
* Geos::LineString#point_n
|
126
|
-
* Geos::LineString#slice
|
127
|
-
* Geos::LinearRing#to_line_string
|
128
|
-
* Geos::LinearRing#to_polygon
|
129
|
-
|
130
|
-
=== Geos::WktWriter
|
131
|
-
|
132
|
-
* Geos::WktWriter#old_3d
|
133
|
-
* Geos::WktWriter#old_3d=
|
134
|
-
* Geos::WktWriter#output_dimensions
|
135
|
-
* Geos::WktWriter#output_dimensions=
|
136
|
-
* Geos::WktWriter#rounding_precision
|
137
|
-
* Geos::WktWriter#rounding_precision=
|
138
|
-
* Geos::WktWriter#trim
|
139
|
-
* Geos::WktWriter#trim=
|
140
|
-
|
141
|
-
=== Geos::CoordinateSequence
|
142
|
-
|
143
|
-
* Geos::CoordinateSequence#has_z?
|
144
|
-
* Geos::CoordinateSequence#to_line_string
|
145
|
-
* Geos::CoordinateSequence#to_linear_ring
|
146
|
-
* Geos::CoordinateSequence#to_point
|
147
|
-
* Geos::CoordinateSequence#to_polygon
|
148
|
-
|
149
|
-
=== Geos::Polygon
|
150
|
-
|
151
|
-
* Geos::Polygon#interior_ring
|
152
|
-
* Geos::Polygon#interior_rings
|
153
|
-
|
154
|
-
=== Geos::Utils
|
155
|
-
|
156
|
-
* Geos::Utils.orientation_index
|
157
|
-
* Geos::Utils.relate_match
|
158
|
-
|
159
|
-
=== Geos::Interrupt
|
160
|
-
|
161
|
-
* Geos::Interrupt.available?
|
162
|
-
* Geos::Interrupt.register
|
163
|
-
* Geos::Interrupt.request
|
164
|
-
* Geos::Interrupt.cancel
|
165
|
-
* Geos::Interrupt.clear
|
70
|
+
* There are many, many new methods added all over the place. Pretty much the
|
71
|
+
entire GEOS C API is represented in ffi-geos along with all sorts of useful
|
72
|
+
convenience methods and geometry conversion and manipulation methods.
|
73
|
+
|
74
|
+
* *NEW IN ffi-geos 1.0.0* -- all errors thrown by ffi-geos are now instances of
|
75
|
+
`Geos::Error` or subclasses thereof. `Geos::Error` itself is a descendant
|
76
|
+
of `RuntimeError` as is the case with the native Geos extension. This means
|
77
|
+
that code like `rescue RuntimeError` should still work but you can now
|
78
|
+
further capture more precise error types by capturing errors like
|
79
|
+
`Geos::Error`, `Geos::ParseError`, etc.
|
166
80
|
|
167
81
|
== Thanks
|
168
82
|
|
data/lib/ffi-geos.rb
CHANGED
@@ -1023,7 +1023,7 @@ module Geos
|
|
1023
1023
|
end
|
1024
1024
|
|
1025
1025
|
def error_handler(*args)
|
1026
|
-
raise
|
1026
|
+
raise Geos::GEOSException.new(args[0] % args[1])
|
1027
1027
|
end
|
1028
1028
|
end
|
1029
1029
|
|
@@ -1110,7 +1110,7 @@ module Geos
|
|
1110
1110
|
create_empty_collection
|
1111
1111
|
create_empty_linear_ring
|
1112
1112
|
}.each do |m|
|
1113
|
-
self.class_eval
|
1113
|
+
self.class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
1114
1114
|
def #{m}(*args)
|
1115
1115
|
Geos::Utils.#{m}(*args)
|
1116
1116
|
end
|
@@ -1178,12 +1178,27 @@ module Geos
|
|
1178
1178
|
].freeze
|
1179
1179
|
end
|
1180
1180
|
|
1181
|
-
class
|
1181
|
+
class Error < ::RuntimeError
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
class GEOSException < Error
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
class IndexBoundsError < Error
|
1188
|
+
def initialize(*)
|
1189
|
+
super("Index out of bounds")
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
class MixedSRIDsError < Error
|
1182
1194
|
def initialize(srid_a, srid_b)
|
1183
1195
|
super("Operation on mixed SRIDs (#{srid_a} vs. #{srid_b})")
|
1184
1196
|
end
|
1185
1197
|
end
|
1186
1198
|
|
1199
|
+
class ParseError < Error
|
1200
|
+
end
|
1201
|
+
|
1187
1202
|
include GeomTypes
|
1188
1203
|
include VersionConstants
|
1189
1204
|
end
|
@@ -4,7 +4,7 @@ module Geos
|
|
4
4
|
|
5
5
|
# A CoordinateSequence is a list of coordinates in a Geometry.
|
6
6
|
class CoordinateSequence
|
7
|
-
class ParseError <
|
7
|
+
class ParseError < Geos::ParseError
|
8
8
|
end
|
9
9
|
|
10
10
|
class CoordinateAccessor
|
@@ -262,7 +262,7 @@ module Geos
|
|
262
262
|
|
263
263
|
def check_bounds(idx) #:nodoc:
|
264
264
|
if idx < 0 || idx >= self.length
|
265
|
-
raise
|
265
|
+
raise Geos::IndexBoundsError.new("Index out of bounds")
|
266
266
|
end
|
267
267
|
end
|
268
268
|
|
data/lib/ffi-geos/geometry.rb
CHANGED
@@ -6,6 +6,12 @@ module Geos
|
|
6
6
|
|
7
7
|
attr_reader :ptr
|
8
8
|
|
9
|
+
class CouldntNormalizeError < Geos::Error
|
10
|
+
def initialize(klass)
|
11
|
+
super("Couldn't normalize #{klass}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
9
15
|
# For internal use. Geometry objects should be created via WkbReader,
|
10
16
|
# WktReader and the various Geos.create_* methods.
|
11
17
|
def initialize(ptr, options = {})
|
@@ -48,7 +54,7 @@ module Geos
|
|
48
54
|
|
49
55
|
def normalize!
|
50
56
|
if FFIGeos.GEOSNormalize_r(Geos.current_handle, self.ptr) == -1
|
51
|
-
raise
|
57
|
+
raise Geos::Geometry::CouldntNormalizeError.new(self.class)
|
52
58
|
end
|
53
59
|
|
54
60
|
self
|
data/lib/ffi-geos/interrupt.rb
CHANGED
@@ -12,10 +12,10 @@ module Geos
|
|
12
12
|
# Registers an interrupt method or block that may be called during
|
13
13
|
# certain operations such as Geos::Geometry#buffer. During these
|
14
14
|
# blocks you can interrupt the current operation using
|
15
|
-
# Geos.
|
16
|
-
# Geos.
|
15
|
+
# Geos::Interrupt.request and cancel that interrupt request using
|
16
|
+
# Geos::Interrupt.clear.
|
17
17
|
#
|
18
|
-
# The return value for Geos.
|
18
|
+
# The return value for Geos::Interrupt.register is a reference to the
|
19
19
|
# previously registered callback, allowing you to chain interrupt
|
20
20
|
# calls together by calling #call on the previously registered callback.
|
21
21
|
#
|
@@ -25,9 +25,9 @@ module Geos
|
|
25
25
|
# up in unexpected ways while interrupts are firing.
|
26
26
|
def register(method_or_block = nil, &block)
|
27
27
|
if method_or_block.nil? && !block_given?
|
28
|
-
raise ArgumentError.new("Expected either a method or a block for Geos.
|
28
|
+
raise ArgumentError.new("Expected either a method or a block for Geos::Interrupt.register")
|
29
29
|
elsif !method_or_block.nil? && block_given?
|
30
|
-
raise ArgumentError.new("Cannot use both a method and a block for Geos.
|
30
|
+
raise ArgumentError.new("Cannot use both a method and a block for Geos::Interrupt.register")
|
31
31
|
else
|
32
32
|
retval = @current_interrupt_callback
|
33
33
|
|
@@ -44,7 +44,7 @@ module Geos
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# Interrupt the current operation. This method should generally be
|
47
|
-
# called from within a callback registered with Geos.
|
47
|
+
# called from within a callback registered with Geos::Interrupt.register
|
48
48
|
# but can be called at any time to interrupt the next interruptable
|
49
49
|
# operation.
|
50
50
|
def request
|
@@ -53,7 +53,7 @@ module Geos
|
|
53
53
|
|
54
54
|
# Cancel a request to interrupt the current operation. This method
|
55
55
|
# should be called from within a callback registered with
|
56
|
-
# Geos.
|
56
|
+
# Geos::Interrupt.register but can be called at any time all the same.
|
57
57
|
def cancel
|
58
58
|
FFIGeos.GEOS_interruptCancel
|
59
59
|
end
|
data/lib/ffi-geos/line_string.rb
CHANGED
@@ -29,7 +29,7 @@ module Geos
|
|
29
29
|
|
30
30
|
def point_n(n)
|
31
31
|
if n < 0 || n >= self.num_points
|
32
|
-
raise
|
32
|
+
raise Geos::IndexBoundsError.new
|
33
33
|
else
|
34
34
|
cast_geometry_ptr(
|
35
35
|
FFIGeos.GEOSGeomGetPointN_r(Geos.current_handle, self.ptr, n), {
|
@@ -68,5 +68,20 @@ module Geos
|
|
68
68
|
bool_result(FFIGeos.GEOSisClosed_r(Geos.current_handle, self.ptr))
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
def to_linear_ring
|
73
|
+
if self.closed?
|
74
|
+
Geos.create_linear_ring(self.coord_seq, :srid => pick_srid_according_to_policy(self.srid))
|
75
|
+
else
|
76
|
+
self_cs = self.coord_seq.to_a
|
77
|
+
self_cs.push(self_cs[0])
|
78
|
+
|
79
|
+
Geos.create_linear_ring(self_cs, :srid => pick_srid_according_to_policy(self.srid))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_polygon
|
84
|
+
self.to_linear_ring.to_polygon
|
85
|
+
end
|
71
86
|
end
|
72
87
|
end
|
data/lib/ffi-geos/point.rb
CHANGED
data/lib/ffi-geos/polygon.rb
CHANGED
@@ -8,7 +8,7 @@ module Geos
|
|
8
8
|
|
9
9
|
def interior_ring_n(n)
|
10
10
|
if n < 0 || n >= self.num_interior_rings
|
11
|
-
raise
|
11
|
+
raise Geos::IndexBoundsError.new
|
12
12
|
else
|
13
13
|
cast_geometry_ptr(
|
14
14
|
FFIGeos.GEOSGetInteriorRingN_r(Geos.current_handle, self.ptr, n), {
|
data/lib/ffi-geos/strtree.rb
CHANGED
@@ -9,6 +9,12 @@ module Geos
|
|
9
9
|
|
10
10
|
undef :clone, :dup
|
11
11
|
|
12
|
+
class AlreadyBuiltError < Geos::Error
|
13
|
+
def initialize(*)
|
14
|
+
super("STRtree has already been built")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
12
18
|
# :call-seq:
|
13
19
|
# new(capacity)
|
14
20
|
# new(geoms_and_objects)
|
@@ -71,7 +77,7 @@ module Geos
|
|
71
77
|
|
72
78
|
def insert(geom, item)
|
73
79
|
if self.built?
|
74
|
-
raise
|
80
|
+
raise AlreadyBuiltError.new
|
75
81
|
else
|
76
82
|
check_geometry(geom)
|
77
83
|
|
data/lib/ffi-geos/tools.rb
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
module Geos
|
4
|
+
class NullPointerError < Geos::Error
|
5
|
+
def initialize(*)
|
6
|
+
super("Tried to create a Geometry from a NULL pointer!")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class InvalidGeometryTypeError < Geos::Error
|
11
|
+
def initialize(*)
|
12
|
+
super("Invalid geometry type")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class UnexpectedBooleanResultError < Geos::Error
|
17
|
+
def initialize(result)
|
18
|
+
super("Unexpected boolean result: #{result}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
4
22
|
module Tools
|
5
23
|
include GeomTypes
|
6
24
|
|
@@ -10,7 +28,7 @@ module Geos
|
|
10
28
|
}.merge(options)
|
11
29
|
|
12
30
|
if geom_ptr.null?
|
13
|
-
raise
|
31
|
+
raise Geos::NullPointerError.new
|
14
32
|
end
|
15
33
|
|
16
34
|
klass = case FFIGeos.GEOSGeomTypeId_r(Geos.current_handle, geom_ptr)
|
@@ -31,7 +49,7 @@ module Geos
|
|
31
49
|
when GEOS_GEOMETRYCOLLECTION
|
32
50
|
GeometryCollection
|
33
51
|
else
|
34
|
-
raise
|
52
|
+
raise Geos::InvalidGeometryTypeError.new
|
35
53
|
end
|
36
54
|
|
37
55
|
klass.new(geom_ptr, options).tap { |ret|
|
@@ -76,14 +94,14 @@ module Geos
|
|
76
94
|
end
|
77
95
|
end
|
78
96
|
|
79
|
-
def bool_result(
|
80
|
-
case
|
97
|
+
def bool_result(result)
|
98
|
+
case result
|
81
99
|
when 1
|
82
100
|
true
|
83
101
|
when 0
|
84
102
|
false
|
85
103
|
else
|
86
|
-
raise
|
104
|
+
raise Geos::UnexpectedBooleanResultError.new(result)
|
87
105
|
end
|
88
106
|
end
|
89
107
|
|
@@ -100,6 +118,14 @@ module Geos
|
|
100
118
|
end
|
101
119
|
end
|
102
120
|
|
121
|
+
def extract_options!(args)
|
122
|
+
if args.last.is_a?(Hash)
|
123
|
+
args.pop
|
124
|
+
else
|
125
|
+
{}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
103
129
|
class << self
|
104
130
|
include Geos::Tools
|
105
131
|
end
|
data/lib/ffi-geos/utils.rb
CHANGED
@@ -28,11 +28,7 @@ module Geos
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def create_point(*args)
|
31
|
-
options =
|
32
|
-
args.pop
|
33
|
-
else
|
34
|
-
{}
|
35
|
-
end
|
31
|
+
options = extract_options!(args)
|
36
32
|
|
37
33
|
if args.length == 1
|
38
34
|
cs = args.first
|
@@ -47,7 +43,7 @@ module Geos
|
|
47
43
|
end
|
48
44
|
|
49
45
|
if cs.length != 1
|
50
|
-
raise
|
46
|
+
raise ArgumentError.new("IllegalArgumentException: Point coordinate list must contain a single element")
|
51
47
|
end
|
52
48
|
|
53
49
|
cs_dup = cs.dup
|
@@ -62,7 +58,7 @@ module Geos
|
|
62
58
|
cs = cs_from_cs_or_geom(cs)
|
63
59
|
|
64
60
|
if cs.length <= 1 && cs.length != 0
|
65
|
-
raise
|
61
|
+
raise ArgumentError.new("IllegalArgumentException: point array must contain 0 or >1 elements")
|
66
62
|
end
|
67
63
|
|
68
64
|
cs_dup = cs.dup
|
@@ -77,7 +73,7 @@ module Geos
|
|
77
73
|
cs = cs_from_cs_or_geom(cs)
|
78
74
|
|
79
75
|
if cs.length <= 1 && cs.length != 0
|
80
|
-
raise
|
76
|
+
raise ArgumentError.new("IllegalArgumentException: point array must contain 0 or >1 elements")
|
81
77
|
end
|
82
78
|
|
83
79
|
cs.ptr.autorelease = false
|
@@ -88,11 +84,7 @@ module Geos
|
|
88
84
|
end
|
89
85
|
|
90
86
|
def create_polygon(outer, *args)
|
91
|
-
options =
|
92
|
-
args.pop
|
93
|
-
else
|
94
|
-
{}
|
95
|
-
end
|
87
|
+
options = extract_options!(args)
|
96
88
|
|
97
89
|
inner_dups = Array(args).flatten.collect { |i|
|
98
90
|
force_to_linear_ring(i) or
|
@@ -174,11 +166,7 @@ module Geos
|
|
174
166
|
Geos::Geometry
|
175
167
|
end
|
176
168
|
|
177
|
-
options =
|
178
|
-
args.pop
|
179
|
-
else
|
180
|
-
{}
|
181
|
-
end
|
169
|
+
options = extract_options!(args)
|
182
170
|
|
183
171
|
geoms = Array(args).flatten.tap { |i|
|
184
172
|
if i.detect { |g| !g.is_a?(klass) }
|