ffi-geos 0.0.1 → 0.0.2

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.
data/README.rdoc CHANGED
@@ -12,12 +12,11 @@ Ruby versions known to work:
12
12
  * Ruby MRI 1.8.7 and 1.9.2, x86_64, OSX 10.6.5+
13
13
  * Ruby MRI 1.8.7 and 1.9.2, i386, linux
14
14
  * Ruby MRI 1.8.7, x86_64, linux
15
+ * JRuby 1.6.3, x86_64 OSX 10.6.5+
15
16
 
16
- Note that versions of JRuby prior to the as-of-yet (25 June 2011) unreleased
17
- version 1.6.3 have problems in their ffi implementation when dealing with
18
- AutoPointers that can lead to segfaults during garbage collection. Upcoming
19
- versions of JRuby should have the problem licked. For details, check out
20
- http://jira.codehaus.org/browse/JRUBY-5813.
17
+ Note that versions of JRuby prior to version 1.6.3 have problems in their ffi
18
+ implementation when dealing with AutoPointers that can lead to segfaults during
19
+ garbage collection.
21
20
 
22
21
  == Features
23
22
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/ffi-geos.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ffi-geos}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["J Smith"]
12
- s.date = %q{2011-06-25}
12
+ s.date = %q{2011-07-22}
13
13
  s.description = %q{An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).}
14
14
  s.email = %q{dark.panda@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -56,7 +56,7 @@ Gem::Specification.new do |s|
56
56
  ]
57
57
  s.homepage = %q{http://github.com/dark-panda/ffi-geos}
58
58
  s.require_paths = ["lib"]
59
- s.rubygems_version = %q{1.7.2}
59
+ s.rubygems_version = %q{1.6.2}
60
60
  s.summary = %q{An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).}
61
61
 
62
62
  if s.respond_to? :specification_version then
data/lib/ffi-geos.rb CHANGED
@@ -1026,10 +1026,10 @@ module Geos
1026
1026
  VERSION = File.read(File.join(GEOS_BASE, %w{ .. .. VERSION })).strip
1027
1027
  GEOS_JTS_PORT = Geos.jts_port
1028
1028
  GEOS_VERSION,
1029
- GEOS_VERSION_MAJOR, GEOS_VERSION_MINOR, GEOS_VERISON_PATCH, GEOS_VERSION_PRERELEASE,
1029
+ GEOS_VERSION_MAJOR, GEOS_VERSION_MINOR, GEOS_VERSION_PATCH, GEOS_VERSION_PRERELEASE,
1030
1030
  GEOS_CAPI_VERSION,
1031
1031
  GEOS_CAPI_VERSION_MAJOR, GEOS_CAPI_VERSION_MINOR, GEOS_CAPI_VERSION_PATCH =
1032
- if !(versions = Geos.version.scan(/^((\d+)\.(\d+)\.(\d+)((?:rc|beta|alpha)\d+)?)-CAPI-((\d+)\.(\d+)\.(\d+))$/)).empty?
1032
+ if !(versions = Geos.version.scan(/^((\d+)\.(\d+)\.(\d+)((?:dev|rc|beta|alpha)\d*)?)-CAPI-((\d+)\.(\d+)\.(\d+))$/)).empty?
1033
1033
  versions = versions[0]
