rgeo 0.1.22 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +31 -0
- data/README.rdoc +53 -59
- data/Spatial_Programming_With_RGeo.rdoc +120 -67
- data/Version +1 -1
- data/ext/proj4_c_impl/extconf.rb +1 -1
- data/lib/rgeo.rb +80 -87
- data/lib/rgeo/cartesian.rb +0 -10
- data/lib/rgeo/coord_sys.rb +0 -7
- data/lib/rgeo/coord_sys/proj4.rb +2 -2
- data/lib/rgeo/error.rb +2 -6
- data/lib/rgeo/feature.rb +0 -7
- data/lib/rgeo/feature/curve.rb +5 -5
- data/lib/rgeo/feature/factory.rb +45 -5
- data/lib/rgeo/feature/factory_generator.rb +2 -4
- data/lib/rgeo/feature/geometry.rb +97 -27
- data/lib/rgeo/feature/geometry_collection.rb +3 -3
- data/lib/rgeo/feature/line_string.rb +3 -3
- data/lib/rgeo/feature/multi_curve.rb +2 -2
- data/lib/rgeo/feature/multi_surface.rb +3 -3
- data/lib/rgeo/feature/point.rb +6 -6
- data/lib/rgeo/feature/polygon.rb +4 -4
- data/lib/rgeo/feature/surface.rb +3 -3
- data/lib/rgeo/geographic.rb +0 -11
- data/lib/rgeo/geographic/factory.rb +5 -2
- data/lib/rgeo/geographic/interface.rb +1 -1
- data/lib/rgeo/geos.rb +0 -7
- data/lib/rgeo/geos/factory.rb +1 -1
- data/lib/rgeo/impl_helper.rb +0 -7
- data/lib/rgeo/wkrep.rb +0 -7
- data/lib/rgeo/wkrep/wkb_parser.rb +2 -2
- data/test/tc_oneoff.rb +0 -1
- metadata +7 -155
- data/lib/active_record/connection_adapters/mysql2spatial_adapter.rb +0 -124
- data/lib/active_record/connection_adapters/mysqlspatial_adapter.rb +0 -136
- data/lib/active_record/connection_adapters/postgis_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/spatialite_adapter.rb +0 -488
- data/lib/rgeo/active_record/arel_modifications.rb +0 -78
- data/lib/rgeo/active_record/base_modifications.rb +0 -124
- data/lib/rgeo/active_record/common.rb +0 -166
- data/lib/rgeo/active_record/mysql_common.rb +0 -150
- data/lib/rgeo/all.rb +0 -49
- data/lib/rgeo/geo_json.rb +0 -60
- data/lib/rgeo/geo_json/coder.rb +0 -401
- data/lib/rgeo/geo_json/entities.rb +0 -285
- data/lib/rgeo/geo_json/interface.rb +0 -129
- data/lib/rgeo/shapefile.rb +0 -60
- data/lib/rgeo/shapefile/reader.rb +0 -898
- data/test/active_record/common_setup_methods.rb +0 -129
- data/test/active_record/readme.txt +0 -43
- data/test/active_record/tc_mysqlspatial.rb +0 -170
- data/test/active_record/tc_postgis.rb +0 -282
- data/test/active_record/tc_spatialite.rb +0 -198
- data/test/shapefile/shapelib_testcases/readme.txt +0 -11
- data/test/shapefile/shapelib_testcases/test.dbf +0 -0
- data/test/shapefile/shapelib_testcases/test.shp +0 -0
- data/test/shapefile/shapelib_testcases/test.shx +0 -0
- data/test/shapefile/shapelib_testcases/test0.shp +0 -0
- data/test/shapefile/shapelib_testcases/test0.shx +0 -0
- data/test/shapefile/shapelib_testcases/test1.shp +0 -0
- data/test/shapefile/shapelib_testcases/test1.shx +0 -0
- data/test/shapefile/shapelib_testcases/test10.shp +0 -0
- data/test/shapefile/shapelib_testcases/test10.shx +0 -0
- data/test/shapefile/shapelib_testcases/test11.shp +0 -0
- data/test/shapefile/shapelib_testcases/test11.shx +0 -0
- data/test/shapefile/shapelib_testcases/test12.shp +0 -0
- data/test/shapefile/shapelib_testcases/test12.shx +0 -0
- data/test/shapefile/shapelib_testcases/test13.shp +0 -0
- data/test/shapefile/shapelib_testcases/test13.shx +0 -0
- data/test/shapefile/shapelib_testcases/test2.shp +0 -0
- data/test/shapefile/shapelib_testcases/test2.shx +0 -0
- data/test/shapefile/shapelib_testcases/test3.shp +0 -0
- data/test/shapefile/shapelib_testcases/test3.shx +0 -0
- data/test/shapefile/shapelib_testcases/test4.shp +0 -0
- data/test/shapefile/shapelib_testcases/test4.shx +0 -0
- data/test/shapefile/shapelib_testcases/test5.shp +0 -0
- data/test/shapefile/shapelib_testcases/test5.shx +0 -0
- data/test/shapefile/shapelib_testcases/test6.shp +0 -0
- data/test/shapefile/shapelib_testcases/test6.shx +0 -0
- data/test/shapefile/shapelib_testcases/test7.shp +0 -0
- data/test/shapefile/shapelib_testcases/test7.shx +0 -0
- data/test/shapefile/shapelib_testcases/test8.shp +0 -0
- data/test/shapefile/shapelib_testcases/test8.shx +0 -0
- data/test/shapefile/shapelib_testcases/test9.shp +0 -0
- data/test/shapefile/shapelib_testcases/test9.shx +0 -0
- data/test/shapefile/tc_shapelib_tests.rb +0 -527
- data/test/tc_geojson.rb +0 -279
data/History.rdoc
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
=== 0.2.0 / 2010-12-07
|
2
|
+
|
3
|
+
This is the first public alpha version of RGeo. With this version, we are soft-locking the API interfaces and will try to retain backwards compatibility from this point. Incompatible API changes may still be done, but only if considered necessary.
|
4
|
+
|
5
|
+
With this release, RGeo has been split into a core library and a set of optional modules. The following modules remain in the core "rgeo" gem:
|
6
|
+
* RGeo::Feature
|
7
|
+
* RGeo::CoordSys
|
8
|
+
* RGeo::Geos
|
9
|
+
* RGeo::Cartesian
|
10
|
+
* RGeo::Geographic
|
11
|
+
* RGeo::WKRep
|
12
|
+
|
13
|
+
The following modules have been spun off into separate gems:
|
14
|
+
* RGeo::GeoJSON has been spun off into the "rgeo-geojson" gem.
|
15
|
+
* RGeo::Shapefile has been spun off into the "rgeo-shapefile" gem.
|
16
|
+
* RGeo::ActiveRecord has been spun off into the "rgeo-activerecord" gem.
|
17
|
+
|
18
|
+
The ActiveRecord adapters have been spun off into gems according to the recommended ActiveRecord naming scheme:
|
19
|
+
* The <b>mysqlspatial</b> adapter is now in the gem "activerecord-mysqlspatial-adapter".
|
20
|
+
* The <b>mysql2spatial</b> adapter is now in the gem "activerecord-mysql2spatial-adapter".
|
21
|
+
* The <b>spatialite</b> adapter is now in the gem "activerecord-spatialite-adapter".
|
22
|
+
* The <b>postgis</b> adapter is now in the gem "activerecord-postgis-adapter".
|
23
|
+
|
24
|
+
Any additional modules likely will be distributed similarly as separate gems.
|
25
|
+
|
26
|
+
Other changes in this version:
|
27
|
+
* API CHANGE: Renamed UnsupportedCapability to UnsupportedOperation since we've done away with the "capability" concept.
|
28
|
+
* Proj4 integration wasn't building into the right location on a gem install. Fixed.
|
29
|
+
* Various updates to the rdocs.
|
30
|
+
* Minor updates to the Spatial Programming paper.
|
31
|
+
|
1
32
|
=== 0.1.22 / 2010-12-05
|
2
33
|
|
3
34
|
This should be the last pre-alpha development version. The next version planned is the 0.2 alpha release.
|
data/README.rdoc
CHANGED
@@ -8,12 +8,11 @@ RGeo is a key component for writing location-aware applications in the
|
|
8
8
|
Ruby programming language. At its core is an implementation of the
|
9
9
|
industry standard OGC Simple Features Specification, which provides data
|
10
10
|
representations of geometric objects such as points, lines, and polygons,
|
11
|
-
along with a set of geometric analysis operations.
|
12
|
-
|
13
|
-
|
14
|
-
applications with Ruby On Rails.
|
11
|
+
along with a set of geometric analysis operations. This makes it ideal
|
12
|
+
for modeling geolocation data. It also supports a suite of optional add-on
|
13
|
+
modules that provide various geolocation-related services.
|
15
14
|
|
16
|
-
Use
|
15
|
+
Use the core *rgeo* gem to:
|
17
16
|
|
18
17
|
* Represent spatial and geolocation data objects such as points, lines,
|
19
18
|
and polygons in your Ruby application.
|
@@ -21,46 +20,44 @@ Use RGeo to:
|
|
21
20
|
intersections, creating buffers, and computing lengths and areas.
|
22
21
|
* Correctly handle spherical geometry, and compute geographic projections
|
23
22
|
for map display and data analysis.
|
24
|
-
*
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
* Read legacy GIS data from ESRI shapefiles.
|
29
|
-
* Extend Ruby On Rails to handle location data in a web application.
|
30
|
-
* Write to the latest standards from the Open Geospatial Consortium.
|
23
|
+
* Read and write location data in the WKT and WKB representations used by
|
24
|
+
spatial databases.
|
25
|
+
|
26
|
+
Several optional modules are currently available:
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
* Generate and interpret GeoJSON data for communication with common
|
29
|
+
location-based web services such as SimpleGeo, using the
|
30
|
+
<b>rgeo-geojson</b> gem.
|
31
|
+
* Read GIS datasets from ESRI shapefiles using the <b>rgeo-shapefile</b>
|
32
|
+
gem.
|
33
|
+
* Extend ActiveRecord to handle spatial data in MySQL Spatial, SpatiaLite,
|
34
|
+
and PostGIS using RGeo's spatial ActiveRecord adapters. These are
|
35
|
+
available via the gems:
|
36
|
+
* <b>activerecord-mysqlspatial-adapter</b>
|
37
|
+
* <b>activerecord-mysql2spatial-adapter</b>
|
38
|
+
* <b>activerecord-spatialite-adapter</b>
|
39
|
+
* <b>activerecord-postgis-adapter</b>
|
40
|
+
* and more to come...
|
37
41
|
|
38
42
|
=== Requirements
|
39
43
|
|
40
|
-
RGeo has the following
|
44
|
+
RGeo has the following requirements:
|
41
45
|
|
42
46
|
* Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred.
|
43
47
|
Rubinius and JRuby are not yet supported.
|
48
|
+
* The build system assumes a unix-like environment. Windows builds may be
|
49
|
+
possible, but not likely "out of the box".
|
44
50
|
|
45
51
|
Some features also require the following:
|
46
52
|
|
47
53
|
* GEOS 3.2 or later is highly recommended. Some functions will not be
|
48
54
|
available without it. This C/C++ library may be available via your
|
49
55
|
operating system's package manager, or you can download it from
|
50
|
-
http://
|
51
|
-
* Proj 4.7
|
52
|
-
to translate coordinates between geographic projections. It also
|
53
|
-
be available via your operating system's package manager, or from
|
54
|
-
http://trac.osgeo.org/proj
|
55
|
-
* If you are using the GeoJSON tools under Ruby 1.8.7, you should
|
56
|
-
install the "json" gem. Ruby 1.9 has JSON support in its standard
|
57
|
-
library and does not require the gem.
|
58
|
-
* If you are using the shapefile reader, you should install the "dbf"
|
59
|
-
gem, version 1.5.2 or later, which is needed to read the attributes.
|
60
|
-
* The ActiveRecord adapters for MySQL Spatial, PostGIS, and SpatiaLite
|
61
|
-
require ActiveRecord 3.0.3 or later, and the corresponding database
|
62
|
-
driver gems (e.g. "mysql", "mysql2", "sqlite3-ruby", "pg", etc.).
|
63
|
-
Note that the adapters are NOT compatible with ActiveRecord 2.3.
|
56
|
+
http://trac.osgeo.org/geos
|
57
|
+
* Proj 4.7 or later is also recommended. This library is needed if you
|
58
|
+
want to translate coordinates between geographic projections. It also
|
59
|
+
may be available via your operating system's package manager, or from
|
60
|
+
http://trac.osgeo.org/proj
|
64
61
|
|
65
62
|
=== Installation
|
66
63
|
|
@@ -68,8 +65,8 @@ Install RGeo as a gem:
|
|
68
65
|
|
69
66
|
gem install rgeo
|
70
67
|
|
71
|
-
Note: By default, the gem installation looks for the
|
72
|
-
|
68
|
+
Note: By default, the gem installation looks for the GEOS library in the
|
69
|
+
following locations:
|
73
70
|
|
74
71
|
* /usr/local
|
75
72
|
* /usr/local/geos
|
@@ -95,20 +92,23 @@ following locations by default:
|
|
95
92
|
If Proj4 is installed in a different location, you must provide its
|
96
93
|
installation prefix directory using the "--with-proj-dir" option.
|
97
94
|
|
98
|
-
=== To-do
|
95
|
+
=== To-do list
|
99
96
|
|
100
|
-
|
97
|
+
The RGeo suite of tools is evolving rapidly. The current to-do list for
|
98
|
+
the core library includes:
|
101
99
|
|
102
|
-
* OGC coordinate system
|
103
|
-
*
|
104
|
-
* Possible Arel extensions for constructing spatial queries.
|
105
|
-
* Support for bbox and crs elements of GeoJSON.
|
100
|
+
* Implementation of the OGC coordinate system spec.
|
101
|
+
* Integration with spatial reference system databases.
|
106
102
|
* Ellipsoidal geography implementation, probably utilizing geographiclib.
|
107
|
-
*
|
108
|
-
*
|
109
|
-
|
110
|
-
|
111
|
-
|
103
|
+
* Rubinius and JRuby support.
|
104
|
+
* Windows build support.
|
105
|
+
|
106
|
+
Each of the current add-on modules also has its own feature roadmap, and
|
107
|
+
we are planning on introducing more add-on modules, including:
|
108
|
+
|
109
|
+
* GeoRSS and KML format support.
|
110
|
+
* Integration with the SimpleGeo API.
|
111
|
+
* Possible additional ActiveRecord adapters.
|
112
112
|
|
113
113
|
=== Development and support
|
114
114
|
|
@@ -116,29 +116,23 @@ Documentation is available at http://virtuoso.rubyforge.org/rgeo/README_rdoc.htm
|
|
116
116
|
|
117
117
|
Source code is hosted on Github at http://github.com/dazuma/rgeo
|
118
118
|
|
119
|
+
Contributions are welcome. Fork the project on Github.
|
120
|
+
|
119
121
|
Report bugs on Github issues at http://github.org/dazuma/rgeo/issues
|
120
122
|
|
121
123
|
Contact the author at dazuma at gmail dot com.
|
122
124
|
|
123
125
|
=== Acknowledgments
|
124
126
|
|
125
|
-
RGeo is written by Daniel Azuma (http://www.daniel-azuma.com
|
127
|
+
RGeo is written by Daniel Azuma (http://www.daniel-azuma.com).
|
126
128
|
|
127
|
-
Development of RGeo is sponsored by GeoPage, Inc. (http://www.geopage.com
|
129
|
+
Development of RGeo is sponsored by GeoPage, Inc. (http://www.geopage.com).
|
128
130
|
|
129
|
-
RGeo
|
130
|
-
calculations, and
|
131
|
-
|
131
|
+
RGeo calls the GEOS library to handle most Cartesian geometric
|
132
|
+
calculations, and the Proj4 library to handle projections and coordinate
|
133
|
+
transformations. These libraries are maintained by the Open Source
|
132
134
|
Geospatial Foundation; more information is available on OSGeo's web site
|
133
|
-
(http://www.osgeo.org
|
134
|
-
|
135
|
-
The ActiveRecord adapters owe some debt to the spatial_adapter plugin
|
136
|
-
(http://github.com/fragility/spatial_adapter). RGeo's implementation is
|
137
|
-
a little different because we made some different design decisions, but
|
138
|
-
studying the spatial_adapter source gave us a head start.
|
139
|
-
|
140
|
-
Although we don't use shapelib (http://shapelib.maptools.org/) to read
|
141
|
-
ESRI shapefiles, we did borrow a bunch of their test cases.
|
135
|
+
(http://www.osgeo.org).
|
142
136
|
|
143
137
|
=== License
|
144
138
|
|
@@ -1,62 +1,66 @@
|
|
1
1
|
= An Introduction to Spatial Programming With RGeo
|
2
2
|
|
3
3
|
* by Daniel Azuma
|
4
|
-
* version 0.
|
4
|
+
* version 0.2 (7 Dec 2010)
|
5
5
|
|
6
6
|
== Introduction
|
7
7
|
|
8
8
|
=== About This Document
|
9
9
|
|
10
|
-
|
10
|
+
One of the most important current trends in the high-tech industry is the rise of spatial and location-based technologies. Once the exclusive domain of complex GIS systems, these technologies are now increasingly available in small applications, websites, and enterprises. This document provides a brief overview of the concepts, techniques, and tools for implementing location-aware application features, focusing on the Ruby programming language and an open-source technology stack.
|
11
11
|
|
12
12
|
The contents of this document are as follows.
|
13
13
|
|
14
|
-
* Section 1 is a short introduction to geospatial
|
14
|
+
* Section 1 is a short introduction to geospatial technology, including a survey of the common tools and libraries available.
|
15
15
|
* Section 2 introduces the standard spatial data types such as points, lines, and polygons used by most geospatial applications.
|
16
16
|
* Section 3 summarizes the standard spatial operations that are defined on those data types.
|
17
17
|
* Section 4 discusses coordinate systems and geographic projections, and why it is important to get them right.
|
18
18
|
* Section 5 covers the most common open source spatial databases.
|
19
|
-
* Section 6 briefly covers interoperability with
|
19
|
+
* Section 6 briefly covers interoperability with location services and other externally-sourced geospatial data.
|
20
20
|
|
21
21
|
Geographic information systems (GIS) is a broad and highly sophisticated field, and this introduction will only scratch the surface of the current state of the art. The goal is not to be comprehensive, but to summarize the important elements, and reference outside resources for readers that want more detailed information.
|
22
22
|
|
23
23
|
=== About The Author
|
24
24
|
|
25
|
-
{Daniel Azuma}[http://www.daniel-azuma.com/] is chief software architect and a co-founder of {GeoPage, Inc.}[http://www.geopage.com/], a Seattle-based startup developing location-aware consumer applications. Daniel has been working with Ruby on Rails since 2006, and has a background in computer graphics and visualization
|
25
|
+
{Daniel Azuma}[http://www.daniel-azuma.com/] is the chief software architect and a co-founder of {GeoPage, Inc.}[http://www.geopage.com/], a Seattle-based startup developing location-aware consumer applications. Daniel has been working with Ruby on Rails since 2006, and has a background in computer graphics and visualization. He is also the author of \RGeo, the advanced spatial data library for Ruby covered in this document.
|
26
26
|
|
27
27
|
== 1. Space: The Next Frontier
|
28
28
|
|
29
29
|
=== 1.1. Why Spatial Programming?
|
30
30
|
|
31
|
-
By 2010, location had established itself as one of the hottest emerging
|
31
|
+
By 2010, location had established itself as one of the hottest emerging technological trends. In January, a Juniper Research report predicted that mobile location services alone could drive revenues of nearly $13 billion by 2014 (see {TechCrunch article}[http://techcrunch.com/2010/02/23/location-based-services-revenue/]), while location dominated new feature offerings from startups and giants such as Facebook and Twitter alike. Although the underlying disciplines of cartography and geographic information systems (GIS) have been around for several decades, they have broken into mainstream consumer technology only very recently. This has largely been due to a few key developments, notably, the success of mapping applications beginning with Google Maps, and the ubiquity of mobile GPS devices especially in mobile phones.
|
32
32
|
|
33
|
-
Despite this growing interest, location-aware applications remain difficult to develop because the concepts and techniques involved are only beginning to make their way into the mainstream developer consciousness and tools. Working with location data requires
|
33
|
+
Despite this growing interest, location-aware applications remain difficult to develop because the concepts and techniques involved are only beginning to make their way into the mainstream developer consciousness and tools. Working with location data requires techniques beyond the document-oriented or relational data typically used in a web application. The primary purpose of this document is to cover the basics that a Ruby developer needs to know when developing with location data, and to introduce the tools that are available.
|
34
34
|
|
35
35
|
=== 1.2. The Emerging Spatial Ecosystem
|
36
36
|
|
37
37
|
Fortunately, a number of software libraries and organizations now exist to promote and assist developing spatial applications. Here we will survey some of the popular and emerging open software systems available for integration into your location-aware application.
|
38
38
|
|
39
|
-
Visualization tools have advanced considerably in recent years. Mapping services such as {Google Maps}[http://maps.google.com/] and {Bing Maps}[http://www.bing.com/maps/] now have extensive API support for developing mapping applications. An open mapping service, {OpenStreetMap}[http://www.openstreetmap.org/], has also been launched and is gaining momentum. In addition, tools such as {OpenLayers}[http://openlayers.org/] and {PolyMaps}[http://polymaps.org/] have also appeared
|
39
|
+
Visualization tools have advanced considerably in recent years. Mapping services such as {Google Maps}[http://maps.google.com/] and {Bing Maps}[http://www.bing.com/maps/] now have extensive API support for developing mapping applications. An open mapping service, {OpenStreetMap}[http://www.openstreetmap.org/], has also been launched and is gaining momentum. In addition, tools which let you serve your own map data, such as {OpenLayers}[http://openlayers.org/] and {PolyMaps}[http://polymaps.org/], have also appeared.
|
40
40
|
|
41
|
-
Most major relational databases now support spatial extensions. The {MySQL}[http://mysql.com/] database provides
|
41
|
+
Most major relational databases now support spatial extensions. The {MySQL}[http://mysql.com/] database provides basic spatial column support out of the box. Third-party add-on libraries exist for {Sqlite3}[http://www.sqlite.org/] and {PostgreSQL}[http://www.postgresql.org/] in the form of {SpatiaLite}[http://www.gaia-gis.it/spatialite/] and {PostGIS}[http://www.postgis.org/], respectively. Commercial databases such as Oracle and Microsoft SQL Server also provide facilities for storing and querying spatial data. Spatial features are also appearing in non-relational data stores. {MongoDB}[http://www.mongodb.org/] recently introduced geospatial indexing, {Solr}[http://lucene.apache.org/solr/] is expected to support spatial queries in the next release of its Lucene-based search engine, and {Sphinx}[http://sphinxsearch.com/] also provides limited spatial search capabilities.
|
42
42
|
|
43
43
|
A variety of data services have also appeared. Geocoding, the process approximating a latitude/longitude coordinate from a street address, is now offered by most major mapping service vendors such as {Google}[http://code.google.com/apis/maps/documentation/geocoding/], {Microsoft}[http://www.microsoft.com/maps/developers/], and {Yahoo}[http://developer.yahoo.com/geo/placefinder/]. Place databases with geocoded business and major location listings are now also available from a variety of vendors. {SimpleGeo}[http://www.simplegeo.com/] is a relatively new service for cloud-based storage and querying of custom location data.
|
44
44
|
|
45
|
-
Integrating these existing services in a web application is often a challenge, but a few integration libraries and frameworks do exist. {GeoDjango}[http://geodjango.org/] is an add-on for the Python-based Django web framework for building location-based applications. {RGeo}[http://github.com/dazuma/rgeo] is a
|
45
|
+
Integrating these existing services in a web application is often a challenge, but a few integration libraries and frameworks do exist. {GeoDjango}[http://geodjango.org/] is an add-on for the Python-based Django web framework for building location-based applications. {RGeo}[http://github.com/dazuma/rgeo] is a suite of libraries for Ruby that can perform the same function for Ruby on Rails.
|
46
46
|
|
47
|
-
Perhaps most important of all, however, are the organizations that have appeared to support the development of geospatial standards and software. The {Open Geospatial Consortium}[http://www.opengeospatial.org/] (OGC) is an international consortium of companies, government agencies, and other organizations that
|
47
|
+
Perhaps most important of all, however, are the organizations that have appeared to support the development of geospatial standards and software. The {Open Geospatial Consortium}[http://www.opengeospatial.org/] (OGC) is an international consortium of companies, government agencies, and other organizations that promote interoperability by developing open standards and interfaces for geospatial software systems. Many of the concepts, data types, and operations described in this document were standardized by the OGC. The {Open Source Geospatial Foundation}[http://www.osgeo.org/] develops and supports a variety of open source geospatial software, including PostGIS, GEOS, Proj, and others we will cover in this document. The {OGP Geomatics Committee}[http://www.epsg.org/] (formerly EPSG, the European Petroleum Survey Group) is part of an industry association maintaining the <i>de facto</i> standard EPSG geodetic data set, a set of coordinate systems and transformations used internationally to describe global position. These and other organizations form the backbone of geospatial technology, and most geospatial applications will interact at least indirectly with their services.
|
48
48
|
|
49
49
|
=== 1.3. Ruby Libraries and \RGeo
|
50
50
|
|
51
|
-
Ruby developers have had access to a fair number of spatial tools, primarily integration libraries for external services. {Geokit}[http://geokit.rubyforge.org/] provides a common interface for querying geocoding services, and a basic
|
51
|
+
Ruby developers have had access to a fair number of spatial tools, primarily integration libraries for external services. {Geokit}[http://geokit.rubyforge.org/] provides a common interface for querying geocoding services, and a basic ActiveRecord extension for simple spatial queries. {YM4R}[http://ym4r.rubyforge.org/] provides a simple interface for integrating the Google and Yahoo map visualization tools in a Ruby application. Finally, {GeoRuby}[http://georuby.rubyforge.org/] provides classes for basic spatial data types such as points, lines, and polygons, and the add-on library {spatial_adapter}[http://github.com/fragility/spatial_adapter] hacks a few of the popular ActiveRecord database adapters to support spatial columns in the database.
|
52
52
|
|
53
53
|
In this document, we will use {RGeo}[http://github.com/dazuma/rgeo], a new spatial data library for Ruby that provides a complete and robust implementation of the standard OGC spatial data types and operations. It covers some of the same functionality as GeoRuby and spatial_adapter. However, where GeoRuby implements only a minimal subset of the OGC feature interfaces, \RGeo supports the entire specification, as well as providing many features and extensions not available with the older libraries.
|
54
54
|
|
55
|
+
\RGeo comprises several libraries, distributed as gems: a core library, and a suite of optional add-on modules. The core library, distributed as the {rgeo}[http://github.com/dazuma/rgeo] gem, includes the spatial data implementation itself. Currently available add-on modules include {rgeo-geojson}[http://github.com/dazuma/rgeo-geojson], which reads and writes the {GeoJSON}[http://www.geojson.org/] format, and {rgeo-shapefile}[http://github.com/dazuma/rgeo-shapefile], which reads ESRI shapefiles. A number of ActiveRecord adapters also utilize \RGeo to communicate with spatial databases; these include {mysqlspatial}[http://github.com/dazuma/activerecord-mysqlspatial-adapter], {mysql2spatial}[http://github.com/dazuma/activerecord-mysql2spatial-adapter], {spatialite}[http://github.com/dazuma/activerecord-spatialite-adapter], and {postgis}[http://github.com/dazuma/activerecord-postgis-adapter].
|
56
|
+
|
55
57
|
== 2. Spatial Data Types
|
56
58
|
|
59
|
+
This section will cover the standard types of spatial data used in geospatial applications.
|
60
|
+
|
57
61
|
=== 2.1. The Simple Features Specification
|
58
62
|
|
59
|
-
The Open Geospatial Consortium (OGC) defines and publishes a {
|
63
|
+
The Open Geospatial Consortium (OGC) defines and publishes a specification entitled "{Geographic information -- Simple feature access}[http://www.opengeospatial.org/standards/sfa]", which defines, among other things, a set of spatial data types and operations that can be done on them. This standard, which we will refer to as the Simple Features Specification (SFS), defines the core interfaces used by most spatial applications and databases. Although more recent versions of the spec are now available, most current implementations, including \RGeo, follow version 1.1 of the SFS, and this is the specification we will cover here.
|
60
64
|
|
61
65
|
A "feature" in the SFS is a geometric object in 2 or 3 dimensional space. These objects can be points, lines, curves, surfaces, and polygons-- in general, most 0, 1, or 2 dimensional objects are supported. Each of these objects is identified by coordinates (X, Y, and sometimes Z), and has an object-oriented interface associated with it, defining a set of operations that can be done. In \RGeo, these interfaces exist as modules in the RGeo::Feature namespace.
|
62
66
|
|
@@ -74,17 +78,17 @@ An SFS "Point" is a single 0-dimensional point in space. Points are typically us
|
|
74
78
|
|
75
79
|
=== 2.4. LineString
|
76
80
|
|
77
|
-
An SFS "LineString" is a set of one or more connected line segments representing a single continuous, piecewise linear path. It could, for example, represent the path of a single street, the full driving directions from one point to another, or the path of a waterway. It is defined by connecting a series of points
|
81
|
+
An SFS "LineString" is a set of one or more connected line segments representing a single continuous, piecewise linear path. It could, for example, represent the path of a single street, the full driving directions from one point to another, or the path of a waterway. It is defined by connecting a series of points in order with line segments, and you can retrieve those points from the LineString object.
|
78
82
|
|
79
83
|
LineString itself has two subclases, Line and LinearRing. Line is restricted to a single line segment (i.e. two points). LinearRing is a "closed" LineString, where the two endpoints are the same point.
|
80
84
|
|
81
|
-
(LineString is actually a subclass of the more general abstract class "Curve", which need not be piecewise linear. However, Curve is not by itself instantiable, and the current SFS version does not actually specify another type of Curve that is not a LineString.)
|
85
|
+
(LineString is actually a subclass of the more general abstract class "Curve", which need not be piecewise linear. However, Curve is not by itself instantiable, and the current SFS version does not actually specify another type of instantiable Curve that is not a LineString.)
|
82
86
|
|
83
87
|
=== 2.5. Polygon
|
84
88
|
|
85
|
-
An SFS "Polygon" is a connected region of two-dimensional space. Its outer boundary is defined as a LinearRing, so it can have any number of straight "sides". Polygons can also optionally contain "holes", represented by inner boundaries which are also LinearRings. You can retrieve the outer and inner boundaries from a Polygon object as LinearRing objects. Polygons are ideal for representing single plots of land such as property boundaries, or larger regions of the earth's surface such as city, state, or national boundaries, time zones, lakes, and so forth.
|
89
|
+
An SFS "Polygon" is a connected region of two-dimensional space. Its outer boundary is defined as a LinearRing, so it can have any number of straight "sides". Polygons can also optionally contain "holes", represented by inner boundaries which are also LinearRings. You can retrieve the outer and inner boundaries from a Polygon object as LinearRing objects. Polygons are ideal for representing single plots of land such as property boundaries, or larger regions of the earth's surface such as city, state, or national boundaries, time zones, lakes, and so forth, as long as they are contiguous.
|
86
90
|
|
87
|
-
(Polygon is also a subclass of a more general abstract class, this one called "Surface". In general, the boundaries of a Surface need not be piecewise linear. However, Surface is not by itself instantiable, and the current SFS version does not actually specify another type of Surface other than Polygon.)
|
91
|
+
(Polygon is also a subclass of a more general abstract class, this one called "Surface". In general, the boundaries of a Surface need not be piecewise linear. However, Surface is not by itself instantiable, and the current SFS version does not actually specify another type of instantiable Surface other than Polygon.)
|
88
92
|
|
89
93
|
=== 2.6. MultiPoint
|
90
94
|
|
@@ -106,25 +110,26 @@ An SFS "MultiPolygon" is a collection of zero or more Polygon objects. It also h
|
|
106
110
|
|
107
111
|
The various geometric data types described above are arranged in a class hierarchy. The base class of this hierarchy is Geometry. The MultiPoint, MultiLineString, and MultiPolygon types (or more precisely, MultiPoint, MultiCurve, and MultiSurface) are subclasses of a more general data type called GeometryCollection. GeometryCollection can also be instantiated by itself. It represents a general collection of other geometry objects, each of which can be any type.
|
108
112
|
|
109
|
-
For complete details on the geometry class hierarchy, download the actual {Simple Features Specification}[http://www.opengeospatial.org/standards/sfa]. I recommend downloading version 1.1, because the newer versions (1.2 and later) describe additional types that are not commonly available in implementations. That additional information may be confusing.
|
113
|
+
For complete details on the geometry class hierarchy, download the actual {Simple Features Specification}[http://www.opengeospatial.org/standards/sfa]. I recommend downloading version 1.1, because the newer versions (1.2 and later) describe additional types and features that are not commonly available in current implementations. That additional information may be confusing.
|
110
114
|
|
111
115
|
=== 2.10. \RGeo Geometry Factories
|
112
116
|
|
113
|
-
The data types we have covered here are actually merely interface specifications. \RGeo actually provides several different implementations of these data
|
117
|
+
The data types we have covered here are actually merely interface specifications. \RGeo actually provides several different implementations of these data type interfaces, intended for different use cases. For example, the RGeo::Geos implementation is \RGeo's main implementation which provides every data type and every operation defined by the SFS. However, that implementation requires a third-party C library, GEOS, to be installed. In cases where that library is not available, \RGeo provides an alternative, the Simple Cartesian implementation, which is a pure Ruby implementation that provides every data type but does not implement some of the more advanced geometric operations. \RGeo also provides further implementations that are designed specifically to work with geographic (longitude/latitude) coordinates, and different projections and ways of performing calculations on the earth's surface. These different implementations are described in more detail in the section on Coordinate Systems and Projections.
|
114
118
|
|
115
|
-
A particular implementation of these spatial data types is represented in \RGeo by a factory. A factory
|
119
|
+
A particular implementation of these spatial data types is represented in \RGeo by a factory. A factory is an object that represents the coordinate system and other settings for that implementation, and provides methods for creating the actual geometric objects, as defined in the RGeo::Feature::Factory interface. For example:
|
116
120
|
|
121
|
+
factory = get_my_factory()
|
117
122
|
point1 = factory.point(1, 2)
|
118
123
|
point2 = factory.point(3, -1)
|
119
124
|
line = factory.line_string([point1, point2])
|
120
125
|
|
121
|
-
The most
|
126
|
+
The most common factory used by \RGeo is the "preferred Cartesian" factory. This factory uses a flat (Cartesian) coordinate system, and is implemented by GEOS (if available) or using the pure Ruby alternative if not. It can be retrieved by calling:
|
122
127
|
|
123
|
-
factory = ::RGeo::Cartesian.preferred_factory
|
128
|
+
factory = ::RGeo::Cartesian.preferred_factory()
|
124
129
|
|
125
130
|
Another common factory you might want to use is the "simple Mercator" factory. This is a geographic factory intended for simple location-based applications that use Google or Bing Maps as a visualization tool. Its coordinate system is longitude-latitude, but it also has a built-in facility for converting those coordinates to the flat "tiling" coordinate system used by the map. You can retrieve it by calling:
|
126
131
|
|
127
|
-
factory = ::RGeo::Geographic.simple_mercator_factory
|
132
|
+
factory = ::RGeo::Geographic.simple_mercator_factory()
|
128
133
|
|
129
134
|
In many cases, these factory creation methods take additional optional arguments that enable various features. For example, the preferred Cartesian factory, by default, uses only X and Y coordinates. You can activate Z and/or M coordinates by passing an appropriate argument, e.g.:
|
130
135
|
|
@@ -137,16 +142,30 @@ Note that, in many cases, the factory class itself as well as the actual impleme
|
|
137
142
|
|
138
143
|
== 3. Spatial Operations
|
139
144
|
|
140
|
-
In addition to representing geometric data, the SFS interfaces define a suite of basic operations on this data
|
145
|
+
In addition to representing geometric data, the SFS interfaces define a suite of basic operations on this data. These operations are available in many forms, depending on the type of software system. Spatial databases such as PostGIS define these as SQL functions that can be used to write queries. \RGeo's goal is to make geometric objects available to Ruby programs, and so these operations are exposed as methods on the geometric Ruby objects.
|
141
146
|
|
142
|
-
These operations cover a wide range of functionality, and some involve difficult problems of computational geometry, especially over a non-flat coordinate system such as geographic coordinates. \RGeo provides a complete implementation for flat Cartesian coordinates that utilizes the {GEOS}[http://trac.osgeo.org/geos/] library internally. However, some of \RGeo's other implementations provide only a subset of these operations. If you use the PostGIS database, you will find a similar situation. The "geometry" data types actually use GEOS internally to perform geometric computations, and pretty much all functions are available. However, the "geography" data type, which operates on a curved coordinate system, only
|
147
|
+
These operations cover a wide range of functionality, and some involve difficult problems of computational geometry, especially over a non-flat coordinate system such as geographic coordinates. \RGeo provides a complete implementation for flat Cartesian coordinates that utilizes the {GEOS}[http://trac.osgeo.org/geos/] library internally. However, some of \RGeo's other implementations provide only a subset of these operations. If you use the PostGIS database, you will find a similar situation. The "geometry" data types actually use GEOS internally to perform geometric computations, and pretty much all functions are available. However, the "geography" data type, which operates on a curved coordinate system, implements only a handful of the defined functions.
|
143
148
|
|
144
149
|
=== 3.1. Basic Properties
|
145
150
|
|
146
151
|
Most geometry types have a "degenerate" form representing no geometry. For example, a GeometryCollection may contain no items, or a LineString may contain no points. This state is indicated by the <tt>Geometry#is_empty?</tt> method. In \RGeo, any geometry type except Point may be empty.
|
147
152
|
|
153
|
+
factory = ::RGeo::Cartesian.preferred_factory
|
154
|
+
factory.point(1, 2).is_empty? # returns false
|
155
|
+
factory.collection([]).is_empty? # returns true
|
156
|
+
|
148
157
|
A second common property of geometry objects is "simplicity", which basically means the geometry doesn't intersect or repeat itself. For example, a LineString that intersects itself is not simple, nor is a MultiPoint that contains the same point more than once. Sometimes, a geometric analysis algorithm will have simplicity as a precondition. This property is indicated by the <tt>Geometry#is_simple?</tt> method.
|
149
158
|
|
159
|
+
factory = ::RGeo::Cartesian.preferred_factory
|
160
|
+
p00 = factory.point(0, 0)
|
161
|
+
p01 = factory.point(0, 1)
|
162
|
+
p11 = factory.point(1, 1)
|
163
|
+
p10 = factory.point(1, 0)
|
164
|
+
zigzag_line = factory.line_string([p00, p10, p01, p11])
|
165
|
+
zigzag_line.is_simple? # returns true
|
166
|
+
self_crossing_line = factory.line_string([p00, p11, p01, p10])
|
167
|
+
self_crossing_line.is_simple? # returns false
|
168
|
+
|
150
169
|
All geometry objects also contain a "spatial reference ID", returned by the <tt>Geometry#srid</tt> method. This is an external ID reference indicating the "spatial reference system", or coordinate system in use by the geometry. See the section on Coordinate Systems and Projections for further discussion.
|
151
170
|
|
152
171
|
=== 3.2. Equality and Comparisons
|
@@ -189,23 +208,48 @@ Similarly, \RGeo's equality checking comes in several forms: geometric equality,
|
|
189
208
|
|
190
209
|
The SFS also provides several operations that take two geometries and yield a third. For example, you can calculate the intersection, union, or difference between two geometries. In addition to the methods specified by the SFS interfaces, \RGeo provides operators for some of these calculations.
|
191
210
|
|
192
|
-
|
193
|
-
|
194
|
-
|
211
|
+
p1 = factory.point(1, 1)
|
212
|
+
p2 = factory.point(2, 2)
|
213
|
+
union = p1.union(p2) # or p1 + p2
|
214
|
+
union.geometry_type # returns RGeo::Feature::MultiPoint
|
215
|
+
union.num_geometries # returns 2
|
216
|
+
diff = p1.difference(p2) # or p1 - p2
|
217
|
+
diff.is_empty? # returns true
|
195
218
|
|
196
219
|
=== 3.4. Boundaries, Envelopes, etc.
|
197
220
|
|
198
|
-
Methods
|
221
|
+
Methods are provided to compute the boundary of an object, the envelope (i.e. the bounding box), and the convex hull. In addition, there is a "buffer" method that attempts to return a polygon approximating the area within a given distance from the object. Note that, because the SFS does not yet define any geometric types with curved edges, most buffers will be polygonal approximations.
|
199
222
|
|
200
223
|
=== 3.5. Size and Distance
|
201
224
|
|
202
225
|
Several size and distance calculations are available. You can compute the distance between two geometric objects, the length of a LineString, or the area of a Polygon. Note that there will be some cases when these computations don't make much sense due to the coordinate system.
|
203
226
|
|
227
|
+
p00 = factory.point(0, 0)
|
228
|
+
p20 = factory.point(2, 0)
|
229
|
+
p11 = factory.point(1, 1)
|
230
|
+
p00.distance(p11) # returns 1.41421356...
|
231
|
+
line = factory.line(p00, p20)
|
232
|
+
line.length # returns 2
|
233
|
+
line.distance(p11) # returns 1
|
234
|
+
ring = factory.linear_ring([p00, p11, p20, p00])
|
235
|
+
ring.length # returns 4.82842712...
|
236
|
+
ring.distance(p11) # returns 0
|
237
|
+
poly = factory.polygon(ring)
|
238
|
+
poly.area # returns 1
|
239
|
+
|
204
240
|
=== 3.6. Serialization
|
205
241
|
|
206
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.
|
207
243
|
|
208
|
-
|
244
|
+
p00 = factory.point(0, 0)
|
245
|
+
p00.as_text # returns "Point(0 0)"
|
246
|
+
p10 = factory.point(1, 0)
|
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
|
251
|
+
|
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.
|
209
253
|
|
210
254
|
== 4. Coordinate Systems and Projections
|
211
255
|
|
@@ -217,49 +261,57 @@ Generally, the spatial technologies we're discussing are used to represent locat
|
|
217
261
|
|
218
262
|
First off, most of us agree that the earth is not flat, but shaped as something resembling a slightly flattened ball. This immediately results in a whole host of complications when dealing with geometric objects on the earth's surface. Distance can't quite be computed accurately using the familiar formulas you learned in high school geometry. Lines that start off parallel will eventually cross. And if you try to display things on a flat computer monitor, you will end up with various kinds of distortion.
|
219
263
|
|
220
|
-
Let's take a simple example. Suppose we have a simple LineString with two points: starting in Vancouver, Canada, and ending in Frankfurt, Germany, both located at around 50 degrees north latitude. The LineString would consist of a straight line between those two points. But what is meant by "straight"? Does the shape follow the 50 degrees north latitude line, passing through Newfoundland? Or does it follow the actual shortest path on the globe, which passes much further north, close to Reykjavik, Iceland? (For a detailed explanation, see Morten Nielsen's post {"Straight Lines on a Sphere"}[http://www.sharpgis.net/post/2008/01/12/Straight-lines-on-a-sphere.aspx], which also includes some helpful diagrams.) If you were to call the SFS "distance" function to measure the distance between
|
264
|
+
Let's take a simple example. Suppose we have a simple LineString with two points: starting in Vancouver, Canada, and ending in Frankfurt, Germany, both located at around 50 degrees north latitude. The LineString would consist of a straight line between those two points. But what is meant by "straight"? Does the shape follow the 50 degrees north latitude line, passing through Newfoundland? Or does it follow the actual shortest path on the globe, which passes much further north, close to Reykjavik, Iceland? (For a detailed explanation, see Morten Nielsen's post {"Straight Lines on a Sphere"}[http://www.sharpgis.net/post/2008/01/12/Straight-lines-on-a-sphere.aspx], which also includes some helpful diagrams.) If you were to call the SFS "distance" function to measure the distance between this LineString and a Point located at Reykjavik, what would you get?
|
221
265
|
|
222
266
|
The answer is, it depends on the coordinate system you're using.
|
223
267
|
|
224
268
|
=== 4.2. Geographic Coordinates And Projections
|
225
269
|
|
226
|
-
GIS systems typically represent locations in one of three different types of coordinate systems: geocentric coordinates, geographic coordinates, and projected coordinates. Geocentric coordinate systems typically locate the origin of a three-dimensional Cartesian coordinate system at the center of the earth. They are not commonly used in an application-level interface, but are often a convenient coordinate system for running
|
270
|
+
GIS systems typically represent locations in one of three different types of coordinate systems: geocentric coordinates, geographic coordinates, and projected coordinates. Geocentric coordinate systems typically locate the origin of a three-dimensional Cartesian coordinate system at the center of the earth. They are not commonly used in an application-level interface, but are often a convenient coordinate system for running computational geometry algorithms. Geographic coordinates use the familiar latitude and longitude measurements, and sometimes also include altitude. These coordinates use a curved surface, either a sphere or an ellipsoid, as the domain, and perform geometric calculations on that non-flat domain. Projected coordinates involve transforming the curved domain of the earth's surface onto a flat domain such as a map display. Projected coordinates, then, are actually X-Y coordinates on the map itself: for example, pixel coordinates.
|
271
|
+
|
272
|
+
In our Vancouver to Frankfurt example, the path of a "straight" line is defined by the type of coordinate system being used. A geocentric coordinate system operates in 3-d space, and so a straight line will actually pass through the interior of the earth. A straight line in a geographic coordinate system (latitudes and longitudes) is typically defined as a geodesic, the shortest path between two points along the earth's surface. This path will take the line near Reykjavik. In a projected coordinate system, a straight line is defined as a straight line on the projection-- that is, a straight line drawn on the flat map. Google and Bing maps use a Mercator projection, in which lines of latitude are straight horizontal lines, so the LineString will follow the 50 degrees latitude line, passing through Newfoundland.
|
227
273
|
|
228
|
-
|
274
|
+
It is important to note that the actual _shape_ of the geometry is different depending on the coordinate system. If you "project" the geodesic (the straight Line in geographic coordinates) into a Mercator-projected Google map, the line will be curved. Therefore, the coordinate system is an integral part of the geometric object. If you get your coordinate systems mixed up, you may get incorrect results when you run a database query or a geometric operation. Morten Nielsen gives an example in {this post}[http://www.sharpgis.net/post/2009/02/06/Why-EPSG4326-is-usually-the-wrong-e2809cprojectione2809d.aspx].
|
229
275
|
|
230
|
-
|
276
|
+
flat_factory = RGeo::Geos.factory
|
277
|
+
curved_factory = RGeo::Geographic.spherical_factory
|
278
|
+
flat_line = flat_factory.line(flat_factory.point(0, 0),
|
279
|
+
flat_factory.point(1, 1))
|
280
|
+
curved_line = curved_factory.line(curved_factory.point(0, 0),
|
281
|
+
curved_factory.point(1, 1))
|
282
|
+
# flat_line and curved_line represent different shapes!
|
231
283
|
|
232
|
-
\RGeo provides access to different coordinate systems via its factories, as we saw earlier. If you are implementing geolocation, you will typically use one of the geographic factories which represent coordinates as latitude and longitude. Note, however, that \RGeo provides both projected and non-projected geographic factories. Projected factories are tied to a particular projection, representing coordinates as latitude and longitude, but doing calculations in the projection. If you use the simple mercator factory, a projected factory, the line between Vancouver and Frankfurt will follow the 50 degree latitude line, and so it will intersect a polygon representing Newfoundland. Non-projected factories perform calculations on a curved earth. Using the spherical factory, a non-projected factory that assumes the earth is a sphere, the line between Vancouver and Frankfurt will intersect a polygon representing Greenland. (In the future, \RGeo should also provide an ellipsoidal factory that performs the more complex calculations needed to model the earth as a
|
284
|
+
\RGeo provides access to different coordinate systems via its factories, as we saw earlier. If you are implementing geolocation, you will typically use one of the geographic factories which represent coordinates as latitude and longitude. Note, however, that \RGeo provides both projected and non-projected geographic factories. Projected factories are tied to a particular projection, representing coordinates as latitude and longitude, but doing calculations in the projection. If you use the simple mercator factory, a projected factory, the line between Vancouver and Frankfurt will follow the 50 degree latitude line, and so it will intersect a polygon representing Newfoundland. Non-projected factories perform calculations on a curved earth. Using the spherical factory, a non-projected factory that assumes the earth is a sphere, the line between Vancouver and Frankfurt will intersect a polygon representing Greenland. (In the future, \RGeo should also provide an ellipsoidal factory that performs the more complex calculations needed to model the earth as a _flattened_ sphere. This feature is not available yet.)
|
233
285
|
|
234
286
|
Some database systems behave similarly. PostGIS, for example, provides separate "geometry" and "geography" types. The former assumes a flat domain: it will behave similarly to \RGeo's simple mercator factory for a horizontal line (though for an oblique line, it will behave differently since the vertical axis is nonuniform in the Mercator projection.) The PostGIS "geography" type, however, operates on a curved earth, similar to \RGeo's spherical factory.
|
235
287
|
|
236
|
-
Does this matter in your application? The answer is, it depends: on what kind of data you have, how it will be analyzed or displayed, and how much accuracy you need. For a simple application that displays point locations or small-scale paths and areas on a Google map, you can probably safely ignore the issue. It would probably be easiest to simply use \RGeo's non-projected spherical factory, and the "geography" type if you are using PostGIS. The Google maps system automatically transforms your latitude-longitude coordinates into projected map coordinates when it displays markers and polygons.
|
288
|
+
Does this matter in your application? The answer is, it depends: on what kind of data you have, how it will be analyzed or displayed, and how much accuracy you need. For a simple application that displays point locations or small-scale paths and areas on a Google map, you can probably safely ignore the issue. It would probably be easiest to simply use \RGeo's non-projected spherical factory, and the "geography" type if you are using PostGIS. The Google maps system automatically transforms your latitude-longitude coordinates into projected map coordinates when it displays markers and polygons. Remember the Vancouver to Frankfurt problem, however: if you display a line or polygon that is very large, the straight sides as displayed on the Google map may not be straight on the actual curved earth, and a LineString represented as a non-projected geographic object should not appear straight on the map. If your objects cover large areas of the globe, or for better accuracy or more sophisticated applications, you will need to pay explicit attention to projections.
|
237
289
|
|
238
290
|
=== 4.3. Geodetic and Projection Parameters
|
239
291
|
|
240
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 conceptual understanding of them.
|
241
293
|
|
242
|
-
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
|
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 merely a function mapping latitude/longitude to flat coordinates, so we need to specify _which_ latitude/longitude.
|
243
295
|
|
244
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:
|
245
297
|
|
246
|
-
*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.
|
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 will take.
|
247
299
|
|
248
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.
|
249
301
|
|
250
|
-
The most common datum in use, and generally the one you will encounter most often when writing location applications, is *WGS84*. This datum comprises both horizontal and vertical parts. The WGS84 horizontal datum defines the latitudes and longitudes used by the global positioning system (GPS). Latitudes are defined using the WGS84 reference ellipsoid, using the standard geodetic definition of the angle from the normal to the ellispoid. Longitudes are measured relative to the *prime meridian*. Interestingly, the WGS84 prime meridian is not exactly on the historical Greenwich prime meridian that passes through the Royal Observatory. A shift of about 100 meters to the east was made in order to make WGS84 more closely match
|
302
|
+
The most common datum in use, and generally the one you will encounter most often when writing location applications, is *WGS84*. This datum comprises both horizontal and vertical parts. The WGS84 horizontal datum defines the latitudes and longitudes used by the global positioning system (GPS). Latitudes are defined using the WGS84 reference ellipsoid, using the standard geodetic definition of the angle from the normal to the ellispoid. Longitudes are measured relative to the *prime meridian*. (Interestingly, the WGS84 prime meridian is not exactly on the historical Greenwich prime meridian that passes through the Royal Observatory. A shift of about 100 meters to the east was made in order to make WGS84 more closely match a commonly-used North America-specific datum.)
|
251
303
|
|
252
304
|
The WGS84 vertical datum is a bumpy ellipsoid representing nominal sea level for all parts of the earth. This shape is also known as the *geoid*.
|
253
305
|
|
254
306
|
A geographic coordinate system is generally defined by a datum and a prime meridian. A projected coordinate system starts from a geographic coordinate system and includes additional parameters specific to the projection.
|
255
307
|
|
256
|
-
Which coordinate system should you use? The simple answer is WGS84.
|
308
|
+
Which coordinate system should you use for location data? The usual simple answer is WGS84. Because this is the same worldwide geographic coordinate system that GPS uses, as do most geocoding services and so forth, most of the data you will encounter will be in WGS84. Only in certain locale-specific cases might a different coordinate system be in common use. However, remember that WGS84 is a geographic coordinate system, not a projected coordinate system. It does not make sense to say that your map uses WGS84, because chances are your map is a flat map, not a map wrapped around the WSG84 ellipsoidal shape.
|
257
309
|
|
258
|
-
What about Google and Bing maps? They use a combination of two coordinate systems with a projection. The API inputs take latitude and longitude in the WGS84 coordinate system. However, the maps themselves are Mercator projections (with a modification to make computations easier), and so the map implementations transform the coordinates internally. Again, Morten Nielsen provides a more {detailed description}[http://www.sharpgis.net/post/2007/07/27/The-Microsoft-Live-Maps-and-Google-Maps-projection.aspx].
|
310
|
+
What about Google and Bing maps? They use a combination of two coordinate systems with a projection. The API inputs take latitude and longitude in the WGS84 coordinate system. However, the maps themselves are Mercator projections (with a minor modification to make computations easier), and so the map implementations transform the coordinates internally. Again, Morten Nielsen provides a more {detailed description}[http://www.sharpgis.net/post/2007/07/27/The-Microsoft-Live-Maps-and-Google-Maps-projection.aspx].
|
259
311
|
|
260
312
|
=== 4.4. Using Proj4
|
261
313
|
|
262
|
-
Under most circumstances, when you're working with geographic data, you can probably use either the spherical factory (if you just want to deal with points on the sphere) or the simple mercator factory (if you want to deal with objects as they would appear on Google or Bing maps). However, if you need to work with arbitrary projections, there exists a software library that understands coordinate systems and handles the math involved. {Proj}[http://trac.osgeo.org/proj/] is a C library that defines a syntax for specifying coordinate systems based on the above parameters, and an implementation for transforming coordinates from one coordinate system to another. Its syntax has become a de facto standard.
|
314
|
+
Under most circumstances, when you're working with geographic data in \RGeo, you can probably use either the spherical factory (if you just want to deal with points on the sphere) or the simple mercator factory (if you want to deal with objects as they would appear on Google or Bing maps). However, if you need to work with arbitrary projections, there exists a software library that understands coordinate systems and handles the math involved. {Proj}[http://trac.osgeo.org/proj/] is a C library that defines a syntax for specifying coordinate systems based on the above parameters, and an implementation for transforming coordinates from one coordinate system to another. Its syntax has become a <i>de facto</i> standard.
|
263
315
|
|
264
316
|
\RGeo provides a Ruby wrapper around the Proj interface, and integrates proj into its representation of geometric objects. You can use the Proj syntax to specify the coordinate system for input data, and tell \RGeo to translate it to a different coordinate system for analysis or output. \RGeo's geographic factories can also be configured with a particular projection using the Proj syntax, and automatically convert between latitude-longitude and that projection's coordinate system. For example:
|
265
317
|
|
@@ -277,9 +329,9 @@ Under most circumstances, when you're working with geographic data, you can prob
|
|
277
329
|
|
278
330
|
=== 4.5. Spatial Reference Systems and the EPSG Dataset
|
279
331
|
|
280
|
-
The OGC also defines a syntax for specifying coordinate systems, the {Coordinate Transformation Services Specification[http://www.opengeospatial.org/standards/ct]. This specification defines both an object model and a well-known text representation for coordinate systems and transformations. \RGeo does not yet implement this specification, but it is on the
|
332
|
+
The OGC also defines a syntax for specifying coordinate systems, the {Coordinate Transformation Services Specification}[http://www.opengeospatial.org/standards/ct]. This specification defines both an object model and a well-known text representation for coordinate systems and transformations. \RGeo does not yet implement this specification, but it is on the to-do list.
|
281
333
|
|
282
|
-
Finally, there also exists a de facto standard database of coordinate systems and related parameters, published by EPSG (now the OGP Geomatics Committee). This is a set of coordinate systems, each tagged with a well-known ID number, including geographic and projected systems. You can browse this database, including both OGC and Proj4 representations, at http://www.spatialreference.org/. This database is also included as a table in many popular spatial databases including PostGIS and SpatiaLite. Typically, the EPSG number is used as the SRID identifying the coordinate system for geometric objects stored in the database.
|
334
|
+
Finally, there also exists a <i>de facto</i> standard database of coordinate systems and related parameters, published by EPSG (now the OGP Geomatics Committee). This is a set of coordinate systems, each tagged with a well-known ID number, including geographic and projected systems. You can browse this database, including both OGC and Proj4 representations, at http://www.spatialreference.org/. This database is also included as a table in many popular spatial databases including PostGIS and SpatiaLite. Typically, the EPSG number is used as the SRID identifying the coordinate system for geometric objects stored in the database.
|
283
335
|
|
284
336
|
The most common EPSG number in use is 4326, which identifies the WGS84 geographic (longitude-latitude) coordinate system on the WGS84 ellipsoid. In fact, current versions of PostGIS restrict geography objects to this SRID. Be aware, again, that this is a non-projected ellipsoidal coordinate system. If you load EPSG 4326 data directly into, say, a Cartesian implementation in \RGeo, then the basic data fields will work fine, but size and distance functions, as well as spatial analysis operations such as intersections, may yield surprising or incorrect results because the data's coordinate system does not match how \RGeo is treating it.
|
285
337
|
|
@@ -291,34 +343,34 @@ As we have seen, there exist a variety of ways to serialize geometric objects, n
|
|
291
343
|
|
292
344
|
=== 5.1. Spatial Queries and Indexes
|
293
345
|
|
294
|
-
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
|
346
|
+
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:
|
295
347
|
|
296
348
|
SELECT * FROM mytable WHERE ST_Distance(geom, ST_WKTToSQL("POINT(10 20)")) > 5;
|
297
349
|
|
298
|
-
Like all database queries, however, when there are a large number of rows, such queries can be slow
|
350
|
+
Like all database queries, however, when there are a large number of rows, such queries 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 geometric columns.
|
299
351
|
|
300
352
|
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 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)? And how do each of those compare with LINESTRING(0 1, 1 0)? More concretely, spatial data exists in two dimensions rather than one, and can span finite ranges.
|
301
353
|
|
302
|
-
Spatial databases
|
354
|
+
Spatial databases handle the problem of indexing spatial data in different 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. 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.
|
303
355
|
|
304
356
|
=== 5.2. MySQL Spatial
|
305
357
|
|
306
|
-
{MySQL}[http://mysql.com/] maintains its dual reputation as probably the easiest of the open source relational databases to manage,
|
358
|
+
{MySQL}[http://mysql.com/] maintains its dual reputation as probably the easiest of the open source relational databases to manage, but as tending to miss some features and standards compliance. Recent versions of MySQL have spatial column support baked in, and they are extremely easy to use: just create a column of type GEOMETRY, or POINT, or LINESTRING, or any of the OGC types. You can also create spatial indexes simply by adding the SPATIAL modifier to CREATE INDEX. Note, however, that as of MySQL 5.1, only MyISAM tables support spatial indexes. If you're using Innodb, you can add spatial columns but you can't index them.
|
307
359
|
|
308
360
|
CREATE TABLE mytable(id INT NOT NULL PRIMARY KEY, latlon POINT) ENGINE=MyISAM;
|
309
361
|
CREATE SPATIAL INDEX idx_latlon ON mytable(latlon);
|
310
362
|
|
311
|
-
MySQL represents data internally using WKB slightly modified
|
363
|
+
MySQL represents data internally using a variant of WKB which has been slightly modified by prepending 4 extra bytes to store an object's SRID. You can interpret this data directly, or use provided functions to convert to and from WKB and WKT.
|
312
364
|
|
313
|
-
What MySQL lacks is support for most of the advanced spatial geometry functions such as the relational operators (e.g. ST_Intersects(), ST_Contains(), etc.), so you will not be able to perform complex geometric calculations using the database engine. You'll have to just load the data into your application and use \RGeo to perform those calculations. It also does not provide the OGC-specified geometry columns or spatial reference system tables. Because the former is not present, you will not be able to specify
|
365
|
+
What MySQL lacks is support for most of the advanced spatial geometry functions such as the relational operators (e.g. ST_Intersects(), ST_Contains(), etc.), so you will not be able to perform complex geometric calculations using the database engine. You'll have to just load the data into your application and use \RGeo to perform those calculations. It also does not provide the OGC-specified geometry columns or spatial reference system tables. Because the former table is not present, you will not be able to specify constraints on your geometries beyond the type: you will not be able to constrain the SRID for a column, and columns will not be able to support Z and M coordinates. Because the latter table is not present, MySQL cannot perform coordinate system transformations itself, nor provide you with the standard EPSG dataset for your own use.
|
314
366
|
|
315
|
-
In general, if you're using MySQL for the rest of your application, and you just need
|
367
|
+
In general, if you're using MySQL for the rest of your application, and you just need simple geospatial data capabilities, it's very easy to use MySQL spatial. Just make sure your table uses the MyISAM engine if you need to index the geometry.
|
316
368
|
|
317
369
|
=== 5.3. SpatiaLite
|
318
370
|
|
319
371
|
{SpatiaLite}[http://www.gaia-gis.it/spatialite/] is an add-on library for the popular database {Sqlite}[http://www.sqlite.org/]. It is close to a fully compliant implementation of the OGC SQL specification, but as a result it is more difficult to manage than MySQL.
|
320
372
|
|
321
|
-
To install SpatiaLite, you must compile it as a shared library, then load that library as an extension using the appropriate sqlite API. This gives you access to the full suite of spatial SQL functions defined by the OGC, along with a set of utility functions for managing spatial columns and indexes as well as the geometry columns and spatial reference systems tables. These utility functions automatically create and manage the appropriate entries in the geometry columns table, and the triggers that enforce type and SRID
|
373
|
+
To install SpatiaLite, you must compile it as a shared library, then load that library as an extension using the appropriate sqlite API. This gives you access to the full suite of spatial SQL functions defined by the OGC, along with a set of utility functions for managing spatial columns and indexes as well as the geometry columns and spatial reference systems tables. These utility functions automatically create and manage the appropriate entries in the geometry columns table, and the triggers that enforce type and SRID constraints and maintain the spatial indexes.
|
322
374
|
|
323
375
|
CREATE TABLE mytable(id INTEGER PRIMARY KEY);
|
324
376
|
SELECT AddGeometryColumn('mytable', 'latlon', 4326, 'POINT', 'XY');
|
@@ -336,24 +388,24 @@ SpatiaLite's internal format is a binary format loosely based on the WKB, but ex
|
|
336
388
|
|
337
389
|
As {PostgreSQL}[http://www.postgresql.org/] is the most complete (and complex) open-source relational database, so the {PostGIS}[http://www.postgis.org/] add-on library is also the most complete and complex of the spatial databases I discuss here. It is a highly compliant implementation of the OGC SQL specification, including all the needed functions and tables. It also supports spatial indexes using PostgreSQL's GiST (generalized search tree) index implementation.
|
338
390
|
|
339
|
-
Like SpatiaLite, PostGIS is compiled and installed as a
|
391
|
+
Like SpatiaLite, PostGIS is compiled and installed as a plug-in library to the database. Also like SpatiaLite, PostGIS provides a suite of utility functions for managing spatial columns and updating the geometry columns table. PostGIS indexes, however, are built in, and so use the more traditional index creation syntax. Like SpatiaLite, PostGIS provides a spatial reference systems table from which you can look up EPSG codes and obtain Proj4 and OGC representations of coordinate systems.
|
340
392
|
|
341
393
|
CREATE TABLE mytable(id INTEGER PRIMARY KEY);
|
342
394
|
SELECT AddGeometryColumn('mytable', 'latlon', 4326, 'POINTM', 3);
|
343
395
|
CREATE INDEX idx_mytable_latlon ON mytable USING GIST (latlon);
|
344
396
|
|
345
|
-
PostGIS uses as its internal format a variant
|
397
|
+
PostGIS uses as its internal format a variant of WKB known as EWKB. This variant provides support for Z and M coordinates as well as embedded SRID values. PostGIS also defines an corresponding EWKT format adding Z and M support and SRIDs to WKT, and provides conversion functions. The EWKB and EWKT variants are commonly used and so are supported by \RGeo's WKB and WKT parsers.
|
346
398
|
|
347
|
-
=== 5.5. \RGeo
|
399
|
+
=== 5.5. \RGeo ActiveRecord Integration
|
348
400
|
|
349
|
-
\RGeo provides extra support for web applications built on Ruby On Rails or similar frameworks
|
401
|
+
\RGeo provides extra support for web applications built on Ruby On Rails or similar frameworks that use the ActiveRecord library, in the form of a suite of ActiveRecord connection adapters for the various spatial databases we have covered. These connection adapters subclass the stock database connection adapters, and add support for the \RGeo geometric data types. You can create spatial columns and indexes using extensions to the ActiveRecord schema definition functions, and the appropriate fields on your ActiveRecord objects will appear as \RGeo spatial data objects. Using one of these connection adapters is probably the easiest way to integrate your Rails application with a spatial database.
|
350
402
|
|
351
|
-
These are the names of these connection adapters:
|
403
|
+
\RGeo's spatial ActiveRecord adapters are provided in separate gems, named according to the recommended convention. These are the names of these connection adapters:
|
352
404
|
|
353
|
-
* *mysqlspatial*:
|
354
|
-
* *mysql2spatial*:
|
355
|
-
* *spatialite*:
|
356
|
-
* *postgis*:
|
405
|
+
* *mysqlspatial*: Subclasses the mysql adapter and adds support for MySQL's spatial types. Available as the <b>activerecord-mysqlspatial-adapter</b> gem.
|
406
|
+
* *mysql2spatial*: Subclasses the mysql2 adapter and adds support for MySQL's spatial types. Available as the <b>activerecord-mysql2spatial-adapter</b> gem.
|
407
|
+
* *spatialite*: Subclasses the sqlite3 adapter and adds support for the SpatiaLite extension. Available as the <b>activerecord-spatialite-adapter</b> gem.
|
408
|
+
* *postgis*: Subclasses the postgresql adapter and adds support for the PostGIS extension. Available as the <b>activerecord-postgis-adapter</b> gem.
|
357
409
|
|
358
410
|
== 6. Location Service Integration
|
359
411
|
|
@@ -361,22 +413,23 @@ When writing a location-aware application, you will often need to interact with
|
|
361
413
|
|
362
414
|
=== 6.1. Shapefiles and Spatial Data Sets
|
363
415
|
|
364
|
-
{ESRI}[http://www.esri.com/] is one of the oldest and most well-known GIS corporations, developing a suite of applications including the venerable {ArcGIS}[http://www.esri.com/software/arcgis/index.html]. ESRI also created the Shapefile, a geospatial data file format that has become a de facto standard despite its legacy and somewhat awkward characteristics. Today, many of the widely-available geospatial data sets are distributed as shapefiles.
|
416
|
+
{ESRI}[http://www.esri.com/] is one of the oldest and most well-known GIS corporations, developing a suite of applications including the venerable {ArcGIS}[http://www.esri.com/software/arcgis/index.html]. ESRI also created the Shapefile, a geospatial data file format that has become a <i>de facto</i> standard despite its legacy and somewhat awkward characteristics. Today, many of the widely-available geospatial data sets are distributed as shapefiles.
|
365
417
|
|
366
|
-
The shapefile format is specified in an ESRI {whitepaper}[http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf]. It typically comprises three files: a geometric data file "*.shp" containing the actual geometric data, a corresponding index file "*.shx" providing offsets into the .shp file to support random access, and a corresponding file "*.dbf" in dBASE format that stores arbitrary attributes for the shape records. Many GIS systems can read and/or write shapefiles. SpatiaLite can treat a shapefile as an external "virtual table". \RGeo
|
418
|
+
The shapefile format is specified in an ESRI {whitepaper}[http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf]. It typically comprises three files: a geometric data file "*.shp" containing the actual geometric data, a corresponding index file "*.shx" providing offsets into the .shp file to support random access, and a corresponding file "*.dbf" in dBASE format that stores arbitrary attributes for the shape records. Many GIS systems can read and/or write shapefiles. SpatiaLite can treat a shapefile as an external "virtual table". An optional \RGeo module, RGeo::Shapefile (distributed as the gem <b>rgeo-shapefile</b>) can read shapefiles and represent their contents as \RGeo's geometric data types.
|
367
419
|
|
368
420
|
=== 6.2. GeoJSON and Location-Based Services
|
369
421
|
|
370
|
-
Location is becoming a common feature of web services as well. An emerging standard in the encoding of geographic data in a web service is {GeoJSON}[http://www.geojson.org/], an
|
422
|
+
Location is becoming a common feature of web services as well. An emerging standard in the encoding of geographic data in a web service is {GeoJSON}[http://www.geojson.org/], an geospatial data format based on JSON. GeoJSON can encode any of the OGR geometry types, along with attributes, bounding boxes, and coordinate system specifications. {SimpleGeo}[http://www.simplegeo.com/] is one of several high-profile location based APIs now using GeoJSON. \RGeo also provides an optional module RGeo::GeoJSON (distrubted as the gem <b>rgeo-geojson</b>) that can read and write this format.
|
371
423
|
|
372
|
-
Other common formats that may be used by web services include {GeoRSS}[http://www.georss.org/], an extension to RSS and Atom for geotagging RSS feed entries, and {KML}[http://www.opengeospatial.org/standards/kml], an XML-based markup language for geographic information originally developed by Google and recently adopted as an OGC standard.
|
424
|
+
Other common formats that may be used by web services include {GeoRSS}[http://www.georss.org/], an extension to RSS and Atom for geotagging RSS feed entries, and {KML}[http://www.opengeospatial.org/standards/kml], an XML-based markup language for geographic information originally developed by Google and recently adopted as an OGC standard. The GeoRuby library provides rudimentary support for these formats. \RGeo does not yet, but appropriate optional modules are on the to-do list.
|
373
425
|
|
374
426
|
== 7. Conclusion
|
375
427
|
|
376
|
-
Geospatial systems represent a rapidly growing and evolving area of technology, and helpful resources are often difficult to find outside of the relatively niche GIS community. Writing a robust location-aware application requires an understanding of a number of GIS concepts, tools, and specifications. We have covered a few of the most important ones in this document.
|
428
|
+
Geospatial systems represent a rapidly growing and evolving area of technology, and helpful resources are often difficult to find outside of the relatively niche GIS community. Writing a robust location-aware application sometimes requires an understanding of a number of GIS concepts, tools, and specifications. We have covered a few of the most important ones in this document.
|
377
429
|
|
378
|
-
At the time of this writing, a number of open source tools and libraries are starting to mature. For Ruby and Rails developers, the \RGeo library
|
430
|
+
At the time of this writing, a number of open source geospatial tools and libraries are starting to mature. For Ruby and Rails developers, the \RGeo library is one of these emerging tools, and represents an important step towards supporting the next generation of geospatial applications.
|
379
431
|
|
380
432
|
== History
|
381
433
|
|
382
434
|
* Version 0.1 / 5 Dec 2010: Initial draft.
|
435
|
+
* Version 0.2 / 7 Dec 2010: More code examples and other minor updates.
|