rgeo 0.3.6 → 0.3.7
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.
- data/History.rdoc +7 -0
- data/README.rdoc +5 -3
- data/Version +1 -1
- data/ext/geos_c_impl/factory.c +160 -0
- data/ext/geos_c_impl/factory.h +4 -0
- data/ext/geos_c_impl/geometry.c +40 -2
- data/lib/rgeo/cartesian/factory.rb +46 -0
- data/lib/rgeo/coord_sys/proj4.rb +3 -0
- data/lib/rgeo/geographic/factory.rb +46 -0
- data/lib/rgeo/geos/ffi_classes.rb +36 -1
- data/lib/rgeo/geos/ffi_factory.rb +34 -0
- data/lib/rgeo/geos/impl_additions.rb +38 -0
- data/lib/rgeo/geos/zm_factory.rb +42 -4
- data/lib/rgeo/geos/zm_impl.rb +46 -14
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +11 -0
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +27 -2
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +6 -0
- data/lib/rgeo/impl_helper/basic_point_methods.rb +9 -0
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +7 -0
- data/test/common/line_string_tests.rb +24 -0
- data/test/common/point_tests.rb +52 -0
- data/test/geos_capi/tc_point.rb +18 -0
- data/test/geos_ffi/tc_point.rb +18 -0
- data/test/tc_oneoff.rb +1 -1
- metadata +2 -2
data/History.rdoc
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
=== 0.3.7 / 2012-03-12
|
2
|
+
|
3
|
+
* Marshal and YAML serialization now fully implemented for geometries.
|
4
|
+
* The spatial predicates for objects using the 4D (ZM) Geos factory almost always returned false because they weren't casting correctly. Fixed.
|
5
|
+
* Proj#canonical_str and the Geos implementations of Geometry#as_text were returning strings encoded as "ASCII-8BIT", which was causing strange binary output in YAML serialization, among other things. Now fixed. These strings are now encoded as "US-ASCII".
|
6
|
+
* YAML serialization for 4D (ZM) Geos factories didn't preserve coordinate systems. Fixed.
|
7
|
+
|
1
8
|
=== 0.3.6 / 2012-03-06
|
2
9
|
|
3
10
|
* Geometry#relate? was incorrectly spelled "Geometry#relate" in the Feature::Geometry module and in some (but not all) implementations, leading to various types of method not found errors. Fixed. We'll keep #relate as a deprecated alias for the time being.
|
data/README.rdoc
CHANGED
@@ -99,18 +99,20 @@ installation prefix directory using the "--with-proj-dir" option.
|
|
99
99
|
The RGeo suite of tools is evolving rapidly. The current to-do list for
|
100
100
|
the core library includes:
|
101
101
|
|
102
|
-
* YAML and Marshal serialization support across all major entities.
|
103
|
-
* Full JRuby support.
|
104
102
|
* Better error handling and reporting.
|
103
|
+
* JRuby support for Proj4
|
105
104
|
* Ellipsoidal geography implementation, possibly utilizing geographiclib.
|
106
105
|
* Windows build support.
|
106
|
+
* GDAL integration including coordinate system interpretation.
|
107
107
|
|
108
108
|
Each of the current add-on modules also has its own feature roadmap, and
|
109
109
|
we are planning on introducing more add-on modules, including:
|
110
110
|
|
111
|
+
* Raster support via GDAL.
|
111
112
|
* GeoRSS and KML format support.
|
112
|
-
*
|
113
|
+
* Custom spatial indexes.
|
113
114
|
* Possible additional ActiveRecord adapters (esp. JDBC adapters)
|
115
|
+
* Integration with third-party APIs.
|
114
116
|
|
115
117
|
=== Development and support
|
116
118
|
|
data/Version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.7
|
data/ext/geos_c_impl/factory.c
CHANGED
@@ -84,6 +84,18 @@ static void destroy_factory_func(RGeo_FactoryData* data)
|
|
84
84
|
if (data->wkb_writer) {
|
85
85
|
GEOSWKBWriter_destroy_r(context, data->wkb_writer);
|
86
86
|
}
|
87
|
+
if (data->psych_wkt_reader) {
|
88
|
+
GEOSWKTReader_destroy_r(context, data->psych_wkt_reader);
|
89
|
+
}
|
90
|
+
if (data->marshal_wkb_reader) {
|
91
|
+
GEOSWKBReader_destroy_r(context, data->marshal_wkb_reader);
|
92
|
+
}
|
93
|
+
if (data->psych_wkt_writer) {
|
94
|
+
GEOSWKTWriter_destroy_r(context, data->psych_wkt_writer);
|
95
|
+
}
|
96
|
+
if (data->marshal_wkb_writer) {
|
97
|
+
GEOSWKBWriter_destroy_r(context, data->marshal_wkb_writer);
|
98
|
+
}
|
87
99
|
finishGEOS_r(context);
|
88
100
|
free(data);
|
89
101
|
}
|
@@ -241,6 +253,130 @@ static VALUE method_factory_parse_wkb(VALUE self, VALUE str)
|
|
241
253
|
}
|
242
254
|
|
243
255
|
|
256
|
+
static VALUE method_factory_read_for_marshal(VALUE self, VALUE str)
|
257
|
+
{
|
258
|
+
RGeo_FactoryData* self_data;
|
259
|
+
GEOSContextHandle_t self_context;
|
260
|
+
GEOSWKBReader* wkb_reader;
|
261
|
+
VALUE result;
|
262
|
+
GEOSGeometry* geom;
|
263
|
+
|
264
|
+
Check_Type(str, T_STRING);
|
265
|
+
self_data = RGEO_FACTORY_DATA_PTR(self);
|
266
|
+
self_context = self_data->geos_context;
|
267
|
+
wkb_reader = self_data->marshal_wkb_reader;
|
268
|
+
if (!wkb_reader) {
|
269
|
+
wkb_reader = GEOSWKBReader_create_r(self_context);
|
270
|
+
self_data->marshal_wkb_reader = wkb_reader;
|
271
|
+
}
|
272
|
+
result = Qnil;
|
273
|
+
if (wkb_reader) {
|
274
|
+
geom = GEOSWKBReader_read_r(self_context, wkb_reader, (unsigned char*)RSTRING_PTR(str), (size_t)RSTRING_LEN(str));
|
275
|
+
if (geom) {
|
276
|
+
result = rgeo_wrap_geos_geometry(self, geom, Qnil);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
return result;
|
280
|
+
}
|
281
|
+
|
282
|
+
|
283
|
+
static VALUE method_factory_read_for_psych(VALUE self, VALUE str)
|
284
|
+
{
|
285
|
+
RGeo_FactoryData* self_data;
|
286
|
+
GEOSContextHandle_t self_context;
|
287
|
+
GEOSWKTReader* wkt_reader;
|
288
|
+
VALUE result;
|
289
|
+
GEOSGeometry* geom;
|
290
|
+
|
291
|
+
Check_Type(str, T_STRING);
|
292
|
+
self_data = RGEO_FACTORY_DATA_PTR(self);
|
293
|
+
self_context = self_data->geos_context;
|
294
|
+
wkt_reader = self_data->psych_wkt_reader;
|
295
|
+
if (!wkt_reader) {
|
296
|
+
wkt_reader = GEOSWKTReader_create_r(self_context);
|
297
|
+
self_data->psych_wkt_reader = wkt_reader;
|
298
|
+
}
|
299
|
+
result = Qnil;
|
300
|
+
if (wkt_reader) {
|
301
|
+
geom = GEOSWKTReader_read_r(self_context, wkt_reader, RSTRING_PTR(str));
|
302
|
+
if (geom) {
|
303
|
+
result = rgeo_wrap_geos_geometry(self, geom, Qnil);
|
304
|
+
}
|
305
|
+
}
|
306
|
+
return result;
|
307
|
+
}
|
308
|
+
|
309
|
+
|
310
|
+
static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
|
311
|
+
{
|
312
|
+
RGeo_FactoryData* self_data;
|
313
|
+
GEOSContextHandle_t self_context;
|
314
|
+
GEOSWKBWriter* wkb_writer;
|
315
|
+
const GEOSGeometry* geom;
|
316
|
+
VALUE result;
|
317
|
+
char* str;
|
318
|
+
size_t size;
|
319
|
+
|
320
|
+
self_data = RGEO_FACTORY_DATA_PTR(self);
|
321
|
+
self_context = self_data->geos_context;
|
322
|
+
wkb_writer = self_data->marshal_wkb_writer;
|
323
|
+
if (!wkb_writer) {
|
324
|
+
wkb_writer = GEOSWKBWriter_create_r(self_context);
|
325
|
+
if (self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M) {
|
326
|
+
GEOSWKBWriter_setOutputDimension_r(self_context, wkb_writer, 3);
|
327
|
+
}
|
328
|
+
self_data->marshal_wkb_writer = wkb_writer;
|
329
|
+
}
|
330
|
+
result = Qnil;
|
331
|
+
if (wkb_writer) {
|
332
|
+
geom = rgeo_get_geos_geometry_safe(obj);
|
333
|
+
if (geom) {
|
334
|
+
str = (char*)GEOSWKBWriter_write_r(self_context, wkb_writer, geom, &size);
|
335
|
+
if (str) {
|
336
|
+
result = rb_str_new(str, size);
|
337
|
+
GEOSFree_r(self_context, str);
|
338
|
+
}
|
339
|
+
}
|
340
|
+
}
|
341
|
+
return result;
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
|
346
|
+
{
|
347
|
+
RGeo_FactoryData* self_data;
|
348
|
+
GEOSContextHandle_t self_context;
|
349
|
+
GEOSWKTWriter* wkt_writer;
|
350
|
+
const GEOSGeometry* geom;
|
351
|
+
VALUE result;
|
352
|
+
char* str;
|
353
|
+
size_t size;
|
354
|
+
|
355
|
+
self_data = RGEO_FACTORY_DATA_PTR(self);
|
356
|
+
self_context = self_data->geos_context;
|
357
|
+
wkt_writer = self_data->psych_wkt_writer;
|
358
|
+
if (!wkt_writer) {
|
359
|
+
wkt_writer = GEOSWKTWriter_create_r(self_context);
|
360
|
+
if (self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M) {
|
361
|
+
GEOSWKTWriter_setOutputDimension_r(self_context, wkt_writer, 3);
|
362
|
+
}
|
363
|
+
self_data->psych_wkt_writer = wkt_writer;
|
364
|
+
}
|
365
|
+
result = Qnil;
|
366
|
+
if (wkt_writer) {
|
367
|
+
geom = rgeo_get_geos_geometry_safe(obj);
|
368
|
+
if (geom) {
|
369
|
+
str = GEOSWKTWriter_write_r(self_context, wkt_writer, geom);
|
370
|
+
if (str) {
|
371
|
+
result = rb_str_new2(str);
|
372
|
+
GEOSFree_r(self_context, str);
|
373
|
+
}
|
374
|
+
}
|
375
|
+
}
|
376
|
+
return result;
|
377
|
+
}
|
378
|
+
|
379
|
+
|
244
380
|
static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE buffer_resolution,
|
245
381
|
VALUE wkt_generator, VALUE wkb_generator, VALUE proj4_obj, VALUE coord_sys_obj)
|
246
382
|
{
|
@@ -264,6 +400,10 @@ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE
|
|
264
400
|
data->wkb_reader = NULL;
|
265
401
|
data->wkt_writer = NULL;
|
266
402
|
data->wkb_writer = NULL;
|
403
|
+
data->psych_wkt_reader = NULL;
|
404
|
+
data->marshal_wkb_reader = NULL;
|
405
|
+
data->psych_wkt_writer = NULL;
|
406
|
+
data->marshal_wkb_writer = NULL;
|
267
407
|
data->wkrep_wkt_generator = wkt_generator;
|
268
408
|
data->wkrep_wkb_generator = wkb_generator;
|
269
409
|
data->wkrep_wkt_parser = Qnil;
|
@@ -311,6 +451,22 @@ static VALUE method_factory_initialize_copy(VALUE self, VALUE orig)
|
|
311
451
|
GEOSWKBWriter_destroy_r(context, self_data->wkb_writer);
|
312
452
|
self_data->wkb_writer = NULL;
|
313
453
|
}
|
454
|
+
if (self_data->psych_wkt_reader) {
|
455
|
+
GEOSWKTReader_destroy_r(context, self_data->psych_wkt_reader);
|
456
|
+
self_data->psych_wkt_reader = NULL;
|
457
|
+
}
|
458
|
+
if (self_data->marshal_wkb_reader) {
|
459
|
+
GEOSWKBReader_destroy_r(context, self_data->marshal_wkb_reader);
|
460
|
+
self_data->marshal_wkb_reader = NULL;
|
461
|
+
}
|
462
|
+
if (self_data->psych_wkt_writer) {
|
463
|
+
GEOSWKTWriter_destroy_r(context, self_data->psych_wkt_writer);
|
464
|
+
self_data->psych_wkt_writer = NULL;
|
465
|
+
}
|
466
|
+
if (self_data->marshal_wkb_writer) {
|
467
|
+
GEOSWKBWriter_destroy_r(context, self_data->marshal_wkb_writer);
|
468
|
+
self_data->marshal_wkb_writer = NULL;
|
469
|
+
}
|
314
470
|
self_data->wkrep_wkt_generator = Qnil;
|
315
471
|
self_data->wkrep_wkb_generator = Qnil;
|
316
472
|
self_data->wkrep_wkt_parser = Qnil;
|
@@ -422,6 +578,10 @@ RGeo_Globals* rgeo_init_geos_factory()
|
|
422
578
|
rb_define_method(geos_factory_class, "_wkb_generator", method_get_wkb_generator, 0);
|
423
579
|
rb_define_method(geos_factory_class, "_wkt_parser", method_get_wkt_parser, 0);
|
424
580
|
rb_define_method(geos_factory_class, "_wkb_parser", method_get_wkb_parser, 0);
|
581
|
+
rb_define_method(geos_factory_class, "_read_for_marshal", method_factory_read_for_marshal, 1);
|
582
|
+
rb_define_method(geos_factory_class, "_write_for_marshal", method_factory_write_for_marshal, 1);
|
583
|
+
rb_define_method(geos_factory_class, "_read_for_psych", method_factory_read_for_psych, 1);
|
584
|
+
rb_define_method(geos_factory_class, "_write_for_psych", method_factory_write_for_psych, 1);
|
425
585
|
rb_define_module_function(geos_factory_class, "_create", cmethod_factory_create, 7);
|
426
586
|
|
427
587
|
// Wrap the globals in a Ruby object and store it off so we have access
|
data/ext/geos_c_impl/factory.h
CHANGED
@@ -101,6 +101,10 @@ typedef struct {
|
|
101
101
|
VALUE wkrep_wkb_generator;
|
102
102
|
VALUE wkrep_wkt_parser;
|
103
103
|
VALUE wkrep_wkb_parser;
|
104
|
+
GEOSWKTReader* psych_wkt_reader;
|
105
|
+
GEOSWKBReader* marshal_wkb_reader;
|
106
|
+
GEOSWKTWriter* psych_wkt_writer;
|
107
|
+
GEOSWKBWriter* marshal_wkb_writer;
|
104
108
|
VALUE proj4_obj;
|
105
109
|
VALUE coord_sys_obj;
|
106
110
|
int flags;
|
data/ext/geos_c_impl/geometry.c
CHANGED
@@ -937,6 +937,44 @@ static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
|
|
937
937
|
}
|
938
938
|
|
939
939
|
|
940
|
+
static VALUE method_geometry_steal(VALUE self, VALUE orig)
|
941
|
+
{
|
942
|
+
RGeo_GeometryData* self_data;
|
943
|
+
const GEOSPreparedGeometry* prep;
|
944
|
+
const GEOSGeometry* geom;
|
945
|
+
RGeo_GeometryData* orig_data;
|
946
|
+
|
947
|
+
geom = rgeo_get_geos_geometry_safe(orig);
|
948
|
+
if (geom) {
|
949
|
+
// Clear out any existing value
|
950
|
+
self_data = RGEO_GEOMETRY_DATA_PTR(self);
|
951
|
+
if (self_data->geom) {
|
952
|
+
GEOSGeom_destroy_r(self_data->geos_context, self_data->geom);
|
953
|
+
}
|
954
|
+
prep = self_data->prep;
|
955
|
+
if (prep && prep != (GEOSPreparedGeometry*)1 && prep != (GEOSPreparedGeometry*)2) {
|
956
|
+
GEOSPreparedGeom_destroy_r(self_data->geos_context, prep);
|
957
|
+
}
|
958
|
+
|
959
|
+
// Steal value from orig
|
960
|
+
orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
|
961
|
+
self_data->geom = orig_data->geom;
|
962
|
+
self_data->prep = orig_data->prep;
|
963
|
+
self_data->geos_context = orig_data->geos_context;
|
964
|
+
self_data->factory = orig_data->factory;
|
965
|
+
self_data->klasses = orig_data->klasses;
|
966
|
+
|
967
|
+
// Clear out orig
|
968
|
+
orig_data->geom = NULL;
|
969
|
+
orig_data->prep = NULL;
|
970
|
+
orig_data->geos_context = NULL;
|
971
|
+
orig_data->factory = Qnil;
|
972
|
+
orig_data->klasses = Qnil;
|
973
|
+
}
|
974
|
+
return self;
|
975
|
+
}
|
976
|
+
|
977
|
+
|
940
978
|
/**** INITIALIZATION FUNCTION ****/
|
941
979
|
|
942
980
|
|
@@ -953,6 +991,7 @@ void rgeo_init_geos_geometry(RGeo_Globals* globals)
|
|
953
991
|
rb_define_alloc_func(geos_geometry_class, alloc_geometry);
|
954
992
|
rb_define_method(geos_geometry_class, "_set_factory", method_geometry_set_factory, 1);
|
955
993
|
rb_define_method(geos_geometry_class, "initialize_copy", method_geometry_initialize_copy, 1);
|
994
|
+
rb_define_method(geos_geometry_class, "_steal", method_geometry_steal, 1);
|
956
995
|
rb_define_method(geos_geometry_class, "initialized?", method_geometry_initialized_p, 0);
|
957
996
|
rb_define_method(geos_geometry_class, "factory", method_geometry_factory, 0);
|
958
997
|
rb_define_method(geos_geometry_class, "prepared?", method_geometry_prepared_p, 0);
|
@@ -962,8 +1001,7 @@ void rgeo_init_geos_geometry(RGeo_Globals* globals)
|
|
962
1001
|
rb_define_method(geos_geometry_class, "srid", method_geometry_srid, 0);
|
963
1002
|
rb_define_method(geos_geometry_class, "envelope", method_geometry_envelope, 0);
|
964
1003
|
rb_define_method(geos_geometry_class, "boundary", method_geometry_boundary, 0);
|
965
|
-
rb_define_method(geos_geometry_class, "
|
966
|
-
rb_define_method(geos_geometry_class, "to_s", method_geometry_as_text, 0);
|
1004
|
+
rb_define_method(geos_geometry_class, "_as_text", method_geometry_as_text, 0);
|
967
1005
|
rb_define_method(geos_geometry_class, "as_binary", method_geometry_as_binary, 0);
|
968
1006
|
rb_define_method(geos_geometry_class, "is_empty?", method_geometry_is_empty, 0);
|
969
1007
|
rb_define_method(geos_geometry_class, "is_simple?", method_geometry_is_simple, 0);
|
@@ -326,6 +326,52 @@ module RGeo
|
|
326
326
|
end
|
327
327
|
|
328
328
|
|
329
|
+
def _generate_wkt(obj_) # :nodoc:
|
330
|
+
@wkt_generator.generate(obj_)
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
def _generate_wkb(obj_) # :nodoc:
|
335
|
+
@wkb_generator.generate(obj_)
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
def _marshal_wkb_generator # :nodoc:
|
340
|
+
unless defined?(@marshal_wkb_generator)
|
341
|
+
@marshal_wkb_generator = ::RGeo::WKRep::WKBGenerator.new(
|
342
|
+
:type_format => :wkb12)
|
343
|
+
end
|
344
|
+
@marshal_wkb_generator
|
345
|
+
end
|
346
|
+
|
347
|
+
|
348
|
+
def _marshal_wkb_parser # :nodoc:
|
349
|
+
unless defined?(@marshal_wkb_parser)
|
350
|
+
@marshal_wkb_parser = ::RGeo::WKRep::WKBParser.new(self,
|
351
|
+
:support_wkb12 => true)
|
352
|
+
end
|
353
|
+
@marshal_wkb_parser
|
354
|
+
end
|
355
|
+
|
356
|
+
|
357
|
+
def _psych_wkt_generator # :nodoc:
|
358
|
+
unless defined?(@psych_wkt_generator)
|
359
|
+
@psych_wkt_generator = ::RGeo::WKRep::WKTGenerator.new(
|
360
|
+
:tag_format => :wkt12)
|
361
|
+
end
|
362
|
+
@psych_wkt_generator
|
363
|
+
end
|
364
|
+
|
365
|
+
|
366
|
+
def _psych_wkt_parser # :nodoc:
|
367
|
+
unless defined?(@psych_wkt_parser)
|
368
|
+
@psych_wkt_parser = ::RGeo::WKRep::WKTParser.new(self,
|
369
|
+
:support_wkt12 => true, :support_ewkt => true)
|
370
|
+
end
|
371
|
+
@psych_wkt_parser
|
372
|
+
end
|
373
|
+
|
374
|
+
|
329
375
|
end
|
330
376
|
|
331
377
|
|
data/lib/rgeo/coord_sys/proj4.rb
CHANGED
@@ -432,6 +432,52 @@ module RGeo
|
|
432
432
|
end
|
433
433
|
|
434
434
|
|
435
|
+
def _generate_wkt(obj_) # :nodoc:
|
436
|
+
@wkt_generator.generate(obj_)
|
437
|
+
end
|
438
|
+
|
439
|
+
|
440
|
+
def _generate_wkb(obj_) # :nodoc:
|
441
|
+
@wkb_generator.generate(obj_)
|
442
|
+
end
|
443
|
+
|
444
|
+
|
445
|
+
def _marshal_wkb_generator # :nodoc:
|
446
|
+
unless defined?(@marshal_wkb_generator)
|
447
|
+
@marshal_wkb_generator = ::RGeo::WKRep::WKBGenerator.new(
|
448
|
+
:type_format => :wkb12)
|
449
|
+
end
|
450
|
+
@marshal_wkb_generator
|
451
|
+
end
|
452
|
+
|
453
|
+
|
454
|
+
def _marshal_wkb_parser # :nodoc:
|
455
|
+
unless defined?(@marshal_wkb_parser)
|
456
|
+
@marshal_wkb_parser = ::RGeo::WKRep::WKBParser.new(self,
|
457
|
+
:support_wkb12 => true)
|
458
|
+
end
|
459
|
+
@marshal_wkb_parser
|
460
|
+
end
|
461
|
+
|
462
|
+
|
463
|
+
def _psych_wkt_generator # :nodoc:
|
464
|
+
unless defined?(@psych_wkt_generator)
|
465
|
+
@psych_wkt_generator = ::RGeo::WKRep::WKTGenerator.new(
|
466
|
+
:tag_format => :wkt12)
|
467
|
+
end
|
468
|
+
@psych_wkt_generator
|
469
|
+
end
|
470
|
+
|
471
|
+
|
472
|
+
def _psych_wkt_parser # :nodoc:
|
473
|
+
unless defined?(@psych_wkt_parser)
|
474
|
+
@psych_wkt_parser = ::RGeo::WKRep::WKTParser.new(self,
|
475
|
+
:support_wkt12 => true, :support_ewkt => true)
|
476
|
+
end
|
477
|
+
@psych_wkt_parser
|
478
|
+
end
|
479
|
+
|
480
|
+
|
435
481
|
end
|
436
482
|
|
437
483
|
end
|
@@ -120,6 +120,39 @@ module RGeo
|
|
120
120
|
end
|
121
121
|
|
122
122
|
|
123
|
+
# Marshal support
|
124
|
+
|
125
|
+
def marshal_dump # :nodoc:
|
126
|
+
[@factory, @factory._write_for_marshal(@fg_geom)]
|
127
|
+
end
|
128
|
+
|
129
|
+
def marshal_load(data_) # :nodoc:
|
130
|
+
@factory = data_[0]
|
131
|
+
@fg_geom = @factory._read_for_marshal(data_[1])
|
132
|
+
@fg_geom.srid = @factory.srid
|
133
|
+
@_fg_prep = @factory._auto_prepare ? 1 : 0
|
134
|
+
@_klasses = nil
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
# Psych support
|
139
|
+
|
140
|
+
def encode_with(coder_) # :nodoc:
|
141
|
+
coder_['factory'] = @factory
|
142
|
+
str_ = @factory._write_for_psych(@fg_geom)
|
143
|
+
str_ = str_.encode('US-ASCII') if str_.respond_to?(:encode)
|
144
|
+
coder_['wkt'] = str_
|
145
|
+
end
|
146
|
+
|
147
|
+
def init_with(coder_) # :nodoc:
|
148
|
+
@factory = coder_['factory']
|
149
|
+
@fg_geom = @factory._read_for_psych(coder_['wkt'])
|
150
|
+
@fg_geom.srid = @factory.srid
|
151
|
+
@_fg_prep = @factory._auto_prepare ? 1 : 0
|
152
|
+
@_klasses = nil
|
153
|
+
end
|
154
|
+
|
155
|
+
|
123
156
|
attr_reader :factory
|
124
157
|
attr_reader :fg_geom
|
125
158
|
|
@@ -184,7 +217,9 @@ module RGeo
|
|
184
217
|
|
185
218
|
|
186
219
|
def as_text
|
187
|
-
@factory._generate_wkt(self)
|
220
|
+
str_ = @factory._generate_wkt(self)
|
221
|
+
str_.force_encoding('US-ASCII') if str_.respond_to?(:force_encoding)
|
222
|
+
str_
|
188
223
|
end
|
189
224
|
alias_method :to_s, :as_text
|
190
225
|
|
@@ -600,6 +600,40 @@ module RGeo
|
|
600
600
|
end
|
601
601
|
|
602
602
|
|
603
|
+
def _write_for_marshal(obj_) # :nodoc:
|
604
|
+
unless defined?(@marshal_wkb_writer)
|
605
|
+
@marshal_wkb_writer = ::Geos::WkbWriter.new
|
606
|
+
@marshal_wkb_writer.output_dimensions = (@_has_3d ? 3 : 2)
|
607
|
+
end
|
608
|
+
@marshal_wkb_writer.write(obj_)
|
609
|
+
end
|
610
|
+
|
611
|
+
|
612
|
+
def _read_for_marshal(str_) # :nodoc:
|
613
|
+
unless defined?(@marshal_wkb_reader)
|
614
|
+
@marshal_wkb_reader = ::Geos::WkbReader.new
|
615
|
+
end
|
616
|
+
@marshal_wkb_reader.read(str_)
|
617
|
+
end
|
618
|
+
|
619
|
+
|
620
|
+
def _write_for_psych(obj_) # :nodoc:
|
621
|
+
unless defined?(@psych_wkt_writer)
|
622
|
+
@psych_wkt_writer = ::Geos::WktWriter.new
|
623
|
+
@psych_wkt_writer.output_dimensions = (@_has_3d ? 3 : 2)
|
624
|
+
end
|
625
|
+
@psych_wkt_writer.write(obj_)
|
626
|
+
end
|
627
|
+
|
628
|
+
|
629
|
+
def _read_for_psych(str_) # :nodoc:
|
630
|
+
unless defined?(@psych_wkt_reader)
|
631
|
+
@psych_wkt_reader = ::Geos::WktReader.new
|
632
|
+
end
|
633
|
+
@psych_wkt_reader.read(str_)
|
634
|
+
end
|
635
|
+
|
636
|
+
|
603
637
|
end
|
604
638
|
|
605
639
|
|
@@ -46,6 +46,44 @@ module RGeo
|
|
46
46
|
"#<#{self.class}:0x#{object_id.to_s(16)} #{as_text.inspect}>"
|
47
47
|
end
|
48
48
|
|
49
|
+
|
50
|
+
# Marshal support
|
51
|
+
|
52
|
+
def marshal_dump # :nodoc:
|
53
|
+
factory_ = self.factory
|
54
|
+
[factory_, factory_._write_for_marshal(self)]
|
55
|
+
end
|
56
|
+
|
57
|
+
def marshal_load(data_) # :nodoc:
|
58
|
+
obj_ = data_[0]._read_for_marshal(data_[1])
|
59
|
+
_steal(obj_)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Psych support
|
64
|
+
|
65
|
+
def encode_with(coder_) # :nodoc:
|
66
|
+
factory_ = self.factory
|
67
|
+
coder_['factory'] = factory_
|
68
|
+
str_ = factory_._write_for_psych(self)
|
69
|
+
str_ = str_.encode('US-ASCII') if str_.respond_to?(:encode)
|
70
|
+
coder_['wkt'] = str_
|
71
|
+
end
|
72
|
+
|
73
|
+
def init_with(coder_) # :nodoc:
|
74
|
+
obj_ = coder_['factory']._read_for_psych(coder_['wkt'])
|
75
|
+
_steal(obj_)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def as_text
|
80
|
+
str_ = _as_text
|
81
|
+
str_.force_encoding('US-ASCII') if str_.respond_to?(:force_encoding)
|
82
|
+
str_
|
83
|
+
end
|
84
|
+
alias_method :to_s, :as_text
|
85
|
+
|
86
|
+
|
49
87
|
end
|
50
88
|
|
51
89
|
|
data/lib/rgeo/geos/zm_factory.rb
CHANGED
@@ -184,11 +184,13 @@ module RGeo
|
|
184
184
|
coder_['wkb_parser'] = @wkb_parser._properties
|
185
185
|
coder_['auto_prepare'] = @zfactory.property(:auto_prepare).to_s
|
186
186
|
coder_['native_interface'] = @zfactory.is_a?(FFIFactory) ? 'ffi' : 'capi'
|
187
|
-
if @proj4
|
188
|
-
str_ =
|
189
|
-
coder_['proj4'] =
|
187
|
+
if (proj4_ = @zfactory.proj4)
|
188
|
+
str_ = proj4_.original_str || proj4_.canonical_str
|
189
|
+
coder_['proj4'] = proj4_.radians? ? {'proj4' => str_, 'radians' => true} : str_
|
190
|
+
end
|
191
|
+
if (coord_sys_ = @zfactory.coord_sys)
|
192
|
+
coder_['coord_sys'] = coord_sys_.to_wkt
|
190
193
|
end
|
191
|
-
coder_['coord_sys'] = @coord_sys.to_wkt if @coord_sys
|
192
194
|
end
|
193
195
|
|
194
196
|
def init_with(coder_) # :nodoc:
|
@@ -408,6 +410,42 @@ module RGeo
|
|
408
410
|
end
|
409
411
|
|
410
412
|
|
413
|
+
def _marshal_wkb_generator # :nodoc:
|
414
|
+
unless defined?(@marshal_wkb_generator)
|
415
|
+
@marshal_wkb_generator = ::RGeo::WKRep::WKBGenerator.new(
|
416
|
+
:type_format => :wkb12)
|
417
|
+
end
|
418
|
+
@marshal_wkb_generator
|
419
|
+
end
|
420
|
+
|
421
|
+
|
422
|
+
def _marshal_wkb_parser # :nodoc:
|
423
|
+
unless defined?(@marshal_wkb_parser)
|
424
|
+
@marshal_wkb_parser = ::RGeo::WKRep::WKBParser.new(self,
|
425
|
+
:support_wkb12 => true)
|
426
|
+
end
|
427
|
+
@marshal_wkb_parser
|
428
|
+
end
|
429
|
+
|
430
|
+
|
431
|
+
def _psych_wkt_generator # :nodoc:
|
432
|
+
unless defined?(@psych_wkt_generator)
|
433
|
+
@psych_wkt_generator = ::RGeo::WKRep::WKTGenerator.new(
|
434
|
+
:tag_format => :wkt12)
|
435
|
+
end
|
436
|
+
@psych_wkt_generator
|
437
|
+
end
|
438
|
+
|
439
|
+
|
440
|
+
def _psych_wkt_parser # :nodoc:
|
441
|
+
unless defined?(@psych_wkt_parser)
|
442
|
+
@psych_wkt_parser = ::RGeo::WKRep::WKTParser.new(self,
|
443
|
+
:support_wkt12 => true, :support_ewkt => true)
|
444
|
+
end
|
445
|
+
@psych_wkt_parser
|
446
|
+
end
|
447
|
+
|
448
|
+
|
411
449
|
end
|
412
450
|
|
413
451
|
|
data/lib/rgeo/geos/zm_impl.rb
CHANGED
@@ -121,53 +121,53 @@ module RGeo
|
|
121
121
|
|
122
122
|
|
123
123
|
def equals?(rhs_)
|
124
|
-
@zgeometry.equals?(rhs_)
|
124
|
+
@zgeometry.equals?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
125
125
|
end
|
126
126
|
|
127
127
|
|
128
128
|
def disjoint?(rhs_)
|
129
|
-
@zgeometry.disjoint?(rhs_)
|
129
|
+
@zgeometry.disjoint?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
130
130
|
end
|
131
131
|
|
132
132
|
|
133
133
|
def intersects?(rhs_)
|
134
|
-
@zgeometry.intersects?(rhs_)
|
134
|
+
@zgeometry.intersects?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
135
135
|
end
|
136
136
|
|
137
137
|
|
138
138
|
def touches?(rhs_)
|
139
|
-
@zgeometry.touches?(rhs_)
|
139
|
+
@zgeometry.touches?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
140
140
|
end
|
141
141
|
|
142
142
|
|
143
143
|
def crosses?(rhs_)
|
144
|
-
@zgeometry.crosses?(rhs_)
|
144
|
+
@zgeometry.crosses?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
145
145
|
end
|
146
146
|
|
147
147
|
|
148
148
|
def within?(rhs_)
|
149
|
-
@zgeometry.within?(rhs_)
|
149
|
+
@zgeometry.within?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
150
150
|
end
|
151
151
|
|
152
152
|
|
153
153
|
def contains?(rhs_)
|
154
|
-
@zgeometry.contains?(rhs_)
|
154
|
+
@zgeometry.contains?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
155
155
|
end
|
156
156
|
|
157
157
|
|
158
158
|
def overlaps?(rhs_)
|
159
|
-
@zgeometry.overlaps?(rhs_)
|
159
|
+
@zgeometry.overlaps?(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
160
160
|
end
|
161
161
|
|
162
162
|
|
163
163
|
def relate?(rhs_, pattern_)
|
164
|
-
@zgeometry.relate?(rhs_, pattern_)
|
164
|
+
@zgeometry.relate?(::RGeo::Feature.cast(rhs_, self).z_geometry, pattern_)
|
165
165
|
end
|
166
166
|
alias_method :relate, :relate? # DEPRECATED
|
167
167
|
|
168
168
|
|
169
169
|
def distance(rhs_)
|
170
|
-
@zgeometry.distance(rhs_)
|
170
|
+
@zgeometry.distance(::RGeo::Feature.cast(rhs_, self).z_geometry)
|
171
171
|
end
|
172
172
|
|
173
173
|
|
@@ -182,26 +182,31 @@ module RGeo
|
|
182
182
|
|
183
183
|
|
184
184
|
def intersection(rhs_)
|
185
|
-
|
185
|
+
rhs_ = ::RGeo::Feature.cast(rhs_, self)
|
186
|
+
ZMGeometryImpl.create(@factory, @zgeometry.intersection(rhs_.z_geometry), @mgeometry.intersection(rhs_.m_geometry))
|
186
187
|
end
|
187
188
|
|
188
189
|
|
189
190
|
def union(rhs_)
|
190
|
-
|
191
|
+
rhs_ = ::RGeo::Feature.cast(rhs_, self)
|
192
|
+
ZMGeometryImpl.create(@factory, @zgeometry.union(rhs_.z_geometry), @mgeometry.union(rhs_.m_geometry))
|
191
193
|
end
|
192
194
|
|
193
195
|
|
194
196
|
def difference(rhs_)
|
195
|
-
|
197
|
+
rhs_ = ::RGeo::Feature.cast(rhs_, self)
|
198
|
+
ZMGeometryImpl.create(@factory, @zgeometry.difference(rhs_.z_geometry), @mgeometry.difference(rhs_.m_geometry))
|
196
199
|
end
|
197
200
|
|
198
201
|
|
199
202
|
def sym_difference(rhs_)
|
200
|
-
|
203
|
+
rhs_ = ::RGeo::Feature.cast(rhs_, self)
|
204
|
+
ZMGeometryImpl.create(@factory, @zgeometry.sym_difference(rhs_.z_geometry), @mgeometry.sym_difference(rhs_.m_geometry))
|
201
205
|
end
|
202
206
|
|
203
207
|
|
204
208
|
def rep_equals?(rhs_)
|
209
|
+
rhs_ = ::RGeo::Feature.cast(rhs_, self)
|
205
210
|
rhs_.is_a?(self.class) && @factory.eql?(rhs_.factory) && @zgeometry.rep_equals?(rhs_.z_geometry) && @mgeometry.rep_equals?(rhs_.m_geometry)
|
206
211
|
end
|
207
212
|
|
@@ -213,6 +218,33 @@ module RGeo
|
|
213
218
|
alias_method :+, :union
|
214
219
|
alias_method :*, :intersection
|
215
220
|
|
221
|
+
|
222
|
+
def _copy_state_from(obj_) # :nodoc:
|
223
|
+
@factory = obj_.factory
|
224
|
+
@zgeometry = obj_.z_geometry
|
225
|
+
@mgeometry = obj_.m_geometry
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
def marshal_dump # :nodoc:
|
230
|
+
[@factory, @factory._marshal_wkb_generator.generate(self)]
|
231
|
+
end
|
232
|
+
|
233
|
+
def marshal_load(data_) # :nodoc:
|
234
|
+
obj_ = data_[0]._marshal_wkb_parser.parse(data_[1])
|
235
|
+
_copy_state_from(data_[0]._marshal_wkb_parser.parse(data_[1]))
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
def encode_with(coder_) # :nodoc:
|
240
|
+
coder_['factory'] = @factory
|
241
|
+
coder_['wkt'] = @factory._psych_wkt_generator.generate(self)
|
242
|
+
end
|
243
|
+
|
244
|
+
def init_with(coder_) # :nodoc:
|
245
|
+
_copy_state_from(coder_['factory']._psych_wkt_parser.parse(coder_['wkt']))
|
246
|
+
end
|
247
|
+
|
216
248
|
end
|
217
249
|
|
218
250
|
|
@@ -68,12 +68,37 @@ module RGeo
|
|
68
68
|
|
69
69
|
|
70
70
|
def as_text
|
71
|
-
@factory.
|
71
|
+
@factory._generate_wkt(self)
|
72
72
|
end
|
73
73
|
|
74
74
|
|
75
75
|
def as_binary
|
76
|
-
@factory.
|
76
|
+
@factory._generate_wkb(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def _copy_state_from(obj_) # :nodoc:
|
81
|
+
@factory = obj_.factory
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def marshal_dump # :nodoc:
|
86
|
+
[@factory, @factory._marshal_wkb_generator.generate(self)]
|
87
|
+
end
|
88
|
+
|
89
|
+
def marshal_load(data_) # :nodoc:
|
90
|
+
obj_ = data_[0]._marshal_wkb_parser.parse(data_[1])
|
91
|
+
_copy_state_from(data_[0]._marshal_wkb_parser.parse(data_[1]))
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
def encode_with(coder_) # :nodoc:
|
96
|
+
coder_['factory'] = @factory
|
97
|
+
coder_['wkt'] = @factory._psych_wkt_generator.generate(self)
|
98
|
+
end
|
99
|
+
|
100
|
+
def init_with(coder_) # :nodoc:
|
101
|
+
_copy_state_from(coder_['factory']._psych_wkt_parser.parse(coder_['wkt']))
|
77
102
|
end
|
78
103
|
|
79
104
|
|
@@ -333,6 +333,30 @@ module RGeo
|
|
333
333
|
end
|
334
334
|
|
335
335
|
|
336
|
+
def test_marshal_roundtrip
|
337
|
+
point1_ = @factory.point(0, 0)
|
338
|
+
point2_ = @factory.point(0, 1)
|
339
|
+
line1_ = @factory.line_string([point1_, point2_])
|
340
|
+
data_ = ::Marshal.dump(line1_)
|
341
|
+
line2_ = ::Marshal.load(data_)
|
342
|
+
assert_equal(line1_, line2_)
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
if ::RGeo.yaml_supported?
|
347
|
+
|
348
|
+
def test_psych_roundtrip
|
349
|
+
point1_ = @factory.point(0, 0)
|
350
|
+
point2_ = @factory.point(0, 1)
|
351
|
+
line1_ = @factory.line_string([point1_, point2_])
|
352
|
+
data_ = ::Psych.dump(line1_)
|
353
|
+
line2_ = ::Psych.load(data_)
|
354
|
+
assert_equal(line1_, line2_)
|
355
|
+
end
|
356
|
+
|
357
|
+
end
|
358
|
+
|
359
|
+
|
336
360
|
end
|
337
361
|
|
338
362
|
end
|
data/test/common/point_tests.rb
CHANGED
@@ -334,6 +334,58 @@ module RGeo
|
|
334
334
|
end
|
335
335
|
|
336
336
|
|
337
|
+
def test_marshal_roundtrip
|
338
|
+
point_ = @factory.point(11, 12)
|
339
|
+
data_ = ::Marshal.dump(point_)
|
340
|
+
point2_ = ::Marshal.load(data_)
|
341
|
+
assert_equal(point_, point2_)
|
342
|
+
end
|
343
|
+
|
344
|
+
|
345
|
+
def test_marshal_roundtrip_3d
|
346
|
+
point_ = @zfactory.point(11, 12, 13)
|
347
|
+
data_ = ::Marshal.dump(point_)
|
348
|
+
point2_ = ::Marshal.load(data_)
|
349
|
+
assert_equal(point_, point2_)
|
350
|
+
end
|
351
|
+
|
352
|
+
|
353
|
+
def test_marshal_roundtrip_4d
|
354
|
+
point_ = @zmfactory.point(11, 12, 13, 14)
|
355
|
+
data_ = ::Marshal.dump(point_)
|
356
|
+
point2_ = ::Marshal.load(data_)
|
357
|
+
assert_equal(point_, point2_)
|
358
|
+
end
|
359
|
+
|
360
|
+
|
361
|
+
if ::RGeo.yaml_supported?
|
362
|
+
|
363
|
+
def test_psych_roundtrip
|
364
|
+
point_ = @factory.point(11, 12)
|
365
|
+
data_ = ::Psych.dump(point_)
|
366
|
+
point2_ = ::Psych.load(data_)
|
367
|
+
assert_equal(point_, point2_)
|
368
|
+
end
|
369
|
+
|
370
|
+
|
371
|
+
def test_psych_roundtrip_3d
|
372
|
+
point_ = @zfactory.point(11, 12, 13)
|
373
|
+
data_ = ::Psych.dump(point_)
|
374
|
+
point2_ = ::Psych.load(data_)
|
375
|
+
assert_equal(point_, point2_)
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
def test_psych_roundtrip_4d
|
380
|
+
point_ = @zmfactory.point(11, 12, 13, 14)
|
381
|
+
data_ = ::Psych.dump(point_)
|
382
|
+
point2_ = ::Psych.load(data_)
|
383
|
+
assert_equal(point_, point2_)
|
384
|
+
end
|
385
|
+
|
386
|
+
end
|
387
|
+
|
388
|
+
|
337
389
|
end
|
338
390
|
|
339
391
|
end
|
data/test/geos_capi/tc_point.rb
CHANGED
@@ -79,6 +79,24 @@ module RGeo
|
|
79
79
|
end
|
80
80
|
|
81
81
|
|
82
|
+
if defined?(::Encoding)
|
83
|
+
|
84
|
+
def test_as_text_encoding
|
85
|
+
factory_ = ::RGeo::Geos.factory(:wkt_generator => :geos)
|
86
|
+
point_ = factory_.point(11, 12)
|
87
|
+
assert_equal(::Encoding::US_ASCII, point_.as_text.encoding)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def test_as_binary_encoding
|
92
|
+
factory_ = ::RGeo::Geos.factory(:wkb_generator => :geos)
|
93
|
+
point_ = factory_.point(11, 12)
|
94
|
+
assert_equal(::Encoding::ASCII_8BIT, point_.as_binary.encoding)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
|
82
100
|
end
|
83
101
|
|
84
102
|
end
|
data/test/geos_ffi/tc_point.rb
CHANGED
@@ -80,6 +80,24 @@ module RGeo
|
|
80
80
|
end
|
81
81
|
|
82
82
|
|
83
|
+
if defined?(::Encoding)
|
84
|
+
|
85
|
+
def test_as_text_encoding
|
86
|
+
factory_ = ::RGeo::Geos.factory(:native_interface => :ffi, :wkt_generator => :geos)
|
87
|
+
point_ = factory_.point(11, 12)
|
88
|
+
assert_equal(::Encoding::US_ASCII, point_.as_text.encoding)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def test_as_binary_encoding
|
93
|
+
factory_ = ::RGeo::Geos.factory(:native_interface => :ffi, :wkb_generator => :geos)
|
94
|
+
point_ = factory_.point(11, 12)
|
95
|
+
assert_equal(::Encoding::ASCII_8BIT, point_.as_binary.encoding)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
|
83
101
|
end
|
84
102
|
|
85
103
|
end
|
data/test/tc_oneoff.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgeo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: RGeo is a geospatial data library for Ruby. It provides an implementation
|
15
15
|
of the Open Geospatial Consortium's Simple Features Specification, used by most
|