1034
1034
  [
1035
1035
  versions[0],
@@ -3,23 +3,53 @@ module Geos
3
3
 
4
4
  # A CoordinateSequence is a list of coordinates in a Geometry.
5
5
  class CoordinateSequence
6
+ class ParseError < ArgumentError
7
+ end
8
+
6
9
  include Enumerable
7
10
 
8
11
  attr_reader :ptr
9
12
 
10
13
  # :call-seq:
11
14
  # new(ptr, auto_free = true)
12
- # new(size, dims = 0)
15
+ # new(size = 0, dims = 0)
16
+ # new(points)
13
17
  #
14
18
  # The ptr version of the initializer is for internal use.
19
+ #
20
+ # new(points) will try to glean the size and dimensions of your
21
+ # CoordinateSequence from an Array of points. The Array should contain
22
+ # uniform-sized Arrays which represent the [ x, y, z ] values of your
23
+ # coordinates.
15
24
  def initialize(*args)
25
+ points = nil # forward declaration we can use later
26
+
16
27
  ptr, auto_free = if args.first.is_a?(FFI::Pointer)
17
28
  [ args.first, args[1] ]
18
29
  else
19
- size, dims = if !args.length.between?(1, 2)
20
- raise ArgumentError.new("wrong number of arguments (#{args.length} for 1-2)")
30
+ size, dims = if args.first.is_a?(Array)
31
+ points = if args.first.first.is_a?(Array)
32
+ args.first
33
+ else
34
+ args
35
+ end
36
+ lengths = points.collect(&:length).uniq
37
+
38
+ if lengths.empty?
39
+ [ 0, 0 ]
40
+ elsif lengths.length != 1
41
+ raise ParseError.new("Different sized points found in Array")
42
+ elsif !lengths.first.between?(1, 3)
43
+ raise ParseError.new("Expected points to contain 1-3 elements")
44
+ else
45
+ [ points.length, points.first.length ]
46
+ end
21
47
  else
22
- [ args[0], args[1] || 0]
48
+ if !args.length.between?(0, 2)
49
+ raise ArgumentError.new("wrong number of arguments (#{args.length} for 0-2)")
50
+ else
51
+ [ args[0] || 0, args[1] || 0 ]
52
+ end
23
53
  end
24
54
 
25
55
  [ FFIGeos.GEOSCoordSeq_create_r(Geos.current_handle, size, dims), true ]
@@ -33,6 +63,14 @@ module Geos
33
63
  if !auto_free
34
64
  @ptr.autorelease = false
35
65
  end
66
+
67
+ if points
68
+ points.each_with_index do |point, idx|
69
+ point.each_with_index do |val, dim|
70
+ self.set_ordinate(idx, dim, val)
71
+ end
72
+ end
73
+ end
36
74
  end
37
75
 
38
76
  def initialize_copy(source)
@@ -122,6 +160,18 @@ module Geos
122
160
  }.read_int
123
161
  end
124
162
 
163
+ def to_linear_ring
164
+ Geos.create_linear_ring(self)
165
+ end
166
+
167
+ def to_line_string
168
+ Geos.create_line_string(self)
169
+ end
170
+
171
+ def to_polygon
172
+ Geos.create_polygon(self)
173
+ end
174
+
125
175
  protected
126
176
 
127
177
  def check_bounds(idx) #:nodoc:
@@ -5,10 +5,16 @@ module Geos
5
5
 
6
6
  # Yields each Geometry in the GeometryCollection.
7
7
  def each
8
- self.num_geometries.times do |n|
9
- yield self.get_geometry_n(n)
8
+ if block_given?
9
+ self.num_geometries.times do |n|
10
+ yield self.get_geometry_n(n)
11
+ end
12
+ self
13
+ else
14
+ self.num_geometries.times.collect { |n|
15
+ self.get_geometry_n(n)
16
+ }.to_enum
10
17
  end
11
- nil
12
18
  end
13
19
 
14
20
  def get_geometry_n(n)
@@ -4,10 +4,16 @@ module Geos
4
4
  include Enumerable
5
5
 
6
6
  def each
7
- self.num_points.times do |n|
8
- yield self.point_n(n)
7
+ if block_given?
8
+ self.num_points.times do |n|
9
+ yield self.point_n(n)
10
+ end
11
+ self
12
+ else
13
+ self.num_points.times.collect { |n|
14
+ self.point_n(n)
15
+ }.to_enum
9
16
  end
10
- nil
11
17
  end
12
18
 
13
19
  if FFIGeos.respond_to?(:GEOSGeomGetNumPoints_r)
@@ -8,7 +8,33 @@ module Geos
8
8
 
9
9
  undef :clone, :dup
10
10
 
11
- def initialize(capacity)
11
+ # :call-seq:
12
+ # new(capacity)
13
+ # new(geoms_and_objects)
14
+ #
15
+ def initialize(*args)
16
+ geoms_and_objects = nil # forward declaration
17
+
18
+ capacity = if args.length == 1 && args.first.is_a?(Fixnum)
19
+ args.first
20
+ else
21
+ geoms_and_objects = if args.first.first.is_a?(Array)
22
+ args.first
23
+ else
24
+ args
25
+ end
26
+
27
+ geoms_and_objects.each do |geom, obj|
28
+ check_geometry(geom)
29
+ end
30
+
31
+ geoms_and_objects.length
32
+ end
33
+
34
+ if capacity <= 0
35
+ raise ArgumentError.new("STRtree capacity must be greater than 0")
36
+ end
37
+
12
38
  ptr = FFIGeos.GEOSSTRtree_create_r(Geos.current_handle, capacity)
