GisLineString.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Handles actions related to GIS LINESTRING objects
  5. *
  6. * @package PhpMyAdmin-GIS
  7. */
  8. declare(strict_types=1);
  9. namespace PhpMyAdmin\Gis;
  10. use TCPDF;
  11. /**
  12. * Handles actions related to GIS LINESTRING objects
  13. *
  14. * @package PhpMyAdmin-GIS
  15. */
  16. class GisLineString extends GisGeometry
  17. {
  18. // Hold the singleton instance of the class
  19. private static $_instance;
  20. /**
  21. * A private constructor; prevents direct creation of object.
  22. *
  23. * @access private
  24. */
  25. private function __construct()
  26. {
  27. }
  28. /**
  29. * Returns the singleton.
  30. *
  31. * @return GisLineString the singleton
  32. * @access public
  33. */
  34. public static function singleton()
  35. {
  36. if (! isset(self::$_instance)) {
  37. self::$_instance = new GisLineString();
  38. }
  39. return self::$_instance;
  40. }
  41. /**
  42. * Scales each row.
  43. *
  44. * @param string $spatial spatial data of a row
  45. *
  46. * @return array an array containing the min, max values for x and y coordinates
  47. * @access public
  48. */
  49. public function scaleRow($spatial)
  50. {
  51. // Trim to remove leading 'LINESTRING(' and trailing ')'
  52. $linestring
  53. = mb_substr(
  54. $spatial,
  55. 11,
  56. mb_strlen($spatial) - 12
  57. );
  58. return $this->setMinMax($linestring, []);
  59. }
  60. /**
  61. * Adds to the PNG image object, the data related to a row in the GIS dataset.
  62. *
  63. * @param string $spatial GIS POLYGON object
  64. * @param string|null $label Label for the GIS POLYGON object
  65. * @param string $line_color Color for the GIS POLYGON object
  66. * @param array $scale_data Array containing data related to scaling
  67. * @param resource $image Image object
  68. *
  69. * @return resource the modified image object
  70. * @access public
  71. */
  72. public function prepareRowAsPng(
  73. $spatial,
  74. ?string $label,
  75. $line_color,
  76. array $scale_data,
  77. $image
  78. ) {
  79. // allocate colors
  80. $black = imagecolorallocate($image, 0, 0, 0);
  81. $red = hexdec(mb_substr($line_color, 1, 2));
  82. $green = hexdec(mb_substr($line_color, 3, 2));
  83. $blue = hexdec(mb_substr($line_color, 4, 2));
  84. $color = imagecolorallocate($image, $red, $green, $blue);
  85. // Trim to remove leading 'LINESTRING(' and trailing ')'
  86. $linesrting
  87. = mb_substr(
  88. $spatial,
  89. 11,
  90. mb_strlen($spatial) - 12
  91. );
  92. $points_arr = $this->extractPoints($linesrting, $scale_data);
  93. foreach ($points_arr as $point) {
  94. if (! isset($temp_point)) {
  95. $temp_point = $point;
  96. } else {
  97. // draw line section
  98. imageline(
  99. $image,
  100. $temp_point[0],
  101. $temp_point[1],
  102. $point[0],
  103. $point[1],
  104. $color
  105. );
  106. $temp_point = $point;
  107. }
  108. }
  109. // print label if applicable
  110. if (isset($label) && trim($label) != '') {
  111. imagestring(
  112. $image,
  113. 1,
  114. $points_arr[1][0],
  115. $points_arr[1][1],
  116. trim($label),
  117. $black
  118. );
  119. }
  120. return $image;
  121. }
  122. /**
  123. * Adds to the TCPDF instance, the data related to a row in the GIS dataset.
  124. *
  125. * @param string $spatial GIS LINESTRING object
  126. * @param string|null $label Label for the GIS LINESTRING object
  127. * @param string $line_color Color for the GIS LINESTRING object
  128. * @param array $scale_data Array containing data related to scaling
  129. * @param TCPDF $pdf TCPDF instance
  130. *
  131. * @return TCPDF the modified TCPDF instance
  132. * @access public
  133. */
  134. public function prepareRowAsPdf($spatial, ?string $label, $line_color, array $scale_data, $pdf)
  135. {
  136. // allocate colors
  137. $red = hexdec(mb_substr($line_color, 1, 2));
  138. $green = hexdec(mb_substr($line_color, 3, 2));
  139. $blue = hexdec(mb_substr($line_color, 4, 2));
  140. $line = [
  141. 'width' => 1.5,
  142. 'color' => [
  143. $red,
  144. $green,
  145. $blue,
  146. ],
  147. ];
  148. // Trim to remove leading 'LINESTRING(' and trailing ')'
  149. $linesrting
  150. = mb_substr(
  151. $spatial,
  152. 11,
  153. mb_strlen($spatial) - 12
  154. );
  155. $points_arr = $this->extractPoints($linesrting, $scale_data);
  156. foreach ($points_arr as $point) {
  157. if (! isset($temp_point)) {
  158. $temp_point = $point;
  159. } else {
  160. // draw line section
  161. $pdf->Line(
  162. $temp_point[0],
  163. $temp_point[1],
  164. $point[0],
  165. $point[1],
  166. $line
  167. );
  168. $temp_point = $point;
  169. }
  170. }
  171. // print label
  172. if (isset($label) && trim($label) != '') {
  173. $pdf->SetXY($points_arr[1][0], $points_arr[1][1]);
  174. $pdf->SetFontSize(5);
  175. $pdf->Cell(0, 0, trim($label));
  176. }
  177. return $pdf;
  178. }
  179. /**
  180. * Prepares and returns the code related to a row in the GIS dataset as SVG.
  181. *
  182. * @param string $spatial GIS LINESTRING object
  183. * @param string $label Label for the GIS LINESTRING object
  184. * @param string $line_color Color for the GIS LINESTRING object
  185. * @param array $scale_data Array containing data related to scaling
  186. *
  187. * @return string the code related to a row in the GIS dataset
  188. * @access public
  189. */
  190. public function prepareRowAsSvg($spatial, $label, $line_color, array $scale_data)
  191. {
  192. $line_options = [
  193. 'name' => $label,
  194. 'id' => $label . mt_rand(),
  195. 'class' => 'linestring vector',
  196. 'fill' => 'none',
  197. 'stroke' => $line_color,
  198. 'stroke-width' => 2,
  199. ];
  200. // Trim to remove leading 'LINESTRING(' and trailing ')'
  201. $linesrting
  202. = mb_substr(
  203. $spatial,
  204. 11,
  205. mb_strlen($spatial) - 12
  206. );
  207. $points_arr = $this->extractPoints($linesrting, $scale_data);
  208. $row = '<polyline points="';
  209. foreach ($points_arr as $point) {
  210. $row .= $point[0] . ',' . $point[1] . ' ';
  211. }
  212. $row .= '"';
  213. foreach ($line_options as $option => $val) {
  214. $row .= ' ' . $option . '="' . trim((string) $val) . '"';
  215. }
  216. $row .= '/>';
  217. return $row;
  218. }
  219. /**
  220. * Prepares JavaScript related to a row in the GIS dataset
  221. * to visualize it with OpenLayers.
  222. *
  223. * @param string $spatial GIS LINESTRING object
  224. * @param int $srid Spatial reference ID
  225. * @param string $label Label for the GIS LINESTRING object
  226. * @param string $line_color Color for the GIS LINESTRING object
  227. * @param array $scale_data Array containing data related to scaling
  228. *
  229. * @return string JavaScript related to a row in the GIS dataset
  230. * @access public
  231. */
  232. public function prepareRowAsOl($spatial, $srid, $label, $line_color, array $scale_data)
  233. {
  234. $style_options = [
  235. 'strokeColor' => $line_color,
  236. 'strokeWidth' => 2,
  237. 'label' => $label,
  238. 'fontSize' => 10,
  239. ];
  240. if ($srid == 0) {
  241. $srid = 4326;
  242. }
  243. $result = $this->getBoundsForOl($srid, $scale_data);
  244. // Trim to remove leading 'LINESTRING(' and trailing ')'
  245. $linesrting
  246. = mb_substr(
  247. $spatial,
  248. 11,
  249. mb_strlen($spatial) - 12
  250. );
  251. $points_arr = $this->extractPoints($linesrting, null);
  252. $result .= 'vectorLayer.addFeatures(new OpenLayers.Feature.Vector('
  253. . $this->getLineForOpenLayers($points_arr, $srid)
  254. . ', null, ' . json_encode($style_options) . '));';
  255. return $result;
  256. }
  257. /**
  258. * Generate the WKT with the set of parameters passed by the GIS editor.
  259. *
  260. * @param array $gis_data GIS data
  261. * @param int $index Index into the parameter object
  262. * @param string $empty Value for empty points
  263. *
  264. * @return string WKT with the set of parameters passed by the GIS editor
  265. * @access public
  266. */
  267. public function generateWkt(array $gis_data, $index, $empty = '')
  268. {
  269. $no_of_points = isset($gis_data[$index]['LINESTRING']['no_of_points'])
  270. ? $gis_data[$index]['LINESTRING']['no_of_points'] : 2;
  271. if ($no_of_points < 2) {
  272. $no_of_points = 2;
  273. }
  274. $wkt = 'LINESTRING(';
  275. for ($i = 0; $i < $no_of_points; $i++) {
  276. $wkt .= ((isset($gis_data[$index]['LINESTRING'][$i]['x'])
  277. && trim((string) $gis_data[$index]['LINESTRING'][$i]['x']) != '')
  278. ? $gis_data[$index]['LINESTRING'][$i]['x'] : $empty)
  279. . ' ' . ((isset($gis_data[$index]['LINESTRING'][$i]['y'])
  280. && trim((string) $gis_data[$index]['LINESTRING'][$i]['y']) != '')
  281. ? $gis_data[$index]['LINESTRING'][$i]['y'] : $empty) . ',';
  282. }
  283. $wkt
  284. = mb_substr(
  285. $wkt,
  286. 0,
  287. mb_strlen($wkt) - 1
  288. );
  289. $wkt .= ')';
  290. return $wkt;
  291. }
  292. /**
  293. * Generate parameters for the GIS data editor from the value of the GIS column.
  294. *
  295. * @param string $value of the GIS column
  296. * @param int $index of the geometry
  297. *
  298. * @return array params for the GIS data editor from the value of the GIS column
  299. * @access public
  300. */
  301. public function generateParams($value, $index = -1)
  302. {
  303. $params = [];
  304. if ($index == -1) {
  305. $index = 0;
  306. $data = GisGeometry::generateParams($value);
  307. $params['srid'] = $data['srid'];
  308. $wkt = $data['wkt'];
  309. } else {
  310. $params[$index]['gis_type'] = 'LINESTRING';
  311. $wkt = $value;
  312. }
  313. // Trim to remove leading 'LINESTRING(' and trailing ')'
  314. $linestring
  315. = mb_substr(
  316. $wkt,
  317. 11,
  318. mb_strlen($wkt) - 12
  319. );
  320. $points_arr = $this->extractPoints($linestring, null);
  321. $no_of_points = count($points_arr);
  322. $params[$index]['LINESTRING']['no_of_points'] = $no_of_points;
  323. for ($i = 0; $i < $no_of_points; $i++) {
  324. $params[$index]['LINESTRING'][$i]['x'] = $points_arr[$i][0];
  325. $params[$index]['LINESTRING'][$i]['y'] = $points_arr[$i][1];
  326. }
  327. return $params;
  328. }
  329. }