rgeo 3.0.0.pre.rc.3 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -0
- data/ext/geos_c_impl/factory.c +41 -5
- data/ext/geos_c_impl/factory.h +13 -2
- data/ext/geos_c_impl/geometry.c +151 -122
- data/ext/geos_c_impl/geometry_collection.c +17 -19
- data/ext/geos_c_impl/line_string.c +46 -36
- data/ext/geos_c_impl/point.c +0 -2
- data/ext/geos_c_impl/polygon.c +10 -11
- data/ext/geos_c_impl/polygon.h +1 -1
- data/ext/geos_c_impl/ruby_more.c +7 -0
- data/ext/geos_c_impl/ruby_more.h +8 -0
- data/lib/rgeo/cartesian/analysis.rb +5 -3
- data/lib/rgeo/cartesian/bounding_box.rb +74 -79
- data/lib/rgeo/cartesian/calculations.rb +20 -26
- data/lib/rgeo/cartesian/factory.rb +47 -49
- data/lib/rgeo/cartesian/planar_graph.rb +10 -16
- data/lib/rgeo/cartesian/sweepline_intersector.rb +1 -3
- data/lib/rgeo/cartesian/valid_op.rb +1 -3
- data/lib/rgeo/coord_sys/cs/entities.rb +87 -101
- data/lib/rgeo/coord_sys/cs/factories.rb +0 -2
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +70 -29
- data/lib/rgeo/feature/curve.rb +0 -1
- data/lib/rgeo/feature/factory.rb +25 -27
- data/lib/rgeo/feature/factory_generator.rb +3 -4
- data/lib/rgeo/feature/geometry.rb +41 -30
- data/lib/rgeo/feature/geometry_collection.rb +3 -4
- data/lib/rgeo/feature/line_string.rb +1 -2
- data/lib/rgeo/feature/linear_ring.rb +0 -1
- data/lib/rgeo/feature/multi_curve.rb +0 -1
- data/lib/rgeo/feature/multi_surface.rb +0 -1
- data/lib/rgeo/feature/point.rb +0 -1
- data/lib/rgeo/feature/polygon.rb +1 -2
- data/lib/rgeo/feature/surface.rb +0 -1
- data/lib/rgeo/feature/types.rb +73 -83
- data/lib/rgeo/geographic/factory.rb +87 -80
- data/lib/rgeo/geographic/interface.rb +40 -23
- data/lib/rgeo/geographic/projected_feature_methods.rb +2 -6
- data/lib/rgeo/geographic/projected_window.rb +35 -21
- data/lib/rgeo/geographic/simple_mercator_projector.rb +25 -13
- data/lib/rgeo/geographic/spherical_feature_methods.rb +8 -3
- data/lib/rgeo/geographic/spherical_math.rb +17 -20
- data/lib/rgeo/geos/capi_factory.rb +50 -50
- data/lib/rgeo/geos/ffi_factory.rb +41 -42
- data/lib/rgeo/geos/ffi_feature_methods.rb +72 -97
- data/lib/rgeo/geos/interface.rb +16 -16
- data/lib/rgeo/geos/utils.rb +3 -3
- data/lib/rgeo/geos/zm_factory.rb +50 -42
- data/lib/rgeo/geos/zm_feature_methods.rb +15 -8
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +4 -4
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -2
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +18 -24
- data/lib/rgeo/impl_helper/basic_point_methods.rb +1 -3
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +15 -16
- data/lib/rgeo/impl_helper/utils.rb +3 -9
- data/lib/rgeo/impl_helper/valid_op.rb +12 -16
- data/lib/rgeo/version.rb +1 -1
- data/lib/rgeo/wkrep/wkb_generator.rb +42 -47
- data/lib/rgeo/wkrep/wkb_parser.rb +17 -18
- data/lib/rgeo/wkrep/wkt_generator.rb +23 -16
- data/lib/rgeo/wkrep/wkt_parser.rb +23 -13
- metadata +5 -5
@@ -250,6 +250,7 @@ method_line_string_project_point(VALUE self, VALUE point)
|
|
250
250
|
RGeo_GeometryData* self_data;
|
251
251
|
const GEOSGeometry* self_geom;
|
252
252
|
const GEOSGeometry* geos_point;
|
253
|
+
int state = 0;
|
253
254
|
|
254
255
|
double location;
|
255
256
|
|
@@ -258,8 +259,12 @@ method_line_string_project_point(VALUE self, VALUE point)
|
|
258
259
|
self_geom = self_data->geom;
|
259
260
|
|
260
261
|
if (self_geom && point) {
|
261
|
-
geos_point =
|
262
|
-
|
262
|
+
geos_point = rgeo_convert_to_geos_geometry(
|
263
|
+
factory, point, rgeo_geos_point_class, &state);
|
264
|
+
if (state) {
|
265
|
+
rb_jump_tag(state);
|
266
|
+
}
|
267
|
+
|
263
268
|
location = GEOSProject(self_geom, geos_point);
|
264
269
|
result = DBL2NUM(location);
|
265
270
|
}
|
@@ -392,7 +397,6 @@ method_line_hash(VALUE self)
|
|
392
397
|
static GEOSCoordSequence*
|
393
398
|
coord_seq_from_array(VALUE factory, VALUE array, char close)
|
394
399
|
{
|
395
|
-
RGeo_FactoryData* factory_data;
|
396
400
|
VALUE point_type;
|
397
401
|
unsigned int len;
|
398
402
|
char has_z;
|
@@ -404,9 +408,9 @@ coord_seq_from_array(VALUE factory, VALUE array, char close)
|
|
404
408
|
const GEOSCoordSequence* entry_cs;
|
405
409
|
double x;
|
406
410
|
GEOSCoordSequence* coord_seq;
|
411
|
+
int state = 0;
|
407
412
|
|
408
413
|
Check_Type(array, T_ARRAY);
|
409
|
-
factory_data = RGEO_FACTORY_DATA_PTR(factory);
|
410
414
|
point_type = rgeo_feature_point_module;
|
411
415
|
len = (unsigned int)RARRAY_LEN(array);
|
412
416
|
has_z = (char)(RGEO_FACTORY_DATA_PTR(factory)->flags &
|
@@ -418,22 +422,26 @@ coord_seq_from_array(VALUE factory, VALUE array, char close)
|
|
418
422
|
}
|
419
423
|
for (i = 0; i < len; ++i) {
|
420
424
|
good = 0;
|
425
|
+
|
421
426
|
entry_geom = rgeo_convert_to_geos_geometry(
|
422
|
-
factory, rb_ary_entry(array, i), point_type);
|
423
|
-
if (
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
427
|
+
factory, rb_ary_entry(array, i), point_type, &state);
|
428
|
+
if (state) {
|
429
|
+
FREE(coords);
|
430
|
+
rb_jump_tag(state);
|
431
|
+
}
|
432
|
+
|
433
|
+
entry_cs = GEOSGeom_getCoordSeq(entry_geom);
|
434
|
+
if (entry_cs) {
|
435
|
+
if (GEOSCoordSeq_getX(entry_cs, 0, &x)) {
|
436
|
+
coords[i * dims] = x;
|
437
|
+
if (GEOSCoordSeq_getY(entry_cs, 0, &x)) {
|
438
|
+
coords[i * dims + 1] = x;
|
439
|
+
good = 1;
|
440
|
+
if (has_z) {
|
441
|
+
if (GEOSCoordSeq_getZ(entry_cs, 0, &x)) {
|
442
|
+
coords[i * dims + 2] = x;
|
443
|
+
} else {
|
444
|
+
good = 0;
|
437
445
|
}
|
438
446
|
}
|
439
447
|
}
|
@@ -474,13 +482,11 @@ cmethod_create_line_string(VALUE module, VALUE factory, VALUE array)
|
|
474
482
|
{
|
475
483
|
VALUE result;
|
476
484
|
GEOSCoordSequence* coord_seq;
|
477
|
-
RGeo_FactoryData* factory_data;
|
478
485
|
GEOSGeometry* geom;
|
479
486
|
|
480
487
|
result = Qnil;
|
481
488
|
coord_seq = coord_seq_from_array(factory, array, 0);
|
482
489
|
if (coord_seq) {
|
483
|
-
factory_data = RGEO_FACTORY_DATA_PTR(factory);
|
484
490
|
geom = GEOSGeom_createLineString(coord_seq);
|
485
491
|
if (geom) {
|
486
492
|
result =
|
@@ -495,13 +501,11 @@ cmethod_create_linear_ring(VALUE module, VALUE factory, VALUE array)
|
|
495
501
|
{
|
496
502
|
VALUE result;
|
497
503
|
GEOSCoordSequence* coord_seq;
|
498
|
-
RGeo_FactoryData* factory_data;
|
499
504
|
GEOSGeometry* geom;
|
500
505
|
|
501
506
|
result = Qnil;
|
502
507
|
coord_seq = coord_seq_from_array(factory, array, 1);
|
503
508
|
if (coord_seq) {
|
504
|
-
factory_data = RGEO_FACTORY_DATA_PTR(factory);
|
505
509
|
geom = GEOSGeom_createLinearRing(coord_seq);
|
506
510
|
if (geom) {
|
507
511
|
result =
|
@@ -549,25 +553,31 @@ cmethod_create_line(VALUE module, VALUE factory, VALUE start, VALUE end)
|
|
549
553
|
const GEOSGeometry* end_geom;
|
550
554
|
GEOSCoordSequence* coord_seq;
|
551
555
|
GEOSGeometry* geom;
|
556
|
+
int state = 0;
|
552
557
|
|
553
558
|
result = Qnil;
|
554
559
|
factory_data = RGEO_FACTORY_DATA_PTR(factory);
|
555
560
|
has_z = (char)(factory_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
|
556
561
|
point_type = rgeo_feature_point_module;
|
557
562
|
|
558
|
-
start_geom =
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
563
|
+
start_geom =
|
564
|
+
rgeo_convert_to_geos_geometry(factory, start, point_type, &state);
|
565
|
+
if (state) {
|
566
|
+
rb_jump_tag(state);
|
567
|
+
}
|
568
|
+
|
569
|
+
end_geom = rgeo_convert_to_geos_geometry(factory, end, point_type, &state);
|
570
|
+
if (state) {
|
571
|
+
rb_jump_tag(state);
|
572
|
+
}
|
573
|
+
|
574
|
+
coord_seq = GEOSCoordSeq_create(2, 3);
|
575
|
+
if (coord_seq) {
|
576
|
+
populate_geom_into_coord_seq(start_geom, coord_seq, 0, has_z);
|
577
|
+
populate_geom_into_coord_seq(end_geom, coord_seq, 1, has_z);
|
578
|
+
geom = GEOSGeom_createLineString(coord_seq);
|
579
|
+
if (geom) {
|
580
|
+
result = rgeo_wrap_geos_geometry(factory, geom, rgeo_geos_line_class);
|
571
581
|
}
|
572
582
|
}
|
573
583
|
|
data/ext/geos_c_impl/point.c
CHANGED
@@ -208,12 +208,10 @@ VALUE
|
|
208
208
|
rgeo_create_geos_point(VALUE factory, double x, double y, double z)
|
209
209
|
{
|
210
210
|
VALUE result;
|
211
|
-
RGeo_FactoryData* factory_data;
|
212
211
|
GEOSCoordSequence* coord_seq;
|
213
212
|
GEOSGeometry* geom;
|
214
213
|
|
215
214
|
result = Qnil;
|
216
|
-
factory_data = RGEO_FACTORY_DATA_PTR(factory);
|
217
215
|
coord_seq = GEOSCoordSeq_create(1, 3);
|
218
216
|
if (coord_seq) {
|
219
217
|
if (GEOSCoordSeq_setX(coord_seq, 0, x)) {
|
data/ext/geos_c_impl/polygon.c
CHANGED
@@ -237,27 +237,23 @@ cmethod_create(VALUE module,
|
|
237
237
|
VALUE exterior,
|
238
238
|
VALUE interior_array)
|
239
239
|
{
|
240
|
-
RGeo_FactoryData* factory_data;
|
241
240
|
VALUE linear_ring_type;
|
242
241
|
GEOSGeometry* exterior_geom;
|
243
242
|
unsigned int len;
|
244
243
|
GEOSGeometry** interior_geoms;
|
245
244
|
unsigned int actual_len;
|
246
245
|
unsigned int i;
|
246
|
+
unsigned int j;
|
247
247
|
GEOSGeometry* interior_geom;
|
248
248
|
GEOSGeometry* polygon;
|
249
249
|
int state = 0;
|
250
250
|
|
251
251
|
Check_Type(interior_array, T_ARRAY);
|
252
|
-
factory_data = RGEO_FACTORY_DATA_PTR(factory);
|
253
252
|
linear_ring_type = rgeo_feature_linear_ring_module;
|
254
253
|
exterior_geom = rgeo_convert_to_detached_geos_geometry(
|
255
254
|
exterior, factory, linear_ring_type, NULL, &state);
|
256
255
|
if (state) {
|
257
|
-
|
258
|
-
}
|
259
|
-
if (!exterior_geom) {
|
260
|
-
return Qnil;
|
256
|
+
rb_jump_tag(state);
|
261
257
|
}
|
262
258
|
|
263
259
|
len = (unsigned int)RARRAY_LEN(interior_array);
|
@@ -271,12 +267,15 @@ cmethod_create(VALUE module,
|
|
271
267
|
linear_ring_type,
|
272
268
|
NULL,
|
273
269
|
&state);
|
274
|
-
if (interior_geom) {
|
275
|
-
interior_geoms[actual_len++] = interior_geom;
|
276
|
-
}
|
277
270
|
if (state) {
|
278
|
-
|
271
|
+
for (j = 0; j < i; j++) {
|
272
|
+
GEOSGeom_destroy(interior_geoms[j]);
|
273
|
+
}
|
274
|
+
GEOSGeom_destroy(exterior_geom);
|
275
|
+
FREE(interior_geoms);
|
276
|
+
rb_jump_tag(state);
|
279
277
|
}
|
278
|
+
interior_geoms[actual_len++] = interior_geom;
|
280
279
|
}
|
281
280
|
if (len == actual_len) {
|
282
281
|
polygon =
|
@@ -295,7 +294,7 @@ cmethod_create(VALUE module,
|
|
295
294
|
}
|
296
295
|
GEOSGeom_destroy(exterior_geom);
|
297
296
|
if (state) {
|
298
|
-
|
297
|
+
rb_jump_tag(state);
|
299
298
|
}
|
300
299
|
return Qnil;
|
301
300
|
}
|
data/ext/geos_c_impl/polygon.h
CHANGED
@@ -18,7 +18,7 @@ void
|
|
18
18
|
rgeo_init_geos_polygon();
|
19
19
|
|
20
20
|
/*
|
21
|
-
|
21
|
+
Compares the values of two GEOS polygons. The two given geometries MUST
|
22
22
|
be polygon types.
|
23
23
|
Returns Qtrue if the polygons are equal, Qfalse if they are inequal, or
|
24
24
|
Qnil if an error occurs.
|
data/ext/geos_c_impl/ruby_more.c
CHANGED
data/ext/geos_c_impl/ruby_more.h
CHANGED
@@ -12,6 +12,14 @@ RGEO_BEGIN_C
|
|
12
12
|
VALUE
|
13
13
|
rb_protect_funcall(VALUE recv, ID mid, int* state, int n, ...);
|
14
14
|
|
15
|
+
/*
|
16
|
+
Raises an error based on the exception passed in, but also returns
|
17
|
+
a VALUE rather than void. This is so we can pass it into rb_protect
|
18
|
+
without getting type mismatch warnings.
|
19
|
+
*/
|
20
|
+
VALUE
|
21
|
+
rb_exc_raise_value(VALUE exc);
|
22
|
+
|
15
23
|
RGEO_END_C
|
16
24
|
|
17
25
|
#endif
|
@@ -10,7 +10,6 @@ module RGeo
|
|
10
10
|
module Cartesian
|
11
11
|
# This provides includes some spatial analysis algorithms supporting
|
12
12
|
# Cartesian data.
|
13
|
-
|
14
13
|
module Analysis
|
15
14
|
class << self
|
16
15
|
# Check orientation of a ring, returns `true` if it is counter-clockwise
|
@@ -79,8 +78,11 @@ module RGeo
|
|
79
78
|
sin = 0.0
|
80
79
|
cos = 1.0
|
81
80
|
angs.each_slice(2) do |(x, y)|
|
82
|
-
ready = y > 0.0 &&
|
83
|
-
|
81
|
+
ready = y > 0.0 &&
|
82
|
+
(sin > 0.0 || sin == 0 && direction == -1) ||
|
83
|
+
y < 0.0 &&
|
84
|
+
(sin < 0.0 || sin == 0 && direction == 1)
|
85
|
+
unless y == 0
|
84
86
|
s = sin * x + cos * y
|
85
87
|
c = cos * x - sin * y
|
86
88
|
r = Math.sqrt(s * s + c * c)
|
@@ -19,8 +19,40 @@ module RGeo
|
|
19
19
|
# adding the geometries to it. You may then query it for the bounds,
|
20
20
|
# or use it to determine whether it encloses other geometries or
|
21
21
|
# bounding boxes.
|
22
|
-
|
23
22
|
class BoundingBox
|
23
|
+
# Returns the bounding box's factory.
|
24
|
+
attr_reader :factory
|
25
|
+
|
26
|
+
# Returns true if this bounding box tracks Z coordinates.
|
27
|
+
attr_reader :has_z
|
28
|
+
|
29
|
+
# Returns true if this bounding box tracks M coordinates.
|
30
|
+
attr_reader :has_m
|
31
|
+
|
32
|
+
# Returns the minimum X, or nil if this bounding box is empty.
|
33
|
+
attr_reader :min_x
|
34
|
+
|
35
|
+
# Returns the maximum X, or nil if this bounding box is empty.
|
36
|
+
attr_reader :max_x
|
37
|
+
|
38
|
+
# Returns the minimum Y, or nil if this bounding box is empty.
|
39
|
+
attr_reader :min_y
|
40
|
+
|
41
|
+
# Returns the maximum Y, or nil if this bounding box is empty.
|
42
|
+
attr_reader :max_y
|
43
|
+
|
44
|
+
# Returns the minimum Z, or nil if this bounding box is empty.
|
45
|
+
attr_reader :min_z
|
46
|
+
|
47
|
+
# Returns the maximum Z, or nil if this bounding box is empty.
|
48
|
+
attr_reader :max_z
|
49
|
+
|
50
|
+
# Returns the minimum M, or nil if this bounding box is empty.
|
51
|
+
attr_reader :min_m
|
52
|
+
|
53
|
+
# Returns the maximum M, or nil if this bounding box is empty.
|
54
|
+
attr_reader :max_m
|
55
|
+
|
24
56
|
# Create a bounding box given two corner points.
|
25
57
|
# The bounding box will be given the factory of the first point.
|
26
58
|
# You may also provide the same options available to
|
@@ -69,19 +101,15 @@ module RGeo
|
|
69
101
|
end
|
70
102
|
end
|
71
103
|
|
72
|
-
def eql?(
|
73
|
-
|
74
|
-
@min_x ==
|
75
|
-
@min_y ==
|
76
|
-
@min_z ==
|
77
|
-
@min_m ==
|
104
|
+
def eql?(other) # :nodoc:
|
105
|
+
other.is_a?(BoundingBox) && @factory == other.factory &&
|
106
|
+
@min_x == other.min_x && @max_x == other.max_x &&
|
107
|
+
@min_y == other.min_y && @max_y == other.max_y &&
|
108
|
+
@min_z == other.min_z && @max_z == other.max_z &&
|
109
|
+
@min_m == other.min_m && @max_m == other.max_m
|
78
110
|
end
|
79
111
|
alias == eql?
|
80
112
|
|
81
|
-
# Returns the bounding box's factory.
|
82
|
-
|
83
|
-
attr_reader :factory
|
84
|
-
|
85
113
|
# Returns true if this bounding box is still empty.
|
86
114
|
|
87
115
|
def empty?
|
@@ -105,22 +133,6 @@ module RGeo
|
|
105
133
|
@min_x && (@min_x == @max_x || @min_y == @max_y)
|
106
134
|
end
|
107
135
|
|
108
|
-
# Returns true if this bounding box tracks Z coordinates.
|
109
|
-
|
110
|
-
attr_reader :has_z
|
111
|
-
|
112
|
-
# Returns true if this bounding box tracks M coordinates.
|
113
|
-
|
114
|
-
attr_reader :has_m
|
115
|
-
|
116
|
-
# Returns the minimum X, or nil if this bounding box is empty.
|
117
|
-
|
118
|
-
attr_reader :min_x
|
119
|
-
|
120
|
-
# Returns the maximum X, or nil if this bounding box is empty.
|
121
|
-
|
122
|
-
attr_reader :max_x
|
123
|
-
|
124
136
|
# Returns the midpoint X, or nil if this bounding box is empty.
|
125
137
|
|
126
138
|
def center_x
|
@@ -133,14 +145,6 @@ module RGeo
|
|
133
145
|
@max_x ? @max_x - @min_x : 0
|
134
146
|
end
|
135
147
|
|
136
|
-
# Returns the minimum Y, or nil if this bounding box is empty.
|
137
|
-
|
138
|
-
attr_reader :min_y
|
139
|
-
|
140
|
-
# Returns the maximum Y, or nil if this bounding box is empty.
|
141
|
-
|
142
|
-
attr_reader :max_y
|
143
|
-
|
144
148
|
# Returns the midpoint Y, or nil if this bounding box is empty.
|
145
149
|
|
146
150
|
def center_y
|
@@ -153,14 +157,6 @@ module RGeo
|
|
153
157
|
@max_y ? @max_y - @min_y : 0
|
154
158
|
end
|
155
159
|
|
156
|
-
# Returns the minimum Z, or nil if this bounding box is empty.
|
157
|
-
|
158
|
-
attr_reader :min_z
|
159
|
-
|
160
|
-
# Returns the maximum Z, or nil if this bounding box is empty.
|
161
|
-
|
162
|
-
attr_reader :max_z
|
163
|
-
|
164
160
|
# Returns the midpoint Z, or nil if this bounding box is empty or has no Z.
|
165
161
|
|
166
162
|
def center_z
|
@@ -170,16 +166,12 @@ module RGeo
|
|
170
166
|
# Returns the Z span, 0 if this bounding box is empty, or nil if it has no Z.
|
171
167
|
|
172
168
|
def z_span
|
173
|
-
|
174
|
-
end
|
169
|
+
return unless @has_z
|
175
170
|
|
176
|
-
|
177
|
-
|
178
|
-
attr_reader :min_m
|
171
|
+
return 0 unless @max_z
|
179
172
|
|
180
|
-
|
181
|
-
|
182
|
-
attr_reader :max_m
|
173
|
+
@max_z - @min_z
|
174
|
+
end
|
183
175
|
|
184
176
|
# Returns the midpoint M, or nil if this bounding box is empty or has no M.
|
185
177
|
|
@@ -190,31 +182,37 @@ module RGeo
|
|
190
182
|
# Returns the M span, 0 if this bounding box is empty, or nil if it has no M.
|
191
183
|
|
192
184
|
def m_span
|
193
|
-
|
185
|
+
return unless @has_m
|
186
|
+
|
187
|
+
return 0 unless @max_m
|
188
|
+
|
189
|
+
@max_m - @min_m
|
194
190
|
end
|
195
191
|
|
196
192
|
# Returns a point representing the minimum extent in all dimensions,
|
197
193
|
# or nil if this bounding box is empty.
|
198
194
|
|
199
195
|
def min_point
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
196
|
+
return unless @min_x
|
197
|
+
|
198
|
+
extras = []
|
199
|
+
extras << @min_z if @has_z
|
200
|
+
extras << @min_m if @has_m
|
201
|
+
|
202
|
+
@factory.point(@min_x, @min_y, *extras)
|
206
203
|
end
|
207
204
|
|
208
205
|
# Returns a point representing the maximum extent in all dimensions,
|
209
206
|
# or nil if this bounding box is empty.
|
210
207
|
|
211
208
|
def max_point
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
209
|
+
return unless @min_x
|
210
|
+
|
211
|
+
extras = []
|
212
|
+
extras << @max_z if @has_z
|
213
|
+
extras << @max_m if @has_m
|
214
|
+
|
215
|
+
@factory.point(@max_x, @max_y, *extras)
|
218
216
|
end
|
219
217
|
|
220
218
|
# Adjusts the extents of this bounding box to encompass the given
|
@@ -280,21 +278,18 @@ module RGeo
|
|
280
278
|
# have M. Default is false.
|
281
279
|
|
282
280
|
def contains?(rhs, opts = {})
|
283
|
-
if Feature::Geometry === rhs
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
else
|
296
|
-
true
|
297
|
-
end
|
281
|
+
return contains?(BoundingBox.new(@factory).add(rhs)) if Feature::Geometry === rhs
|
282
|
+
|
283
|
+
return true if rhs.empty?
|
284
|
+
|
285
|
+
return false if empty?
|
286
|
+
|
287
|
+
cmp_xymz =
|
288
|
+
(@min_x > rhs.min_x || @max_x < rhs.max_x || @min_y > rhs.min_y || @max_y < rhs.max_y) ||
|
289
|
+
(@has_m && rhs.has_m && !opts[:ignore_m] && (@min_m > rhs.min_m || @max_m < rhs.max_m)) ||
|
290
|
+
(@has_z && rhs.has_z && !opts[:ignore_z] && (@min_z > rhs.min_z || @max_z < rhs.max_z))
|
291
|
+
|
292
|
+
!cmp_xymz
|
298
293
|
end
|
299
294
|
|
300
295
|
# Returns this bounding box subdivided, as an array of bounding boxes.
|
@@ -23,17 +23,14 @@ module RGeo
|
|
23
23
|
@lensq = @dx * @dx + @dy * @dy
|
24
24
|
end
|
25
25
|
|
26
|
-
attr_reader :s
|
27
|
-
attr_reader :e
|
28
|
-
attr_reader :dx
|
29
|
-
attr_reader :dy
|
26
|
+
attr_reader :s, :e, :dx, :dy
|
30
27
|
|
31
28
|
def to_s
|
32
29
|
"#{@s} - #{@e}"
|
33
30
|
end
|
34
31
|
|
35
|
-
def eql?(
|
36
|
-
|
32
|
+
def eql?(other)
|
33
|
+
other.is_a?(Segment) && @s == other.s && @e == other.e
|
37
34
|
end
|
38
35
|
alias == eql?
|
39
36
|
|
@@ -45,23 +42,23 @@ module RGeo
|
|
45
42
|
# a positive value if the point is to the right, or
|
46
43
|
# 0 if the point is collinear to the segment.
|
47
44
|
|
48
|
-
def side(
|
49
|
-
px =
|
50
|
-
py =
|
45
|
+
def side(point)
|
46
|
+
px = point.x
|
47
|
+
py = point.y
|
51
48
|
(@sx - px) * (@ey - py) - (@sy - py) * (@ex - px)
|
52
49
|
end
|
53
50
|
|
54
|
-
def tproj(
|
51
|
+
def tproj(point)
|
55
52
|
if @lensq == 0
|
56
53
|
nil
|
57
54
|
else
|
58
|
-
(@dx * (
|
55
|
+
(@dx * (point.x - @sx) + @dy * (point.y - @sy)) / @lensq
|
59
56
|
end
|
60
57
|
end
|
61
58
|
|
62
|
-
def contains_point?(
|
63
|
-
if side(
|
64
|
-
t = tproj(
|
59
|
+
def contains_point?(point)
|
60
|
+
if side(point) == 0
|
61
|
+
t = tproj(point)
|
65
62
|
t && t >= 0.0 && t <= 1.0
|
66
63
|
else
|
67
64
|
false
|
@@ -84,11 +81,9 @@ module RGeo
|
|
84
81
|
s2 = seg.s
|
85
82
|
# Handle degenerate cases
|
86
83
|
if seg.degenerate?
|
87
|
-
if @lensq == 0 && @s == s2
|
88
|
-
|
89
|
-
|
90
|
-
return contains_point?(s2) ? s2 : nil
|
91
|
-
end
|
84
|
+
return @s if @lensq == 0 && @s == s2
|
85
|
+
|
86
|
+
return contains_point?(s2) ? s2 : nil
|
92
87
|
elsif @lensq == 0
|
93
88
|
return seg.contains_point?(@s) ? @s : nil
|
94
89
|
end
|
@@ -132,13 +127,12 @@ module RGeo
|
|
132
127
|
# If this is the case, return the closest point from
|
133
128
|
# either segment.
|
134
129
|
int_pt = @s.factory.point(x, y)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
130
|
+
|
131
|
+
return int_pt if contains_point?(int_pt)
|
132
|
+
|
133
|
+
# find closest of @s, @e, seg.s, seg.e
|
134
|
+
[@e, seg.s, seg.e].reduce(@s) do |closest, pt|
|
135
|
+
int_pt.distance(pt) < int_pt.distance(closest) ? pt : closest
|
142
136
|
end
|
143
137
|
end
|
144
138
|
end
|