rgeo 0.1.22 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/History.rdoc +31 -0
  2. data/README.rdoc +53 -59
  3. data/Spatial_Programming_With_RGeo.rdoc +120 -67
  4. data/Version +1 -1
  5. data/ext/proj4_c_impl/extconf.rb +1 -1
  6. data/lib/rgeo.rb +80 -87
  7. data/lib/rgeo/cartesian.rb +0 -10
  8. data/lib/rgeo/coord_sys.rb +0 -7
  9. data/lib/rgeo/coord_sys/proj4.rb +2 -2
  10. data/lib/rgeo/error.rb +2 -6
  11. data/lib/rgeo/feature.rb +0 -7
  12. data/lib/rgeo/feature/curve.rb +5 -5
  13. data/lib/rgeo/feature/factory.rb +45 -5
  14. data/lib/rgeo/feature/factory_generator.rb +2 -4
  15. data/lib/rgeo/feature/geometry.rb +97 -27
  16. data/lib/rgeo/feature/geometry_collection.rb +3 -3
  17. data/lib/rgeo/feature/line_string.rb +3 -3
  18. data/lib/rgeo/feature/multi_curve.rb +2 -2
  19. data/lib/rgeo/feature/multi_surface.rb +3 -3
  20. data/lib/rgeo/feature/point.rb +6 -6
  21. data/lib/rgeo/feature/polygon.rb +4 -4
  22. data/lib/rgeo/feature/surface.rb +3 -3
  23. data/lib/rgeo/geographic.rb +0 -11
  24. data/lib/rgeo/geographic/factory.rb +5 -2
  25. data/lib/rgeo/geographic/interface.rb +1 -1
  26. data/lib/rgeo/geos.rb +0 -7
  27. data/lib/rgeo/geos/factory.rb +1 -1
  28. data/lib/rgeo/impl_helper.rb +0 -7
  29. data/lib/rgeo/wkrep.rb +0 -7
  30. data/lib/rgeo/wkrep/wkb_parser.rb +2 -2
  31. data/test/tc_oneoff.rb +0 -1
  32. metadata +7 -155
  33. data/lib/active_record/connection_adapters/mysql2spatial_adapter.rb +0 -124
  34. data/lib/active_record/connection_adapters/mysqlspatial_adapter.rb +0 -136
  35. data/lib/active_record/connection_adapters/postgis_adapter.rb +0 -426
  36. data/lib/active_record/connection_adapters/spatialite_adapter.rb +0 -488
  37. data/lib/rgeo/active_record/arel_modifications.rb +0 -78
  38. data/lib/rgeo/active_record/base_modifications.rb +0 -124
  39. data/lib/rgeo/active_record/common.rb +0 -166
  40. data/lib/rgeo/active_record/mysql_common.rb +0 -150
  41. data/lib/rgeo/all.rb +0 -49
  42. data/lib/rgeo/geo_json.rb +0 -60
  43. data/lib/rgeo/geo_json/coder.rb +0 -401
  44. data/lib/rgeo/geo_json/entities.rb +0 -285
  45. data/lib/rgeo/geo_json/interface.rb +0 -129
  46. data/lib/rgeo/shapefile.rb +0 -60
  47. data/lib/rgeo/shapefile/reader.rb +0 -898
  48. data/test/active_record/common_setup_methods.rb +0 -129
  49. data/test/active_record/readme.txt +0 -43
  50. data/test/active_record/tc_mysqlspatial.rb +0 -170
  51. data/test/active_record/tc_postgis.rb +0 -282
  52. data/test/active_record/tc_spatialite.rb +0 -198
  53. data/test/shapefile/shapelib_testcases/readme.txt +0 -11
  54. data/test/shapefile/shapelib_testcases/test.dbf +0 -0
  55. data/test/shapefile/shapelib_testcases/test.shp +0 -0
  56. data/test/shapefile/shapelib_testcases/test.shx +0 -0
  57. data/test/shapefile/shapelib_testcases/test0.shp +0 -0
  58. data/test/shapefile/shapelib_testcases/test0.shx +0 -0
  59. data/test/shapefile/shapelib_testcases/test1.shp +0 -0
  60. data/test/shapefile/shapelib_testcases/test1.shx +0 -0
  61. data/test/shapefile/shapelib_testcases/test10.shp +0 -0
  62. data/test/shapefile/shapelib_testcases/test10.shx +0 -0
  63. data/test/shapefile/shapelib_testcases/test11.shp +0 -0
  64. data/test/shapefile/shapelib_testcases/test11.shx +0 -0
  65. data/test/shapefile/shapelib_testcases/test12.shp +0 -0
  66. data/test/shapefile/shapelib_testcases/test12.shx +0 -0
  67. data/test/shapefile/shapelib_testcases/test13.shp +0 -0
  68. data/test/shapefile/shapelib_testcases/test13.shx +0 -0
  69. data/test/shapefile/shapelib_testcases/test2.shp +0 -0
  70. data/test/shapefile/shapelib_testcases/test2.shx +0 -0
  71. data/test/shapefile/shapelib_testcases/test3.shp +0 -0
  72. data/test/shapefile/shapelib_testcases/test3.shx +0 -0
  73. data/test/shapefile/shapelib_testcases/test4.shp +0 -0
  74. data/test/shapefile/shapelib_testcases/test4.shx +0 -0
  75. data/test/shapefile/shapelib_testcases/test5.shp +0 -0
  76. data/test/shapefile/shapelib_testcases/test5.shx +0 -0
  77. data/test/shapefile/shapelib_testcases/test6.shp +0 -0
  78. data/test/shapefile/shapelib_testcases/test6.shx +0 -0
  79. data/test/shapefile/shapelib_testcases/test7.shp +0 -0
  80. data/test/shapefile/shapelib_testcases/test7.shx +0 -0
  81. data/test/shapefile/shapelib_testcases/test8.shp +0 -0
  82. data/test/shapefile/shapelib_testcases/test8.shx +0 -0
  83. data/test/shapefile/shapelib_testcases/test9.shp +0 -0
  84. data/test/shapefile/shapelib_testcases/test9.shx +0 -0
  85. data/test/shapefile/tc_shapelib_tests.rb +0 -527
  86. data/test/tc_geojson.rb +0 -279
