rgeo 2.1.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +160 -0
  3. data/ext/geos_c_impl/analysis.c +78 -0
  4. data/ext/geos_c_impl/analysis.h +42 -0
  5. data/ext/geos_c_impl/errors.c +35 -0
  6. data/ext/geos_c_impl/errors.h +22 -0
  7. data/ext/geos_c_impl/extconf.rb +1 -0
  8. data/ext/geos_c_impl/factory.c +15 -7
  9. data/ext/geos_c_impl/factory.h +5 -1
  10. data/ext/geos_c_impl/geometry.c +9 -8
  11. data/ext/geos_c_impl/geometry_collection.c +1 -1
  12. data/ext/geos_c_impl/line_string.c +2 -2
  13. data/ext/geos_c_impl/main.c +5 -2
  14. data/ext/geos_c_impl/preface.h +3 -0
  15. data/lib/rgeo/cartesian/analysis.rb +22 -0
  16. data/lib/rgeo/cartesian/feature_methods.rb +6 -1
  17. data/lib/rgeo/cartesian.rb +7 -7
  18. data/lib/rgeo/coord_sys.rb +6 -6
  19. data/lib/rgeo/error.rb +4 -0
  20. data/lib/rgeo/feature/curve.rb +12 -2
  21. data/lib/rgeo/feature/geometry.rb +12 -2
  22. data/lib/rgeo/feature/linear_ring.rb +10 -0
  23. data/lib/rgeo/feature/multi_curve.rb +6 -1
  24. data/lib/rgeo/feature.rb +17 -17
  25. data/lib/rgeo/geographic/interface.rb +2 -1
  26. data/lib/rgeo/geographic/projected_feature_methods.rb +12 -2
  27. data/lib/rgeo/geographic/spherical_feature_classes.rb +1 -0
  28. data/lib/rgeo/geographic/spherical_feature_methods.rb +29 -1
  29. data/lib/rgeo/geographic.rb +10 -10
  30. data/lib/rgeo/geos/capi_factory.rb +5 -1
  31. data/lib/rgeo/geos/capi_feature_classes.rb +33 -0
  32. data/lib/rgeo/geos/ffi_feature_methods.rb +34 -5
  33. data/lib/rgeo/geos/interface.rb +18 -4
  34. data/lib/rgeo/geos/zm_feature_methods.rb +30 -5
  35. data/lib/rgeo/geos.rb +11 -11
  36. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +33 -5
  37. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +62 -8
  38. data/lib/rgeo/impl_helper/basic_point_methods.rb +12 -2
  39. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +45 -3
  40. data/lib/rgeo/impl_helper.rb +7 -7
  41. data/lib/rgeo/version.rb +1 -1
  42. data/lib/rgeo/wkrep/wkb_generator.rb +1 -1
  43. data/lib/rgeo/wkrep/wkt_generator.rb +6 -6
  44. data/lib/rgeo/wkrep.rb +4 -4
  45. data/lib/rgeo.rb +9 -9
  46. metadata +21 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2430c81b8d65c3e98a0e4411c4b10d5b71e6eb1d90ae59bffeab5f71c2da2cb3
4
- data.tar.gz: 55aca2dc0b4f7b08641d54b40d8248e594a58574c13690e092dcd8718a392c1c
3
+ metadata.gz: b93de3431a81612631cfa612d589bc0e1026f16276d3c1e848b71f1a3e682731
4
+ data.tar.gz: 992a46705454a1fe1c77405e9b6f753739af0c80b9e6f58d8e60da07b75eea93
5
5
  SHA512:
