rgeo 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +11 -3
- data/Spatial_Programming_With_RGeo.rdoc +8 -8
- data/Version +1 -1
- data/ext/geos_c_impl/factory.c +20 -3
- data/ext/geos_c_impl/factory.h +2 -0
- data/ext/geos_c_impl/geometry.c +31 -19
- data/lib/rgeo/cartesian/factory.rb +32 -3
- data/lib/rgeo/cartesian/interface.rb +22 -2
- data/lib/rgeo/feature/factory.rb +1 -1
- data/lib/rgeo/feature/factory_generator.rb +1 -1
- data/lib/rgeo/feature/types.rb +3 -3
- data/lib/rgeo/geographic/factory.rb +31 -2
- data/lib/rgeo/geographic/interface.rb +68 -5
- data/lib/rgeo/geographic/proj4_projector.rb +8 -1
- data/lib/rgeo/geos.rb +1 -1
- data/lib/rgeo/geos/factory.rb +69 -4
- data/lib/rgeo/geos/impl_additions.rb +1 -1
- data/lib/rgeo/geos/interface.rb +31 -0
- data/lib/rgeo/geos/zm_factory.rb +33 -2
- data/lib/rgeo/geos/zm_impl.rb +3 -3
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +2 -2
- data/lib/rgeo/wkrep/wkb_generator.rb +1 -24
- data/lib/rgeo/wkrep/wkb_parser.rb +32 -43
- data/lib/rgeo/wkrep/wkt_generator.rb +21 -43
- data/lib/rgeo/wkrep/wkt_parser.rb +10 -41
- data/test/common/point_tests.rb +7 -1
- data/test/geos/tc_parsing_unparsing.rb +80 -0
- data/test/wkrep/tc_wkb_parser.rb +44 -37
- data/test/wkrep/tc_wkt_generator.rb +25 -25
- data/test/wkrep/tc_wkt_parser.rb +1 -3
- metadata +4 -2
data/History.rdoc
CHANGED
@@ -1,15 +1,23 @@
|
|
1
|
+
=== 0.2.9 / 2011-04-25
|
2
|
+
|
3
|
+
* INCOMPATIBLE CHANGE: mutator methods for the configurations of the WKRep parsers and generators have been removed. Create a new parser/generator if you need to change behavior.
|
4
|
+
* POSSIBLE INCOMPATIBLE CHANGE: The GEOS implementation now uses WKRep (by default) instead of the native GEOS WKB/WKT parsers and generators. This is because of some issues with the GEOS 3.2.2 implementation: namely, that the GEOS WKT generator suffers from some floating-point roundoff issues due to its "fixed point" output, and that the GEOS WKT parser fails to recognize names not in all caps, in violation of the version 1.2 update of the SFS. (Thanks to sharpone74 for report GH-4.)
|
5
|
+
* WKRep::WKTGenerator injects some more whitespace to make output more readable and more in line with the examples in the SFS.
|
6
|
+
* It is now possible to configure the WKT/WKB parsers/generators for each of the implementations, by passing the configuration hash to the factory constructor. In addition, it is also possible to configure the GEOS factory to use the native GEOS WKT/WKB implementation instead of RGeo::WKRep (that is, to restore the behavior of RGeo <= 0.2.8).
|
7
|
+
* The WKB parser auto-detects and interprets hex strings.
|
8
|
+
|
1
9
|
=== 0.2.8 / 2011-04-11
|
2
10
|
|
3
11
|
* A .gemspec file is now available for gem building and bundler git integration.
|
4
12
|
|
5
13
|
=== 0.2.7 / 2011-04-09
|
6
14
|
|
7
|
-
* POSSIBLE INCOMPATIBLE CHANGE: GeometryCollection#geometry_n, Polygon#interior_ring_n, and LineString#point_n, in some implementations, allowed negative indexes (which counted backwards from the end of the collection as per Ruby arrays.
|
15
|
+
* POSSIBLE INCOMPATIBLE CHANGE: GeometryCollection#geometry_n, Polygon#interior_ring_n, and LineString#point_n, in some implementations, allowed negative indexes (which counted backwards from the end of the collection as per Ruby arrays). This was contrary to the SFS interface, and so the behavior has been removed. However, GeometryCollection#[], because it is supposed to model Ruby arrays, now explicitly DOES allow negative indexes. This means GeometryCollection#[] is no longer exactly the same as GeometryCollection#geometry_n. These clarifications have also been made in the RDoc.
|
8
16
|
* The GEOS implementations of GeometryCollection#geometry_n and Polygon#interior_ring_n segfaulted when given an index out of bounds. Bounds Check Fail fixed. (Reported by sharpone74.)
|
9
17
|
|
10
18
|
=== 0.2.6 / 2011-03-31
|
11
19
|
|
12
|
-
* Ring direction analysis
|
20
|
+
* Ring direction analysis raised an exception if any of the line segments were zero length. Fixed. (Reported by spara.)
|
13
21
|
|
14
22
|
=== 0.2.5 / 2011-03-21
|
15
23
|
|
@@ -25,7 +33,7 @@
|
|
25
33
|
|
26
34
|
=== 0.2.3 / 2010-12-19
|
27
35
|
|
28
|
-
* The "
|
36
|
+
* The "simple mercator" geographic type incorrectly reported EPSG 3857 instead of EPSG 3785 for the projection. Dyslexia fixed.
|
29
37
|
* Geographic types couldn't have their coord_sys set. Fixed.
|
30
38
|
* You can now pass an :srs_database option when creating most factory types. This lets the factory look up its coordinate system using the given SRID.
|
31
39
|
* There are now explicit methods you can call to obtain FactoryGenerator objects; you should not need to call <tt>method</tt>.
|
@@ -242,12 +242,12 @@ Several size and distance calculations are available. You can compute the distan
|
|
242
242
|
The SFS defines two serialization schemes for geometric objects, known as the WKT (well-known text) and WKB (well-known binary) formats. The WKT is often used for textual display and transmission of a geometric object, while the WKB is sometimes used as an internal data format by spatial databases. Geometric objects in \RGeo define the <tt>as_text</tt> and <tt>as_binary</tt> methods to serialize the object into a data string, while \RGeo factories provide <tt>parse_wkt</tt> and <tt>parse_wkb</tt> methods to reconstruct geometric objects from their serialized form.
|
243
243
|
|
244
244
|
p00 = factory.point(0, 0)
|
245
|
-
p00.as_text # returns "Point(0 0)"
|
245
|
+
p00.as_text # returns "Point (0.0 0.0)"
|
246
246
|
p10 = factory.point(1, 0)
|
247
247
|
line = factory.line(p00, p10)
|
248
|
-
line.as_text # returns "LineString(0 0, 1 0)"
|
249
|
-
p = factory.parse_wkt('POINT(3 4)')
|
250
|
-
p.x # returns 3
|
248
|
+
line.as_text # returns "LineString (0.0 0.0, 1.0 0.0)"
|
249
|
+
p = factory.parse_wkt('POINT (3 4)')
|
250
|
+
p.x # returns 3.0
|
251
251
|
|
252
252
|
Note that there are several key shortcomings in the WKT and WKB formats as strictly defined by the SFS. In particular, neither format has official support for Z or M coordinates, and neither provides a way to specify the coordinate system (i.e. spatial reference ID) in which the object is represented. Because of this, variants of these formats have been developed. The most important to know are probably the EWKT and EWKB (or "extended" well-known formats) used by the PostGIS database, which supports Z and M as well as SRID. More recent versions of the SFS also have defined extensions to handle Z and M coordinates, but do not embed an SRID. \RGeo supports parsing and generating these variants through the RGeo::WKRep module.
|
253
253
|
|
@@ -291,11 +291,11 @@ Does this matter in your application? The answer is, it depends: on what kind of
|
|
291
291
|
|
292
292
|
This subsection covers some more advanced topics that most developers may not need to deal with directly, but I believe it is important to have at least a high-level understanding of them.
|
293
293
|
|
294
|
-
Simply put, there's more to a coordinate system than just the type: geocentric, geographic, or projected. For a geocentric coordinate system, we know it's centered at the center of the earth, but where _is_ the center of the earth? Which direction do the axes point? And do we measure the units in meters, miles, or light-years? For a geographic coordinate system, again, we need a center and orientation (i.e. where is the "zero longitude" line?), but we also need to define specifically _which_ "latitude". The latitude commonly used is the "geodetic latitude", which is the angle between the equator and what is normal (i.e. vertical) to the surface of the earth. This means it is dependent on one's model of the earth's surface, whether you use a sphere or a flattened ellipsoid, and how much flattening you choose. The same location on the earth's surface may have different latitudes depending on which system you use! As for projected systems, not only do we need to specify which projection to use (and there are hundreds defined), but we also need to know which geographic (latitude-longitude) system to start from. That is, a map projection is
|
294
|
+
Simply put, there's more to a coordinate system than just the type: geocentric, geographic, or projected. For a geocentric coordinate system, we know it's centered at the center of the earth, but where _is_ the center of the earth? Which direction do the axes point? And do we measure the units in meters, miles, or light-years? For a geographic coordinate system, again, we need a center and orientation (i.e. where is the "zero longitude" line?), but we also need to define specifically _which_ "latitude". The latitude commonly used is the "geodetic latitude", which is the angle between the equator and what is normal (i.e. vertical) to the surface of the earth. This means it is dependent on one's model of the earth's surface, whether you use a sphere or a flattened ellipsoid, and how much flattening you choose. The same location on the earth's surface may have different latitudes depending on which system you use! As for projected systems, not only do we need to specify which projection to use (and there are hundreds defined), but we also need to know which geographic (latitude-longitude) system to start from. That is, because a map projection is a function mapping latitude/longitude to flat coordinates, we need to specify _which_ latitude/longitude.
|
295
295
|
|
296
296
|
To completely specify a coordinate system, then, a number of parameters are involved. Below I briefly describe the major parameters and what they mean:
|
297
297
|
|
298
|
-
*Ellipsoid*: (Also called a *sphereoid*) An ellipsoid is an approximation of the shape of the earth, defined by the length of the <b>semi-major axis</b>, or the radius at the equator (measured in meters) and the <b>inverse flattening</b> ratio, defined as the ratio between the semi-major axis, and the difference between the semi-major and semi-minor axes. Note that the earth is not a true ellipsoid, both because the gravitational and centrifugal bulging is not solved exactly by an ellipsoid, and because of local changes in gravity due to, for example, large mountain ranges. However, an ellipsoid is commonly used for cartographic applications. The ellipsoid matters because it defines how latitude is measured and what path a straight line
|
298
|
+
*Ellipsoid*: (Also called a *sphereoid*) An ellipsoid is an approximation of the shape of the earth, defined by the length of the <b>semi-major axis</b>, or the radius at the equator (measured in meters) and the <b>inverse flattening</b> ratio, defined as the ratio between the semi-major axis, and the difference between the semi-major and semi-minor axes. Note that the earth is not a true ellipsoid, both because the gravitational and centrifugal bulging is not solved exactly by an ellipsoid, and because of local changes in gravity due to, for example, large mountain ranges. However, an ellipsoid is commonly used for cartographic applications. The ellipsoid matters because it defines how latitude is measured and what path will be followed by a "straight" line across the earth's surface.
|
299
299
|
|
300
300
|
*Datum*: This is a reference location against which measurements are made. There are generally two types of datums: horizontal datums, which define horizontal (e.g. latitude-longitude) coordinate systems, and vertical datums, which define the "zero altitude" point against which altitude measurements are made.
|
301
301
|
|
@@ -347,11 +347,11 @@ As we have seen, there exist a variety of ways to serialize geometric objects, n
|
|
347
347
|
|
348
348
|
The OGC defines a {specification}[http://www.opengeospatial.org/standards/sfs], related to the SFS, describing SQL extensions for a spatial database. This specification includes a table for spatial reference systems (that is, coordinate systems) which can contain OGC and Proj4 representations, and a table of metadata for geometry columns which stores such information as type, dimension, and srid constraints. It also defines a suite of SQL functions that you can call in a query. For example, in a compliant database, to find all rows in "mytable" where the geometry-valued column "geom" contains data within 5 units of the coordinates (10, 20), you might be able to run a query similar to:
|
349
349
|
|
350
|
-
SELECT * FROM mytable WHERE ST_Distance(geom, ST_WKTToSQL("POINT(10 20)")) > 5;
|
350
|
+
SELECT * FROM mytable WHERE ST_Distance(geom, ST_WKTToSQL("POINT (10 20)")) > 5;
|
351
351
|
|
352
352
|
Like all database queries, however, when there are a large number of rows, such a query can be slow if it has to do a full table scan. This is especially true if it has to evaluate geometric functions like the above, which can be numerically complex and slow to execute. To speed up queries, it is necessary to index your spatial columns.
|
353
353
|
|
354
|
-
Spatial indexes are somewhat more complex than typical database indexes. A typical B-tree index relies on a global ordering of data: the fact that you can sort scalar values in a binary tree and hence perform logarithmic-time searches. However, there isn't an obvious global ordering for spatial data. Should POINT(0 1) come before or after POINT(1 0)
|
354
|
+
Spatial indexes are somewhat more complex than typical database indexes. A typical B-tree index relies on a global ordering of data: the fact that you can sort scalar values in a binary tree and hence perform logarithmic-time searches. However, there isn't an obvious global ordering for spatial data. Should <tt>POINT (0 1)</tt> come before or after <tt>POINT (1 0)</tt>? And how do each of those compare with <tt>LINESTRING (0 1, 1 0)</tt>? Becase spatial data exists in two dimensions rather than one, and can span finite ranges in additional to infinitesimal points, the notion of a global ordering becomes ill-defined, and normal database indexes do not apply as well as we would like.
|
355
355
|
|
356
356
|
Spatial databases handle the problem of indexing spatial data in various ways, but most techniques are variants on an indexing algorithm known as an R-tree. I won't go into the details of how an R-tree works here. For the interested, I recommend the text {"Spatial Databases With Application To GIS"}[http://www.amazon.com/dp/1558605886], which covers a wide variety of issues related to basic spatial database implementation. For our purposes, just note that for large datasets, it is necessary to index the geometry columns, and that the index creation process may be different from that of normal scalar columns. The next sections provide some information specific to some of the common spatial databases.
|
357
357
|
|
data/Version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.9
|
data/ext/geos_c_impl/factory.c
CHANGED
@@ -99,6 +99,20 @@ static void destroy_geometry_func(RGeo_GeometryData* data)
|
|
99
99
|
}
|
100
100
|
|
101
101
|
|
102
|
+
// Mark function for factory data. This marks the wkt and wkb generator
|
103
|
+
// handles so they don't get collected.
|
104
|
+
|
105
|
+
static void mark_factory_func(RGeo_FactoryData* data)
|
106
|
+
{
|
107
|
+
if (!NIL_P(data->wkrep_wkt_generator)) {
|
108
|
+
rb_gc_mark(data->wkrep_wkt_generator);
|
109
|
+
}
|
110
|
+
if (!NIL_P(data->wkrep_wkb_generator)) {
|
111
|
+
rb_gc_mark(data->wkrep_wkb_generator);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
|
102
116
|
// Mark function for geometry data. This marks the factory and klasses
|
103
117
|
// held by the geometry so those don't get collected.
|
104
118
|
|
@@ -193,7 +207,8 @@ static VALUE method_factory_parse_wkb(VALUE self, VALUE str)
|
|
193
207
|
}
|
194
208
|
|
195
209
|
|
196
|
-
static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE buffer_resolution
|
210
|
+
static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE buffer_resolution,
|
211
|
+
VALUE wkt_generator, VALUE wkb_generator)
|
197
212
|
{
|
198
213
|
VALUE result = Qnil;
|
199
214
|
RGeo_FactoryData* data = ALLOC(RGeo_FactoryData);
|
@@ -210,7 +225,9 @@ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE
|
|
210
225
|
data->wkb_reader = NULL;
|
211
226
|
data->wkt_writer = NULL;
|
212
227
|
data->wkb_writer = NULL;
|
213
|
-
|
228
|
+
data->wkrep_wkt_generator = wkt_generator;
|
229
|
+
data->wkrep_wkb_generator = wkb_generator;
|
230
|
+
result = Data_Wrap_Struct(klass, mark_factory_func, destroy_factory_func, data);
|
214
231
|
}
|
215
232
|
else {
|
216
233
|
free(data);
|
@@ -237,7 +254,7 @@ RGeo_Globals* rgeo_init_geos_factory()
|
|
237
254
|
rb_define_method(geos_factory_class, "_srid", method_factory_srid, 0);
|
238
255
|
rb_define_method(geos_factory_class, "_buffer_resolution", method_factory_buffer_resolution, 0);
|
239
256
|
rb_define_method(geos_factory_class, "_flags", method_factory_flags, 0);
|
240
|
-
rb_define_module_function(geos_factory_class, "_create", cmethod_factory_create,
|
257
|
+
rb_define_module_function(geos_factory_class, "_create", cmethod_factory_create, 5);
|
241
258
|
|
242
259
|
// Wrap the globals in a Ruby object and store it off so we have access
|
243
260
|
// to it later. Each factory instance will reference it internally.
|
data/ext/geos_c_impl/factory.h
CHANGED
data/ext/geos_c_impl/geometry.c
CHANGED
@@ -209,16 +209,22 @@ static VALUE method_geometry_as_text(VALUE self)
|
|
209
209
|
const GEOSGeometry* self_geom = self_data->geom;
|
210
210
|
if (self_geom) {
|
211
211
|
RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory);
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
wkt_writer = GEOSWKTWriter_create_r(geos_context);
|
216
|
-
factory_data->wkt_writer = wkt_writer;
|
212
|
+
VALUE wkt_generator = factory_data->wkrep_wkt_generator;
|
213
|
+
if (!NIL_P(wkt_generator)) {
|
214
|
+
result = rb_funcall(wkt_generator, rb_intern("generate"), 1, self);
|
217
215
|
}
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
216
|
+
else {
|
217
|
+
GEOSWKTWriter* wkt_writer = factory_data->wkt_writer;
|
218
|
+
GEOSContextHandle_t geos_context = self_data->geos_context;
|
219
|
+
if (!wkt_writer) {
|
220
|
+
wkt_writer = GEOSWKTWriter_create_r(geos_context);
|
221
|
+
factory_data->wkt_writer = wkt_writer;
|
222
|
+
}
|
223
|
+
char* str = GEOSWKTWriter_write_r(geos_context, wkt_writer, self_geom);
|
224
|
+
if (str) {
|
225
|
+
result = rb_str_new2(str);
|
226
|
+
GEOSFree_r(geos_context, str);
|
227
|
+
}
|
222
228
|
}
|
223
229
|
}
|
224
230
|
return result;
|
@@ -232,17 +238,23 @@ static VALUE method_geometry_as_binary(VALUE self)
|
|
232
238
|
const GEOSGeometry* self_geom = self_data->geom;
|
233
239
|
if (self_geom) {
|
234
240
|
RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(self_data->factory);
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
wkb_writer = GEOSWKBWriter_create_r(geos_context);
|
239
|
-
factory_data->wkb_writer = wkb_writer;
|
241
|
+
VALUE wkb_generator = factory_data->wkrep_wkb_generator;
|
242
|
+
if (!NIL_P(wkb_generator)) {
|
243
|
+
result = rb_funcall(wkb_generator, rb_intern("generate"), 1, self);
|
240
244
|
}
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
245
|
+
else {
|
246
|
+
GEOSWKBWriter* wkb_writer = factory_data->wkb_writer;
|
247
|
+
GEOSContextHandle_t geos_context = self_data->geos_context;
|
248
|
+
if (!wkb_writer) {
|
249
|
+
wkb_writer = GEOSWKBWriter_create_r(geos_context);
|
250
|
+
factory_data->wkb_writer = wkb_writer;
|
251
|
+
}
|
252
|
+
size_t size;
|
253
|
+
char* str = (char*)GEOSWKBWriter_write_r(geos_context, wkb_writer, self_geom, &size);
|
254
|
+
if (str) {
|
255
|
+
result = rb_str_new(str, size);
|
256
|
+
GEOSFree_r(geos_context, str);
|
257
|
+
}
|
246
258
|
}
|
247
259
|
}
|
248
260
|
return result;
|
@@ -49,7 +49,7 @@ module RGeo
|
|
49
49
|
|
50
50
|
# Create a new simple cartesian factory.
|
51
51
|
#
|
52
|
-
# See ::RGeo::Cartesian
|
52
|
+
# See ::RGeo::Cartesian.simple_factory for a list of supported options.
|
53
53
|
|
54
54
|
def initialize(opts_={})
|
55
55
|
@has_z = opts_[:has_z_coordinate] ? true : false
|
@@ -76,6 +76,35 @@ module RGeo
|
|
76
76
|
end
|
77
77
|
srid_ ||= @coord_sys.authority_code if @coord_sys
|
78
78
|
@srid = srid_.to_i
|
79
|
+
|
80
|
+
wkt_generator_ = opts_[:wkt_generator]
|
81
|
+
case wkt_generator_
|
82
|
+
when ::Hash
|
83
|
+
@wkt_generator = WKRep::WKTGenerator.new(wkt_generator_)
|
84
|
+
else
|
85
|
+
@wkt_generator = WKRep::WKTGenerator.new(:convert_case => :upper)
|
86
|
+
end
|
87
|
+
wkb_generator_ = opts_[:wkb_generator]
|
88
|
+
case wkb_generator_
|
89
|
+
when ::Hash
|
90
|
+
@wkb_generator = WKRep::WKBGenerator.new(wkb_generator_)
|
91
|
+
else
|
92
|
+
@wkb_generator = WKRep::WKBGenerator.new
|
93
|
+
end
|
94
|
+
wkt_parser_ = opts_[:wkt_parser]
|
95
|
+
case wkt_parser_
|
96
|
+
when ::Hash
|
97
|
+
@wkt_parser = WKRep::WKTParser.new(self, wkt_parser_)
|
98
|
+
else
|
99
|
+
@wkt_parser = WKRep::WKTParser.new(self)
|
100
|
+
end
|
101
|
+
wkb_parser_ = opts_[:wkb_parser]
|
102
|
+
case wkb_parser_
|
103
|
+
when ::Hash
|
104
|
+
@wkb_parser = WKRep::WKBParser.new(self, wkb_parser_)
|
105
|
+
else
|
106
|
+
@wkb_parser = WKRep::WKBParser.new(self)
|
107
|
+
end
|
79
108
|
end
|
80
109
|
|
81
110
|
|
@@ -113,14 +142,14 @@ module RGeo
|
|
113
142
|
# See ::RGeo::Feature::Factory#parse_wkt
|
114
143
|
|
115
144
|
def parse_wkt(str_)
|
116
|
-
|
145
|
+
@wkt_parser.parse(str_)
|
117
146
|
end
|
118
147
|
|
119
148
|
|
120
149
|
# See ::RGeo::Feature::Factory#parse_wkb
|
121
150
|
|
122
151
|
def parse_wkb(str_)
|
123
|
-
|
152
|
+
@wkb_parser.parse(str_)
|
124
153
|
end
|
125
154
|
|
126
155
|
|
@@ -54,8 +54,9 @@ module RGeo
|
|
54
54
|
#
|
55
55
|
# The given options are passed to the factory's constructor.
|
56
56
|
# What options are available depends on the particular
|
57
|
-
# implementation. See Geos
|
58
|
-
# for details. Unsupported options
|
57
|
+
# implementation. See RGeo::Geos.factory and
|
58
|
+
# RGeo::Cartesian.simple_factory for details. Unsupported options
|
59
|
+
# are ignored.
|
59
60
|
|
60
61
|
def preferred_factory(opts_={})
|
61
62
|
if ::RGeo::Geos.supported?
|
@@ -110,6 +111,25 @@ module RGeo
|
|
110
111
|
# Support a Z coordinate. Default is false.
|
111
112
|
# [<tt>:has_m_coordinate</tt>]
|
112
113
|
# Support an M coordinate. Default is false.
|
114
|
+
# [<tt>:wkt_parser</tt>]
|
115
|
+
# Configure the parser for WKT. The value is a hash of
|
116
|
+
# configuration parameters for WKRep::WKTParser.new. Default is
|
117
|
+
# the empty hash, indicating the default configuration for
|
118
|
+
# WKRep::WKTParser.
|
119
|
+
# [<tt>:wkb_parser</tt>]
|
120
|
+
# Configure the parser for WKB. The value is a hash of
|
121
|
+
# configuration parameters for WKRep::WKBParser.new. Default is
|
122
|
+
# the empty hash, indicating the default configuration for
|
123
|
+
# WKRep::WKBParser.
|
124
|
+
# [<tt>:wkt_generator</tt>]
|
125
|
+
# Configure the generator for WKT. The value is a hash of
|
126
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
127
|
+
# Default is <tt>{:convert_case => :upper}</tt>.
|
128
|
+
# [<tt>:wkb_generator</tt>]
|
129
|
+
# Configure the generator for WKT. The value is a hash of
|
130
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
131
|
+
# Default is the empty hash, indicating the default configuration
|
132
|
+
# for WKRep::WKBGenerator.
|
113
133
|
|
114
134
|
def simple_factory(opts_={})
|
115
135
|
Cartesian::Factory.new(opts_)
|
data/lib/rgeo/feature/factory.rb
CHANGED
@@ -313,7 +313,7 @@ module RGeo
|
|
313
313
|
#
|
314
314
|
# It should return either a casted result object, false, or nil.
|
315
315
|
# A nil return value indicates that casting should be forced to
|
316
|
-
# fail (and RGeo::Feature
|
316
|
+
# fail (and RGeo::Feature.cast will return nil).
|
317
317
|
# A false return value indicates that this method declines to
|
318
318
|
# override the casting algorithm, and RGeo should use its default
|
319
319
|
# algorithm to cast the object. Therefore, by default, you should
|
@@ -50,7 +50,7 @@ module RGeo
|
|
50
50
|
# factory generator.
|
51
51
|
#
|
52
52
|
# Many of the implementations provide a factory method for creating
|
53
|
-
# factories. For example, RGeo::Cartesian
|
53
|
+
# factories. For example, RGeo::Cartesian.preferred_factory can be
|
54
54
|
# called to create a factory using the preferred Cartesian
|
55
55
|
# implementation. Thus, to get a corresponding factory generator,
|
56
56
|
# you can use the <tt>method</tt> method. e.g.
|
data/lib/rgeo/feature/types.rb
CHANGED
@@ -146,9 +146,9 @@ module RGeo
|
|
146
146
|
# values to true. You can even combine separate arguments and hash
|
147
147
|
# arguments. For example, the following three calls are equivalent:
|
148
148
|
#
|
149
|
-
# Feature.cast(geom, :type => Feature::Point, :project => true)
|
150
|
-
# Feature.cast(geom, Feature::Point, :project => true)
|
151
|
-
# Feature.cast(geom, Feature::Point, :project)
|
149
|
+
# RGeo::Feature.cast(geom, :type => RGeo::Feature::Point, :project => true)
|
150
|
+
# RGeo::Feature.cast(geom, RGeo::Feature::Point, :project => true)
|
151
|
+
# RGeo::Feature.cast(geom, RGeo::Feature::Point, :project)
|
152
152
|
#
|
153
153
|
# RGeo provides a default casting algorithm. Individual feature
|
154
154
|
# implementation factories may override this and customize the
|
@@ -74,6 +74,35 @@ module RGeo
|
|
74
74
|
if @coord_sys.kind_of?(::String)
|
75
75
|
@coord_sys = CoordSys::CS.create_from_wkt(@coord_sys) rescue nil
|
76
76
|
end
|
77
|
+
|
78
|
+
wkt_generator_ = opts_[:wkt_generator]
|
79
|
+
case wkt_generator_
|
80
|
+
when ::Hash
|
81
|
+
@wkt_generator = WKRep::WKTGenerator.new(wkt_generator_)
|
82
|
+
else
|
83
|
+
@wkt_generator = WKRep::WKTGenerator.new(:convert_case => :upper)
|
84
|
+
end
|
85
|
+
wkb_generator_ = opts_[:wkb_generator]
|
86
|
+
case wkb_generator_
|
87
|
+
when ::Hash
|
88
|
+
@wkb_generator = WKRep::WKBGenerator.new(wkb_generator_)
|
89
|
+
else
|
90
|
+
@wkb_generator = WKRep::WKBGenerator.new
|
91
|
+
end
|
92
|
+
wkt_parser_ = opts_[:wkt_parser]
|
93
|
+
case wkt_parser_
|
94
|
+
when ::Hash
|
95
|
+
@wkt_parser = WKRep::WKTParser.new(self, wkt_parser_)
|
96
|
+
else
|
97
|
+
@wkt_parser = WKRep::WKTParser.new(self)
|
98
|
+
end
|
99
|
+
wkb_parser_ = opts_[:wkb_parser]
|
100
|
+
case wkb_parser_
|
101
|
+
when ::Hash
|
102
|
+
@wkb_parser = WKRep::WKBParser.new(self, wkb_parser_)
|
103
|
+
else
|
104
|
+
@wkb_parser = WKRep::WKBParser.new(self)
|
105
|
+
end
|
77
106
|
end
|
78
107
|
|
79
108
|
|
@@ -192,14 +221,14 @@ module RGeo
|
|
192
221
|
# See ::RGeo::Feature::Factory#parse_wkt
|
193
222
|
|
194
223
|
def parse_wkt(str_)
|
195
|
-
|
224
|
+
@wkt_parser.parse(str_)
|
196
225
|
end
|
197
226
|
|
198
227
|
|
199
228
|
# See ::RGeo::Feature::Factory#parse_wkb
|
200
229
|
|
201
230
|
def parse_wkb(str_)
|
202
|
-
|
231
|
+
@wkb_parser.parse(str_)
|
203
232
|
end
|
204
233
|
|
205
234
|
|
@@ -110,6 +110,25 @@ module RGeo
|
|
110
110
|
# CoordSys::SRSDatabase::Interface. If both this and an SRID are
|
111
111
|
# provided, they are used to look up the proj4 and coord_sys
|
112
112
|
# objects from a spatial reference system database.
|
113
|
+
# [<tt>:wkt_parser</tt>]
|
114
|
+
# Configure the parser for WKT. The value is a hash of
|
115
|
+
# configuration parameters for WKRep::WKTParser.new. Default is
|
116
|
+
# the empty hash, indicating the default configuration for
|
117
|
+
# WKRep::WKTParser.
|
118
|
+
# [<tt>:wkb_parser</tt>]
|
119
|
+
# Configure the parser for WKB. The value is a hash of
|
120
|
+
# configuration parameters for WKRep::WKBParser.new. Default is
|
121
|
+
# the empty hash, indicating the default configuration for
|
122
|
+
# WKRep::WKBParser.
|
123
|
+
# [<tt>:wkt_generator</tt>]
|
124
|
+
# Configure the generator for WKT. The value is a hash of
|
125
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
126
|
+
# Default is <tt>{:convert_case => :upper}</tt>.
|
127
|
+
# [<tt>:wkb_generator</tt>]
|
128
|
+
# Configure the generator for WKT. The value is a hash of
|
129
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
130
|
+
# Default is the empty hash, indicating the default configuration
|
131
|
+
# for WKRep::WKBGenerator.
|
113
132
|
|
114
133
|
def spherical_factory(opts_={})
|
115
134
|
proj4_ = opts_[:proj4]
|
@@ -177,12 +196,31 @@ module RGeo
|
|
177
196
|
# Support a Z coordinate. Default is false.
|
178
197
|
# [<tt>:has_m_coordinate</tt>]
|
179
198
|
# Support an M coordinate. Default is false.
|
199
|
+
# [<tt>:wkt_parser</tt>]
|
200
|
+
# Configure the parser for WKT. The value is a hash of
|
201
|
+
# configuration parameters for WKRep::WKTParser.new. Default is
|
202
|
+
# the empty hash, indicating the default configuration for
|
203
|
+
# WKRep::WKTParser.
|
204
|
+
# [<tt>:wkb_parser</tt>]
|
205
|
+
# Configure the parser for WKB. The value is a hash of
|
206
|
+
# configuration parameters for WKRep::WKBParser.new. Default is
|
207
|
+
# the empty hash, indicating the default configuration for
|
208
|
+
# WKRep::WKBParser.
|
209
|
+
# [<tt>:wkt_generator</tt>]
|
210
|
+
# Configure the generator for WKT. The value is a hash of
|
211
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
212
|
+
# Default is <tt>{:convert_case => :upper}</tt>.
|
213
|
+
# [<tt>:wkb_generator</tt>]
|
214
|
+
# Configure the generator for WKT. The value is a hash of
|
215
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
216
|
+
# Default is the empty hash, indicating the default configuration
|
217
|
+
# for WKRep::WKBGenerator.
|
180
218
|
#
|
181
219
|
# You may also provide options understood by the underlying
|
182
220
|
# projected Cartesian factory. For example, if GEOS is used for the
|
183
221
|
# projected factory, you may also set the
|
184
222
|
# <tt>:lenient_multi_polygon_assertions</tt> and
|
185
|
-
# <tt>:buffer_resolution</tt> options. See RGeo::Geos
|
223
|
+
# <tt>:buffer_resolution</tt> options. See RGeo::Geos.factory for
|
186
224
|
# more details.
|
187
225
|
|
188
226
|
def simple_mercator_factory(opts_={})
|
@@ -287,12 +325,31 @@ module RGeo
|
|
287
325
|
# Note: this is ignored if a <tt>:projection_factory</tt> is
|
288
326
|
# provided; in that case, the geographic factory's m-coordinate
|
289
327
|
# availability will match the projection factory's setting.
|
328
|
+
# [<tt>:wkt_parser</tt>]
|
329
|
+
# Configure the parser for WKT. The value is a hash of
|
330
|
+
# configuration parameters for WKRep::WKTParser.new. Default is
|
331
|
+
# the empty hash, indicating the default configuration for
|
332
|
+
# WKRep::WKTParser.
|
333
|
+
# [<tt>:wkb_parser</tt>]
|
334
|
+
# Configure the parser for WKB. The value is a hash of
|
335
|
+
# configuration parameters for WKRep::WKBParser.new. Default is
|
336
|
+
# the empty hash, indicating the default configuration for
|
337
|
+
# WKRep::WKBParser.
|
338
|
+
# [<tt>:wkt_generator</tt>]
|
339
|
+
# Configure the generator for WKT. The value is a hash of
|
340
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
341
|
+
# Default is <tt>{:convert_case => :upper}</tt>.
|
342
|
+
# [<tt>:wkb_generator</tt>]
|
343
|
+
# Configure the generator for WKT. The value is a hash of
|
344
|
+
# configuration parameters for WKRep::WKTGenerator.new.
|
345
|
+
# Default is the empty hash, indicating the default configuration
|
346
|
+
# for WKRep::WKBGenerator.
|
290
347
|
#
|
291
348
|
# If a <tt>:projection_factory</tt> is _not_ provided, you may also
|
292
349
|
# provide options for configuring the projected Cartesian factory.
|
293
350
|
# For example, if GEOS is used for the projected factory, you may
|
294
351
|
# also set the <tt>:lenient_multi_polygon_assertions</tt> and
|
295
|
-
# <tt>:buffer_resolution</tt> options. See RGeo::Geos
|
352
|
+
# <tt>:buffer_resolution</tt> options. See RGeo::Geos.factory for
|
296
353
|
# more details.
|
297
354
|
|
298
355
|
def projected_factory(opts_={})
|
@@ -333,7 +390,9 @@ module RGeo
|
|
333
390
|
:coord_sys => coord_sys_,
|
334
391
|
:srid => srid_.to_i,
|
335
392
|
:has_z_coordinate => projection_factory_.property(:has_z_coordinate),
|
336
|
-
:has_m_coordinate => projection_factory_.property(:has_m_coordinate)
|
393
|
+
:has_m_coordinate => projection_factory_.property(:has_m_coordinate),
|
394
|
+
:wkt_parser => opts_[:wkt_parser], :wkt_generator => opts_[:wkt_generator],
|
395
|
+
:wkb_parser => opts_[:wkb_parser], :wkb_generator => opts_[:wkb_generator])
|
337
396
|
projector_ = Geographic::Proj4Projector.create_from_existing_factory(factory_,
|
338
397
|
projection_factory_)
|
339
398
|
else
|
@@ -388,7 +447,9 @@ module RGeo
|
|
388
447
|
:coord_sys => coord_sys_,
|
389
448
|
:srid => srid_.to_i,
|
390
449
|
:has_z_coordinate => opts_[:has_z_coordinate],
|
391
|
-
:has_m_coordinate => opts_[:has_m_coordinate]
|
450
|
+
:has_m_coordinate => opts_[:has_m_coordinate],
|
451
|
+
:wkt_parser => opts_[:wkt_parser], :wkt_generator => opts_[:wkt_generator],
|
452
|
+
:wkb_parser => opts_[:wkb_parser], :wkb_generator => opts_[:wkb_generator])
|
392
453
|
projector_ = Geographic::Proj4Projector.create_from_proj4(factory_,
|
393
454
|
projection_proj4_,
|
394
455
|
:srid => projection_srid_,
|
@@ -396,7 +457,9 @@ module RGeo
|
|
396
457
|
:buffer_resolution => opts_[:buffer_resolution],
|
397
458
|
:lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions],
|
398
459
|
:has_z_coordinate => opts_[:has_z_coordinate],
|
399
|
-
:has_m_coordinate => opts_[:has_m_coordinate]
|
460
|
+
:has_m_coordinate => opts_[:has_m_coordinate],
|
461
|
+
:wkt_parser => opts_[:wkt_parser], :wkt_generator => opts_[:wkt_generator],
|
462
|
+
:wkb_parser => opts_[:wkb_parser], :wkb_generator => opts_[:wkb_generator])
|
400
463
|
end
|
401
464
|
factory_._set_projector(projector_)
|
402
465
|
factory_
|