rgeo 2.1.1 → 2.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65bbadb93580fd02234007e3ddfb888b4a38b4a7dfaa2d2b0d072d313b98adfb
4
- data.tar.gz: b45a6f33bba7543ee86e0211a8b9d976cfef470222ab2adb9107f98b06818fff
3
+ metadata.gz: 0f0ded4953c3ad02eb5512ae8a9e8dd204e2008360678807a4ecea567c39533c
4
+ data.tar.gz: 577998a9cc566eba2146fb5a5e02e26db330e38f2b8518551b50c86fa8a7a027
5
5
  SHA512:
6
- metadata.gz: 33d2c278eb28f697047c98091676fae7161f3b410375ba8b5042f51cb5e10158c69617d044a19d1c68b86c399439fc6a22e3bf39d8767b303194f1d64b191d41
7
- data.tar.gz: 5e77a71cc569f9826fbac6d97ccd2aac46d2b7e37284cba950b6d8621ae04b52ed60c9a63bec7c5d227b3656e2015b1d3062eb1eaf15438de383209f1d6b291e
6
+ metadata.gz: 01f855c7553814054b662dbc9e84629f878ee71f642901cfb32f09386737cba9e0a86a2e91cbbe660515095d24cb09fb45d4b0ed680eac2f8194e0399eafe7c7
7
+ data.tar.gz: 810f5ef0b1b0f7c20d1a2b8845cdd443b9646aa564965d98d2b0d9b4bb25211e810cc73b780ff14e405dd824f5d7305a8a473a952e89e0f397406672f8fceab1
@@ -0,0 +1,144 @@
1
+ ## RGeo
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rgeo.svg)](http://badge.fury.io/rb/rgeo)
4
+ [![Build Status](https://travis-ci.org/rgeo/rgeo.svg?branch=master)](https://travis-ci.org/rgeo/rgeo)
5
+
6
+ RGeo is a geospatial data library for Ruby.
7
+
8
+ :warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning:
9
+
10
+ This organization is looking for maintainers, see [this issue](https://github.com/rgeo/rgeo/issues/216) for more information.
11
+
12
+ :warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning::warning:
13
+
14
+ ### Summary
15
+
16
+ RGeo is a key component for writing location-aware applications in the Ruby
17
+ programming language. At its core is an implementation of the industry
18
+ standard OGC Simple Features Specification, which provides data
19
+ representations of geometric objects such as points, lines, and polygons,
20
+ along with a set of geometric analysis operations. This makes it ideal for
21
+ modeling geolocation data. It also supports a suite of optional add-on modules
22
+ that provide various geolocation-related services.
23
+
24
+ Use the core **rgeo** gem to:
25
+
26
+ * Represent spatial and geolocation data objects such as points, lines, and
27
+ polygons in your Ruby application.
28
+ * Perform standard spatial analysis operations such as finding
29
+ intersections, creating buffers, and computing lengths and areas.
30
+ * Correctly handle spherical geometry, and compute geographic projections
31
+ for map display and data analysis.
32
+ * Read and write location data in the WKT and WKB representations used by
33
+ spatial databases.
34
+
35
+
36
+ ### Dependencies
37
+
38
+ RGeo works with the following Ruby implementations:
39
+
40
+ * MRI Ruby 2.3.0 or later.
41
+ * Partial support for JRuby 9.0 or later. The FFI implementation of GEOS
42
+ is available (ffi-geos gem required) but CAPI is not.
43
+ * See earlier versions for support for older ruby versions.
44
+
45
+ Some features also require the following:
46
+
47
+ * GEOS 3.2 or later is highly recommended. (3.3.3 or later preferred.) Some
48
+ functions will not be available without it. This C/C++ library may be
49
+ available via your operating system's package manager (`sudo aptitude
50
+ install libgeos-dev` for debian based Linux distributions, `yum install geos geos-devel` for redhat based Linux distributions), or you can
51
+ download it from http://trac.osgeo.org/geos
52
+ * On some platforms, you should install the ffi-geos gem (version 1.2.0 or
53
+ later recommended.) JRuby requires this gem to link properly with Geos,
54
+ and Windows builds probably do as well.
55
+
56
+ ### Installation
57
+
58
+ Install the RGeo gem:
59
+
60
+ ```sh
61
+ gem install rgeo
62
+ ```
63
+
64
+ or include it in your Gemfile:
65
+
66
+ ```ruby
67
+ gem "rgeo"
68
+ ```
69
+
70
+ If you are using proj.4 extensions, include
71
+ [`rgeo-proj4`](https://github.com/rgeo/rgeo-proj4):
72
+
73
+ ```ruby
74
+ gem "rgeo-proj4"
75
+ ```
76
+
77
+
78
+ ### Extensions
79
+
80
+ The [RGeo organization](https://github.com/rgeo) provides several gems that extend RGeo:
81
+
82
+ #### [`rgeo-proj4`](https://github.com/rgeo/rgeo-proj4)
83
+
84
+ Proj4 extensions
85
+
86
+ #### [`rgeo-geojson`](https://github.com/rgeo/rgeo-geojson)
87
+
88
+ Read and write GeoJSON
89
+
90
+ #### [`rgeo-shapefile`](https://github.com/rgeo/rgeo-shapefile)
91
+
92
+ Read ESRI shapefiles
93
+
94
+ #### [`activerecord-postgis-adapter`](https://github.com/rgeo/activerecord-postgis-adapter)
95
+
96
+ ActiveRecord connection adapter for PostGIS, based on postgresql (pg gem)
97
+
98
+ #### [`activerecord-mysql2spatial-adapter`](https://github.com/rgeo/activerecord-mysql2spatial-adapter)
99
+
100
+ ActiveRecord connection adapter for MySQL Spatial Extensions, based on mysql2
101
+
102
+ #### [`activerecord-spatialite-adapter`](https://github.com/rgeo/activerecord-spatialite-adapter)
103
+
104
+ ActiveRecord connection adapter for SpatiaLite, based on sqlite3 (*not maintained)
105
+
106
+
107
+ ### Development and support
108
+
109
+ RDoc Documentation is available at https://www.rubydoc.info/gems/rgeo
110
+
111
+ Contributions are welcome. Please read the
112
+ [Contributing guidelines](https://github.com/rgeo/rgeo/blob/master/CONTRIBUTING.md).
113
+
114
+ Support may be available on the
115
+ [rgeo-users google group](https://groups.google.com/forum/#!forum/rgeo-users)
116
+ or on [Stack Overflow](https://stackoverflow.com/questions/tagged/rgeo).
117
+
118
+
119
+ ### Acknowledgments
120
+
121
+ RGeo was created by [Daniel Azuma](http://www.daniel-azuma.com).
122
+ [Tee Parham](https://github.com/teeparham) is the current maintainer.
123
+
124
+ Thanks to [Pirq](http://www.pirq.com) and [Neighborland](https://neighborland.com)
125
+ for development support.
126
+
127
+ Thanks to [Travis-CI](https://travis-ci.org) for CI testing.
128
+
129
+ Thanks to [JetBrains](https://www.jetbrains.com/?from=rgeo) for RubyMine license.
130
+
131
+ RGeo calls the GEOS library to handle most Cartesian geometric calculations,
132
+ and the Proj4 library to handle projections and coordinate transformations.
133
+ These libraries are maintained by the Open Source Geospatial Foundation; more
134
+ information is available on [OSGeo's web site](http://www.osgeo.org).
135
+
136
+ JRuby support is made possible by the ffi-geos (and upcoming ffi-proj4) gems,
137
+ by [J Smith](https://github.com/dark-panda).
138
+
139
+
140
+ ### License
141
+
142
+ Copyright (c) Daniel Azuma, Tee Parham
143
+
144
+ [License](https://github.com/rgeo/rgeo/blob/master/LICENSE.txt)
@@ -0,0 +1,78 @@
1
+ /*
2
+ Analysis methos for GEOS wrapper
3
+ */
4
+
5
+ #include "preface.h"
6
+
7
+ #ifdef RGEO_GEOS_SUPPORTED
8
+
9
+ #include <ruby.h>
10
+ #include <geos_c.h>
11
+
12
+ #include "analysis.h"
13
+ #include "factory.h"
14
+ #include "errors.h"
15
+
16
+ RGEO_BEGIN_C
17
+
18
+ /*
19
+ * call-seq:
20
+ * RGeo::Geos::Analysis.ccw? -> true or false
21
+ *
22
+ * Checks direction for a ring, returns +true+ if counter-clockwise, +false+
23
+ * otherwise.
24
+ */
25
+ #ifdef RGEO_GEOS_SUPPORTS_ISCCW
26
+ VALUE rgeo_geos_analysis_ccw_p(VALUE self, VALUE ring)
27
+ {
28
+
29
+ const RGeo_GeometryData* ring_data;
30
+ const GEOSCoordSequence* coord_seq;
31
+ char is_ccw;
32
+
33
+ rgeo_check_geos_object(ring);
34
+
35
+ ring_data = RGEO_GEOMETRY_DATA_PTR(ring);
36
+
37
+ coord_seq = GEOSGeom_getCoordSeq_r(ring_data->geos_context, ring_data->geom);
38
+ if (!coord_seq) { rb_raise(geos_error, "Could not retrieve CoordSeq from given ring."); }
39
+ if (!GEOSCoordSeq_isCCW_r(ring_data->geos_context, coord_seq, &is_ccw)) {
40
+ rb_raise(geos_error, "Could not determine if the CoordSeq is CCW.");
41
+ }
42
+
43
+ return is_ccw ? Qtrue : Qfalse;
44
+ };
45
+ #endif // RGEO_GEOS_SUPPORTS_ISCCW
46
+
47
+
48
+ /**
49
+ * call-seq:
50
+ * RGeo::Geos::Analysis.ccw_supported? -> true or false
51
+ *
52
+ * Checks if the RGEO_GEOS_SUPPORTS_ISCCW macro is defined, returns +true+
53
+ * if it is, +false+ otherwise
54
+ */
55
+ VALUE rgeo_geos_analysis_supports_ccw(VALUE self)
56
+ {
57
+ #ifdef RGEO_GEOS_SUPPORTS_ISCCW
58
+ return Qtrue;
59
+ #else
60
+ return Qfalse;
61
+ #endif
62
+ }
63
+
64
+
65
+ void rgeo_init_geos_analysis(RGeo_Globals* globals)
66
+ {
67
+ VALUE geos_analysis_module;
68
+
69
+ geos_analysis_module = rb_define_module_under(globals->geos_module, "Analysis");
70
+ rb_define_singleton_method(geos_analysis_module, "ccw_supported?", rgeo_geos_analysis_supports_ccw, 0);
71
+ #ifdef RGEO_GEOS_SUPPORTS_ISCCW
72
+ rb_define_singleton_method(geos_analysis_module, "ccw?", rgeo_geos_analysis_ccw_p, 1);
73
+ #endif // RGEO_GEOS_SUPPORTS_ISCCW
74
+ }
75
+
76
+ RGEO_END_C
77
+
78
+ #endif
@@ -0,0 +1,42 @@
1
+ /*
2
+ Analysis methos for GEOS wrapper
3
+ */
4
+
5
+ #ifndef RGEO_GEOS_ANALYSIS_INCLUDED
6
+ #define RGEO_GEOS_ANALYSIS_INCLUDED
7
+
8
+ #include <ruby.h>
9
+
10
+ #ifdef RGEO_GEOS_SUPPORTED
11
+
12
+ #include "factory.h"
13
+
14
+ RGEO_BEGIN_C
15
+
16
+ /*
17
+ * call-seq:
18
+ * RGeo::Geos::Analysis.ccw? -> true or false
19
+ *
20
+ * Checks direction for a ring, returns +true+ if counter-clockwise, +false+
21
+ * otherwise.
22
+ */
23
+ #ifdef RGEO_GEOS_SUPPORTS_CCW
24
+ VALUE rgeo_geos_analysis_ccw_p(VALUE self, VALUE ring);
25
+ #endif // RGEO_GEOS_SUPPORTS_CCW
26
+
27
+ /**
28
+ * call-seq:
29
+ * RGeo::Geos::Analysis.ccw_supported? -> true or false
30
+ *
31
+ * Checks if the RGEO_GEOS_SUPPORTS_ISCCW macro is defined, returns +true+
32
+ * if it is, +false+ otherwise
33
+ */
34
+ VALUE rgeo_geos_analysis_supports_ccw(VALUE self);
35
+
36
+ void rgeo_init_geos_analysis(RGeo_Globals* globals);
37
+
38
+ RGEO_END_C
39
+
40
+ #endif // RGEO_GEOS_SUPPORTED
41
+
42
+ #endif // RGEO_GEOS_ANALYSIS_INCLUDED
@@ -0,0 +1,35 @@
1
+
2
+ #ifndef RGEO_GEOS_ERROS_INCLUDED
3
+ #define RGEO_GEOS_ERROS_INCLUDED
4
+
5
+ #include <ruby.h>
6
+
7
+ #include "preface.h"
8
+
9
+ #ifdef RGEO_GEOS_SUPPORTED
10
+
11
+ #include "errors.h"
12
+
13
+ RGEO_BEGIN_C
14
+
15
+ // Any error relative to RGeo.
16
+ VALUE rgeo_error;
17
+ // RGeo error specific to the GEOS implementation.
18
+ VALUE geos_error;
19
+
20
+
21
+ void rgeo_init_geos_errors() {
22
+ VALUE rgeo_module;
23
+ VALUE error_module;
24
+
25
+ rgeo_module = rb_define_module("RGeo");
26
+ error_module = rb_define_module_under(rgeo_module, "Error");
27
+ rgeo_error = rb_define_class_under(error_module, "RGeoError", rb_eRuntimeError);
28
+ geos_error = rb_define_class_under(error_module, "GeosError", rgeo_error);
29
+ }
30
+
31
+ RGEO_END_C
32
+
33
+ #endif // RGEO_GEOS_SUPPORTED
34
+
35
+ #endif // RGEO_GEOS_ERROS_INCLUDED
@@ -0,0 +1,22 @@
1
+
2
+ #ifndef RGEO_GEOS_ERROS_INCLUDED
3
+ #define RGEO_GEOS_ERROS_INCLUDED
4
+
5
+ #include <ruby.h>
6
+
7
+ #ifdef RGEO_GEOS_SUPPORTED
8
+
9
+ RGEO_BEGIN_C
10
+
11
+ // Any error relative to RGeo.
12
+ extern VALUE rgeo_error;
13
+ // RGeo error specific to the GEOS implementation.
14
+ extern VALUE geos_error;
15
+
16
+ void rgeo_init_geos_errors();
17
+
18
+ RGEO_END_C
19
+
20
+ #endif // RGEO_GEOS_SUPPORTED
21
+
22
+ #endif // RGEO_GEOS_ERROS_INCLUDED
@@ -31,6 +31,7 @@ else
31
31
  have_func("GEOSPreparedContains_r", "geos_c.h")
32
32
  have_func("GEOSPreparedDisjoint_r", "geos_c.h")
33
33
  have_func("GEOSUnaryUnion_r", "geos_c.h")
34
+ have_func("GEOSCoordSeq_isCCW_r", "geos_c.h")
34
35
  have_func("rb_memhash", "ruby.h")
35
36
  end
36
37
 
@@ -16,6 +16,7 @@
16
16
  #include "line_string.h"
17
17
  #include "polygon.h"
18
18
  #include "geometry_collection.h"
19
+ #include "errors.h"
19
20
 
20
21
  RGEO_BEGIN_C
21
22
 
@@ -576,10 +577,11 @@ RGeo_Globals* rgeo_init_geos_factory()
576
577
  VALUE wrapped_globals;
577
578
  VALUE feature_module;
578
579
 
580
+ rgeo_module = rb_define_module("RGeo");
581
+
579
582
  globals = ALLOC(RGeo_Globals);
580
583
 
581
584
  // Cache some modules so we don't have to look them up by name every time
582
- rgeo_module = rb_define_module("RGeo");
583
585
  feature_module = rb_define_module_under(rgeo_module, "Feature");
584
586
  globals->feature_module = feature_module;
585
587
  globals->geos_module = rb_define_module_under(rgeo_module, "Geos");
@@ -831,6 +833,13 @@ char rgeo_is_geos_object(VALUE obj)
831
833
  return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? 1 : 0;
832
834
  }
833
835
 
836
+ void rgeo_check_geos_object(VALUE obj)
837
+ {
838
+ if (!rgeo_is_geos_object(obj)) {
839
+ rb_raise(rgeo_error, "Not a GEOS Geometry object.");
840
+ }
841
+ }
842
+
834
843
 
835
844
  const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj)
836
845
  {
@@ -10,7 +10,6 @@
10
10
 
11
11
  RGEO_BEGIN_C
12
12
 
13
-
14
13
  /*
15
14
  Per-interpreter globals.
16
15
  Most of these are cached references to commonly used classes, modules,
@@ -187,6 +186,11 @@ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, V
187
186
  */
188
187
  char rgeo_is_geos_object(VALUE obj);
189
188
 
189
+ /*
190
+ Raises a rgeo error if the object is not a GEOS Geometry implementation.
191
+ */
192
+ void rgeo_check_geos_object(VALUE obj);
193
+
190
194
  /*
191
195
  Gets the underlying GEOS geometry for a given ruby object. Returns NULL
192
196
  if the given ruby object is not a GEOS geometry wrapper.
@@ -2,7 +2,6 @@
2
2
  Main initializer for GEOS wrapper
3
3
  */
4
4
 
5
-
6
5
  #include "preface.h"
7
6
 
8
7
  #ifdef RGEO_GEOS_SUPPORTED
@@ -10,18 +9,20 @@
10
9
  #include <ruby.h>
11
10
  #include <geos_c.h>
12
11
 
12
+ #include "errors.h"
13
+
13
14
  #include "factory.h"
14
15
  #include "geometry.h"
15
16
  #include "point.h"
16
17
  #include "line_string.h"
17
18
  #include "polygon.h"
18
19
  #include "geometry_collection.h"
20
+ #include "analysis.h"
19
21
 
20
22
  #endif
21
23
 
22
24
  RGEO_BEGIN_C
23
25
 
24
-
25
26
  void Init_geos_c_impl()
26
27
  {
27
28
  #ifdef RGEO_GEOS_SUPPORTED
@@ -33,6 +34,8 @@ void Init_geos_c_impl()
33
34
  rgeo_init_geos_line_string(globals);
34
35
  rgeo_init_geos_polygon(globals);
35
36
  rgeo_init_geos_geometry_collection(globals);
37
+ rgeo_init_geos_analysis(globals);
38
+ rgeo_init_geos_errors();
36
39
  #endif
37
40
  }
38
41
 
@@ -21,6 +21,9 @@
21
21
  #ifdef HAVE_GEOSUNARYUNION_R
22
22
  #define RGEO_GEOS_SUPPORTS_UNARYUNION
23
23
  #endif
24
+ #ifdef HAVE_GEOSCOORDSEQ_ISCCW_R
25
+ #define RGEO_GEOS_SUPPORTS_ISCCW
26
+ #endif
24
27
  #ifdef HAVE_RB_MEMHASH
25
28
  #define RGEO_SUPPORTS_NEW_HASHING
26
29
  #endif
@@ -75,12 +75,12 @@
75
75
  # database, and based on the postgresql adapter. Available as the
76
76
  # activerecord-postgis-adapter gem.
77
77
 
78
- require "rgeo/version"
79
- require "rgeo/error"
80
- require "rgeo/feature"
81
- require "rgeo/coord_sys"
82
- require "rgeo/impl_helper"
83
- require "rgeo/wkrep"
84
- require "rgeo/geos"
85
- require "rgeo/cartesian"
86
- require "rgeo/geographic"
78
+ require_relative "rgeo/version"
79
+ require_relative "rgeo/error"
80
+ require_relative "rgeo/feature"
81
+ require_relative "rgeo/coord_sys"
82
+ require_relative "rgeo/impl_helper"
83
+ require_relative "rgeo/wkrep"
84
+ require_relative "rgeo/geos"
85
+ require_relative "rgeo/cartesian"
86
+ require_relative "rgeo/geographic"
@@ -6,10 +6,10 @@
6
6
  # the simple Cartesian implementation. It also provides a namespace
7
7
  # for Cartesian-specific analysis tools.
8
8
 
9
- require "rgeo/cartesian/calculations"
10
- require "rgeo/cartesian/feature_methods"
11
- require "rgeo/cartesian/feature_classes"
12
- require "rgeo/cartesian/factory"
13
- require "rgeo/cartesian/interface"
14
- require "rgeo/cartesian/bounding_box"
15
- require "rgeo/cartesian/analysis"
9
+ require_relative "cartesian/calculations"
10
+ require_relative "cartesian/feature_methods"
11
+ require_relative "cartesian/feature_classes"
12
+ require_relative "cartesian/factory"
13
+ require_relative "cartesian/interface"
14
+ require_relative "cartesian/bounding_box"
15
+ require_relative "cartesian/analysis"
@@ -13,6 +13,28 @@ module RGeo
13
13
 
14
14
  module Analysis
15
15
  class << self
16
+ # Check orientation of a ring, returns `true` if it is counter-clockwise
17
+ # and false otherwise.
18
+ #
19
+ # If the factory used is GEOS based, use the GEOS implementation to
20
+ # check that. Otherwise, this methods falls back to `ring_direction`.
21
+ #
22
+ # == Note
23
+ #
24
+ # This method does not ensure a correct result for an invalid geometry.
25
+ # You should make sure your ring is valid beforehand using `is_ring?`
26
+ # if you are using a LineString, or directly `valid?` for a
27
+ # `linear_ring?`.
28
+ # This will be subject to changes in v3.
29
+ def ccw?(ring)
30
+ if RGeo::Geos.is_capi_geos?(ring) && RGeo::Geos::Analysis.ccw_supported?
31
+ RGeo::Geos::Analysis.ccw?(ring)
32
+ else
33
+ RGeo::Cartesian::Analysis.ring_direction(ring) == 1
34
+ end
35
+ end
36
+ alias counter_clockwise? ccw?
37
+
16
38
  # Given a LineString, which must be a ring, determine whether the
17
39
  # ring proceeds clockwise or counterclockwise.
18
40
  # Returns 1 for counterclockwise, or -1 for clockwise.
@@ -6,12 +6,12 @@
6
6
  #
7
7
  # -----------------------------------------------------------------------------
8
8
 
9
- require "rgeo/coord_sys/cs/factories"
10
- require "rgeo/coord_sys/cs/entities"
11
- require "rgeo/coord_sys/cs/wkt_parser"
12
- require "rgeo/coord_sys/srs_database/entry"
13
- require "rgeo/coord_sys/srs_database/url_reader"
14
- require "rgeo/coord_sys/srs_database/sr_org"
9
+ require_relative "coord_sys/cs/factories"
10
+ require_relative "coord_sys/cs/entities"
11
+ require_relative "coord_sys/cs/wkt_parser"
12
+ require_relative "coord_sys/srs_database/entry"
13
+ require_relative "coord_sys/srs_database/url_reader"
14
+ require_relative "coord_sys/srs_database/sr_org"
15
15
 
16
16
  module RGeo
17
17
  # This module provides data structures and tools related to coordinate
@@ -14,6 +14,10 @@ module RGeo
14
14
  class RGeoError < RuntimeError
15
15
  end
16
16
 
17
+ # RGeo error specific to the GEOS implementation.
18
+ class GeosError < RGeoError
19
+ end
20
+
17
21
  # The specified geometry is invalid
18
22
  class InvalidGeometry < RGeoError
19
23
  end
@@ -24,20 +24,20 @@
24
24
  # itself. The implementation should separately document any such
25
25
  # extensions that it may provide.
26
26
 
27
- require "rgeo/feature/factory"
28
- require "rgeo/feature/types"
29
- require "rgeo/feature/geometry"
30
- require "rgeo/feature/point"
31
- require "rgeo/feature/curve"
32
- require "rgeo/feature/line_string"
33
- require "rgeo/feature/linear_ring"
34
- require "rgeo/feature/line"
35
- require "rgeo/feature/surface"
36
- require "rgeo/feature/polygon"
37
- require "rgeo/feature/geometry_collection"
38
- require "rgeo/feature/multi_point"
39
- require "rgeo/feature/multi_curve"
40
- require "rgeo/feature/multi_line_string"
41
- require "rgeo/feature/multi_surface"
42
- require "rgeo/feature/multi_polygon"
43
- require "rgeo/feature/factory_generator"
27
+ require_relative "feature/factory"
28
+ require_relative "feature/types"
29
+ require_relative "feature/geometry"
30
+ require_relative "feature/point"
31
+ require_relative "feature/curve"
32
+ require_relative "feature/line_string"
33
+ require_relative "feature/linear_ring"
34
+ require_relative "feature/line"
35
+ require_relative "feature/surface"
36
+ require_relative "feature/polygon"
37
+ require_relative "feature/geometry_collection"
38
+ require_relative "feature/multi_point"
39
+ require_relative "feature/multi_curve"
40
+ require_relative "feature/multi_line_string"
41
+ require_relative "feature/multi_surface"
42
+ require_relative "feature/multi_polygon"
43
+ require_relative "feature/factory_generator"
@@ -23,6 +23,16 @@ module RGeo
23
23
  module LinearRing
24
24
  include LineString
25
25
  extend Type
26
+
27
+ # Returns +true+ if the ring is oriented in a counter clockwise direction
28
+ # otherwise returns +false+.
29
+ #
30
+ # == Notes
31
+ #
32
+ # Not a standard SFS method for linear rings, but added for convenience.
33
+ def ccw?
34
+ raise Error::UnsupportedOperation, "Method LinearRing#ccw? not defined."
35
+ end
26
36
  end
27
37
  end
28
38
  end
@@ -18,13 +18,13 @@
18
18
  # See the various class methods of Geographic for more information on
19
19
  # the behaviors of the factories they generate.
20
20
 
21
- require "rgeo/geographic/factory"
22
- require "rgeo/geographic/projected_window"
23
- require "rgeo/geographic/interface"
24
- require "rgeo/geographic/spherical_math"
25
- require "rgeo/geographic/spherical_feature_methods"
26
- require "rgeo/geographic/spherical_feature_classes"
27
- require "rgeo/geographic/proj4_projector"
28
- require "rgeo/geographic/simple_mercator_projector"
29
- require "rgeo/geographic/projected_feature_methods"
30
- require "rgeo/geographic/projected_feature_classes"
21
+ require_relative "geographic/factory"
22
+ require_relative "geographic/projected_window"
23
+ require_relative "geographic/interface"
24
+ require_relative "geographic/spherical_math"
25
+ require_relative "geographic/spherical_feature_methods"
26
+ require_relative "geographic/spherical_feature_classes"
27
+ require_relative "geographic/proj4_projector"
28
+ require_relative "geographic/simple_mercator_projector"
29
+ require_relative "geographic/projected_feature_methods"
30
+ require_relative "geographic/projected_feature_classes"
@@ -47,6 +47,7 @@ module RGeo
47
47
  include ImplHelper::BasicGeometryMethods
48
48
  include ImplHelper::BasicPolygonMethods
49
49
  include SphericalGeometryMethods
50
+ include SphericalPolygonMethods
50
51
  end
51
52
 
52
53
  class SphericalGeometryCollectionImpl # :nodoc:
@@ -130,5 +130,28 @@ module RGeo
130
130
  inject(0.0) { |sum, geom| sum + geom.length }
131
131
  end
132
132
  end
133
+
134
+ module SphericalPolygonMethods # :nodoc:
135
+ def centroid
136
+ return super unless num_interior_rings == 0
137
+
138
+ centroid_lat = 0.0
139
+ centroid_lng = 0.0
140
+ signed_area = 0.0
141
+
142
+ exterior_ring.points.each_cons(2) do |p0, p1|
143
+ area = (p0.x * p1.y) - (p1.x * p0.y)
144
+ signed_area += area
145
+ centroid_lat += (p0.x + p1.x) * area
146
+ centroid_lng += (p0.y + p1.y) * area
147
+ end
148
+
149
+ signed_area *= 0.5
150
+ centroid_lat /= (6.0 * signed_area)
151
+ centroid_lng /= (6.0 * signed_area)
152
+
153
+ RGeo::Geographic.spherical_factory.point(centroid_lat, centroid_lng)
154
+ end
155
+ end
133
156
  end
134
157
  end
@@ -21,24 +21,24 @@
21
21
 
22
22
  module RGeo
23
23
  module Geos
24
- require "rgeo/geos/utils"
25
- require "rgeo/geos/interface"
24
+ require_relative "geos/utils"
25
+ require_relative "geos/interface"
26
26
  begin
27
- require "rgeo/geos/geos_c_impl"
27
+ require_relative "geos/geos_c_impl"
28
28
  rescue LoadError
29
29
  # continue
30
30
  end
31
31
  CAPI_SUPPORTED = RGeo::Geos.const_defined?(:CAPIGeometryMethods)
32
32
  if CAPI_SUPPORTED
33
- require "rgeo/geos/capi_feature_classes"
34
- require "rgeo/geos/capi_factory"
33
+ require_relative "geos/capi_feature_classes"
34
+ require_relative "geos/capi_factory"
35
35
  end
36
- require "rgeo/geos/ffi_feature_methods"
37
- require "rgeo/geos/ffi_feature_classes"
38
- require "rgeo/geos/ffi_factory"
39
- require "rgeo/geos/zm_feature_methods"
40
- require "rgeo/geos/zm_feature_classes"
41
- require "rgeo/geos/zm_factory"
36
+ require_relative "geos/ffi_feature_methods"
37
+ require_relative "geos/ffi_feature_classes"
38
+ require_relative "geos/ffi_factory"
39
+ require_relative "geos/zm_feature_methods"
40
+ require_relative "geos/zm_feature_classes"
41
+ require_relative "geos/zm_factory"
42
42
 
43
43
  # Determine ffi support.
44
44
  begin
@@ -297,10 +297,10 @@ module RGeo
297
297
  if (wkb_parser_ = _wkb_parser)
298
298
  wkb_parser_.parse(str_)
299
299
  else
300
- if str_[0] =~ /[0-oa-fA-F]/
301
- _parse_wkb_impl([str_].pack('H*'))
302
- else
300
+ if str_[0] == "\x00" || str_[0] == "\x01"
303
301
  _parse_wkb_impl(str_)
302
+ else
303
+ _parse_wkb_impl([str_].pack('H*'))
304
304
  end
305
305
  end
306
306
  end
@@ -72,6 +72,10 @@ module RGeo
72
72
  include CAPIGeometryMethods
73
73
  include CAPILineStringMethods
74
74
  include CAPILinearRingMethods
75
+
76
+ def ccw?
77
+ RGeo::Cartesian::Analysis.ccw?(self)
78
+ end
75
79
  end
76
80
 
77
81
  class CAPILineImpl # :nodoc:
@@ -393,6 +393,10 @@ module RGeo
393
393
  def geometry_type
394
394
  Feature::LinearRing
395
395
  end
396
+
397
+ def ccw?
398
+ RGeo::Cartesian::Analysis.ccw?(self)
399
+ end
396
400
  end
397
401
 
398
402
  module FFILineMethods # :nodoc:
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rgeo/impl_helper/utils"
4
- require "rgeo/impl_helper/math"
5
- require "rgeo/impl_helper/basic_geometry_methods"
6
- require "rgeo/impl_helper/basic_geometry_collection_methods"
7
- require "rgeo/impl_helper/basic_point_methods"
8
- require "rgeo/impl_helper/basic_line_string_methods"
9
- require "rgeo/impl_helper/basic_polygon_methods"
3
+ require_relative "impl_helper/utils"
4
+ require_relative "impl_helper/math"
5
+ require_relative "impl_helper/basic_geometry_methods"
6
+ require_relative "impl_helper/basic_geometry_collection_methods"
7
+ require_relative "impl_helper/basic_point_methods"
8
+ require_relative "impl_helper/basic_line_string_methods"
9
+ require_relative "impl_helper/basic_polygon_methods"
@@ -114,6 +114,12 @@ module RGeo
114
114
  @elements.map(&:coordinates)
115
115
  end
116
116
 
117
+ def contains?(rhs)
118
+ return super unless Feature::Point === rhs
119
+
120
+ @elements.any? { |line| line.contains?(rhs) }
121
+ end
122
+
117
123
  private
118
124
 
119
125
  def add_boundary(hash, point)
@@ -171,12 +177,18 @@ module RGeo
171
177
  array << poly.exterior_ring unless poly.is_empty?
172
178
  array.concat(poly.interior_rings)
173
179
  end
174
- factory.multilinestring(array)
180
+ factory.multi_line_string(array)
175
181
  end
176
182
 
177
183
  def coordinates
178
184
  @elements.map(&:coordinates)
179
185
  end
186
+
187
+ def contains?(rhs)
188
+ return super unless Feature::Point === rhs
189
+
190
+ @elements.any? { |poly| poly.contains?(rhs) }
191
+ end
180
192
  end
181
193
  end
182
194
  end
@@ -87,8 +87,43 @@ module RGeo
87
87
  @points.map(&:coordinates)
88
88
  end
89
89
 
90
+ def contains?(rhs)
91
+ if Feature::Point === rhs
92
+ contains_point?(rhs)
93
+ else
94
+ raise(Error::UnsupportedOperation,
95
+ "Method LineString#contains? is only defined for Point")
96
+ end
97
+ end
98
+
90
99
  private
91
100
 
101
+ def contains_point?(point)
102
+ @points.each_cons(2) do |start_point, end_point|
103
+ return true if point_intersect_segment?(point, start_point, end_point)
104
+ end
105
+ false
106
+ end
107
+
108
+ def point_intersect_segment?(point, start_point, end_point)
109
+ return false unless point_collinear?(point, start_point, end_point)
110
+
111
+ if start_point.x != end_point.x
112
+ between_coordinate?(point.x, start_point.x, end_point.x)
113
+ else
114
+ between_coordinate?(point.y, start_point.y, end_point.y)
115
+ end
116
+ end
117
+
118
+ def point_collinear?(a, b, c)
119
+ (b.x - a.x) * (c.y - a.y) == (c.x - a.x) * (b.y - a.y)
120
+ end
121
+
122
+ def between_coordinate?(coord, start_coord, end_coord)
123
+ end_coord >= coord && coord >= start_coord ||
124
+ start_coord >= coord && coord >= end_coord
125
+ end
126
+
92
127
  def copy_state_from(obj)
93
128
  super
94
129
  @points = obj.points
@@ -137,6 +172,10 @@ module RGeo
137
172
  Feature::LinearRing
138
173
  end
139
174
 
175
+ def ccw?
176
+ RGeo::Cartesian::Analysis.ccw?(self)
177
+ end
178
+
140
179
  private
141
180
 
142
181
  def validate_geometry
@@ -79,8 +79,45 @@ module RGeo
79
79
  ([@exterior_ring] + @interior_rings).map(&:coordinates)
80
80
  end
81
81
 
82
+ def contains?(rhs)
83
+ if Feature::Point === rhs
84
+ contains_point?(rhs)
85
+ else
86
+ raise(Error::UnsupportedOperation,
87
+ "Method Polygon#contains? is only defined for Point"
88
+ )
89
+ end
90
+ end
91
+
82
92
  private
83
93
 
94
+ def contains_point?(point)
95
+ ring_encloses_point?(@exterior_ring, point) &&
96
+ !@interior_rings.any? do |exclusion|
97
+ ring_encloses_point?(exclusion, point, on_border_return: true)
98
+ end
99
+ end
100
+
101
+ def ring_encloses_point?(ring, point, on_border_return: false)
102
+ # This is an implementation of the ray casting algorithm, greatly inspired
103
+ # by https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html
104
+ # Since this algorithm does not handle point on edge, we check first if
105
+ # the ring is on the border.
106
+ # on_border_return is used for exclusion ring
107
+ return on_border_return if ring.contains?(point)
108
+ encloses_point = false
109
+ ring.points.each_cons(2) do |start_point, end_point|
110
+ next unless (point.y < end_point.y) != (point.y < start_point.y)
111
+
112
+ if point.x < (end_point.x - start_point.x) * (point.y - start_point.y) /
113
+ (end_point.y - start_point.y) + start_point.x
114
+ encloses_point = !encloses_point
115
+ end
116
+ end
117
+ encloses_point
118
+ end
119
+
120
+
84
121
  def copy_state_from(obj)
85
122
  super
86
123
  @exterior_ring = obj.exterior_ring
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RGeo
4
- VERSION = "2.1.1"
4
+ VERSION = "2.2.0"
5
5
  end
@@ -21,7 +21,7 @@
21
21
  # To parse a byte string in WKB (well-known binary) format back into a
22
22
  # geometry object, use the WKRep::WKBParser class.
23
23
 
24
- require "rgeo/wkrep/wkt_parser"
25
- require "rgeo/wkrep/wkt_generator"
26
- require "rgeo/wkrep/wkb_parser"
27
- require "rgeo/wkrep/wkb_generator"
24
+ require_relative "wkrep/wkt_parser"
25
+ require_relative "wkrep/wkt_generator"
26
+ require_relative "wkrep/wkb_parser"
27
+ require_relative "wkrep/wkb_generator"
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgeo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Daniel Azuma, Tee Parham
7
+ - Daniel Azuma
8
+ - Tee Parham
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2019-08-26 00:00:00.000000000 Z
12
+ date: 2020-11-19 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: ffi-geos
@@ -85,15 +86,23 @@ description: RGeo is a geospatial data library for Ruby. It provides an implemen
85
86
  standard spatial/geographic data storage systems such as PostGIS. A number of add-on
86
87
  modules are also available to help with writing location-based applications using
87
88
  Ruby-based frameworks such as Ruby On Rails.
88
- email: dazuma@gmail.com, parhameter@gmail.com
89
+ email:
90
+ - dazuma@gmail.com
91
+ - parhameter@gmail.com
92
+ - kfdoggett@gmail.com
89
93
  executables: []
90
94
  extensions:
91
95
  - ext/geos_c_impl/extconf.rb
92
96
  extra_rdoc_files: []
93
97
  files:
94
98
  - LICENSE.txt
99
+ - README.md
100
+ - ext/geos_c_impl/analysis.c
101
+ - ext/geos_c_impl/analysis.h
95
102
  - ext/geos_c_impl/coordinates.c
96
103
  - ext/geos_c_impl/coordinates.h
104
+ - ext/geos_c_impl/errors.c
105
+ - ext/geos_c_impl/errors.h
97
106
  - ext/geos_c_impl/extconf.rb
98
107
  - ext/geos_c_impl/factory.c
99
108
  - ext/geos_c_impl/factory.h
@@ -181,7 +190,8 @@ files:
181
190
  - lib/rgeo/wkrep/wkt_generator.rb
182
191
  - lib/rgeo/wkrep/wkt_parser.rb
183
192
  homepage: https://github.com/rgeo/rgeo
184
- licenses: []
193
+ licenses:
194
+ - BSD-3-Clause
185
195
  metadata: {}
186
196
  post_install_message:
187
197
  rdoc_options: []
@@ -191,14 +201,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
201
  requirements:
192
202
  - - ">="
193
203
  - !ruby/object:Gem::Version
194
- version: 2.3.0
204
+ version: 2.4.0
195
205
  required_rubygems_version: !ruby/object:Gem::Requirement
196
206
  requirements:
197
207
  - - ">="
198
208
  - !ruby/object:Gem::Version
199
209
  version: '0'
200
210
  requirements: []
201
- rubygems_version: 3.0.6
211
+ rubygems_version: 3.0.3
202
212
  signing_key:
203
213
  specification_version: 4
204
214
  summary: RGeo is a geospatial data library for Ruby.