/[drupal]/contributions/modules/geo/db/mysql_spatial.inc
ViewVC logotype

Contents of /contributions/modules/geo/db/mysql_spatial.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.13 - (show annotations) (download) (as text)
Thu Jun 4 02:02:19 2009 UTC (5 months, 3 weeks ago) by vauxia
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-ALPHA1, HEAD
Changes since 1.12: +11 -1 lines
File MIME type: text/x-php
- Add extent handling (bounding box of an entire dataset)
- Add some 'aggregate => true''s to my function fields to keep Views in line.

- Beginnings of storage -> expected inputs for formatters.
- Beginnings of the "common language" thing I keep talking about.
- Beginnings of "selectable inputs" to switch out, say, a geocoded text field
  as an exposed view input.

THIS COMMIT WILL DO MORE HARM THAN GOOD!  STUFF IS PROBABLY BROKEN!
I just wanted to commit the proof-of-concept before tinkering with it on a
refactor.
1 <?php // $Id: mysql_spatial.inc,v 1.12 2009/05/30 04:21:15 vauxia Exp $
2
3 /**
4 * @file
5 * MySQL Spatial Extensions backend for the geo field module
6 *
7 * @package geo
8 */
9
10 /*** API Functions ***/
11
12 /**
13 * Adds a geometry column to the specified table.
14 *
15 * @param $table
16 * The name of the table to which to add the column. Do not include braces ({}).
17 * @param $field_name
18 * The name of the field to use.
19 * @param $type
20 * The OpenGIS type of the column.
21 * Valid types are: POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION
22 * @param $srid
23 * The Spatial Reference ID of this column's projection. The most commonly used SRID is GEO_SRID_DEFAULT, which corresponds to unprojected lat-long in WGS84.
24 * @return boolean
25 * Success or failure
26 */
27 function geo_mysql_spatial_add_field(&$ret, $table, $field, $spec) {
28 // NOTE for now, all geometries are 2d. deal with it
29 $ret[] = db_query("ALTER TABLE {%s} ADD %s %s NOT NULL", $table, $field, $spec['type']);
30 db_query("CREATE SPATIAL INDEX {$table}_${field}_idx ON {". $table ."} ($field)");
31
32 // @@@ Error handling
33 return true;
34 }
35
36 /**
37 * Remove a geometry column from the specified table.
38 *
39 * @param $table
40 * The name of the table from which to drop the column.
41 * @param $field_name
42 * The name of the field to drop.
43 *
44 * @return boolean
45 * Success or failure
46 */
47 function geo_mysql_spatial_drop_field($table, $column) {
48 db_query("ALTER TABLE {%s} DROP COLUMN %s", $table, $column);
49 return true;
50 }
51
52 function geo_mysql_spatial_query_function($func, $field, $value, $srid) {
53 return array("$func(GeomFromText('$value', $srid), $field)");
54 }
55
56 /**
57 * Calculate the distance using the Pythagorean theorem. It's cheaper than
58 * the spherical versions, but less accurate.
59 * TODO only works for points - the X() and Y() functions should be supplanted
60 * by something that's cognizant of other geometries.
61 */
62 function geo_mysql_spatial_query_distance($field, $srid, $point) {
63 // Point data.
64 $x = $point['lon'];
65 $y = $point['lat'];
66
67 // Offsets, in meters.
68 $mod_x = GEO_DEGREE_M * cos($y / 57.2958);
69 $mod_y = GEO_DEGREE_M;
70
71 return "SQRT(POW(($mod_x * (X($field) - $x)), 2) + POW(($mod_y * (Y($field) - $y)), 2))";
72 }
73
74 /**
75 * Calculate the distance using the Great Circle Distance Formula.
76 * TODO only works for points - the X() and Y() functions should be supplanted
77 * by something that's cognizant of other geometries.
78 */
79 function geo_mysql_spatial_query_distance_sphere($field, $srid, $point) {
80 // Radius of the earth in meters.
81 $r = 6370986;
82
83 // Degree offset.
84 $d = 57.2958;
85
86 // Point data.
87 $x = $point['lon'];
88 $y = $point['lat'];
89
90 // Offsets, in meters.
91 $ysin = sin($y / $d);
92 $ycos = cos($y / $d);
93 $xd = $x/$d;
94
95 return "($r * ACOS($ysin * SIN(Y($field)/$d) + $ycos * COS(Y($field)/$d) * COS(X($field)/$d - $xd)))";
96 }
97
98 /**
99 * Aggregate function that returns the total boundary of a result set.
100 */
101 function mysql_spatial_geo_query_extent($field) {
102 return "MIN(X(PointN(ExteriorRing(envelope($field)), 1))) AS minx,
103 MAX(X(PointN(ExteriorRing(envelope($field)), 3))) AS maxx,
104 MIN(Y(PointN(ExteriorRing(Envelope($field)), 1))) AS miny,
105 MAX(Y(PointN(ExteriorRing(Envelope($field)), 3))) AS maxy";
106 }
107
108 /*** Helper functions ***/
109
110 /**
111 * Return a list of fields, keyed by table, of geo tables.
112 *
113 * @param $table
114 * an optional string of the table name to look in
115 *
116 * @return array
117 * an array of fields, keyed by table
118 */
119 function geo_mysql_spatial_tables($exclude = NULL) {
120 static $tables;
121
122 if (!is_array($tables)) {
123 $tables = array();
124
125 // Query for all available geometry columns.
126 // @@@ Mysql5 + only.
127 $res = db_query("SELECT TABLE_NAME AS 'table', COLUMN_NAME AS 'field'
128 FROM information_schema.columns
129 WHERE TABLE_SCHEMA = database()
130 AND DATA_TYPE IN ('GEOMETRY','POINT','LINESTRING','POLYGON','MULTIPOINT',
131 'MULTILINESTRING','MULTIPOLYGON','GEOMETRYCOLLECTION')
132 ORDER BY TABLE_NAME, COLUMN_NAME");
133
134 while ($row = db_fetch_object($res)) {
135 // Ignore exclusions.
136 if ($exclude && preg_match($exclude, $row->table)) continue;
137
138 if (!isset($tables[$row->table])) {
139 $tables[$row->table] = array();
140 }
141 $tables[$row->table][] = $row->field;
142 }
143 }
144 return $tables;
145 }
146
147 /**
148 * Parse out the table descriptions from the geometry information stored in the table.
149 */
150 function geo_mysql_spatial_table_desc($table) {
151 $res = db_query("SELECT COLUMN_NAME AS 'name',
152 COLUMN_COMMENT AS 'description',
153 DATA_TYPE AS 'type',
154 IS_NULLABLE AS 'null_ok',
155 COLUMN_DEFAULT AS 'default'
156 FROM information_schema.columns
157 WHERE TABLE_SCHEMA = database()
158 AND TABLE_NAME = '%s' ORDER BY ORDINAL_POSITION", $table);
159
160 $columns = array();
161 $geo = array();
162 while ($row = db_fetch_array($res)) {
163 if ($row['type'] == 'geometry') {
164 $geo[] = $row['name'];
165 }
166
167 $columns[$row['name']] = $row;
168 $columns[$row['name']]['not_null'] = $row['null_ok']=='YES' ? FALSE : TRUE;
169 unset($columns[$row['name']]['null_ok']);
170 }
171
172 // @@@ I have no clue what this section is for. ~Bdragon
173
174 /* $res = db_query("SELECT c.relname AS table,
175 pg_catalog.pg_get_constraintdef(r.oid, true) AS constraint
176 FROM pg_catalog.pg_constraint r
177 LEFT JOIN pg_catalog.pg_class c ON r.conrelid = c.oid
178 WHERE c.relname = '%s' AND r.contype = 'c'", $table);
179 */
180
181 /*
182 Find constraints that are similar to the ones here, and set attributes
183
184 CHECK (geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL)
185 CHECK (ndims(the_geom) = 2)
186 CHECK (srid(the_geom) = 26915)
187 */
188 //while ($row = db_fetch_object($res)) {
189 // $table = $row->table;
190 // foreach($geo as $f) {
191 // if (strpos($row->constraint, "ndims($f)" )) {
192 // $columns[$f]['dimensions'] = preg_replace('/\D/','', $row->constraint);
193 // }
194 // elseif (strpos($row->constraint, "srid($f)" )) {
195 // $columns[$f]['srid'] = preg_replace('/\D/','', $row->constraint);
196 // }
197 // elseif (strpos($row->constraint, "geometrytype($f)" )) {
198 // $columns[$f]['geometry_type'] = preg_replace('/.*\'(\w+)\'.*/','$1', $row->constraint);
199 // }
200 // }
201 //}
202
203 return $columns;
204 }
205
206 // provide a quick way to get the SRID of a column and use it in the storage
207 function _geo_fromtext($string, $table, $field) {
208 $srid = db_result(db_query("SELECT srid FROM {gis_sources}
209 WHERE table = '%s' AND field = '%s'"));
210
211 return "GeomFromText('$string', $srid)";
212 }
213
214 // Point to latlon
215 function _geo_latlonfrompoint($wkt, $srid = GEO_SRID_DEFAULT) {
216 // Yep. Not efficient.
217 return array(
218 'lat' => db_result(db_query("SELECT X(GeomFromText('%s', %d))", $wkt, $srid)),
219 'lon' => db_result(db_query("SELECT Y(GeomFromText('%s', %d))", $wkt, $srid)),
220 );
221 }
222
223 // returns the PostGIS version information
224 function geo_mysql_spatial_version() {
225 // No clue what to do here...
226 // return db_result(db_query("SELECT postgis_version()"));
227 }

  ViewVC Help
Powered by ViewVC 1.1.2