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

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

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


Revision 1.15 - (show annotations) (download) (as text)
Thu Jun 18 01:24:11 2009 UTC (5 months, 1 week ago) by vauxia
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-ALPHA1
Changes since 1.14: +10 -8 lines
File MIME type: text/x-php
- Some refactoring of the gis input / output mechanisms.
- Implement a crude on-the-fly conversion so that gis elements can expect one
  format, backends (e.g. field storage or views filters) can expect another
  and the conversion is quietly performed.

- Make elements for wkt, latlon work as both elements and views filters
- Refactor widgets to account for the changes on geo_field
- Get PostGIS distance handling working
1 <?php // $Id: geo.inc,v 1.14 2009/06/10 20:52:03 vauxia Exp $
2
3 /**
4 * Return the geo backend database type.
5 *
6 * @return string
7 * The name of the backend: postgis, cck, mysql_spatial
8 */
9 function geo_backend_type() {
10 static $backend;
11
12 if (!isset($backend)) {
13 switch ($GLOBALS['db_type']) {
14 case 'pgsql':
15 // use the postgis backend if installed
16 if (db_result(db_query("SELECT 1 FROM pg_catalog.pg_proc
17 WHERE proname = 'postgis_version'"))) {
18 $backend = 'postgis';
19 }
20 break;
21
22 case 'mysql':
23 case 'mysqli':
24 // Capabilities check.
25 // If it can convert between native and wkt, assume it's working.
26 if (db_result(@db_query("SELECT AsText(GeomFromText('POINT(1 1)'))")) == 'POINT(1 1)') {
27 $backend = 'mysql_spatial';
28 }
29 }
30 }
31
32 return $backend;
33 }
34
35 function geo_supported_types() {
36 return array(
37 'point' => t('Point'),
38 'linestring' => t('Linestring'),
39 'polygon' => t('Polygon'),
40 );
41 }
42
43 // TODO seriously clean this up! And add data types!
44 function geo_wkt($data) {
45 if (!is_scalar($data)) {
46 $data = (object) $data;
47 if (!isset($data->type)) $data->type = 'point';
48 switch ($data->type) {
49 case 'point':
50 return 'POINT('. $data->lon .' '. $data->lat .')';
51 }
52 }
53 }
54
55 function geo_wkt_from_point($lat, $lon) {
56 if (strlen($lat) || strlen($lon)) {
57 return 'POINT('. $lon .' '. $lat .')';
58 }
59 }
60
61 function geo_field_select($field) {
62 if (!$field) return;
63 $field = check_plain($field);
64 $alias = str_replace('.', '_', $field);
65 $alias = preg_replace('/_geo$/', '', $alias);
66
67 return " SRID($field) as {$alias}_srid,
68 AsBinary($field) AS {$alias}_wkb,
69 AsBinary(Envelope($field)) AS {$alias}_bbox,
70 AsBinary(Centroid($field)) AS $alias}_centroid";
71 }
72
73 function geo_query_operators($geo_type) {
74 return array(
75 'Equals' => t('Equals'),
76 'NOT Equals' => t('Does not equal'),
77 'Intersects' => t('Intersects'),
78 'NOT Intersects' => t('Does not intersect'),
79 'Within' => t('Within'),
80 'NOT Within' => t('Not within'),
81 );
82 }
83
84 function geo_query_functions($geo_type) {
85 $geo_type = strtolower($geo_type);
86 $functions = array( 'wkt' => 'wkt', 'wkb' => 'wkb' );
87
88 if ($geo_type == 'point') {
89 $functions['lat'] = 'lat';
90 $functions['lon'] = 'lon';
91 }
92
93 if ($geo_type == 'polygon' || $geo_type == 'linestring') {
94 $functions['area'] = 'area';
95 $functions['bbox'] = 'bbox';
96 $functions['perimeter'] = 'perimeter';
97 }
98
99 if ($geo_type == 'linestring') {
100 $functions['start'] = 'start';
101 $functions['end'] = 'end';
102 }
103
104 // TODO distance? given that we have a starting point?
105
106 return $functions;
107 }
108
109 function geo_query_handlers($geo_type) {
110 // TODO are these all supported by default? (and through which functions?)
111 return array(
112 'wkt' => t('Well Known Text'),
113 'wkb' => t('Well Known Binary'),
114 'svg' => t('SVG'),
115 'kml' => t('KML'),
116 'gml' => t('GML'),
117 );
118 }
119
120 function geo_query_area($field, $srid = null) {
121 return 'Area('. $field .')';
122 }
123
124 function geo_query_bbox($field, $srid = null) {
125 return 'Envelope('. $field .')';
126 }
127
128 function geo_query_centroid($field, $srid = null) {
129 return 'Centroid('. $field .')';
130 }
131
132 function geo_query_geo_type($field, $srid = null) {
133 return 'GeometryType('. $field .')';
134 }
135
136 function geo_query_end($field, $srid = null) {
137 return 'EndPoint('. $field .')';
138 }
139
140 function geo_query_lat($field, $srid = null) {
141 return 'Y('. $field .')';
142 }
143
144 function geo_query_lon($field, $srid = null) {
145 return 'X('. $field .')';
146 }
147
148 function geo_query_length($field, $srid = null) {
149 return 'Length('. $field .')';
150 }
151
152 function geo_query_perimeter($field, $srid = null) {
153 return 'Length(ConvexHull('. $field .')';
154 }
155
156 function geo_query_start($field, $srid = null) {
157 return 'StartPoint('. $field .')';
158 }
159
160 function geo_query_wkt($field, $srid = null) {
161 return 'asText('. $field .')';
162 }
163
164 function geo_query_wkb($field, $srid = null) {
165 return 'asBinary('. $field .')';
166 }
167
168 function geo_query_distance($field, $srid = null, $target) {
169 $target = geo_wkt_from_point($target['lat'], $target['lon']);
170 $query = 'Distance('. $field .", GeomFromText('". $target ."', $srid))";
171 return '('. GEO_DEGREE_M .' * '. $query .')';
172 }
173
174 function geo_query_within($field, $srid = null, $target) {
175 return "Within($field, GeomFromText('". $target['wkt'] ."', $srid))";
176 }
177
178 function geo_query_contains($field, $srid = null, $target) {
179 return "Contains(GeomFromText('". $target['wkt'] ."', $srid), $field)";
180 }
181
182 function geo_query_extent($field) {
183 return "ST_Extent($field)";
184 }
185
186 function geo_schema_field($gis_type = 'geometry', $name = 'geo', $srid = NULL) {
187 $types = geo_supported_types();
188 $schema = array();
189 if (isset($types[$gis_type])) {
190 $schema[$name] = array(
191 'type' => 'blob',
192 'mysql_type' => 'geometry',
193 'pgsql_type' => 'geometry',
194 'gis type' => $gis_type,
195 'description' => t('Geometry field'),
196 );
197 }
198 return $schema;
199 }
200
201 function geo_make_bbox($target, $limit) {
202 $x = $target['lon'];
203 $y = $target['lat'];
204 $offset_x = $limit / (GEO_DEGREE_M * cos($y));
205 $offset_y = $limit / GEO_DEGREE_M;
206
207 $offset_x = $limit / GEO_DEGREE_M; // TODO Miles
208 $offset_y = $limit / round(GEO_DEGREE_M * cos($x / 92215));
209
210 $bbox = array(
211 'points' => array(
212 array('lon' => $x - $offset_x, 'lat' => $y + $offset_y),
213 array('lon' => $x + $offset_x, 'lat' => $y + $offset_y),
214 array('lon' => $x + $offset_x, 'lat' => $y - $offset_y),
215 array('lon' => $x - $offset_x, 'lat' => $y - $offset_y),
216 array('lon' => $x - $offset_x, 'lat' => $y + $offset_y),
217 ),
218 );
219 // TODO call a function?
220 $wkt = '';
221 foreach ($bbox['points'] as $p) $wkt .= $p['lon'] .' '. $p['lat'] .', ';
222 $bbox['wkt'] = 'POLYGON(('. substr($wkt, 0, -2) .'))';
223 return $bbox;
224 }
225
226 /**
227 * Insert a geometry object into the database on the specified row
228 *
229 * @param $table
230 * The name of the table that currently holds the geometry information.
231 * @param $field_name
232 * The name of the field in which to insert the data.
233 * @return void
234 */
235 function geo_geo_from_wkt($wkt, $srid = GEO_DEFAULT_SRID) {
236 return " GeomFromText('". $wkt ."') ";
237 }
238
239 function geo_rss_item($wkb) {
240 $data = geo_wkb_get_data($wkb, 'text');
241 return array(
242 'key' => 'georss:'. strtolower($data['type']),
243 'value' => $data['value'],
244 'namespace' => array('xmlns:georss' => 'http://www.georss.org/georss'),
245 );
246 }
247
248 function geo_gis_input_selector($default_value) {
249 // Provide a selection of input handlers.
250 $input_types = array();
251 foreach (module_invoke_all('gis_input_info') as $name => $info) {
252 $input_types[$name] = $info['label'];
253 }
254
255 $form = array(
256 '#type' => 'select',
257 '#title' => 'Widget',
258 '#options' => $input_types,
259 '#default_value' => $default_value,
260 );
261 return $form;
262 }
263
264 function geo_wkt_validate($wkt, $geo_type = NULL, $srid = GEO_DEFAULT_SRID) {
265
266 // TODO this should probabaly be moved into db-specific backend files.
267 $type = db_result(@db_query("SELECT GeometryType(GeomFromText('%s'))", $wkt));
268
269 if (empty($type)) {
270 return t('Unable to parse WKT.');
271 }
272
273 if ($geo_type && strtolower($geo_type) != strtolower($type)) {
274 return t('Wrong geometry type. Got %result, was expecting %type.', array('%result' => $type, '%type' => $geo_type));
275 }
276
277 // All's well that ends well!
278 return TRUE;
279 }

  ViewVC Help
Powered by ViewVC 1.1.2