rgeo 2.3.0 → 3.0.0.pre.rc.1
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 +4 -4
- data/.yardopts +6 -0
- data/README.md +1 -0
- data/ext/geos_c_impl/analysis.c +8 -6
- data/ext/geos_c_impl/analysis.h +1 -3
- data/ext/geos_c_impl/errors.c +10 -8
- data/ext/geos_c_impl/errors.h +7 -3
- data/ext/geos_c_impl/extconf.rb +3 -0
- data/ext/geos_c_impl/factory.c +251 -182
- data/ext/geos_c_impl/factory.h +43 -62
- data/ext/geos_c_impl/geometry.c +56 -24
- data/ext/geos_c_impl/geometry.h +8 -3
- data/ext/geos_c_impl/geometry_collection.c +41 -148
- data/ext/geos_c_impl/geometry_collection.h +1 -14
- data/ext/geos_c_impl/globals.c +91 -0
- data/ext/geos_c_impl/globals.h +45 -0
- data/ext/geos_c_impl/line_string.c +28 -29
- data/ext/geos_c_impl/line_string.h +1 -3
- data/ext/geos_c_impl/main.c +10 -9
- data/ext/geos_c_impl/point.c +9 -8
- data/ext/geos_c_impl/point.h +1 -3
- data/ext/geos_c_impl/polygon.c +15 -51
- data/ext/geos_c_impl/polygon.h +1 -3
- data/ext/geos_c_impl/preface.h +8 -0
- data/lib/rgeo/cartesian/analysis.rb +2 -2
- data/lib/rgeo/cartesian/calculations.rb +54 -17
- data/lib/rgeo/cartesian/factory.rb +0 -7
- data/lib/rgeo/cartesian/feature_classes.rb +66 -46
- data/lib/rgeo/cartesian/feature_methods.rb +56 -20
- data/lib/rgeo/cartesian/interface.rb +0 -6
- data/lib/rgeo/cartesian/planar_graph.rb +379 -0
- data/lib/rgeo/cartesian/sweepline_intersector.rb +149 -0
- data/lib/rgeo/cartesian/valid_op.rb +71 -0
- data/lib/rgeo/cartesian.rb +3 -0
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +6 -6
- data/lib/rgeo/error.rb +15 -0
- data/lib/rgeo/feature/curve.rb +12 -2
- data/lib/rgeo/feature/geometry.rb +38 -28
- data/lib/rgeo/feature/geometry_collection.rb +13 -5
- data/lib/rgeo/feature/line_string.rb +3 -3
- data/lib/rgeo/feature/multi_curve.rb +6 -1
- data/lib/rgeo/feature/multi_surface.rb +3 -3
- data/lib/rgeo/feature/point.rb +4 -4
- data/lib/rgeo/feature/surface.rb +3 -3
- data/lib/rgeo/geographic/factory.rb +0 -7
- data/lib/rgeo/geographic/interface.rb +4 -18
- data/lib/rgeo/geographic/proj4_projector.rb +0 -2
- data/lib/rgeo/geographic/projected_feature_classes.rb +21 -9
- data/lib/rgeo/geographic/projected_feature_methods.rb +63 -30
- data/lib/rgeo/geographic/simple_mercator_projector.rb +0 -2
- data/lib/rgeo/geographic/spherical_feature_classes.rb +29 -9
- data/lib/rgeo/geographic/spherical_feature_methods.rb +68 -2
- data/lib/rgeo/geos/capi_factory.rb +21 -31
- data/lib/rgeo/geos/capi_feature_classes.rb +64 -11
- data/lib/rgeo/geos/ffi_factory.rb +0 -28
- data/lib/rgeo/geos/ffi_feature_classes.rb +34 -10
- data/lib/rgeo/geos/ffi_feature_methods.rb +53 -10
- data/lib/rgeo/geos/interface.rb +18 -10
- data/lib/rgeo/geos/zm_factory.rb +0 -12
- data/lib/rgeo/geos/zm_feature_methods.rb +30 -5
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +18 -8
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -1
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +37 -26
- data/lib/rgeo/impl_helper/basic_point_methods.rb +13 -3
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +8 -3
- data/lib/rgeo/impl_helper/valid_op.rb +354 -0
- data/lib/rgeo/impl_helper/validity_check.rb +138 -0
- data/lib/rgeo/impl_helper.rb +1 -0
- data/lib/rgeo/version.rb +1 -1
- data/lib/rgeo/wkrep/wkb_generator.rb +1 -1
- data/lib/rgeo/wkrep/wkt_generator.rb +6 -6
- metadata +30 -7
data/ext/geos_c_impl/factory.c
CHANGED
@@ -9,6 +9,11 @@
|
|
9
9
|
|
10
10
|
#include <ruby.h>
|
11
11
|
#include <geos_c.h>
|
12
|
+
#include <ctype.h>
|
13
|
+
#include <stdarg.h>
|
14
|
+
#include <stdio.h>
|
15
|
+
|
16
|
+
#include "globals.h"
|
12
17
|
|
13
18
|
#include "factory.h"
|
14
19
|
#include "geometry.h"
|
@@ -24,94 +29,138 @@ RGEO_BEGIN_C
|
|
24
29
|
/**** RUBY AND GEOS CALLBACKS ****/
|
25
30
|
|
26
31
|
|
27
|
-
//
|
28
|
-
// for
|
29
|
-
|
30
|
-
|
32
|
+
// The notice handler is very rarely used by GEOS, only in
|
33
|
+
// GEOSIsValid_r (check for NOTICE_MESSAGE in GEOS codebase).
|
34
|
+
// We still set it to make sure we do not miss any implementation
|
35
|
+
// change. Use `DEBUG=1 rake` to show notice.
|
36
|
+
#ifdef RGEO_GEOS_DEBUG
|
37
|
+
static void notice_handler(const char* fmt, ...)
|
31
38
|
{
|
39
|
+
va_list args;
|
40
|
+
va_start(args, fmt);
|
41
|
+
fprintf(stderr, "GEOS Notice -- ");
|
42
|
+
vfprintf(stderr, fmt, args);
|
43
|
+
fprintf(stderr, "\n");
|
44
|
+
va_end(args);
|
32
45
|
}
|
46
|
+
#endif
|
33
47
|
|
48
|
+
static void error_handler(const char* fmt, ...)
|
49
|
+
{
|
50
|
+
// See https://en.cppreference.com/w/c/io/vfprintf
|
51
|
+
va_list args1;
|
52
|
+
va_start(args1, fmt);
|
53
|
+
va_list args2;
|
54
|
+
va_copy(args2, args1);
|
55
|
+
int size = 1+vsnprintf(NULL, 0, fmt, args1);
|
56
|
+
va_end(args1);
|
57
|
+
char geos_full_error[size];
|
58
|
+
vsnprintf(geos_full_error, sizeof geos_full_error, fmt, args2);
|
59
|
+
va_end(args2);
|
60
|
+
|
61
|
+
// NOTE: strtok is destructive, geos_full_error is not to be used afterwards.
|
62
|
+
char *geos_error = strtok(geos_full_error, ":");
|
63
|
+
char *geos_message = strtok(NULL, ":");
|
64
|
+
while(isspace(*geos_message)) geos_message++;
|
65
|
+
|
66
|
+
if (streq(geos_error, "UnsupportedOperationException")) {
|
67
|
+
rb_raise(rb_eRGeoUnsupportedOperation, "%s", geos_message);
|
68
|
+
} else if (streq(geos_error, "IllegalArgumentException")) {
|
69
|
+
rb_raise(rb_eRGeoInvalidGeometry, "%s", geos_message);
|
70
|
+
} else if (geos_message) {
|
71
|
+
rb_raise(rb_eGeosError, "%s: %s", geos_error, geos_message);
|
72
|
+
} else {
|
73
|
+
rb_raise(rb_eGeosError, "%s", geos_error);
|
74
|
+
}
|
75
|
+
}
|
34
76
|
|
35
77
|
// Destroy function for factory data. We destroy any serialization
|
36
78
|
// objects that have been created for the factory, and then destroy
|
37
79
|
// the GEOS context, before freeing the factory data itself.
|
38
80
|
|
39
|
-
static void destroy_factory_func(
|
81
|
+
static void destroy_factory_func(void* data)
|
40
82
|
{
|
83
|
+
RGeo_FactoryData* factory_data;
|
41
84
|
GEOSContextHandle_t context;
|
42
85
|
|
43
|
-
|
44
|
-
|
45
|
-
|
86
|
+
factory_data = (RGeo_FactoryData*)data;
|
87
|
+
context = factory_data->geos_context;
|
88
|
+
if (factory_data->wkt_reader) {
|
89
|
+
GEOSWKTReader_destroy_r(context, factory_data->wkt_reader);
|
46
90
|
}
|
47
|
-
if (
|
48
|
-
GEOSWKBReader_destroy_r(context,
|
91
|
+
if (factory_data->wkb_reader) {
|
92
|
+
GEOSWKBReader_destroy_r(context, factory_data->wkb_reader);
|
49
93
|
}
|
50
|
-
if (
|
51
|
-
GEOSWKTWriter_destroy_r(context,
|
94
|
+
if (factory_data->wkt_writer) {
|
95
|
+
GEOSWKTWriter_destroy_r(context, factory_data->wkt_writer);
|
52
96
|
}
|
53
|
-
if (
|
54
|
-
GEOSWKBWriter_destroy_r(context,
|
97
|
+
if (factory_data->wkb_writer) {
|
98
|
+
GEOSWKBWriter_destroy_r(context, factory_data->wkb_writer);
|
55
99
|
}
|
56
|
-
if (
|
57
|
-
GEOSWKTReader_destroy_r(context,
|
100
|
+
if (factory_data->psych_wkt_reader) {
|
101
|
+
GEOSWKTReader_destroy_r(context, factory_data->psych_wkt_reader);
|
58
102
|
}
|
59
|
-
if (
|
60
|
-
GEOSWKBReader_destroy_r(context,
|
103
|
+
if (factory_data->marshal_wkb_reader) {
|
104
|
+
GEOSWKBReader_destroy_r(context, factory_data->marshal_wkb_reader);
|
61
105
|
}
|
62
|
-
if (
|
63
|
-
GEOSWKTWriter_destroy_r(context,
|
106
|
+
if (factory_data->psych_wkt_writer) {
|
107
|
+
GEOSWKTWriter_destroy_r(context, factory_data->psych_wkt_writer);
|
64
108
|
}
|
65
|
-
if (
|
66
|
-
GEOSWKBWriter_destroy_r(context,
|
109
|
+
if (factory_data->marshal_wkb_writer) {
|
110
|
+
GEOSWKBWriter_destroy_r(context, factory_data->marshal_wkb_writer);
|
67
111
|
}
|
68
112
|
finishGEOS_r(context);
|
69
|
-
free(
|
113
|
+
free(factory_data);
|
70
114
|
}
|
71
115
|
|
72
116
|
|
73
117
|
// Destroy function for geometry data. We destroy the internal
|
74
118
|
// GEOS geometry (if present) before freeing the data itself.
|
75
119
|
|
76
|
-
static void destroy_geometry_func(
|
120
|
+
static void destroy_geometry_func(void* data)
|
77
121
|
{
|
122
|
+
RGeo_GeometryData* geometry_data;
|
78
123
|
const GEOSPreparedGeometry* prep;
|
79
124
|
|
80
|
-
|
81
|
-
|
125
|
+
geometry_data = (RGeo_GeometryData*)data;
|
126
|
+
if (geometry_data->geom) {
|
127
|
+
GEOSGeom_destroy_r(geometry_data->geos_context, geometry_data->geom);
|
82
128
|
}
|
83
|
-
prep =
|
129
|
+
prep = geometry_data->prep;
|
84
130
|
if (prep && prep != (const GEOSPreparedGeometry*)1 && prep != (const GEOSPreparedGeometry*)2 &&
|
85
131
|
prep != (const GEOSPreparedGeometry*)3)
|
86
132
|
{
|
87
|
-
GEOSPreparedGeom_destroy_r(
|
133
|
+
GEOSPreparedGeom_destroy_r(geometry_data->geos_context, prep);
|
88
134
|
}
|
89
|
-
free(
|
135
|
+
free(geometry_data);
|
90
136
|
}
|
91
137
|
|
92
138
|
|
93
139
|
// Mark function for factory data. This marks the wkt and wkb generator
|
94
140
|
// handles so they don't get collected.
|
95
141
|
|
96
|
-
static void mark_factory_func(
|
142
|
+
static void mark_factory_func(void* data)
|
97
143
|
{
|
98
|
-
|
99
|
-
|
144
|
+
RGeo_FactoryData* factory_data;
|
145
|
+
|
146
|
+
factory_data = (RGeo_FactoryData*)data;
|
147
|
+
if (!NIL_P(factory_data->wkrep_wkt_generator)) {
|
148
|
+
mark(factory_data->wkrep_wkt_generator);
|
100
149
|
}
|
101
|
-
if (!NIL_P(
|
102
|
-
|
150
|
+
if (!NIL_P(factory_data->wkrep_wkb_generator)) {
|
151
|
+
mark(factory_data->wkrep_wkb_generator);
|
103
152
|
}
|
104
|
-
if (!NIL_P(
|
105
|
-
|
153
|
+
if (!NIL_P(factory_data->wkrep_wkt_parser)) {
|
154
|
+
mark(factory_data->wkrep_wkt_parser);
|
106
155
|
}
|
107
|
-
if (!NIL_P(
|
108
|
-
|
156
|
+
if (!NIL_P(factory_data->wkrep_wkb_parser)) {
|
157
|
+
mark(factory_data->wkrep_wkb_parser);
|
109
158
|
}
|
110
|
-
if (!NIL_P(
|
111
|
-
|
159
|
+
if (!NIL_P(factory_data->proj4_obj)) {
|
160
|
+
mark(factory_data->proj4_obj);
|
112
161
|
}
|
113
|
-
if (!NIL_P(
|
114
|
-
|
162
|
+
if (!NIL_P(factory_data->coord_sys_obj)) {
|
163
|
+
mark(factory_data->coord_sys_obj);
|
115
164
|
}
|
116
165
|
}
|
117
166
|
|
@@ -119,32 +168,83 @@ static void mark_factory_func(RGeo_FactoryData* data)
|
|
119
168
|
// Mark function for geometry data. This marks the factory and klasses
|
120
169
|
// held by the geometry so those don't get collected.
|
121
170
|
|
122
|
-
static void mark_geometry_func(
|
171
|
+
static void mark_geometry_func(void* data)
|
123
172
|
{
|
124
|
-
|
125
|
-
|
173
|
+
RGeo_GeometryData* geometry_data;
|
174
|
+
|
175
|
+
geometry_data = (RGeo_GeometryData*)data;
|
176
|
+
if (!NIL_P(geometry_data->factory)) {
|
177
|
+
mark(geometry_data->factory);
|
126
178
|
}
|
127
|
-
if (!NIL_P(
|
128
|
-
|
179
|
+
if (!NIL_P(geometry_data->klasses)) {
|
180
|
+
mark(geometry_data->klasses);
|
129
181
|
}
|
130
182
|
}
|
131
183
|
|
132
184
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
static void destroy_globals_func(RGeo_Globals* data)
|
185
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
186
|
+
static void compact_factory_func(void* data)
|
137
187
|
{
|
138
|
-
|
139
|
-
}
|
188
|
+
RGeo_FactoryData* factory_data;
|
140
189
|
|
190
|
+
factory_data = (RGeo_FactoryData*)data;
|
191
|
+
if (!NIL_P(factory_data->wkrep_wkt_generator)) {
|
192
|
+
factory_data->wkrep_wkt_generator = rb_gc_location(factory_data->wkrep_wkt_generator);
|
193
|
+
}
|
194
|
+
if (!NIL_P(factory_data->wkrep_wkb_generator)) {
|
195
|
+
factory_data->wkrep_wkb_generator = rb_gc_location(factory_data->wkrep_wkb_generator);
|
196
|
+
}
|
197
|
+
if (!NIL_P(factory_data->wkrep_wkt_parser)) {
|
198
|
+
factory_data->wkrep_wkt_parser = rb_gc_location(factory_data->wkrep_wkt_parser);
|
199
|
+
}
|
200
|
+
if (!NIL_P(factory_data->wkrep_wkb_parser)) {
|
201
|
+
factory_data->wkrep_wkb_parser = rb_gc_location(factory_data->wkrep_wkb_parser);
|
202
|
+
}
|
203
|
+
if (!NIL_P(factory_data->proj4_obj)) {
|
204
|
+
factory_data->proj4_obj = rb_gc_location(factory_data->proj4_obj);
|
205
|
+
}
|
206
|
+
if (!NIL_P(factory_data->coord_sys_obj)) {
|
207
|
+
factory_data->coord_sys_obj = rb_gc_location(factory_data->coord_sys_obj);
|
208
|
+
}
|
209
|
+
}
|
141
210
|
|
142
|
-
// Mark function for globals data. This should mark any globals that
|
143
|
-
// need to be held through garbage collection (none at the moment.)
|
144
211
|
|
145
|
-
static void
|
212
|
+
static void compact_geometry_func(void* data)
|
146
213
|
{
|
214
|
+
RGeo_GeometryData* geometry_data;
|
215
|
+
|
216
|
+
geometry_data = (RGeo_GeometryData*)data;
|
217
|
+
if (!NIL_P(geometry_data->factory)) {
|
218
|
+
geometry_data->factory = rb_gc_location(geometry_data->factory);
|
219
|
+
}
|
220
|
+
if (!NIL_P(geometry_data->klasses)) {
|
221
|
+
geometry_data->klasses = rb_gc_location(geometry_data->klasses);
|
222
|
+
}
|
147
223
|
}
|
224
|
+
#endif
|
225
|
+
|
226
|
+
|
227
|
+
const rb_data_type_t rgeo_factory_type = {
|
228
|
+
.wrap_struct_name = "RGeo/Factory",
|
229
|
+
.function = {
|
230
|
+
.dmark = mark_factory_func,
|
231
|
+
.dfree = destroy_factory_func,
|
232
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
233
|
+
.dcompact = compact_factory_func,
|
234
|
+
#endif
|
235
|
+
}
|
236
|
+
};
|
237
|
+
|
238
|
+
const rb_data_type_t rgeo_geometry_type = {
|
239
|
+
.wrap_struct_name = "RGeo/Geometry",
|
240
|
+
.function = {
|
241
|
+
.dmark = mark_geometry_func,
|
242
|
+
.dfree = destroy_geometry_func,
|
243
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
244
|
+
.dcompact = compact_geometry_func,
|
245
|
+
#endif
|
246
|
+
}
|
247
|
+
};
|
148
248
|
|
149
249
|
|
150
250
|
/**** RUBY METHOD DEFINITIONS ****/
|
@@ -167,6 +267,25 @@ static VALUE method_factory_flags(VALUE self)
|
|
167
267
|
return INT2NUM(RGEO_FACTORY_DATA_PTR(self)->flags);
|
168
268
|
}
|
169
269
|
|
270
|
+
VALUE method_factory_supports_z_p(VALUE self)
|
271
|
+
{
|
272
|
+
return RGEO_FACTORY_DATA_PTR(self)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z ? Qtrue : Qfalse;
|
273
|
+
}
|
274
|
+
|
275
|
+
VALUE method_factory_supports_m_p(VALUE self)
|
276
|
+
{
|
277
|
+
return RGEO_FACTORY_DATA_PTR(self)->flags & RGEO_FACTORYFLAGS_SUPPORTS_M ? Qtrue : Qfalse;
|
278
|
+
}
|
279
|
+
|
280
|
+
VALUE method_factory_supports_z_or_m_p(VALUE self)
|
281
|
+
{
|
282
|
+
return RGEO_FACTORY_DATA_PTR(self)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M ? Qtrue : Qfalse;
|
283
|
+
}
|
284
|
+
|
285
|
+
VALUE method_factory_prepare_heuristic_p(VALUE self)
|
286
|
+
{
|
287
|
+
return RGEO_FACTORY_DATA_PTR(self)->flags & RGEO_FACTORYFLAGS_PREPARE_HEURISTIC ? Qtrue : Qfalse;
|
288
|
+
}
|
170
289
|
|
171
290
|
static VALUE method_factory_parse_wkt(VALUE self, VALUE str)
|
172
291
|
{
|
@@ -248,7 +367,6 @@ static VALUE method_factory_read_for_marshal(VALUE self, VALUE str)
|
|
248
367
|
return result;
|
249
368
|
}
|
250
369
|
|
251
|
-
|
252
370
|
static VALUE method_factory_read_for_psych(VALUE self, VALUE str)
|
253
371
|
{
|
254
372
|
RGeo_FactoryData* self_data;
|
@@ -275,6 +393,9 @@ static VALUE method_factory_read_for_psych(VALUE self, VALUE str)
|
|
275
393
|
return result;
|
276
394
|
}
|
277
395
|
|
396
|
+
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
397
|
+
static VALUE marshal_wkb_generator;
|
398
|
+
#endif
|
278
399
|
|
279
400
|
static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
|
280
401
|
{
|
@@ -286,25 +407,18 @@ static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
|
|
286
407
|
char* str;
|
287
408
|
size_t size;
|
288
409
|
char has_3d;
|
289
|
-
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
290
|
-
RGeo_Globals* globals;
|
291
|
-
VALUE wkb_generator;
|
292
|
-
#endif
|
293
410
|
|
294
411
|
self_data = RGEO_FACTORY_DATA_PTR(self);
|
295
412
|
self_context = self_data->geos_context;
|
296
413
|
has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
|
297
414
|
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
298
415
|
if (has_3d) {
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
wkb_generator = rb_funcall(
|
303
|
-
rb_const_get_at(globals->geos_module, rb_intern("Utils")),
|
416
|
+
if (NIL_P(marshal_wkb_generator)) {
|
417
|
+
marshal_wkb_generator = rb_funcall(
|
418
|
+
rb_const_get_at(rgeo_geos_module, rb_intern("Utils")),
|
304
419
|
rb_intern("marshal_wkb_generator"), 0);
|
305
|
-
globals->marshal_wkb_generator = wkb_generator;
|
306
420
|
}
|
307
|
-
return rb_funcall(
|
421
|
+
return rb_funcall(marshal_wkb_generator, rb_intern("generate"), 1, obj);
|
308
422
|
}
|
309
423
|
#endif
|
310
424
|
wkb_writer = self_data->marshal_wkb_writer;
|
@@ -329,6 +443,9 @@ static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
|
|
329
443
|
return result;
|
330
444
|
}
|
331
445
|
|
446
|
+
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
447
|
+
static VALUE psych_wkt_generator;
|
448
|
+
#endif
|
332
449
|
|
333
450
|
static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
|
334
451
|
{
|
@@ -339,25 +456,18 @@ static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
|
|
339
456
|
VALUE result;
|
340
457
|
char* str;
|
341
458
|
char has_3d;
|
342
|
-
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
343
|
-
RGeo_Globals* globals;
|
344
|
-
VALUE wkt_generator;
|
345
|
-
#endif
|
346
459
|
|
347
460
|
self_data = RGEO_FACTORY_DATA_PTR(self);
|
348
461
|
self_context = self_data->geos_context;
|
349
462
|
has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
|
350
463
|
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
351
464
|
if (has_3d) {
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
wkt_generator = rb_funcall(
|
356
|
-
rb_const_get_at(globals->geos_module, rb_intern("Utils")),
|
465
|
+
if (NIL_P(psych_wkt_generator)) {
|
466
|
+
psych_wkt_generator = rb_funcall(
|
467
|
+
rb_const_get_at(rgeo_geos_module, rb_intern("Utils")),
|
357
468
|
rb_intern("psych_wkt_generator"), 0);
|
358
|
-
globals->psych_wkt_generator = wkt_generator;
|
359
469
|
}
|
360
|
-
return rb_funcall(
|
470
|
+
return rb_funcall(psych_wkt_generator, rb_intern("generate"), 1, obj);
|
361
471
|
}
|
362
472
|
#endif
|
363
473
|
wkt_writer = self_data->psych_wkt_writer;
|
@@ -404,15 +514,17 @@ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE
|
|
404
514
|
VALUE result;
|
405
515
|
RGeo_FactoryData* data;
|
406
516
|
GEOSContextHandle_t context;
|
407
|
-
VALUE wrapped_globals;
|
408
517
|
|
409
518
|
result = Qnil;
|
410
519
|
data = ALLOC(RGeo_FactoryData);
|
411
520
|
if (data) {
|
412
|
-
context =
|
521
|
+
context = GEOS_init_r();
|
522
|
+
#ifdef RGEO_GEOS_DEBUG
|
523
|
+
GEOSContext_setNoticeHandler_r(context, notice_handler);
|
524
|
+
#endif
|
525
|
+
GEOSContext_setErrorHandler_r(context, error_handler);
|
526
|
+
|
413
527
|
if (context) {
|
414
|
-
wrapped_globals = rb_const_get_at(klass, rb_intern("INTERNAL_CGLOBALS"));
|
415
|
-
data->globals = (RGeo_Globals*)DATA_PTR(wrapped_globals);
|
416
528
|
data->geos_context = context;
|
417
529
|
data->flags = NUM2INT(flags);
|
418
530
|
data->srid = NUM2INT(srid);
|
@@ -431,7 +543,7 @@ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE
|
|
431
543
|
data->wkrep_wkb_parser = Qnil;
|
432
544
|
data->proj4_obj = proj4_obj;
|
433
545
|
data->coord_sys_obj = coord_sys_obj;
|
434
|
-
result =
|
546
|
+
result = TypedData_Wrap_Struct(klass, &rgeo_factory_type, data);
|
435
547
|
}
|
436
548
|
else {
|
437
549
|
free(data);
|
@@ -496,7 +608,7 @@ static VALUE method_factory_initialize_copy(VALUE self, VALUE orig)
|
|
496
608
|
self_data->coord_sys_obj = Qnil;
|
497
609
|
|
498
610
|
// Copy new data from original object
|
499
|
-
if (
|
611
|
+
if (RGEO_FACTORY_TYPEDDATA_P(orig)) {
|
500
612
|
orig_data = RGEO_FACTORY_DATA_PTR(orig);
|
501
613
|
self_data->flags = orig_data->flags;
|
502
614
|
self_data->srid = orig_data->srid;
|
@@ -569,55 +681,36 @@ static VALUE alloc_geometry(VALUE klass)
|
|
569
681
|
/**** INITIALIZATION FUNCTION ****/
|
570
682
|
|
571
683
|
|
572
|
-
|
684
|
+
void rgeo_init_geos_factory()
|
573
685
|
{
|
574
|
-
RGeo_Globals* globals;
|
575
|
-
VALUE rgeo_module;
|
576
686
|
VALUE geos_factory_class;
|
577
|
-
|
578
|
-
VALUE feature_module;
|
579
|
-
|
580
|
-
rgeo_module = rb_define_module("RGeo");
|
581
|
-
|
582
|
-
globals = ALLOC(RGeo_Globals);
|
583
|
-
|
584
|
-
// Cache some modules so we don't have to look them up by name every time
|
585
|
-
feature_module = rb_define_module_under(rgeo_module, "Feature");
|
586
|
-
globals->feature_module = feature_module;
|
587
|
-
globals->geos_module = rb_define_module_under(rgeo_module, "Geos");
|
588
|
-
globals->feature_geometry = rb_const_get_at(feature_module, rb_intern("Geometry"));
|
589
|
-
globals->feature_point = rb_const_get_at(feature_module, rb_intern("Point"));
|
590
|
-
globals->feature_line_string = rb_const_get_at(feature_module, rb_intern("LineString"));
|
591
|
-
globals->feature_linear_ring = rb_const_get_at(feature_module, rb_intern("LinearRing"));
|
592
|
-
globals->feature_line = rb_const_get_at(feature_module, rb_intern("Line"));
|
593
|
-
globals->feature_polygon = rb_const_get_at(feature_module, rb_intern("Polygon"));
|
594
|
-
globals->feature_geometry_collection = rb_const_get_at(feature_module, rb_intern("GeometryCollection"));
|
595
|
-
globals->feature_multi_point = rb_const_get_at(feature_module, rb_intern("MultiPoint"));
|
596
|
-
globals->feature_multi_line_string = rb_const_get_at(feature_module, rb_intern("MultiLineString"));
|
597
|
-
globals->feature_multi_polygon = rb_const_get_at(feature_module, rb_intern("MultiPolygon"));
|
598
|
-
|
599
|
-
// Cache some commonly used names
|
600
|
-
globals->id_cast = rb_intern("cast");
|
601
|
-
globals->id_eql = rb_intern("eql?");
|
602
|
-
globals->id_generate = rb_intern("generate");
|
603
|
-
globals->id_enum_for = rb_intern("enum_for");
|
604
|
-
globals->id_hash = rb_intern("hash");
|
605
|
-
globals->sym_force_new = ID2SYM(rb_intern("force_new"));
|
606
|
-
globals->sym_keep_subtype = ID2SYM(rb_intern("keep_subtype"));
|
687
|
+
|
607
688
|
#ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
|
608
|
-
|
609
|
-
|
689
|
+
/* We favor rb_gc_register_address over rb_gc_register_mark_object because the value changes at runtime */
|
690
|
+
psych_wkt_generator = Qnil;
|
691
|
+
rb_gc_register_address(&psych_wkt_generator);
|
692
|
+
marshal_wkb_generator = Qnil;
|
693
|
+
rb_gc_register_address(&marshal_wkb_generator);
|
610
694
|
#endif
|
611
695
|
|
612
|
-
|
613
|
-
geos_factory_class = rb_define_class_under(globals->geos_module, "CAPIFactory", rb_cObject);
|
696
|
+
geos_factory_class = rb_define_class_under(rgeo_geos_module, "CAPIFactory", rb_cObject);
|
614
697
|
rb_define_alloc_func(geos_factory_class, alloc_factory);
|
698
|
+
// Add C constants to the factory.
|
699
|
+
rb_define_const(geos_factory_class, "FLAG_SUPPORTS_Z", INT2FIX(RGEO_FACTORYFLAGS_SUPPORTS_Z));
|
700
|
+
rb_define_const(geos_factory_class, "FLAG_SUPPORTS_M", INT2FIX(RGEO_FACTORYFLAGS_SUPPORTS_M));
|
701
|
+
rb_define_const(geos_factory_class, "FLAG_SUPPORTS_Z_OR_M", INT2FIX(RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M));
|
702
|
+
rb_define_const(geos_factory_class, "FLAG_PREPARE_HEURISTIC", INT2FIX(RGEO_FACTORYFLAGS_PREPARE_HEURISTIC));
|
703
|
+
// Add C methods to the factory.
|
615
704
|
rb_define_method(geos_factory_class, "initialize_copy", method_factory_initialize_copy, 1);
|
616
705
|
rb_define_method(geos_factory_class, "_parse_wkt_impl", method_factory_parse_wkt, 1);
|
617
706
|
rb_define_method(geos_factory_class, "_parse_wkb_impl", method_factory_parse_wkb, 1);
|
618
707
|
rb_define_method(geos_factory_class, "_srid", method_factory_srid, 0);
|
619
708
|
rb_define_method(geos_factory_class, "_buffer_resolution", method_factory_buffer_resolution, 0);
|
620
709
|
rb_define_method(geos_factory_class, "_flags", method_factory_flags, 0);
|
710
|
+
rb_define_method(geos_factory_class, "supports_z?", method_factory_supports_z_p, 0);
|
711
|
+
rb_define_method(geos_factory_class, "supports_m?", method_factory_supports_m_p, 0);
|
712
|
+
rb_define_method(geos_factory_class, "supports_z_or_m?", method_factory_supports_z_or_m_p, 0);
|
713
|
+
rb_define_method(geos_factory_class, "prepare_heuristic?", method_factory_prepare_heuristic_p, 0);
|
621
714
|
rb_define_method(geos_factory_class, "_set_wkrep_parsers", method_set_wkrep_parsers, 2);
|
622
715
|
rb_define_method(geos_factory_class, "_proj4", method_get_proj4, 0);
|
623
716
|
rb_define_method(geos_factory_class, "_coord_sys", method_get_coord_sys, 0);
|
@@ -633,34 +726,17 @@ RGeo_Globals* rgeo_init_geos_factory()
|
|
633
726
|
rb_define_module_function(geos_factory_class, "_geos_version", cmethod_factory_geos_version, 0);
|
634
727
|
rb_define_module_function(geos_factory_class, "_supports_unary_union?", cmethod_factory_supports_unary_union, 0);
|
635
728
|
|
636
|
-
//
|
637
|
-
|
638
|
-
rb_define_alloc_func(
|
639
|
-
|
640
|
-
rb_define_alloc_func(
|
641
|
-
|
642
|
-
rb_define_alloc_func(
|
643
|
-
|
644
|
-
rb_define_alloc_func(
|
645
|
-
|
646
|
-
rb_define_alloc_func(
|
647
|
-
globals->geos_polygon = rb_define_class_under(globals->geos_module, "CAPIPolygonImpl", rb_cObject);
|
648
|
-
rb_define_alloc_func(globals->geos_polygon, alloc_geometry);
|
649
|
-
globals->geos_geometry_collection = rb_define_class_under(globals->geos_module, "CAPIGeometryCollectionImpl", rb_cObject);
|
650
|
-
rb_define_alloc_func(globals->geos_geometry_collection, alloc_geometry);
|
651
|
-
globals->geos_multi_point = rb_define_class_under(globals->geos_module, "CAPIMultiPointImpl", rb_cObject);
|
652
|
-
rb_define_alloc_func(globals->geos_multi_point, alloc_geometry);
|
653
|
-
globals->geos_multi_line_string = rb_define_class_under(globals->geos_module, "CAPIMultiLineStringImpl", rb_cObject);
|
654
|
-
rb_define_alloc_func(globals->geos_multi_line_string, alloc_geometry);
|
655
|
-
globals->geos_multi_polygon = rb_define_class_under(globals->geos_module, "CAPIMultiPolygonImpl", rb_cObject);
|
656
|
-
rb_define_alloc_func(globals->geos_multi_polygon, alloc_geometry);
|
657
|
-
|
658
|
-
// Wrap the globals in a Ruby object and store it off so we have access
|
659
|
-
// to it later. Each factory instance will reference it internally.
|
660
|
-
wrapped_globals = Data_Wrap_Struct(rb_cObject, mark_globals_func, destroy_globals_func, globals);
|
661
|
-
rb_define_const(geos_factory_class, "INTERNAL_CGLOBALS", wrapped_globals);
|
662
|
-
|
663
|
-
return globals;
|
729
|
+
// Define allocation methods for global class types
|
730
|
+
rb_define_alloc_func(rgeo_geos_geometry_class, alloc_geometry);
|
731
|
+
rb_define_alloc_func(rgeo_geos_point_class, alloc_geometry);
|
732
|
+
rb_define_alloc_func(rgeo_geos_line_string_class, alloc_geometry);
|
733
|
+
rb_define_alloc_func(rgeo_geos_linear_ring_class, alloc_geometry);
|
734
|
+
rb_define_alloc_func(rgeo_geos_line_class, alloc_geometry);
|
735
|
+
rb_define_alloc_func(rgeo_geos_polygon_class, alloc_geometry);
|
736
|
+
rb_define_alloc_func(rgeo_geos_geometry_collection_class, alloc_geometry);
|
737
|
+
rb_define_alloc_func(rgeo_geos_multi_point_class, alloc_geometry);
|
738
|
+
rb_define_alloc_func(rgeo_geos_multi_line_string_class, alloc_geometry);
|
739
|
+
rb_define_alloc_func(rgeo_geos_multi_polygon_class, alloc_geometry);
|
664
740
|
}
|
665
741
|
|
666
742
|
|
@@ -673,7 +749,6 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
|
|
673
749
|
RGeo_FactoryData* factory_data;
|
674
750
|
GEOSContextHandle_t factory_context;
|
675
751
|
VALUE klasses;
|
676
|
-
RGeo_Globals* globals;
|
677
752
|
VALUE inferred_klass;
|
678
753
|
char is_collection;
|
679
754
|
RGeo_GeometryData* data;
|
@@ -682,7 +757,6 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
|
|
682
757
|
if (geom || !NIL_P(klass)) {
|
683
758
|
factory_data = NIL_P(factory) ? NULL : RGEO_FACTORY_DATA_PTR(factory);
|
684
759
|
factory_context = factory_data ? factory_data->geos_context : NULL;
|
685
|
-
globals = factory_data ? factory_data->globals : NULL;
|
686
760
|
|
687
761
|
// We don't allow "empty" points, so replace such objects with
|
688
762
|
// an empty collection.
|
@@ -690,7 +764,7 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
|
|
690
764
|
if (GEOSGeomTypeId_r(factory_context, geom) == GEOS_POINT && GEOSGetNumCoordinates_r(factory_context, geom) == 0) {
|
691
765
|
GEOSGeom_destroy_r(factory_context, geom);
|
692
766
|
geom = GEOSGeom_createCollection_r(factory_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
|
693
|
-
klass =
|
767
|
+
klass = rgeo_geos_geometry_collection_class;
|
694
768
|
}
|
695
769
|
}
|
696
770
|
|
@@ -700,35 +774,35 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
|
|
700
774
|
is_collection = 0;
|
701
775
|
switch (GEOSGeomTypeId_r(factory_context, geom)) {
|
702
776
|
case GEOS_POINT:
|
703
|
-
inferred_klass =
|
777
|
+
inferred_klass = rgeo_geos_point_class;
|
704
778
|
break;
|
705
779
|
case GEOS_LINESTRING:
|
706
|
-
inferred_klass =
|
780
|
+
inferred_klass = rgeo_geos_line_string_class;
|
707
781
|
break;
|
708
782
|
case GEOS_LINEARRING:
|
709
|
-
inferred_klass =
|
783
|
+
inferred_klass = rgeo_geos_linear_ring_class;
|
710
784
|
break;
|
711
785
|
case GEOS_POLYGON:
|
712
|
-
inferred_klass =
|
786
|
+
inferred_klass = rgeo_geos_polygon_class;
|
713
787
|
break;
|
714
788
|
case GEOS_MULTIPOINT:
|
715
|
-
inferred_klass =
|
789
|
+
inferred_klass = rgeo_geos_multi_point_class;
|
716
790
|
is_collection = 1;
|
717
791
|
break;
|
718
792
|
case GEOS_MULTILINESTRING:
|
719
|
-
inferred_klass =
|
793
|
+
inferred_klass = rgeo_geos_multi_line_string_class;
|
720
794
|
is_collection = 1;
|
721
795
|
break;
|
722
796
|
case GEOS_MULTIPOLYGON:
|
723
|
-
inferred_klass =
|
797
|
+
inferred_klass = rgeo_geos_multi_polygon_class;
|
724
798
|
is_collection = 1;
|
725
799
|
break;
|
726
800
|
case GEOS_GEOMETRYCOLLECTION:
|
727
|
-
inferred_klass =
|
801
|
+
inferred_klass = rgeo_geos_geometry_collection_class;
|
728
802
|
is_collection = 1;
|
729
803
|
break;
|
730
804
|
default:
|
731
|
-
inferred_klass =
|
805
|
+
inferred_klass = rgeo_geos_geometry_class;
|
732
806
|
break;
|
733
807
|
}
|
734
808
|
if (TYPE(klass) == T_ARRAY && is_collection) {
|
@@ -747,13 +821,12 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
|
|
747
821
|
(GEOSPreparedGeometry*)1 : NULL;
|
748
822
|
data->factory = factory;
|
749
823
|
data->klasses = klasses;
|
750
|
-
result =
|
824
|
+
result = TypedData_Wrap_Struct(klass, &rgeo_geometry_type, data);
|
751
825
|
}
|
752
826
|
}
|
753
827
|
return result;
|
754
828
|
}
|
755
829
|
|
756
|
-
|
757
830
|
VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass)
|
758
831
|
{
|
759
832
|
VALUE result;
|
@@ -773,21 +846,18 @@ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VAL
|
|
773
846
|
const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type)
|
774
847
|
{
|
775
848
|
VALUE object;
|
776
|
-
const GEOSGeometry* geom;
|
777
|
-
RGeo_Globals* globals;
|
778
849
|
|
779
|
-
if (NIL_P(type) &&
|
850
|
+
if (NIL_P(type) && RGEO_GEOMETRY_TYPEDDATA_P(obj) && RGEO_GEOMETRY_DATA_PTR(obj)->factory == factory) {
|
780
851
|
object = obj;
|
781
852
|
}
|
782
853
|
else {
|
783
|
-
|
784
|
-
object = rb_funcall(globals->feature_module, globals->id_cast, 3, obj, factory, type);
|
854
|
+
object = rb_funcall(rgeo_feature_module, rb_intern("cast"), 3, obj, factory, type);
|
785
855
|
}
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
return geom;
|
856
|
+
if (NIL_P(object))
|
857
|
+
return NULL;
|
858
|
+
|
859
|
+
Check_TypedStruct(object, &rgeo_geometry_type);
|
860
|
+
return RGEO_GEOMETRY_DATA_PTR(object)->geom;
|
791
861
|
}
|
792
862
|
|
793
863
|
|
@@ -797,13 +867,11 @@ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, V
|
|
797
867
|
GEOSGeometry* geom;
|
798
868
|
RGeo_GeometryData* object_data;
|
799
869
|
const GEOSPreparedGeometry* prep;
|
800
|
-
RGeo_Globals* globals;
|
801
870
|
|
802
871
|
if (klasses) {
|
803
872
|
*klasses = Qnil;
|
804
873
|
}
|
805
|
-
|
806
|
-
object = rb_funcall(globals->feature_module, globals->id_cast, 5, obj, factory, type, globals->sym_force_new, globals->sym_keep_subtype);
|
874
|
+
object = rb_funcall(rgeo_feature_module, rb_intern("cast"), 5, obj, factory, type, ID2SYM(rb_intern("force_new")), ID2SYM(rb_intern("keep_subtype")));
|
807
875
|
geom = NULL;
|
808
876
|
if (!NIL_P(object)) {
|
809
877
|
object_data = RGEO_GEOMETRY_DATA_PTR(object);
|
@@ -830,20 +898,20 @@ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, V
|
|
830
898
|
|
831
899
|
char rgeo_is_geos_object(VALUE obj)
|
832
900
|
{
|
833
|
-
return (
|
901
|
+
return RGEO_GEOMETRY_TYPEDDATA_P(obj) ? 1 : 0;
|
834
902
|
}
|
835
903
|
|
836
904
|
void rgeo_check_geos_object(VALUE obj)
|
837
905
|
{
|
838
906
|
if (!rgeo_is_geos_object(obj)) {
|
839
|
-
rb_raise(
|
907
|
+
rb_raise(rb_eRGeoError, "Not a GEOS Geometry object.");
|
840
908
|
}
|
841
909
|
}
|
842
910
|
|
843
911
|
|
844
912
|
const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj)
|
845
913
|
{
|
846
|
-
return (
|
914
|
+
return RGEO_GEOMETRY_TYPEDDATA_P(obj) ? (const GEOSGeometry*)(RGEO_GEOMETRY_DATA_PTR(obj)->geom) : NULL;
|
847
915
|
}
|
848
916
|
|
849
917
|
|
@@ -931,7 +999,8 @@ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2)
|
|
931
999
|
}
|
932
1000
|
else {
|
933
1001
|
factory = RGEO_GEOMETRY_DATA_PTR(obj1)->factory;
|
934
|
-
|
1002
|
+
/* No need to cache the internal here (https://ips.fastruby.io/4x) */
|
1003
|
+
result = rb_funcall(factory, rb_intern("eql?"), 1, RGEO_GEOMETRY_DATA_PTR(obj2)->factory);
|
935
1004
|
}
|
936
1005
|
return result;
|
937
1006
|
}
|
@@ -984,7 +1053,7 @@ st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t h
|
|
984
1053
|
ID hash_method;
|
985
1054
|
RGeo_Objbase_Hash_Struct hash_struct;
|
986
1055
|
|
987
|
-
hash_method =
|
1056
|
+
hash_method = rb_intern("hash");
|
988
1057
|
hash_struct.seed_hash = hash;
|
989
1058
|
hash_struct.h1 = FIX2LONG(rb_funcall(factory, hash_method, 0));
|
990
1059
|
hash_struct.h2 = FIX2LONG(rb_funcall(type_module, hash_method, 0));
|