@@ -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.
@@ -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. It also includes a
12
- suite of components for modeling location data, communicating with
13
- location-aware services and database systems, and writing location-aware
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 RGeo to:
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
- * Store and retrieve data in industry standard spatial database
25
- systems such as MySQL Spatial, SpatiaLite, and PostGIS.
26
- * Generate and interpret GeoJSON data for communication with common
27
- location-based web services such as SimpleGeo.
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
- IMPORTANT: RGeo is currently under development, and we consider it to be
33
- in a "pre-alpha" state. Several features are not yet complete, and there
34
- are known bugs and holes in the test suite. We also expect the APIs to be
35
- in flux for a short while longer. Therefore, we do not yet recommend the
36
- use of RGeo in production.
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 hard requirements:
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://geos.osgeo.org/
51
- * Proj 4.7.0 or later is also recommended. This is needed if you want
52
- to translate coordinates between geographic projections. It also may
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 required GEOS
72
- library in the following locations:
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 items
95
+ === To-do list
99
96
 
100
- This is our planned roadmap, in rough priority order.
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 representation.
103
- * Continued work on the ActiveRecord adapters.
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
- * Integration with certain third-party services such as SimpleGeo.
108
- * Rubinius support for C library integration.
109
- * JRuby support via JTS integration.
110
- * Support for writing shapefiles. (Reading is already implemented.)
111
- * Read and write other formats such as GeoRSS and KML.
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 links with the GEOS library to handle most Cartesian geometric
130
- calculations, and with the Proj4 library to handle projections and
131
- coordinate transforms. These libraries are maintained by the Open Source
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.1 (5 Dec 2010)
4
+ * version 0.2 (7 Dec 2010)
5
5
 
6
6
  == Introduction
7
7
 
8
8
  === About This Document
9
9
 
