Upgraded phpmyadmin to 4.0.4 (All Languages) - No modifications yet
[openemr.git] / phpmyadmin / libraries / gis / pma_gis_visualization.php
blobc49589e83d8459e0e5f4ac206a459f5e61fc1441
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Handles visualization of GIS data
6 * @package PhpMyAdmin-GIS
7 */
9 if (! defined('PHPMYADMIN')) {
10 exit;
13 /**
14 * Handles visualization of GIS data
16 * @package PhpMyAdmin-GIS
18 class PMA_GIS_Visualization
20 /**
21 * @var array Raw data for the visualization
23 private $_data;
25 /**
26 * @var array Set of default settigs values are here.
28 private $_settings = array(
30 // Array of colors to be used for GIS visualizations.
31 'colors' => array(
32 '#B02EE0',
33 '#E0642E',
34 '#E0D62E',
35 '#2E97E0',
36 '#BCE02E',
37 '#E02E75',
38 '#5CE02E',
39 '#E0B02E',
40 '#0022E0',
41 '#726CB1',
42 '#481A36',
43 '#BAC658',
44 '#127224',
45 '#825119',
46 '#238C74',
47 '#4C489B',
48 '#87C9BF',
51 // The width of the GIS visualization.
52 'width' => 600,
54 // The height of the GIS visualization.
55 'height' => 450,
58 /**
59 * @var array Options that the user has specified.
61 private $_userSpecifiedSettings = null;
63 /**
64 * Returns the settings array
66 * @return array the settings array
67 * @access public
69 public function getSettings()
71 return $this->_settings;
74 /**
75 * Constructor. Stores user specified options.
77 * @param array $data Data for the visualization
78 * @param array $options Users specified options
80 * @access public
82 public function __construct($data, $options)
84 $this->_userSpecifiedSettings = $options;
85 $this->_data = $data;
88 /**
89 * All the variable initialization, options handling has to be done here.
91 * @return void
92 * @access protected
94 protected function init()
96 $this->_handleOptions();
99 /**
100 * A function which handles passed parameters. Useful if desired
101 * chart needs to be a little bit different from the default one.
103 * @return void
104 * @access private
106 private function _handleOptions()
108 if (! is_null($this->_userSpecifiedSettings)) {
109 $this->_settings = array_merge(
110 $this->_settings,
111 $this->_userSpecifiedSettings
117 * Sanitizes the file name.
119 * @param string $file_name file name
120 * @param string $ext extension of the file
122 * @return string the sanitized file name
123 * @access private
125 private function _sanitizeName($file_name, $ext)
127 $file_name = PMA_sanitizeFilename($file_name);
129 // Check if the user already added extension;
130 // get the substring where the extension would be if it was included
131 $extension_start_pos = strlen($file_name) - strlen($ext) - 1;
132 $user_extension = substr(
133 $file_name, $extension_start_pos, strlen($file_name)
135 $required_extension = "." . $ext;
136 if (strtolower($user_extension) != $required_extension) {
137 $file_name .= $required_extension;
139 return $file_name;
143 * Handles common tasks of writing the visualization to file for various formats.
145 * @param string $file_name file name
146 * @param string $type mime type
147 * @param string $ext extension of the file
149 * @return void
150 * @access private
152 private function _toFile($file_name, $type, $ext)
154 $file_name = $this->_sanitizeName($file_name, $ext);
155 PMA_downloadHeader($file_name, $type);
159 * Generate the visualization in SVG format.
161 * @return string the generated image resource
162 * @access private
164 private function _svg()
166 $this->init();
168 $output = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n";
169 $output .= '<svg version="1.1" xmlns:svg="http://www.w3.org/2000/svg"'
170 . ' xmlns="http://www.w3.org/2000/svg"'
171 . ' width="' . $this->_settings['width'] . '"'
172 . ' height="' . $this->_settings['height'] . '">';
173 $output .= '<g id="groupPanel">';
175 $scale_data = $this->_scaleDataSet($this->_data);
176 $output .= $this->_prepareDataSet($this->_data, $scale_data, 'svg', '');
178 $output .= '</g>';
179 $output .= '</svg>';
181 return $output;
185 * Get the visualization as a SVG.
187 * @return string the visualization as a SVG
188 * @access public
190 public function asSVG()
192 $output = $this->_svg();
193 return $output;
197 * Saves as a SVG image to a file.
199 * @param string $file_name File name
201 * @return void
202 * @access public
204 public function toFileAsSvg($file_name)
206 $img = $this->_svg();
207 $this->_toFile($file_name, 'image/svg+xml', 'svg');
208 echo($img);
212 * Generate the visualization in PNG format.
214 * @return object the generated image resource
215 * @access private
217 private function _png()
219 $this->init();
221 // create image
222 $image = imagecreatetruecolor(
223 $this->_settings['width'],
224 $this->_settings['height']
227 // fill the background
228 $bg = imagecolorallocate($image, 229, 229, 229);
229 imagefilledrectangle(
230 $image, 0, 0, $this->_settings['width'] - 1,
231 $this->_settings['height'] - 1, $bg
234 $scale_data = $this->_scaleDataSet($this->_data);
235 $image = $this->_prepareDataSet($this->_data, $scale_data, 'png', $image);
237 return $image;
241 * Get the visualization as a PNG.
243 * @return string the visualization as a PNG
244 * @access public
246 public function asPng()
248 $img = $this->_png();
250 // render and save it to variable
251 ob_start();
252 imagepng($img, null, 9, PNG_ALL_FILTERS);
253 imagedestroy($img);
254 $output = ob_get_contents();
255 ob_end_clean();
257 // base64 encode
258 $encoded = base64_encode($output);
259 return '<img src="data:image/png;base64,'. $encoded .'" />';
263 * Saves as a PNG image to a file.
265 * @param string $file_name File name
267 * @return void
268 * @access public
270 public function toFileAsPng($file_name)
272 $img = $this->_png();
273 $this->_toFile($file_name, 'image/png', 'png');
274 imagepng($img, null, 9, PNG_ALL_FILTERS);
275 imagedestroy($img);
279 * Get the code for visualization with OpenLayers.
281 * @return string the code for visualization with OpenLayers
282 * @access public
284 public function asOl()
286 $this->init();
287 $scale_data = $this->_scaleDataSet($this->_data);
288 $output
289 = 'var options = {'
290 . 'projection: new OpenLayers.Projection("EPSG:900913"),'
291 . 'displayProjection: new OpenLayers.Projection("EPSG:4326"),'
292 . 'units: "m",'
293 . 'numZoomLevels: 18,'
294 . 'maxResolution: 156543.0339,'
295 . 'maxExtent: new OpenLayers.Bounds('
296 . '-20037508, -20037508, 20037508, 20037508),'
297 . 'restrictedExtent: new OpenLayers.Bounds('
298 . '-20037508, -20037508, 20037508, 20037508)'
299 . '};'
300 . 'var map = new OpenLayers.Map("openlayersmap", options);'
301 . 'var layerNone = new OpenLayers.Layer.Boxes('
302 . '"None", {isBaseLayer: true});'
303 . 'var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");'
304 . 'var layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");'
305 . 'map.addLayers([layerMapnik,layerCycleMap,layerNone]);'
306 . 'var vectorLayer = new OpenLayers.Layer.Vector("Data");'
307 . 'var bound;';
308 $output .= $this->_prepareDataSet($this->_data, $scale_data, 'ol', '');
309 $output .=
310 'map.addLayer(vectorLayer);'
311 . 'map.zoomToExtent(bound);'
312 . 'if (map.getZoom() < 2) {'
313 . 'map.zoomTo(2);'
314 . '}'
315 . 'map.addControl(new OpenLayers.Control.LayerSwitcher());'
316 . 'map.addControl(new OpenLayers.Control.MousePosition());';
317 return $output;
321 * Saves as a PDF to a file.
323 * @param string $file_name File name
325 * @return void
326 * @access public
328 public function toFileAsPdf($file_name)
330 $this->init();
332 include_once './libraries/tcpdf/tcpdf.php';
334 // create pdf
335 $pdf = new TCPDF(
336 '', 'pt', $GLOBALS['cfg']['PDFDefaultPageSize'], true, 'UTF-8', false
339 // disable header and footer
340 $pdf->setPrintHeader(false);
341 $pdf->setPrintFooter(false);
343 //set auto page breaks
344 $pdf->SetAutoPageBreak(false);
346 // add a page
347 $pdf->AddPage();
349 $scale_data = $this->_scaleDataSet($this->_data);
350 $pdf = $this->_prepareDataSet($this->_data, $scale_data, 'pdf', $pdf);
352 // sanitize file name
353 $file_name = $this->_sanitizeName($file_name, 'pdf');
354 $pdf->Output($file_name, 'D');
358 * Calculates the scale, horizontal and vertical offset that should be used.
360 * @param array $data Row data
362 * @return array an array containing the scale, x and y offsets
363 * @access private
365 private function _scaleDataSet($data)
367 $min_max = array();
368 $border = 15;
369 // effective width and height of the plot
370 $plot_width = $this->_settings['width'] - 2 * $border;
371 $plot_height = $this->_settings['height'] - 2 * $border;
373 foreach ($data as $row) {
375 // Figure out the data type
376 $ref_data = $row[$this->_settings['spatialColumn']];
377 $type_pos = stripos($ref_data, '(');
378 $type = substr($ref_data, 0, $type_pos);
380 $gis_obj = PMA_GIS_Factory::factory($type);
381 if (! $gis_obj) {
382 continue;
384 $scale_data = $gis_obj->scaleRow(
385 $row[$this->_settings['spatialColumn']]
388 // Upadate minimum/maximum values for x and y cordinates.
389 $c_maxX = (float) $scale_data['maxX'];
390 if (! isset($min_max['maxX']) || $c_maxX > $min_max['maxX']) {
391 $min_max['maxX'] = $c_maxX;
394 $c_minX = (float) $scale_data['minX'];
395 if (! isset($min_max['minX']) || $c_minX < $min_max['minX']) {
396 $min_max['minX'] = $c_minX;
399 $c_maxY = (float) $scale_data['maxY'];
400 if (! isset($min_max['maxY']) || $c_maxY > $min_max['maxY']) {
401 $min_max['maxY'] = $c_maxY;
404 $c_minY = (float) $scale_data['minY'];
405 if (! isset($min_max['minY']) || $c_minY < $min_max['minY']) {
406 $min_max['minY'] = $c_minY;
410 // scale the visualization
411 $x_ratio = ($min_max['maxX'] - $min_max['minX']) / $plot_width;
412 $y_ratio = ($min_max['maxY'] - $min_max['minY']) / $plot_height;
413 $ratio = ($x_ratio > $y_ratio) ? $x_ratio : $y_ratio;
415 $scale = ($ratio != 0) ? (1 / $ratio) : 1;
417 if ($x_ratio < $y_ratio) {
418 // center horizontally
419 $x = ($min_max['maxX'] + $min_max['minX'] - $plot_width / $scale) / 2;
420 // fit vertically
421 $y = $min_max['minY'] - ($border / $scale);
422 } else {
423 // fit horizontally
424 $x = $min_max['minX'] - ($border / $scale);
425 // center vertically
426 $y =($min_max['maxY'] + $min_max['minY'] - $plot_height / $scale) / 2;
429 return array(
430 'scale' => $scale,
431 'x' => $x,
432 'y' => $y,
433 'minX' => $min_max['minX'],
434 'maxX' => $min_max['maxX'],
435 'minY' => $min_max['minY'],
436 'maxY' => $min_max['maxY'],
437 'height' => $this->_settings['height'],
442 * Prepares and return the dataset as needed by the visualization.
444 * @param array $data Raw data
445 * @param array $scale_data Data related to scaling
446 * @param string $format Format of the visulaization
447 * @param object $results Image object in the case of png
448 * TCPDF object in the case of pdf
450 * @return mixed the formatted array of data
451 * @access private
453 private function _prepareDataSet($data, $scale_data, $format, $results)
455 $color_number = 0;
457 // loop through the rows
458 foreach ($data as $row) {
459 $index = $color_number % sizeof($this->_settings['colors']);
461 // Figure out the data type
462 $ref_data = $row[$this->_settings['spatialColumn']];
463 $type_pos = stripos($ref_data, '(');
464 $type = substr($ref_data, 0, $type_pos);
466 $gis_obj = PMA_GIS_Factory::factory($type);
467 if (! $gis_obj) {
468 continue;
470 $label = '';
471 if (isset($this->_settings['labelColumn'])
472 && isset($row[$this->_settings['labelColumn']])
474 $label = $row[$this->_settings['labelColumn']];
477 if ($format == 'svg') {
478 $results .= $gis_obj->prepareRowAsSvg(
479 $row[$this->_settings['spatialColumn']], $label,
480 $this->_settings['colors'][$index], $scale_data
482 } elseif ($format == 'png') {
483 $results = $gis_obj->prepareRowAsPng(
484 $row[$this->_settings['spatialColumn']], $label,
485 $this->_settings['colors'][$index], $scale_data, $results
487 } elseif ($format == 'pdf') {
488 $results = $gis_obj->prepareRowAsPdf(
489 $row[$this->_settings['spatialColumn']], $label,
490 $this->_settings['colors'][$index], $scale_data, $results
492 } elseif ($format == 'ol') {
493 $results .= $gis_obj->prepareRowAsOl(
494 $row[$this->_settings['spatialColumn']], $row['srid'],
495 $label, $this->_settings['colors'][$index], $scale_data
498 $color_number++;
500 return $results;