13
39
 
14
40
  @ptr = FFI::AutoPointer.new(
@@ -17,9 +43,16 @@ module Geos
17
43
  )
18
44
 
19
45
  @storage = {}
20
- @storage_pointers = {}
46
+ @ptrs = {}
47
+
21
48
  @storage_key = 0
22
49
  @built = false
50
+
51
+ if geoms_and_objects
52
+ geoms_and_objects.each do |geom, obj|
53
+ self.insert(geom, obj)
54
+ end
55
+ end
23
56
  end
24
57
 
25
58
  def self.release(ptr) #:nodoc:
@@ -36,17 +69,21 @@ module Geos
36
69
  private :next_key
37
70
 
38
71
  def insert(geom, item)
39
- check_geometry(geom)
40
-
41
72
  if self.built?
42
73
  raise RuntimeError.new("STRtree has already been built")
43
74
  else
75
+ check_geometry(geom)
76
+
44
77
  key = next_key
45
78
  key_ptr = FFI::MemoryPointer.new(:pointer)
46
79
  key_ptr.write_int(key)
47
80
 
48
- @storage[key] = item
49
- @storage_pointers[key] = key_ptr
81
+ @storage[key] = {
82
+ :item => item,
83
+ :geometry => geom
84
+ }
85
+ @ptrs[key] = key_ptr
86
+
50
87
  FFIGeos.GEOSSTRtree_insert_r(Geos.current_handle, self.ptr, geom.ptr, key_ptr)
51
88
  end
52
89
  end
@@ -54,41 +91,36 @@ module Geos
54
91
  def remove(geom, item)
55
92
  check_geometry(geom)
56
93
 
57
- key = if @storage.respond_to?(:key)
58
- @storage.key(item)
59
- else
60
- @storage.index(item)
94
+ key = if storage = @storage.detect { |k, v| v[:item] == item }
95
+ storage[0]
61
96
  end
62
97
 
63
98
  if key
64
- key_ptr = @storage_pointers[key]
99
+ key_ptr = @ptrs[key]
65
100
  result = FFIGeos.GEOSSTRtree_remove_r(Geos.current_handle, self.ptr, geom.ptr, key_ptr)
66
101
  @built = true
67
102
 
68
103
  if result == 1
69
- @storage[key] = nil
70
- @storage_pointers[key] = nil
104
+ @storage.delete(key)
71
105
  end
72
106
  end
73
107
  end
74
108
 
75
- def query(geom)
109
+ def query_all(geom)
76
110
  check_geometry(geom)
77
111
 
78
112
  @built = true
79
- retval = nil
113
+ retval = []
80
114
 
81
- callback = if block_given?
82
- proc { |*args|
83
- key = args.first.read_int
84
- yield(@storage[key])
85
- }
86
- else
87
- retval = []
88
- proc { |*args|
89
- retval << @storage[args.first.read_int]
90
- }
91
- end
115
+ callback = proc { |*args|
116
+ key = args.first.read_int
117
+ storage = @storage[key]
118
+ retval << storage
119
+
120
+ if block_given?
121
+ yield(storage)
122
+ end
123
+ }
92
124
 
93
125
  FFIGeos.GEOSSTRtree_query_r(
94
126
  Geos.current_handle,
@@ -98,12 +130,42 @@ module Geos
98
130
  nil
99
131
  )
100
132
 
101
- if retval
102
- retval.compact
103
- end
104
133
  retval
105
134
  end
106
135
 
136
+ def query(geom, ret = :item)
137
+ self.query_all(geom).collect { |storage|
138
+ item = if ret.is_a?(Array)
139
+ storage.inject({}) do |memo, k|
140
+ memo.tap {
141
+ memo[k] = storage[k]
142
+ }
143
+ end
144
+ elsif ret == :all
145
+ storage
146
+ else
147
+ storage[ret]
148
+ end
149
+
150
+ item.tap {
151
+ if block_given?
152
+ yield(item)
153
+ end
154
+ }
155
+ }.compact
156
+ end
157
+
158
+ def query_geometries(geom)
159
+ self.query_all(geom).collect { |storage|
160
+ storage[:geometry].tap { |val|
161
+ if block_given?
162
+ yield(val)
163
+ end
164
+ }
165
+ }.compact
166
+ end
167
+ alias :query_geoms :query_geometries
168
+
107
169
  def iterate
