rgeo 0.3.8 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,11 @@
1
+ === 0.3.9 / 2012-04-10
2
+
3
+ * Implemented LineString#length and MultiLineString#length for simple cartesian and simple spherical factories.
4
+ * Added Cartesian::BoundingBox.create_from_points.
5
+ * Serialization was broken for some 3d geometries when running libgeos 3.2.x (3.3.x was unaffected). Fixed.
6
+ * Fixed an exception when creating adding a geometry to a Cartesian::BoundingBox when a cast is necessary.
7
+ * Added configuration for Travis CI.
8
+
1
9
  === 0.3.8 / 2012-03-23
2
10
 
3
11
  * When using the spherical factory, some negative longitudes might get perturbed slightly due to floating point errors. Fixed. (Reported by Pete Deffendol)
data/README.rdoc CHANGED
@@ -122,6 +122,8 @@ Source code is hosted on Github at http://github.com/dazuma/rgeo
122
122
 
123
123
  Contributions are welcome. Fork the project on Github.
124
124
 
125
+ Build status: {<img src="https://secure.travis-ci.org/dazuma/rgeo.png" />}[http://travis-ci.org/dazuma/rgeo]
126
+
125
127
  Report bugs on Github issues at http://github.org/dazuma/rgeo/issues
126
128
 
127
129
  Support available on the rgeo-users google group at http://groups.google.com/group/rgeo-users
@@ -132,7 +134,9 @@ Contact the author at dazuma at gmail dot com.
132
134
 
133
135
  RGeo is written by Daniel Azuma (http://www.daniel-azuma.com).
134
136
 
135
- Development is supported by Pirq. (http://www.pirq.com).
137
+ Development is supported by Pirq (http://www.pirq.com).
138
+
139
+ Continuous integration service provided by Travis-CI (http://travis-ci.org).
136
140
 
137
141
  RGeo calls the GEOS library to handle most Cartesian geometric
138
142
  calculations, and the Proj4 library to handle projections and coordinate
data/Version CHANGED
@@ -1 +1 @@
1
- 0.3.8
1
+ 0.3.9
@@ -78,6 +78,7 @@ else
78
78
  end
79
79
  have_func('GEOSPreparedContains_r', 'geos_c.h')
80
80
  have_func('GEOSPreparedDisjoint_r', 'geos_c.h')
81
+ have_func('GEOSWKTWriter_setOutputDimension_r', 'geos_c.h')
81
82
  end
82
83
  unless found_geos_
83
84
  puts "**** WARNING: Unable to find GEOS headers or GEOS version is too old."
@@ -316,13 +316,32 @@ static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
316
316
  VALUE result;
317
317
  char* str;
318
318
  size_t size;
319
+ char has_3d;
320
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
321
+ RGeo_Globals* globals;
322
+ VALUE wkb_generator;
323
+ #endif
319
324
 
320
325
  self_data = RGEO_FACTORY_DATA_PTR(self);
321
326
  self_context = self_data->geos_context;
327
+ has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
328
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
329
+ if (has_3d) {
330
+ globals = self_data->globals;
331
+ wkb_generator = globals->marshal_wkb_generator;
332
+ if (NIL_P(wkb_generator)) {
333
+ wkb_generator = rb_funcall(
334
+ rb_const_get_at(globals->geos_module, rb_intern("Utils")),
335
+ rb_intern("marshal_wkb_generator"), 0);
336
+ globals->marshal_wkb_generator = wkb_generator;
337
+ }
338
+ return rb_funcall(wkb_generator, globals->id_generate, 1, obj);
339
+ }
340
+ #endif
322
341
  wkb_writer = self_data->marshal_wkb_writer;
323
342
  if (!wkb_writer) {
324
343
  wkb_writer = GEOSWKBWriter_create_r(self_context);
325
- if (self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M) {
344
+ if (has_3d) {
326
345
  GEOSWKBWriter_setOutputDimension_r(self_context, wkb_writer, 3);
327
346
  }
328
347
  self_data->marshal_wkb_writer = wkb_writer;
@@ -351,13 +370,32 @@ static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
351
370
  VALUE result;
352
371
  char* str;
353
372
  size_t size;
373
+ char has_3d;
374
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
375
+ RGeo_Globals* globals;
376
+ VALUE wkt_generator;
377
+ #endif
354
378
 
355
379
  self_data = RGEO_FACTORY_DATA_PTR(self);
356
380
  self_context = self_data->geos_context;
381
+ has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
382
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
383
+ if (has_3d) {
384
+ globals = self_data->globals;
385
+ wkt_generator = globals->psych_wkt_generator;
386
+ if (NIL_P(wkt_generator)) {
387
+ wkt_generator = rb_funcall(
388
+ rb_const_get_at(globals->geos_module, rb_intern("Utils")),
389
+ rb_intern("psych_wkt_generator"), 0);
390
+ globals->psych_wkt_generator = wkt_generator;
391
+ }
392
+ return rb_funcall(wkt_generator, globals->id_generate, 1, obj);
393
+ }
394
+ #endif
357
395
  wkt_writer = self_data->psych_wkt_writer;
358
396
  if (!wkt_writer) {
359
397
  wkt_writer = GEOSWKTWriter_create_r(self_context);
360
- if (self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M) {
398
+ if (has_3d) {
361
399
  GEOSWKTWriter_setOutputDimension_r(self_context, wkt_writer, 3);
362
400
  }
363
401
  self_data->psych_wkt_writer = wkt_writer;
@@ -561,6 +599,11 @@ RGeo_Globals* rgeo_init_geos_factory()
561
599
  globals->id_enum_for = rb_intern("enum_for");
562
600
  globals->sym_force_new = ID2SYM(rb_intern("force_new"));
563
601
  globals->sym_keep_subtype = ID2SYM(rb_intern("keep_subtype"));
602
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
603
+ globals->psych_wkt_generator = Qnil;
604
+ globals->marshal_wkb_generator = Qnil;
605
+ #endif
606
+
564
607
 
565
608
  // Add C methods to the factory.
566
609
  geos_factory_class = rb_const_get_at(globals->geos_module, rb_intern("Factory"));
@@ -80,6 +80,10 @@ typedef struct {
80
80
  ID id_enum_for;
81
81
  VALUE sym_force_new;
82
82
  VALUE sym_keep_subtype;
83
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
84
+ VALUE psych_wkt_generator;
85
+ VALUE marshal_wkb_generator;
86
+ #endif
83
87
  } RGeo_Globals;
84
88
 
85
89
 
@@ -47,6 +47,9 @@
47
47
  #ifdef HAVE_GEOSPREPAREDDISJOINT_R
48
48
  #define RGEO_GEOS_SUPPORTS_PREPARED2
49
49
  #endif
50
+ #ifdef HAVE_GEOSWKTWWRITER_SETOUTPUTDIMENSION_R
51
+ #define RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
52
+ #endif
50
53
 
51
54
  #ifdef __cplusplus
52
55
  #define RGEO_BEGIN_C extern "C" {
@@ -54,6 +54,20 @@ module RGeo
54
54
  class BoundingBox
55
55
 
56
56
 
57
+ # Create a bounding box given two corner points.
58
+ # The bounding box will be given the factory of the first point.
59
+ # You may also provide the same options available to
60
+ # BoundingBox.new.
61
+
62
+ def self.create_from_points(point1_, point2_, opts_={})
63
+ factory_ = point1_.factory
64
+ box_ = new(factory_, opts_)
65
+ box_._add_geometry(point1_)
66
+ box_.add(point2_)
67
+ box_
68
+ end
69
+
70
+
57
71
  # Create a new empty bounding box with the given factory.
58
72
  #
59
73
  # The factory defines the coordinate system for the bounding box,
@@ -216,7 +230,7 @@ module RGeo
216
230
  if geometry_.factory == @factory
217
231
  _add_geometry(geometry_)
218
232
  else
219
- _add_geometry(Factory.cast(geometry_, @factory))
233
+ _add_geometry(Feature.cast(geometry_, @factory))
220
234
  end
221
235
  end
222
236
  self
@@ -152,6 +152,7 @@ module RGeo
152
152
  include ::RGeo::ImplHelper::BasicGeometryCollectionMethods
153
153
  include ::RGeo::ImplHelper::BasicMultiLineStringMethods
154
154
  include ::RGeo::Cartesian::GeometryMethods
155
+ include ::RGeo::Cartesian::MultiLineStringMethods
155
156
 
156
157
  Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self, true)
157
158
 
@@ -114,12 +114,24 @@ module RGeo
114
114
 
115
115
 
116
116
  def length
117
- @segments.inject(0.0){ |sum_, seg_| sum_ + seg_.length }
117
+ _segments.inject(0.0){ |sum_, seg_| sum_ + seg_.length }
118
118
  end
119
119
 
120
120
 
121
121
  end
122
122
 
123
+
124
+ module MultiLineStringMethods # :nodoc:
125
+
126
+
127
+ def length
128
+ inject(0.0){ |sum_, geom_| sum_ + geom_.length }
129
+ end
130
+
131
+
132
+ end
133
+
134
+
123
135
  end
124
136
 
125
137
  end
@@ -212,6 +212,7 @@ module RGeo
212
212
  include ImplHelper::BasicGeometryCollectionMethods
213
213
  include ImplHelper::BasicMultiLineStringMethods
214
214
  include SphericalGeometryMethods
215
+ include SphericalMultiLineStringMethods
215
216
 
216
217
 
217
218
  Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self, true)
@@ -89,6 +89,22 @@ module RGeo
89
89
  end
90
90
 
91
91
 
92
+ def length
93
+ _arcs.inject(0.0){ |sum_, arc_| sum_ + arc_.length } * SphericalMath::RADIUS
94
+ end
95
+
96
+
97
+ end
98
+
99
+
100
+ module SphericalMultiLineStringMethods
101
+
102
+
103
+ def length
104
+ inject(0.0){ |sum_, geom_| sum_ + geom_.length }
105
+ end
106
+
107
+
92
108
  end
93
109
 
94
110
 
@@ -196,6 +196,11 @@ module RGeo
196
196
  end
197
197
 
198
198
 
199
+ def length
200
+ @s.dist_to_point(@e)
201
+ end
202
+
203
+
199
204
  end
200
205
 
201
206
 
data/lib/rgeo/geos.rb CHANGED
@@ -64,6 +64,7 @@ end
64
64
  # :stopdoc:
65
65
 
66
66
  # Implementation files
67
+ require 'rgeo/geos/utils'
67
68
  require 'rgeo/geos/factory'
68
69
  require 'rgeo/geos/interface'
69
70
  begin
@@ -79,7 +80,6 @@ require 'rgeo/geos/zm_impl'
79
80
  begin
80
81
  require 'ffi-geos'
81
82
  ::RGeo::Geos::FFI_SUPPORTED = true
82
- ::RGeo::Geos::FFIUtils._init
83
83
  rescue ::LoadError
84
84
  ::RGeo::Geos::FFI_SUPPORTED = false
85
85
  rescue
@@ -96,4 +96,7 @@ elsif ::RGeo::Geos::FFI_SUPPORTED
96
96
  ::RGeo::Geos.preferred_native_interface = :ffi
97
97
  end
98
98
 
99
+ # Init internal utilities
100
+ ::RGeo::Geos::Utils._init
101
+
99
102
  # :startdoc:
@@ -39,66 +39,6 @@ module RGeo
39
39
  module Geos
40
40
 
41
41
 
42
- module FFIUtils # :nodoc:
43
-
44
- class << self
45
-
46
-
47
- def coord_seqs_equal?(cs1_, cs2_, check_z_)
48
- len1_ = cs1_.length
49
- len2_ = cs2_.length
50
- if len1_ == len2_
51
- (0...len1_).each do |i_|
52
- return false unless cs1_.get_x(i_) == cs2_.get_x(i_) &&
53
- cs1_.get_y(i_) == cs2_.get_y(i_) &&
54
- (!check_z_ || cs1_.get_z(i_) == cs2_.get_z(i_))
55
- end
56
- true
57
- else
58
- false
59
- end
60
- end
61
-
62
-
63
- def compute_dimension(geom_)
64
- result_ = -1
65
- case geom_.type_id
66
- when ::Geos::GeomTypes::GEOS_POINT
67
- result_ = 0
68
- when ::Geos::GeomTypes::GEOS_MULTIPOINT
69
- result_ = 0 unless geom_.empty?
70
- when ::Geos::GeomTypes::GEOS_LINESTRING, ::Geos::GeomTypes::GEOS_LINEARRING
71
- result_ = 1
72
- when ::Geos::GeomTypes::GEOS_MULTILINESTRING
73
- result_ = 1 unless geom_.empty?
74
- when ::Geos::GeomTypes::GEOS_POLYGON
75
- result_ = 2
76
- when ::Geos::GeomTypes::GEOS_MULTIPOLYGON
77
- result_ = 2 unless geom_.empty?
78
- when ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION
79
- geom_.each do |g_|
80
- dim_ = compute_dimension(g_)
81
- result_ = dim_ if result_ < dim_
82
- end
83
- end
84
- result_
85
- end
86
-
87
-
88
- def _init
89
- @supports_prepared_level_1 = ::Geos::FFIGeos.respond_to?(:GEOSPreparedContains_r)
90
- @supports_prepared_level_2 = ::Geos::FFIGeos.respond_to?(:GEOSPreparedDisjoint_r)
91
- end
92
-
93
- attr_reader :supports_prepared_level_1
94
- attr_reader :supports_prepared_level_2
95
-
96
-
97
- end
98
-
99
- end
100
-
101
-
102
42
  class FFIGeometryImpl # :nodoc:
103
43
 
104
44
  include Feature::Instance
@@ -123,7 +63,7 @@ module RGeo
123
63
  # Marshal support
124
64
 
125
65
  def marshal_dump # :nodoc:
126
- [@factory, @factory._write_for_marshal(@fg_geom)]
66
+ [@factory, @factory._write_for_marshal(self)]
127
67
  end
128
68
 
129
69
  def marshal_load(data_) # :nodoc:
@@ -139,7 +79,7 @@ module RGeo
139
79
 
140
80
  def encode_with(coder_) # :nodoc:
141
81
  coder_['factory'] = @factory
142
- str_ = @factory._write_for_psych(@fg_geom)
82
+ str_ = @factory._write_for_psych(self)
143
83
  str_ = str_.encode('US-ASCII') if str_.respond_to?(:encode)
144
84
  coder_['wkt'] = str_
145
85
  end
@@ -174,7 +114,7 @@ module RGeo
174
114
 
175
115
 
176
116
  def dimension
177
- FFIUtils.compute_dimension(@fg_geom)
117
+ Utils.ffi_compute_dimension(@fg_geom)
178
118
  end
179
119
 
180
120
 
@@ -258,7 +198,7 @@ module RGeo
258
198
  def disjoint?(rhs_)
259
199
  fg_ = factory._convert_to_fg_geometry(rhs_)
260
200
  if fg_
261
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_2
201
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_2
262
202
  prep_ ? prep_.disjoint?(fg_) : @fg_geom.disjoint?(fg_)
263
203
  else
264
204
  false
@@ -269,7 +209,7 @@ module RGeo
269
209
  def intersects?(rhs_)
270
210
  fg_ = factory._convert_to_fg_geometry(rhs_)
271
211
  if fg_
272
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_1
212
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_1
273
213
  prep_ ? prep_.intersects?(fg_) : @fg_geom.intersects?(fg_)
274
214
  else
275
215
  false
@@ -280,7 +220,7 @@ module RGeo
280
220
  def touches?(rhs_)
281
221
  fg_ = factory._convert_to_fg_geometry(rhs_)
282
222
  if fg_
283
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_2
223
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_2
284
224
  prep_ ? prep_.touches?(fg_) : @fg_geom.touches?(fg_)
285
225
  else
286
226
  false
@@ -291,7 +231,7 @@ module RGeo
291
231
  def crosses?(rhs_)
292
232
  fg_ = factory._convert_to_fg_geometry(rhs_)
293
233
  if fg_
294
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_2
234
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_2
295
235
  prep_ ? prep_.crosses?(fg_) : @fg_geom.crosses?(fg_)
296
236
  else
297
237
  false
@@ -302,7 +242,7 @@ module RGeo
302
242
  def within?(rhs_)
303
243
  fg_ = factory._convert_to_fg_geometry(rhs_)
304
244
  if fg_
305
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_2
245
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_2
306
246
  prep_ ? prep_.within?(fg_) : @fg_geom.within?(fg_)
307
247
  else
308
248
  false
@@ -313,7 +253,7 @@ module RGeo
313
253
  def contains?(rhs_)
314
254
  fg_ = factory._convert_to_fg_geometry(rhs_)
315
255
  if fg_
316
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_1
256
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_1
317
257
  prep_ ? prep_.contains?(fg_) : @fg_geom.contains?(fg_)
318
258
  else
319
259
  false
@@ -324,7 +264,7 @@ module RGeo
324
264
  def overlaps?(rhs_)
325
265
  fg_ = factory._convert_to_fg_geometry(rhs_)
326
266
  if fg_
327
- prep_ = _request_prepared if FFIUtils.supports_prepared_level_2
267
+ prep_ = _request_prepared if Utils.ffi_supports_prepared_level_2
328
268
  prep_ ? prep_.overlaps?(fg_) : @fg_geom.overlaps?(fg_)
329
269
  else
330
270
  false
@@ -449,7 +389,7 @@ module RGeo
449
389
 
450
390
  def rep_equals?(rhs_)
451
391
  rhs_.class == self.class && rhs_.factory.eql?(@factory) &&
452
- FFIUtils.coord_seqs_equal?(rhs_.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
392
+ Utils.ffi_coord_seqs_equal?(rhs_.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
453
393
  end
454
394
 
455
395
 
@@ -525,7 +465,7 @@ module RGeo
525
465
 
526
466
  def rep_equals?(rhs_)
527
467
  rhs_.class == self.class && rhs_.factory.eql?(@factory) &&
528
- FFIUtils.coord_seqs_equal?(rhs_.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
468
+ Utils.ffi_coord_seqs_equal?(rhs_.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
529
469
  end
530
470
 
531
471
 
@@ -599,12 +599,16 @@ module RGeo
599
599
  end
600
600
 
601
601
 
602
- def _write_for_marshal(obj_) # :nodoc:
603
- unless defined?(@marshal_wkb_writer)
604
- @marshal_wkb_writer = ::Geos::WkbWriter.new
605
- @marshal_wkb_writer.output_dimensions = (@_has_3d ? 3 : 2)
602
+ def _write_for_marshal(geom_) # :nodoc:
603
+ if Utils.ffi_supports_set_output_dimension || !@_has_3d
604
+ unless defined?(@marshal_wkb_writer)
605
+ @marshal_wkb_writer = ::Geos::WkbWriter.new
606
+ @marshal_wkb_writer.output_dimensions = 3 if @_has_3d
607
+ end
608
+ @marshal_wkb_writer.write(geom_.fg_geom)
609
+ else
610
+ Utils.marshal_wkb_generator.generate(geom_)
606
611
  end
607
- @marshal_wkb_writer.write(obj_)
608
612
  end
609
613
 
610
614
 
@@ -616,12 +620,16 @@ module RGeo
616
620
  end
617
621
 
618
622
 
619
- def _write_for_psych(obj_) # :nodoc:
620
- unless defined?(@psych_wkt_writer)
621
- @psych_wkt_writer = ::Geos::WktWriter.new
622
- @psych_wkt_writer.output_dimensions = (@_has_3d ? 3 : 2)
623
+ def _write_for_psych(geom_) # :nodoc:
624
+ if Utils.ffi_supports_set_output_dimension || !@_has_3d
625
+ unless defined?(@psych_wkt_writer)
626
+ @psych_wkt_writer = ::Geos::WktWriter.new
627
+ @psych_wkt_writer.output_dimensions = 3 if @_has_3d
628
+ end
629
+ @psych_wkt_writer.write(geom_.fg_geom)
630
+ else
631
+ Utils.psych_wkt_generator.generate(geom_)
623
632
  end
624
- @psych_wkt_writer.write(obj_)
625
633
  end
626
634
 
627
635
 
@@ -0,0 +1,112 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Various Geos-related internal utilities
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010-2012 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module RGeo
38
+
39
+ module Geos
40
+
41
+
42
+ module Utils # :nodoc:
43
+
44
+ class << self
45
+
46
+
47
+ def ffi_coord_seqs_equal?(cs1_, cs2_, check_z_)
48
+ len1_ = cs1_.length
49
+ len2_ = cs2_.length
50
+ if len1_ == len2_
51
+ (0...len1_).each do |i_|
52
+ return false unless cs1_.get_x(i_) == cs2_.get_x(i_) &&
53
+ cs1_.get_y(i_) == cs2_.get_y(i_) &&
54
+ (!check_z_ || cs1_.get_z(i_) == cs2_.get_z(i_))
55
+ end
56
+ true
57
+ else
58
+ false
59
+ end
60
+ end
61
+
62
+
63
+ def ffi_compute_dimension(geom_)
64
+ result_ = -1
65
+ case geom_.type_id
66
+ when ::Geos::GeomTypes::GEOS_POINT
67
+ result_ = 0
68
+ when ::Geos::GeomTypes::GEOS_MULTIPOINT
69
+ result_ = 0 unless geom_.empty?
70
+ when ::Geos::GeomTypes::GEOS_LINESTRING, ::Geos::GeomTypes::GEOS_LINEARRING
71
+ result_ = 1
72
+ when ::Geos::GeomTypes::GEOS_MULTILINESTRING
73
+ result_ = 1 unless geom_.empty?
74
+ when ::Geos::GeomTypes::GEOS_POLYGON
75
+ result_ = 2
76
+ when ::Geos::GeomTypes::GEOS_MULTIPOLYGON
77
+ result_ = 2 unless geom_.empty?
78
+ when ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION
79
+ geom_.each do |g_|
80
+ dim_ = ffi_compute_dimension(g_)
81
+ result_ = dim_ if result_ < dim_
82
+ end
83
+ end
84
+ result_
85
+ end
86
+
87
+
88
+ def _init
89
+ if FFI_SUPPORTED
90
+ @ffi_supports_prepared_level_1 = ::Geos::FFIGeos.respond_to?(:GEOSPreparedContains_r)
91
+ @ffi_supports_prepared_level_2 = ::Geos::FFIGeos.respond_to?(:GEOSPreparedDisjoint_r)
92
+ @ffi_supports_set_output_dimension = ::Geos::FFIGeos.respond_to?(:GEOSWKTWriter_setOutputDimension_r)
93
+ end
94
+ @psych_wkt_generator = WKRep::WKTGenerator.new(:convert_case => :upper)
95
+ @marshal_wkb_generator = WKRep::WKBGenerator.new
96
+ end
97
+
98
+ attr_reader :ffi_supports_prepared_level_1
99
+ attr_reader :ffi_supports_prepared_level_2
100
+ attr_reader :ffi_supports_set_output_dimension
101
+ attr_reader :psych_wkt_generator
102
+ attr_reader :marshal_wkb_generator
103
+
104
+
105
+ end
106
+
107
+ end
108
+
109
+
110
+ end
111
+
112
+ end
@@ -48,9 +48,9 @@ module RGeo
48
48
  @factory = create_factory
49
49
  point1_ = @factory.point(0, 0)
50
50
  point2_ = @factory.point(1, 0)
51
- point3_ = @factory.point(-4, 2)
52
- point4_ = @factory.point(-5, 3)
53
- point5_ = @factory.point(-3, 5)
51
+ point3_ = @factory.point(-4, 2) # (-4, 2)
52
+ point4_ = @factory.point(-7, 6) # (-5, 3)
53
+ point5_ = @factory.point(5, 11) # (-3, 5)
54
54
  @linestring1 = @factory.line_string([point1_, point2_])
55
55
  @linestring2 = @factory.line_string([point3_, point4_, point5_])
56
56
  @linearring1 = @factory.linear_ring([point5_, point3_, point4_, point5_])
@@ -137,7 +137,7 @@ module RGeo
137
137
 
138
138
 
139
139
  def test_wkt_creation_simple
140
- parsed_geom_ = @factory.parse_wkt('MULTILINESTRING((0 0, 1 0), (-4 2, -5 3, -3 5))')
140
+ parsed_geom_ = @factory.parse_wkt('MULTILINESTRING((0 0, 1 0), (-4 2, -7 6, 5 11))')
141
141
  built_geom_ = @factory.multi_line_string([@linestring1, @linestring2])
142
142
  assert(built_geom_.eql?(parsed_geom_))
143
143
  end
@@ -210,6 +210,14 @@ module RGeo
210
210
  end
211
211
 
212
212
 
213
+ def test_length
214
+ geom1_ = @factory.multi_line_string([@linestring1, @linestring2])
215
+ assert_equal(19, geom1_.length)
216
+ geom2_ = @factory.multi_line_string([])
217
+ assert_equal(0, geom2_.length)
218
+ end
219
+
220
+
213
221
  end
214
222
 
215
223
  end
@@ -81,7 +81,9 @@ module RGeo
81
81
 
82
82
 
83
83
  def _assert_close_enough(a_, b_)
84
- assert_in_delta(a_, b_, ::Math.sqrt(a_*a_+b_*b_)*0.00000001)
84
+ delta_ = ::Math.sqrt(a_*a_+b_*b_)*0.00000001
85
+ delta_ = 0.000000000001 if delta_ < 0.000000000001
86
+ assert_in_delta(a_, b_, delta_)
85
87
  end
86
88
 
87
89
 
@@ -55,6 +55,9 @@ module RGeo
55
55
  include ::RGeo::Tests::Common::MultiLineStringTests
56
56
 
57
57
 
58
+ undef_method :test_length
59
+
60
+
58
61
  end
59
62
 
60
63
  end
@@ -55,6 +55,9 @@ module RGeo
55
55
  include ::RGeo::Tests::Common::MultiLineStringTests
56
56
 
57
57
 
58
+ undef_method :test_length
59
+
60
+
58
61
  end
59
62
 
60
63
  end
@@ -58,6 +58,7 @@ module RGeo
58
58
  undef_method :test_fully_equal
59
59
  undef_method :test_geometrically_equal
60
60
  undef_method :test_not_equal
61
+ undef_method :test_length
61
62
 
62
63
 
63
64
  end
@@ -0,0 +1,121 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Tests for basic GeoJSON usage
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010-2012 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ require 'test/unit'
38
+ require 'rgeo'
39
+
40
+
41
+ module RGeo
42
+ module Tests # :nodoc:
43
+
44
+ class TestCartesianBBox < ::Test::Unit::TestCase # :nodoc:
45
+
46
+
47
+ def setup
48
+ @factory = ::RGeo::Cartesian.factory
49
+ end
50
+
51
+
52
+ def test_empty_bbox
53
+ bbox_ = ::RGeo::Cartesian::BoundingBox.new(@factory)
54
+ assert_equal(true, bbox_.empty?)
55
+ assert_equal(false, bbox_.has_z)
56
+ assert_nil(bbox_.min_x)
57
+ assert_equal(@factory, bbox_.factory)
58
+ assert_nil(bbox_.min_point)
59
+ assert_equal(true, bbox_.to_geometry.is_empty?)
60
+ assert_equal(true, bbox_.contains?(bbox_))
61
+ assert_equal(false, bbox_.contains?(@factory.point(1, 1)))
62
+ end
63
+
64
+
65
+ def test_point_bbox
66
+ empty_bbox_ = ::RGeo::Cartesian::BoundingBox.new(@factory)
67
+ bbox_ = ::RGeo::Cartesian::BoundingBox.new(@factory)
68
+ bbox_.add(@factory.point(1, 1))
69
+ assert_equal(false, bbox_.empty?)
70
+ assert_equal(false, bbox_.has_z)
71
+ assert_equal(1.0, bbox_.min_x)
72
+ assert_equal(1.0, bbox_.min_y)
73
+ assert_equal(1.0, bbox_.max_x)
74
+ assert_equal(1.0, bbox_.max_y)
75
+ assert_equal(@factory, bbox_.factory)
76
+ assert_equal(@factory.point(1, 1), bbox_.min_point)
77
+ assert_equal(@factory.point(1, 1), bbox_.max_point)
78
+ assert_equal(@factory.point(1, 1), bbox_.to_geometry)
79
+ assert_equal(true, bbox_.contains?(empty_bbox_))
80
+ assert_equal(false, empty_bbox_.contains?(bbox_))
81
+ assert_equal(true, bbox_.contains?(@factory.point(1, 1)))
82
+ assert_equal(false, bbox_.contains?(@factory.point(2, 1)))
83
+ end
84
+
85
+
86
+ def test_rect_bbox
87
+ empty_bbox_ = ::RGeo::Cartesian::BoundingBox.new(@factory)
88
+ bbox_ = ::RGeo::Cartesian::BoundingBox.new(@factory)
89
+ bbox_.add(@factory.point(1, 4))
90
+ bbox_.add(@factory.point(2, 3))
91
+ assert_equal(false, bbox_.empty?)
92
+ assert_equal(false, bbox_.has_z)
93
+ assert_equal(1.0, bbox_.min_x)
94
+ assert_equal(3.0, bbox_.min_y)
95
+ assert_equal(2.0, bbox_.max_x)
96
+ assert_equal(4.0, bbox_.max_y)
97
+ assert_equal(@factory, bbox_.factory)
98
+ assert_equal(@factory.point(1, 3), bbox_.min_point)
99
+ assert_equal(@factory.point(2, 4), bbox_.max_point)
100
+ assert_equal(1.0, bbox_.to_geometry.area)
101
+ assert_equal(true, bbox_.contains?(empty_bbox_))
102
+ assert_equal(false, empty_bbox_.contains?(bbox_))
103
+ assert_equal(true, bbox_.contains?(@factory.point(1, 3)))
104
+ assert_equal(false, bbox_.contains?(@factory.point(2, 1)))
105
+ end
106
+
107
+
108
+ def test_bbox_from_points
109
+ bbox_ = ::RGeo::Cartesian::BoundingBox.new(@factory)
110
+ bbox_.add(@factory.point(1, 4))
111
+ bbox_.add(@factory.point(2, 3))
112
+ bbox2_ = ::RGeo::Cartesian::BoundingBox.create_from_points(
113
+ @factory.point(2, 3), @factory.point(1, 4))
114
+ assert_equal(bbox_, bbox2_)
115
+ end
116
+
117
+
118
+ end
119
+
120
+ end
121
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgeo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.3.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-23 00:00:00.000000000 Z
12
+ date: 2012-04-11 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: RGeo is a geospatial data library for Ruby. It provides an implementation
15
15
  of the Open Geospatial Consortium's Simple Features Specification, used by most
@@ -80,6 +80,7 @@ files:
80
80
  - lib/rgeo/geos/ffi_factory.rb
81
81
  - lib/rgeo/geos/impl_additions.rb
82
82
  - lib/rgeo/geos/interface.rb
83
+ - lib/rgeo/geos/utils.rb
83
84
  - lib/rgeo/geos/zm_factory.rb
84
85
  - lib/rgeo/geos/zm_impl.rb
85
86
  - lib/rgeo/geos.rb
@@ -188,6 +189,7 @@ files:
188
189
  - test/spherical_geographic/tc_point.rb
189
190
  - test/spherical_geographic/tc_polygon.rb
190
191
  - test/tc_cartesian_analysis.rb
192
+ - test/tc_cartesian_bbox.rb
191
193
  - test/tc_mixins.rb
192
194
  - test/tc_oneoff.rb
193
195
  - test/tc_types.rb
@@ -288,6 +290,7 @@ test_files:
288
290
  - test/spherical_geographic/tc_point.rb
289
291
  - test/spherical_geographic/tc_polygon.rb
290
292
  - test/tc_cartesian_analysis.rb
293
+ - test/tc_cartesian_bbox.rb
291
294
  - test/tc_mixins.rb
292
295
  - test/tc_oneoff.rb
293
296
  - test/tc_types.rb