PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/classes/Gis/GisLineString.php

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