10
- Spatial programming and location-based services are an important emerging technology. Once the exclusive domain of complex GIS systems, these techniques and features are now increasingly available in small applications, websites, and enterprises. This document provides a brief overview of techniques and tools used to implement these location-aware application features, focusing on the Ruby programming language and an open-source technology stack. We will cover both the key technical concepts and the necessary software components.
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 programming, including a survey of the common tools and libraries available.
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 external location data and services.
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, computational geometry, software architecture, and large scale web services. He is also the author of \RGeo, the advanced spatial data library for Ruby covered in this document.
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 technologies. 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 of startups up to the giants such as Facebook and Twitter. 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.
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 a few 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.
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, which let you serve your own map data.
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 partial spatial 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.
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 newer library for Ruby that can perform the same function for Ruby on Rails.
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 develop open standards and open interfaces for geospatial software systems to promote interoperability. Most of the specific concepts, data types, and operations in this document were developed 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 de facto 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 spatial applications will interact at least indirectly with their services.
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 \ActiveRecord extension for 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] introduces a hack into a few of the popular \ActiveRecord database adapters to support spatial columns in the database.
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 {standard}[http://www.opengeospatial.org/standards/sfa] entitled "Geographic information -- Simple feature access", 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 are now available, most current implementations, including \RGeo, follow version 1.1 of the SFS, and this is the specification we will cover here.
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 together with line segments, and you can retrieve those points from the LineString object.
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 types, for different use cases. For example, the RGeo::Geos implementation is \RGeo's main implementation which provides all these data types and all the operations 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.
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 simply represents the coordinate system and other settings for that implementation. You can then create actual geometric objects by calling methods on that factory, as defined in the RGeo::Feature::Factory interface. For example:
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 basic 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:
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, defines as methods on the object interfaces. 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.
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 implements a handful of the defined functions.
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
- mp = point1.union(point2)
193
- # or
194
- mp = point1 + point2
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 exist 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.
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
- 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 formats through the RGeo::WKRep module.
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 the LineString and a Point located at Reykjavik, what would you get?
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 geometric analysis 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.
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
- 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 the LineString will actually go 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 on 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.
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
- 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 query or a geometric analysis. Morten Nielsen gives an example in {this post}[http://www.sharpgis.net/post/2009/02/06/Why-EPSG4326-is-usually-the-wrong-e2809cprojectione2809d.aspx].
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 *flattened* sphere. This feature is not available yet.)
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. Just remember the Vancouver to Frankfurt problem: 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. For better accuracy or more sophisticated applications, you will need to pay explicit attention to projections.
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 what we mean by "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. A map projection is merely a function mapping latitude-longitude to flat coordinates, but again, we need to specify _which_ latitude/longitude.
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 the older (and North-America specific) NAD27 datum.
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. This is the same worldwide geographic coordinate system that GPS uses, as do most maps, geocoding services, and so forth. Only in certain locale-specific cases might a different coordinate system be in 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 an ellipsoidal map.
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 radar.
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 restrictions. 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:
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 because it has to scan and compare every row. This is especially true of 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.
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 will handle the problem of indexing spatial data in different ways, but most 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.
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, and 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.
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 with 4 extra bytes at the beginning to store an object's SRID. You can interpret this data directly, or use provided functions to convert to and from WKB and WKT.
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 restrictions on your geometries beyond the type: you will not be able to restrict the SRID for a column, and columns will not be able to support Z and M coordinates. Because the latter is not present, MySQL cannot perform coordinate system transformations itself, nor provide you with the standard EPSG dataset for your own use.
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 to add some simple geometric data, it's very easy to use MySQL spatial. Just make sure your table uses the MyISAM engine if you need to index the geometry.
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 restrictions and maintain the spatial indexes.
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 separate add-on library to Postgres. 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.
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 on 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 common enough that they are supported by \RGeo's WKB and WKT parsers.
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 \ActiveRecord Integration
399
+ === 5.5. \RGeo ActiveRecord Integration
348
400
 
349
- \RGeo provides extra support for web applications built on Ruby On Rails or similar frameworks, and 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 connection adapters for the databases, 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.
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*: subclasses the mysql adapter and adds support for spatial types
354
- * *mysql2spatial*: subclasses the mysql2 adapter and adds support for spatial types
355
- * *spatialite*: subclasses the sqlite3 adapter and adds support for the SpatiaLite extension
356
- * *postgis*: subclasses the postgresql adapter and adds support for the PostGIS extension
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 provides a module, RGeo::Shapefile, that can read shapefiles and represent their contents as geometric data objects.
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 object format based on JSON. GeoJSON can encode any of the OGR geometry types, and includes facilities to attach 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 a RGeo::GeoJSON module that can read and write this format.
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, along with this emerging suite of tools, represents an important step in the support for writing the next generation of geospatial applications.
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.