108
170
  @storage.values.each do |v|
109
171
  yield(v)
@@ -63,16 +63,15 @@ module Geos
63
63
  end
64
64
 
65
65
  def create_polygon(outer, *inner)
66
- inner = Array(inner).flatten.tap { |i|
67
- if i.detect { |g| !g.is_a?(Geos::LinearRing) }
68
- raise TypeError.new("Expected inner Array to contain Geometry::LinearRing objects")
69
- end
66
+ inner_clones = Array(inner).flatten.collect { |i|
67
+ force_to_linear_ring(i) or
68
+ raise TypeError.new("Expected inner Array to contain Geos::LinearRing or Geos::CoordinateSequence objects")
70
69
  }
71
70
 
72
- outer_clone = outer.clone
73
- inner_clones = inner.map(&:clone)
71
+ outer_clone = force_to_linear_ring(outer) or
72
+ raise TypeError.new("Expected outer shell to be a Geos::LinearRing or Geos::CoordinateSequence")
74
73
 
75
- ary = FFI::MemoryPointer.new(:pointer, inner.length)
74
+ ary = FFI::MemoryPointer.new(:pointer, inner_clones.length)
76
75
  ary.write_array_of_pointer(inner_clones.map(&:ptr))
77
76
 
78
77
  cast_geometry_ptr(FFIGeos.GEOSGeom_createPolygon_r(Geos.current_handle, outer_clone.ptr, ary, inner_clones.length)).tap {
@@ -161,6 +160,16 @@ module Geos
161
160
  def create_geometry_collection(*geoms)
162
161
  create_collection(:geometry_collection, *geoms)
163
162
  end
163
+
164
+ private
165
+ def force_to_linear_ring(geom)
166
+ case geom
167
+ when Geos::CoordinateSequence
168
+ geom.to_linear_ring
169
+ when Geos::LinearRing
170
+ geom.clone
171
+ end
172
+ end
164
173
  end
165
174
  end
166
175
  end
@@ -7,21 +7,22 @@ class CoordinateSequenceTests < Test::Unit::TestCase
7
7
 
8
8
  def setup
9
9
  @cs = Geos::CoordinateSequence.new(3, 0)
10
+ super
10
11
  end
11
12
 
12
13
  def test_set_and_get_x
13
14
  @cs.set_x(0, 10.01)
14
- assert_in_delta(10.01, @cs.get_x(0), 0.0000001)
15
+ assert_in_delta(10.01, @cs.get_x(0), TOLERANCE)
15
16
  end
16
17
 
17
18
  def test_set_and_get_y
18
19
  @cs.set_y(0, 20.02)
19
- assert_in_delta(20.02, @cs.get_y(0), 0.0000001)
20
+ assert_in_delta(20.02, @cs.get_y(0), TOLERANCE)
20
21
  end
21
22
 
22
23
  def test_set_and_get_z
23
24
  @cs.set_z(0, 20.02)
24
- assert_in_delta(20.02, @cs.get_z(0), 0.0000001)
25
+ assert_in_delta(20.02, @cs.get_z(0), TOLERANCE)
25
26
  end
26
27
 
27
28
  def test_set_and_get_ordinate
@@ -29,9 +30,9 @@ class CoordinateSequenceTests < Test::Unit::TestCase
29
30
  @cs.set_ordinate(0, 1, 20.02)
30
31
  @cs.set_ordinate(0, 2, 30.03)
31
32
 
32
- assert_in_delta(10.01, @cs.get_ordinate(0, 0), 0.0000001)
33
- assert_in_delta(20.02, @cs.get_ordinate(0, 1), 0.0000001)
34
- assert_in_delta(30.03, @cs.get_ordinate(0, 2), 0.0000001)
33
+ assert_in_delta(10.01, @cs.get_ordinate(0, 0), TOLERANCE)
34
+ assert_in_delta(20.02, @cs.get_ordinate(0, 1), TOLERANCE)
35
+ assert_in_delta(30.03, @cs.get_ordinate(0, 2), TOLERANCE)
35
36
  end
36
37
 
37
38
  def test_length
@@ -89,4 +90,89 @@ class CoordinateSequenceTests < Test::Unit::TestCase
89
90
  assert_equal(@cs.get_y(0), cs_b.get_y(0))
90
91
  assert_equal(@cs.dimensions, cs_b.dimensions)
91
92
  end
93
+
94
+ def test_with_no_arguments
95
+ cs = Geos::CoordinateSequence.new
96
+ assert_equal(0, cs.size)
97
+ assert_equal(3, cs.dimensions)
98
+ end
99
+
100
+ def test_read_from_array
101
+ cs = Geos::CoordinateSequence.new([
102
+ [ 0, 0 ],
103
+ [ 1, 1 ],
104
+ [ 2, 2 ],
105
+ [ 3, 3 ],
106
+ [ 4, 4 ]
107
+ ])
108
+
109
+ assert_equal(2, cs.dimensions)
110
+ assert_equal(5, cs.length)
111
+
112
+ assert_raise(Geos::CoordinateSequence::ParseError) do
113
+ cs = Geos::CoordinateSequence.new([
114
+ [ 1, 2 ],
115
+ [ 1, 2, 3 ]
116
+ ])
117
+ end
118
+
119
+ assert_raise(Geos::CoordinateSequence::ParseError) do
120
+ cs = Geos::CoordinateSequence.new([
121
+ [ 1, 2, 3, 4 ]
122
+ ])
123
+ end
124
+ end
125
+
126
+ def test_to_to_linear_ring
127
+ cs = Geos::CoordinateSequence.new([
128
+ [ 0, 0 ],
129
+ [ 0, 5 ],
130
+ [ 5, 5 ],
131
+ [ 5, 0 ],
132
+ [ 0, 0 ]
133
+ ])
134
+
135
+ assert_equal('LINEARRING (0 0, 0 5, 5 5, 5 0, 0 0)', write(cs.to_linear_ring, :trim => true))
136
+ end
137
+
138
+ def test_to_empty_linear_ring
139
+ cs = Geos::CoordinateSequence.new
140
+
141
+ assert_equal('LINEARRING EMPTY', write(cs.to_linear_ring, :trim => true))
142
+ end
143
+
144
+ def test_to_line_string
145
+ cs = Geos::CoordinateSequence.new([
146
+ [ 0, 0 ],
147
+ [ 0, 5 ],
148
+ [ 5, 5 ],
149
+ [ 5, 0 ]
150
+ ])
151
+
152
+ assert_equal('LINESTRING (0 0, 0 5, 5 5, 5 0)', write(cs.to_line_string, :trim => true))
153
+ end
154
+
155
+ def test_to_empty_line_string
156
+ cs = Geos::CoordinateSequence.new
157
+
158
+ assert_equal('LINESTRING EMPTY', write(cs.to_line_string, :trim => true))
159
+ end
160
+
161
+ def test_to_polygon
162
+ cs = Geos::CoordinateSequence.new([
163
+ [ 0, 0 ],
164
+ [ 0, 5 ],
165
+ [ 5, 5 ],
166
+ [ 5, 0 ],
167
+ [ 0, 0 ]
168
+ ])
169
+
170
+ assert_equal('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))', write(cs.to_polygon, :trim => true))
171
+ end
172
+
173
+ def test_to_empty_polygon
174
+ cs = Geos::CoordinateSequence.new
175
+
176
+ assert_equal('POLYGON EMPTY', write(cs.to_polygon, :trim => true))
177
+ end
92
178
  end
@@ -1530,4 +1530,18 @@ class GeometryTests < Test::Unit::TestCase
1530
1530
 
1531
1531
  assert(geom_a.eql?(geom_b))
1532
1532
  end
1533
+
1534
+ def test_geometry_collection_enumerator
1535
+ geom = read('GEOMETRYCOLLECTION(POINT(0 0))')
1536
+ assert_kind_of(Enumerable, geom.each)
1537
+ assert_kind_of(Enumerable, geom.to_enum)
1538
+ assert_equal(geom, geom.each {})
1539
+ end
1540
+
1541
+ def test_line_string_enumerator
1542
+ geom = read('LINESTRING(0 0, 10 10))')
1543
+ assert_kind_of(Enumerable, geom.each)
1544
+ assert_kind_of(Enumerable, geom.to_enum)
1545
+ assert_equal(geom, geom.each {})
1546
+ end
1533
1547
  end
@@ -34,10 +34,106 @@ if defined?(Geos::STRtree)
34
34
  def test_query
35
35
  setup_tree
36
36
 
37
- assert_equal(1, @tree.query(read('LINESTRING(5 5, 6 6)')).length)
38
- assert_equal(0, @tree.query(read('LINESTRING(20 0, 30 10)')).length)
39
- assert_equal(2, @tree.query(read('LINESTRING(25 25, 26 26)')).length)
40
- assert_equal(3, @tree.query(read('LINESTRING(0 0, 100 100)')).length)
37
+ assert_equal([@item_1],
38
+ @tree.query(read('LINESTRING(5 5, 6 6)')))
39
+
40
+ assert_equal([],
41
+ @tree.query(read('LINESTRING(20 0, 30 10)')))
42
+
43
+ assert_equal([@item_2, @item_3],
44
+ @tree.query(read('LINESTRING(25 25, 26 26)')))
45
+
46
+ assert_equal([@item_1, @item_2, @item_3],
47
+ @tree.query(read('LINESTRING(0 0, 100 100)')))
48
+ end
49
+
50
+ def test_query_with_ret_keys
51
+ setup_tree
52
+
53
+ assert_equal([@item_1],
54
+ @tree.query(read('LINESTRING(5 5, 6 6)'), :item))
55
+
56
+ assert_equal([],
57
+ @tree.query(read('LINESTRING(20 0, 30 10)'), :item))
58
+
59
+ assert_equal([@item_2, @item_3],
60
+ @tree.query(read('LINESTRING(25 25, 26 26)'), :item))
61
+
62
+ assert_equal([@item_1, @item_2, @item_3],
63
+ @tree.query(read('LINESTRING(0 0, 100 100)'), :item))
64
+
65
+
66
+ assert_equal([@geom_1],
67
+ @tree.query(read('LINESTRING(5 5, 6 6)'), :geometry))
68
+
69
+ assert_equal([],
70
+ @tree.query(read('LINESTRING(20 0, 30 10)'), :geometry))
71
+
72
+ assert_equal([@geom_2, @geom_3],
73
+ @tree.query(read('LINESTRING(25 25, 26 26)'), :geometry))
74
+
75
+ assert_equal([@geom_1, @geom_2, @geom_3],
76
+ @tree.query(read('LINESTRING(0 0, 100 100)'), :geometry))
77
+
78
+
79
+ assert_equal(
80
+ [
81
+ { :item => @item_1, :geometry => @geom_1 }
82
+ ],
83
+ @tree.query(read('LINESTRING(5 5, 6 6)'), :all)
84
+ )
85
+
86
+ assert_equal([],
87
+ @tree.query(read('LINESTRING(20 0, 30 10)'), :all))
88
+
89
+ assert_equal(
90
+ [
91
+ { :item => @item_2, :geometry => @geom_2 },
92
+ { :item => @item_3, :geometry => @geom_3 }
93
+ ],
94
+ @tree.query(read('LINESTRING(25 25, 26 26)'), :all)
95
+ )
96
+
97
+ assert_equal(
98
+ [
99
+ { :item => @item_1, :geometry => @geom_1 },
100
+ { :item => @item_2, :geometry => @geom_2 },
101
+ { :item => @item_3, :geometry => @geom_3 }
102
+ ],
103
+ @tree.query(read('LINESTRING(0 0, 100 100)'), :all)
104
+ )
105
+ end
106
+
107
+ def test_query_all
108
+ setup_tree
109
+
110
+ assert_equal([@item_1],
111
+ @tree.query_all(read('LINESTRING(5 5, 6 6)')).collect { |v| v[:item] })
112
+
113
+ assert_equal([],
114
+ @tree.query_all(read('LINESTRING(20 0, 30 10)')))
115
+
116
+ assert_equal([@item_2, @item_3],
117
+ @tree.query_all(read('LINESTRING(25 25, 26 26)')).collect { |v| v[:item] })
118
+
119
+ assert_equal([@item_1, @item_2, @item_3],
120
+ @tree.query_all(read('LINESTRING(0 0, 100 100)')).collect { |v| v[:item] })
121
+ end
122
+
123
+ def test_query_geometries
124
+ setup_tree
125
+
126
+ assert_equal([@geom_1],
127
+ @tree.query_geometries(read('LINESTRING(5 5, 6 6)')))
128
+
129
+ assert_equal([],
130
+ @tree.query_geometries(read('LINESTRING(20 0, 30 10)')))
131
+
132
+ assert_equal([@geom_2, @geom_3],
133
+ @tree.query_geometries(read('LINESTRING(25 25, 26 26)')))
134
+
135
+ assert_equal([@geom_1, @geom_2, @geom_3],
136
+ @tree.query_geometries(read('LINESTRING(0 0, 100 100)')))
41
137
  end
42
138
 
43
139
  def test_remove
@@ -45,10 +141,17 @@ if defined?(Geos::STRtree)
45
141
 
46
142
  @tree.remove(read('POINT(5 5)'), @item_1)
47
143
 
48
- assert_equal(0, @tree.query(read('LINESTRING(5 5, 6 6)')).length)
49
- assert_equal(0, @tree.query(read('LINESTRING(20 0, 30 10)')).length)
50
- assert_equal(2, @tree.query(read('LINESTRING(25 25, 26 26)')).length)
51
- assert_equal(2, @tree.query(read('LINESTRING(0 0, 100 100)')).length)
144
+ assert_equal([],
145
+ @tree.query(read('LINESTRING(5 5, 6 6)')))
146
+
147
+ assert_equal([],
148
+ @tree.query(read('LINESTRING(20 0, 30 10)')))
149
+
150
+ assert_equal([@item_2, @item_3],
151
+ @tree.query(read('LINESTRING(25 25, 26 26)')))
152
+
153
+ assert_equal([@item_2, @item_3],
154
+ @tree.query(read('LINESTRING(0 0, 100 100)')))
52
155
  end
53
156
 
54
157
  def test_cant_clone
@@ -62,5 +165,37 @@ if defined?(Geos::STRtree)
62
165
  Geos::STRtree.new(3).dup
63
166
  end
64
167
  end
168
+
169
+ def test_setup_with_array
170
+ tree = Geos::STRtree.new(
171
+ [ read('LINESTRING(0 0, 10 10)'), item_1 = { :item_1 => :test } ],
172
+ [ read('LINESTRING(20 20, 30 30)'), item_2 = [ :test ] ],
173
+ [ read('LINESTRING(20 20, 30 30)'), item_3 = Object.new ]
174
+ )
175
+
176
+ assert_equal([item_1],
177
+ tree.query(read('LINESTRING(5 5, 6 6)')))
178
+
179
+ assert_equal([],
180
+ tree.query(read('LINESTRING(20 0, 30 10)')))
181
+
182
+ assert_equal([item_2, item_3],
183
+ tree.query(read('LINESTRING(25 25, 26 26)')))
184
+
185
+ assert_equal([item_1, item_2, item_3],
186
+ tree.query(read('LINESTRING(0 0, 100 100)')))
187
+ end
188
+
189
+ def test_capacity
190
+ assert_raise(ArgumentError) do
191
+ Geos::STRtree.new(0)
192
+ end
193
+ end
194
+
195
+ def test_geometries
196
+ assert_raise(TypeError) do
197
+ Geos::STRtree.new([])
198
+ end
199
+ end
65
200
  end
66
201
  end
data/test/utils_tests.rb CHANGED
@@ -131,66 +131,71 @@ class UtilsTests < Test::Unit::TestCase
131
131
  end
132
132
 
133
133
  def test_create_polygon
134
- cs = Geos::CoordinateSequence.new(5, 2)
135
- cs.set_x(0, 0)
136
- cs.set_y(0, 0)
137
-
138
- cs.set_x(1, 0)
139
- cs.set_y(1, 10)
134
+ cs = Geos::CoordinateSequence.new([
135
+ [ 0, 0 ],
136
+ [ 0, 10 ],
137
+ [ 10, 10 ],
138
+ [ 10, 0 ],
139
+ [ 0, 0 ]
140
+ ])
140
141
 
141
- cs.set_x(2, 10)
142
- cs.set_y(2, 10)
142
+ exterior_ring = Geos::create_linear_ring(cs)
143
143
 
144
- cs.set_x(3, 10)
145
- cs.set_y(3, 0)
144
+ geom = Geos::create_polygon(exterior_ring)
145
+ assert_instance_of(Geos::Polygon, geom)
146
+ assert_equal('Polygon', geom.geom_type)
147
+ assert_equal(Geos::GEOS_POLYGON, geom.type_id)
148
+ assert_equal('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))', write(geom, :trim => true))
149
+ end
146
150
 
147
- cs.set_x(4, 0)
148
- cs.set_y(4, 0)
151
+ def test_create_polygon_with_coordinate_sequences
152
+ outer = Geos::CoordinateSequence.new(
153
+ [ 0, 0 ],
154
+ [ 0, 10 ],
155
+ [ 10, 10 ],
156
+ [ 10, 0 ],
157
+ [ 0, 0 ]
158
+ )
149
159
 
150
- exterior_ring = Geos::create_linear_ring(cs)
160
+ inner = Geos::CoordinateSequence.new(
161
+ [ 2, 2 ],
162
+ [ 2, 4 ],
163
+ [ 4, 4 ],
164
+ [ 4, 2 ],
165
+ [ 2, 2 ]
166
+ )
151
167
 
152
- geom = Geos::create_polygon(exterior_ring)
168
+ geom = Geos::create_polygon(outer, inner)
153
169
  assert_instance_of(Geos::Polygon, geom)
154
170
  assert_equal('Polygon', geom.geom_type)
155
171
  assert_equal(Geos::GEOS_POLYGON, geom.type_id)
156
- assert(read('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))').eql_exact?(geom, TOLERANCE))
172
+ assert_equal('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))', write(geom, :trim => true))
157
173
  end
158
174
 
159
175
  def test_create_polygon_with_holes
160
- create_ring = lambda { |*points|
161
- Geos.create_linear_ring(
162
- Geos::CoordinateSequence.new(points.length, 2).tap { |cs|
163
- points.each_with_index do |(x, y), i|
164
- cs.set_x(i, x)
165
- cs.set_y(i, y)
166
- end
167
- }
168
- )
169
- }
170
-
171
- exterior_ring = create_ring[
176
+ exterior_ring = Geos::CoordinateSequence.new(
172
177
  [ 0, 0 ],
173
178
  [ 0, 10 ],
174
179
  [ 10, 10 ],
175
180
  [ 10, 0 ],
176
181
  [ 0, 0 ]
177
- ]
182
+ )
178
183
 
179
- hole_1 = create_ring[
184
+ hole_1 = Geos::CoordinateSequence.new(
180
185
  [ 2, 2 ],
181
186
  [ 2, 4 ],
182
187
  [ 4, 4 ],
183
188
  [ 4, 2 ],
184
189
  [ 2, 2 ]
185
- ]
190
+ )
186
191
 
187
- hole_2 = create_ring[
192
+ hole_2 = Geos::CoordinateSequence.new(
188
193
  [ 6, 6 ],
189
194
  [ 6, 8 ],
190
195
  [ 8, 8 ],
191
196
  [ 8, 6 ],
192
197
  [ 6, 6 ]
193
- ]
198
+ )
194
199
 
195
200
  geom = Geos::create_polygon(exterior_ring, [ hole_1, hole_2 ])
196
201
  assert_instance_of(Geos::Polygon, geom)
metadata CHANGED
@@ -1,32 +1,24 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ffi-geos
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - J Smith
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-06-25 00:00:00 Z
12
+ date: 2011-07-22 00:00:00.000000000 -04:00
13
+ default_executable:
19
14
  dependencies: []
20
-
21
15
  description: An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).
22
16
  email: dark.panda@gmail.com
23
17
  executables: []
24
-
25
18
  extensions: []
26
-
27
- extra_rdoc_files:
19
+ extra_rdoc_files:
28
20
  - README.rdoc
29
- files:
21
+ files:
30
22
  - MIT-LICENSE
31
23
  - README.rdoc
32
24
  - Rakefile
@@ -64,38 +56,29 @@ files:
64
56
  - test/wkb_writer_tests.rb
65
57
  - test/wkt_reader_tests.rb
66
58
  - test/wkt_writer_tests.rb
59
+ has_rdoc: true
67
60
  homepage: http://github.com/dark-panda/ffi-geos
68
61
  licenses: []
69
-
70
62
  post_install_message:
71
63
  rdoc_options: []
72
-
73
- require_paths:
64
+ require_paths:
74
65
  - lib
75
- required_ruby_version: !ruby/object:Gem::Requirement
66
+ required_ruby_version: !ruby/object:Gem::Requirement
76
67
  none: false
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- hash: 3
81
- segments:
82
- - 0
83
- version: "0"
84
- required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
73
  none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- hash: 3
90
- segments:
91
- - 0
92
- version: "0"
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
93
78
  requirements: []
94
-
95
79
  rubyforge_project:
96
- rubygems_version: 1.7.2
80
+ rubygems_version: 1.6.2
97
81
  signing_key:
98
82
  specification_version: 3
99
83
  summary: An ffi wrapper for GEOS, a C++ port of the Java Topology Suite (JTS).
100
84
  test_files: []
101
-