6
- metadata.gz: 70f91cfbacb9c87fc6aa974eeeb3863452ebe3a041544249e8a9824864352f9f1f32525c6c952a37091b4f632b29269e9249a57098533c9a971c4d79c6406e29
7
- data.tar.gz: 708edf08257aa5f3215aeb43fbcfe3aa36afe1950974b9a1120805d0512b6cd2edeaf334baf44f486cbf766cd1faa44b52d084e1ae415dae5d0f5e6014cd5e04
6
+ metadata.gz: aca5ecae4e1c3ee2d022591ccf612aae3e4f8539543cc740ba3875b15ae156da6e1e13180a305e0c2a41a9bcf3a60e3eafb5c87eb737f95ef194e08fe66c39f9
7
+ data.tar.gz: 94ae519f52c0a6deada3e560722256e99fc482528be8ceea67496cf0dbc7488da9bf643ab2905a28294aaa68ac3f532e913c3afb7fea2877b438ecf282911153
data/README.md ADDED
@@ -0,0 +1,160 @@
1
+ ## RGeo
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rgeo.svg)](http://badge.fury.io/rb/rgeo)
4
+ [![CI](https://github.com/rgeo/rgeo/workflows/CI/badge.svg)](https://github.com/rgeo/rgeo/actions?query=workflow%3ACI+branch%3Amaster+event%3Apush)
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
+ ### Documentation
119
+
120
+ You can see more in-depth documentation in the `doc` folder. Factories and
121
+ methods are documented inline, you should consider checking
122
+ https://rubydoc.info/gems/rgeo with the version you are currently using. Or
123
+ generate documentation locally if you're working on RGeo: `yardoc server`.
124
+
125
+ Here's the current list of available topics:
126
+
127
+ - [An introduction to Spatial Programming With RGeo](https://github.com/rgeo/rgeo/blob/master/doc/An-Introduction-to-Spatial-Programming-With-RGeo.md)
128
+ - [Enable GEOS and Proj4 on Heroku](https://github.com/rgeo/rgeo/blob/master/doc/Enable-GEOS-and-Proj4-on-Heroku.md)
129
+ - [Installing GEOS](https://github.com/rgeo/rgeo/blob/master/doc/Installing-GEOS.md)
130
+ - [Factory Compatibility](https://github.com/rgeo/rgeo/blob/master/doc/Factory-Compatibility.md)
131
+ - [Which factory should I use?](https://github.com/rgeo/rgeo/blob/master/doc/Which-factory-should-I-use.md)
132
+ - [Examples](https://github.com/rgeo/rgeo/blob/master/doc/Examples.md)
133
+ - [Who uses `rgeo`?](https://github.com/rgeo/rgeo/blob/master/doc/Gallery.md)
134
+
135
+ You can see an exhaustive and up to date list at https://rubydoc.info/gems/rgeo/index.
136
+ ### Acknowledgments
137
+
138
+ [Daniel Azuma](http://www.daniel-azuma.com) created RGeo.
139
+ [Tee Parham](http://twitter.com/teeparham) is a former maintainer.
140
+ [Keith Doggett](http://www.github.com/keithdoggett), [Ulysse Buonomo](http://www.github.com/BuonOmo) are current maintainers.
141
+
142
+ Development is supported by:
143
+
144
+ - [Klaxit](https://www.github.com/klaxit)
145
+ - Goldfish Ads
146
+
147
+ RGeo calls the GEOS library to handle most Cartesian geometric calculations,
148
+ and the Proj4 library to handle projections and coordinate transformations.
149
+ These libraries are maintained by the Open Source Geospatial Foundation; more
150
+ information is available on [OSGeo's web site](http://www.osgeo.org).
151
+
152
+ JRuby support is made possible by the ffi-geos (and upcoming ffi-proj4) gems,
153
+ by [J Smith](https://github.com/dark-panda).
154
+
155
+
156
+ ### License
157
+
158
+ Copyright (c) Daniel Azuma, Tee Parham
159
+
160
+ [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");
@@ -771,7 +773,6 @@ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VAL
771
773
  const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type)
772
774
  {
773
775
  VALUE object;
774
- const GEOSGeometry* geom;
775
776
  RGeo_Globals* globals;
776
777
 
777
778
  if (NIL_P(type) && TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func && RGEO_GEOMETRY_DATA_PTR(obj)->factory == factory) {
@@ -781,11 +782,11 @@ const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALU
781
782
  globals = RGEO_FACTORY_DATA_PTR(factory)->globals;
782
783
  object = rb_funcall(globals->feature_module, globals->id_cast, 3, obj, factory, type);
783
784
  }
784
- geom = NULL;
785
- if (!NIL_P(object)) {
786
- geom = RGEO_GEOMETRY_DATA_PTR(object)->geom;
787
- }
788
- return geom;
785
+ if (NIL_P(object))
786
+ return NULL;
787
+
788
+ Check_Type(object, T_DATA);
789
+ return RGEO_GEOMETRY_DATA_PTR(object)->geom;
789
790
  }
790
791
 
791
792
 
@@ -831,6 +832,13 @@ char rgeo_is_geos_object(VALUE obj)
831
832
  return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? 1 : 0;
832
833
  }
833
834
 
835
+ void rgeo_check_geos_object(VALUE obj)
836
+ {
837
+ if (!rgeo_is_geos_object(obj)) {
838
+ rb_raise(rgeo_error, "Not a GEOS Geometry object.");
839
+ }
840
+ }
841
+
834
842
 
835
843
  const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj)
836
844
  {
@@ -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.
@@ -1045,12 +1045,13 @@ static VALUE method_geometry_invalid_reason(VALUE self)
1045
1045
  self_geom = self_data->geom;
1046
1046
  if (self_geom) {
1047
1047
  str = GEOSisValidReason_r(self_data->geos_context, self_geom);
1048
- if (str) {
1049
- result = rb_str_new2(str);
1050
- }
1051
- else {
1052
- result = rb_str_new2("Exception");
1053
- }
1048
+ // Per documentation, a valid geometry should give an empty string.
1049
+ // However it seems not to be the case. Hence the comparison against
1050
+ // the string that is really given: `"Valid Geometry"`.
1051
+ // See https://github.com/libgeos/geos/issues/431.
1052
+ if (str) result = (str[0] == '\0' || !strcmp(str, "Valid Geometry")) ? Qnil : rb_str_new2(str);
1053
+ else result = rb_str_new2("Exception");
1054
+ GEOSFree_r(self_data->geos_context, str);
1054
1055
  }
1055
1056
  return result;
1056
1057
  }
@@ -1094,8 +1095,8 @@ void rgeo_init_geos_geometry(RGeo_Globals* globals)
1094
1095
  rb_define_method(geos_geometry_methods, "boundary", method_geometry_boundary, 0);
1095
1096
  rb_define_method(geos_geometry_methods, "_as_text", method_geometry_as_text, 0);
1096
1097
  rb_define_method(geos_geometry_methods, "as_binary", method_geometry_as_binary, 0);
1097
- rb_define_method(geos_geometry_methods, "is_empty?", method_geometry_is_empty, 0);
1098
- rb_define_method(geos_geometry_methods, "is_simple?", method_geometry_is_simple, 0);
1098
+ rb_define_method(geos_geometry_methods, "empty?", method_geometry_is_empty, 0);
1099
+ rb_define_method(geos_geometry_methods, "simple?", method_geometry_is_simple, 0);
1099
1100
  rb_define_method(geos_geometry_methods, "equals?", method_geometry_equals, 1);
1100
1101
  rb_define_method(geos_geometry_methods, "==", method_geometry_equals, 1);
1101
1102
  rb_define_method(geos_geometry_methods, "rep_equals?", method_geometry_eql, 1);
@@ -623,7 +623,7 @@ void rgeo_init_geos_geometry_collection(RGeo_Globals* globals)
623
623
  geos_multi_line_string_methods = rb_define_module_under(globals->geos_module, "CAPIMultiLineStringMethods");
624
624
  rb_define_method(geos_multi_line_string_methods, "geometry_type", method_multi_line_string_geometry_type, 0);
625
625
  rb_define_method(geos_multi_line_string_methods, "length", method_multi_line_string_length, 0);
626
- rb_define_method(geos_multi_line_string_methods, "is_closed?", method_multi_line_string_is_closed, 0);
626
+ rb_define_method(geos_multi_line_string_methods, "closed?", method_multi_line_string_is_closed, 0);
627
627
  rb_define_method(geos_multi_line_string_methods, "hash", method_multi_line_string_hash, 0);
628
628
  rb_define_method(geos_multi_line_string_methods, "coordinates", method_multi_line_string_coordinates, 0);
629
629
 
@@ -663,8 +663,8 @@ void rgeo_init_geos_line_string(RGeo_Globals* globals)
663
663
  rb_define_method(geos_line_string_methods, "end_point", method_line_string_end_point, 0);
664
664
  rb_define_method(geos_line_string_methods, "project_point", method_line_string_project_point, 1);
665
665
  rb_define_method(geos_line_string_methods, "interpolate_point", method_line_string_interpolate_point, 1);
666
- rb_define_method(geos_line_string_methods, "is_closed?", method_line_string_is_closed, 0);
667
- rb_define_method(geos_line_string_methods, "is_ring?", method_line_string_is_ring, 0);
666
+ rb_define_method(geos_line_string_methods, "closed?", method_line_string_is_closed, 0);
667
+ rb_define_method(geos_line_string_methods, "ring?", method_line_string_is_ring, 0);
668
668
  rb_define_method(geos_line_string_methods, "coordinates", method_line_string_coordinates, 0);
669
669
 
670
670
  // CAPILinearRingMethods module
@@ -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
@@ -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 `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.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.
@@ -49,7 +49,7 @@ module RGeo
49
49
  end
50
50
  end
51
51
 
52
- def is_simple?
52
+ def simple?
53
53
  len = segments.length
54
54
  return false if segments.any?(&:degenerate?)
55
55
  return true if len == 1
@@ -72,6 +72,11 @@ module RGeo
72
72
  true
73
73
  end
74
74
 
75
+ def is_simple?
76
+ warn "The is_simple? method is deprecated, please use the simple? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
77
+ simple?
78
+ end
79
+
75
80
  def length
76
81
  segments.inject(0.0) { |sum, seg| sum + seg.length }
77
82
  end
@@ -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"
@@ -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
data/lib/rgeo/error.rb CHANGED
@@ -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