1<?php 2/* vim: set expandtab sw=4 ts=4 sts=4: */ 3/** 4 * Handles actions related to GIS MULTILINESTRING objects 5 * 6 * @package PhpMyAdmin-GIS 7 */ 8 9namespace PhpMyAdmin\Gis; 10 11use TCPDF; 12 13/** 14 * Handles actions related to GIS MULTILINESTRING objects 15 * 16 * @package PhpMyAdmin-GIS 17 */ 18class GisMultiLineString extends GisGeometry 19{ 20 // Hold the singleton instance of the class 21 private static $_instance; 22 23 /** 24 * A private constructor; prevents direct creation of object. 25 * 26 * @access private 27 */ 28 private function __construct() 29 { 30 } 31 32 /** 33 * Returns the singleton. 34 * 35 * @return GisMultiLineString the singleton 36 * @access public 37 */ 38 public static function singleton() 39 { 40 if (!isset(self::$_instance)) { 41 $class = __CLASS__; 42 self::$_instance = new $class; 43 } 44 45 return self::$_instance; 46 } 47 48 /** 49 * Scales each row. 50 * 51 * @param string $spatial spatial data of a row 52 * 53 * @return array an array containing the min, max values for x and y coordinates 54 * @access public 55 */ 56 public function scaleRow($spatial) 57 { 58 $min_max = array(); 59 60 // Trim to remove leading 'MULTILINESTRING((' and trailing '))' 61 $multilinestirng 62 = mb_substr( 63 $spatial, 64 17, 65 mb_strlen($spatial) - 19 66 ); 67 // Separate each linestring 68 $linestirngs = explode("),(", $multilinestirng); 69 70 foreach ($linestirngs as $linestring) { 71 $min_max = $this->setMinMax($linestring, $min_max); 72 } 73 74 return $min_max; 75 } 76 77 /** 78 * Adds to the PNG image object, the data related to a row in the GIS dataset. 79 * 80 * @param string $spatial GIS MULTILINESTRING object 81 * @param string $label Label for the GIS MULTILINESTRING object 82 * @param string $line_color Color for the GIS MULTILINESTRING object 83 * @param array $scale_data Array containing data related to scaling 84 * @param object $image Image object 85 * 86 * @return object the modified image object 87 * @access public 88 */ 89 public function prepareRowAsPng( 90 $spatial, 91 $label, 92 $line_color, 93 array $scale_data, 94 $image 95 ) { 96 // allocate colors 97 $black = imagecolorallocate($image, 0, 0, 0); 98 $red = hexdec(mb_substr($line_color, 1, 2)); 99 $green = hexdec(mb_substr($line_color, 3, 2)); 100 $blue = hexdec(mb_substr($line_color, 4, 2)); 101 $color = imagecolorallocate($image, $red, $green, $blue); 102 103 // Trim to remove leading 'MULTILINESTRING((' and trailing '))' 104 $multilinestirng 105 = mb_substr( 106 $spatial, 107 17, 108 mb_strlen($spatial) - 19 109 ); 110 // Separate each linestring 111 $linestirngs = explode("),(", $multilinestirng); 112 113 $first_line = true; 114 foreach ($linestirngs as $linestring) { 115 $points_arr = $this->extractPoints($linestring, $scale_data); 116 foreach ($points_arr as $point) { 117 if (!isset($temp_point)) { 118 $temp_point = $point; 119 } else { 120 // draw line section 121 imageline( 122 $image, 123 $temp_point[0], 124 $temp_point[1], 125 $point[0], 126 $point[1], 127 $color 128 ); 129 $temp_point = $point; 130 } 131 } 132 unset($temp_point); 133 // print label if applicable 134 if (isset($label) && trim($label) != '' && $first_line) { 135 imagestring( 136 $image, 137 1, 138 $points_arr[1][0], 139 $points_arr[1][1], 140 trim($label), 141 $black 142 ); 143 } 144 $first_line = false; 145 } 146 147 return $image; 148 } 149 150 /** 151 * Adds to the TCPDF instance, the data related to a row in the GIS dataset. 152 * 153 * @param string $spatial GIS MULTILINESTRING object 154 * @param string $label Label for the GIS MULTILINESTRING object 155 * @param string $line_color Color for the GIS MULTILINESTRING object 156 * @param array $scale_data Array containing data related to scaling 157 * @param TCPDF $pdf TCPDF instance 158 * 159 * @return TCPDF the modified TCPDF instance 160 * @access public 161 */ 162 public function prepareRowAsPdf($spatial, $label, $line_color, array $scale_data, $pdf) 163 { 164 // allocate colors 165 $red = hexdec(mb_substr($line_color, 1, 2)); 166 $green = hexdec(mb_substr($line_color, 3, 2)); 167 $blue = hexdec(mb_substr($line_color, 4, 2)); 168 $line = array('width' => 1.5, 'color' => array($red, $green, $blue)); 169 170 // Trim to remove leading 'MULTILINESTRING((' and trailing '))' 171 $multilinestirng 172 = mb_substr( 173 $spatial, 174 17, 175 mb_strlen($spatial) - 19 176 ); 177 // Separate each linestring 178 $linestirngs = explode("),(", $multilinestirng); 179 180 $first_line = true; 181 foreach ($linestirngs as $linestring) { 182 $points_arr = $this->extractPoints($linestring, $scale_data); 183 foreach ($points_arr as $point) { 184 if (!isset($temp_point)) { 185 $temp_point = $point; 186 } else { 187 // draw line section 188 $pdf->Line( 189 $temp_point[0], 190 $temp_point[1], 191 $point[0], 192 $point[1], 193 $line 194 ); 195 $temp_point = $point; 196 } 197 } 198 unset($temp_point); 199 // print label 200 if (isset($label) && trim($label) != '' && $first_line) { 201 $pdf->SetXY($points_arr[1][0], $points_arr[1][1]); 202 $pdf->SetFontSize(5); 203 $pdf->Cell(0, 0, trim($label)); 204 } 205 $first_line = false; 206 } 207 208 return $pdf; 209 } 210 211 /** 212 * Prepares and returns the code related to a row in the GIS dataset as SVG. 213 * 214 * @param string $spatial GIS MULTILINESTRING object 215 * @param string $label Label for the GIS MULTILINESTRING object 216 * @param string $line_color Color for the GIS MULTILINESTRING object 217 * @param array $scale_data Array containing data related to scaling 218 * 219 * @return string the code related to a row in the GIS dataset 220 * @access public 221 */ 222 public function prepareRowAsSvg($spatial, $label, $line_color, array $scale_data) 223 { 224 $line_options = array( 225 'name' => $label, 226 'class' => 'linestring vector', 227 'fill' => 'none', 228 'stroke' => $line_color, 229 'stroke-width' => 2, 230 ); 231 232 // Trim to remove leading 'MULTILINESTRING((' and trailing '))' 233 $multilinestirng 234 = mb_substr( 235 $spatial, 236 17, 237 mb_strlen($spatial) - 19 238 ); 239 // Separate each linestring 240 $linestirngs = explode("),(", $multilinestirng); 241 242 $row = ''; 243 foreach ($linestirngs as $linestring) { 244 $points_arr = $this->extractPoints($linestring, $scale_data); 245 246 $row .= '<polyline points="'; 247 foreach ($points_arr as $point) { 248 $row .= $point[0] . ',' . $point[1] . ' '; 249 } 250 $row .= '"'; 251 $line_options['id'] = $label . rand(); 252 foreach ($line_options as $option => $val) { 253 $row .= ' ' . $option . '="' . trim($val) . '"'; 254 } 255 $row .= '/>'; 256 } 257 258 return $row; 259 } 260 261 /** 262 * Prepares JavaScript related to a row in the GIS dataset 263 * to visualize it with OpenLayers. 264 * 265 * @param string $spatial GIS MULTILINESTRING object 266 * @param int $srid Spatial reference ID 267 * @param string $label Label for the GIS MULTILINESTRING object 268 * @param string $line_color Color for the GIS MULTILINESTRING object 269 * @param array $scale_data Array containing data related to scaling 270 * 271 * @return string JavaScript related to a row in the GIS dataset 272 * @access public 273 */ 274 public function prepareRowAsOl($spatial, $srid, $label, $line_color, array $scale_data) 275 { 276 $style_options = array( 277 'strokeColor' => $line_color, 278 'strokeWidth' => 2, 279 'label' => $label, 280 'fontSize' => 10, 281 ); 282 if ($srid == 0) { 283 $srid = 4326; 284 } 285 $row = $this->getBoundsForOl($srid, $scale_data); 286 287 // Trim to remove leading 'MULTILINESTRING((' and trailing '))' 288 $multilinestirng 289 = mb_substr( 290 $spatial, 291 17, 292 mb_strlen($spatial) - 19 293 ); 294 // Separate each linestring 295 $linestirngs = explode("),(", $multilinestirng); 296 297 $row .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector(' 298 . 'new OpenLayers.Geometry.MultiLineString(' 299 . $this->getLineArrayForOpenLayers($linestirngs, $srid) 300 . '), null, ' . json_encode($style_options) . '));'; 301 302 return $row; 303 } 304 305 /** 306 * Generate the WKT with the set of parameters passed by the GIS editor. 307 * 308 * @param array $gis_data GIS data 309 * @param int $index Index into the parameter object 310 * @param string $empty Value for empty points 311 * 312 * @return string WKT with the set of parameters passed by the GIS editor 313 * @access public 314 */ 315 public function generateWkt(array $gis_data, $index, $empty = '') 316 { 317 $data_row = $gis_data[$index]['MULTILINESTRING']; 318 319 $no_of_lines = isset($data_row['no_of_lines']) 320 ? $data_row['no_of_lines'] : 1; 321 if ($no_of_lines < 1) { 322 $no_of_lines = 1; 323 } 324 325 $wkt = 'MULTILINESTRING('; 326 for ($i = 0; $i < $no_of_lines; $i++) { 327 $no_of_points = isset($data_row[$i]['no_of_points']) 328 ? $data_row[$i]['no_of_points'] : 2; 329 if ($no_of_points < 2) { 330 $no_of_points = 2; 331 } 332 $wkt .= '('; 333 for ($j = 0; $j < $no_of_points; $j++) { 334 $wkt .= ((isset($data_row[$i][$j]['x']) 335 && trim($data_row[$i][$j]['x']) != '') 336 ? $data_row[$i][$j]['x'] : $empty) 337 . ' ' . ((isset($data_row[$i][$j]['y']) 338 && trim($data_row[$i][$j]['y']) != '') 339 ? $data_row[$i][$j]['y'] : $empty) . ','; 340 } 341 $wkt 342 = mb_substr( 343 $wkt, 344 0, mb_strlen($wkt) - 1 345 ); 346 $wkt .= '),'; 347 } 348 $wkt 349 = mb_substr( 350 $wkt, 351 0, 352 mb_strlen($wkt) - 1 353 ); 354 $wkt .= ')'; 355 356 return $wkt; 357 } 358 359 /** 360 * Generate the WKT for the data from ESRI shape files. 361 * 362 * @param array $row_data GIS data 363 * 364 * @return string the WKT for the data from ESRI shape files 365 * @access public 366 */ 367 public function getShape(array $row_data) 368 { 369 $wkt = 'MULTILINESTRING('; 370 for ($i = 0; $i < $row_data['numparts']; $i++) { 371 $wkt .= '('; 372 foreach ($row_data['parts'][$i]['points'] as $point) { 373 $wkt .= $point['x'] . ' ' . $point['y'] . ','; 374 } 375 $wkt 376 = mb_substr( 377 $wkt, 378 0, 379 mb_strlen($wkt) - 1 380 ); 381 $wkt .= '),'; 382 } 383 $wkt 384 = mb_substr( 385 $wkt, 386 0, 387 mb_strlen($wkt) - 1 388 ); 389 $wkt .= ')'; 390 391 return $wkt; 392 } 393 394 /** 395 * Generate parameters for the GIS data editor from the value of the GIS column. 396 * 397 * @param string $value Value of the GIS column 398 * @param int $index Index of the geometry 399 * 400 * @return array params for the GIS data editor from the value of the GIS column 401 * @access public 402 */ 403 public function generateParams($value, $index = -1) 404 { 405 $params = array(); 406 if ($index == -1) { 407 $index = 0; 408 $data = GisGeometry::generateParams($value); 409 $params['srid'] = $data['srid']; 410 $wkt = $data['wkt']; 411 } else { 412 $params[$index]['gis_type'] = 'MULTILINESTRING'; 413 $wkt = $value; 414 } 415 416 // Trim to remove leading 'MULTILINESTRING((' and trailing '))' 417 $multilinestirng 418 = mb_substr( 419 $wkt, 420 17, 421 mb_strlen($wkt) - 19 422 ); 423 // Separate each linestring 424 $linestirngs = explode("),(", $multilinestirng); 425 $params[$index]['MULTILINESTRING']['no_of_lines'] = count($linestirngs); 426 427 $j = 0; 428 foreach ($linestirngs as $linestring) { 429 $points_arr = $this->extractPoints($linestring, null); 430 $no_of_points = count($points_arr); 431 $params[$index]['MULTILINESTRING'][$j]['no_of_points'] = $no_of_points; 432 for ($i = 0; $i < $no_of_points; $i++) { 433 $params[$index]['MULTILINESTRING'][$j][$i]['x'] = $points_arr[$i][0]; 434 $params[$index]['MULTILINESTRING'][$j][$i]['y'] = $points_arr[$i][1]; 435 } 436 $j++; 437 } 438 439 return $params; 440 } 441} 442