3 * Handles actions related to GIS LINESTRING objects
6 declare(strict_types
=1);
8 namespace PhpMyAdmin\Gis
;
10 use PhpMyAdmin\Gis\Ds\Extent
;
11 use PhpMyAdmin\Gis\Ds\ScaleData
;
12 use PhpMyAdmin\Image\ImageWrapper
;
17 use function json_encode
;
19 use function mb_substr
;
24 * Handles actions related to GIS LINESTRING objects
26 class GisLineString
extends GisGeometry
28 private static self
$instance;
31 * A private constructor; prevents direct creation of object.
33 private function __construct()
38 * Returns the singleton.
40 * @return GisLineString the singleton
42 public static function singleton(): GisLineString
44 if (! isset(self
::$instance)) {
45 self
::$instance = new GisLineString();
48 return self
::$instance;
52 * Get coordinate extent for this wkt.
54 * @param string $wkt Well Known Text represenatation of the geometry
56 * @return Extent the min, max values for x and y coordinates
58 public function getExtent(string $wkt): Extent
60 // Trim to remove leading 'LINESTRING(' and trailing ')'
61 $linestring = mb_substr($wkt, 11, -1);
63 return $this->getCoordinatesExtent($linestring);
67 * Adds to the PNG image object, the data related to a row in the GIS dataset.
69 * @param string $spatial GIS POLYGON object
70 * @param string $label Label for the GIS POLYGON object
71 * @param int[] $color Color for the GIS POLYGON object
72 * @param ScaleData $scaleData Array containing data related to scaling
74 public function prepareRowAsPng(
82 $black = $image->colorAllocate(0, 0, 0);
83 $lineColor = $image->colorAllocate(...$color);
85 // Trim to remove leading 'LINESTRING(' and trailing ')'
86 $lineString = mb_substr($spatial, 11, -1);
87 $pointsArr = $this->extractPoints1d($lineString, $scaleData);
89 foreach ($pointsArr as $point) {
90 if (isset($tempPoint)) {
93 (int) round($tempPoint[0]),
94 (int) round($tempPoint[1]),
95 (int) round($point[0]),
96 (int) round($point[1]),
108 // print label if applicable
111 (int) round($pointsArr[1][0]),
112 (int) round($pointsArr[1][1]),
119 * Adds to the TCPDF instance, the data related to a row in the GIS dataset.
121 * @param string $spatial GIS LINESTRING object
122 * @param string $label Label for the GIS LINESTRING object
123 * @param int[] $color Color for the GIS LINESTRING object
124 * @param ScaleData $scaleData Array containing data related to scaling
126 public function prepareRowAsPdf(
130 ScaleData
$scaleData,
133 $line = ['width' => 1.5, 'color' => $color];
135 // Trim to remove leading 'LINESTRING(' and trailing ')'
136 $linestring = mb_substr($spatial, 11, -1);
137 $pointsArr = $this->extractPoints1d($linestring, $scaleData);
139 foreach ($pointsArr as $point) {
140 if (isset($tempPoint)) {
142 $pdf->Line($tempPoint[0], $tempPoint[1], $point[0], $point[1], $line);
153 $pdf->setXY($pointsArr[1][0], $pointsArr[1][1]);
154 $pdf->setFontSize(5);
155 $pdf->Cell(0, 0, $label);
159 * Prepares and returns the code related to a row in the GIS dataset as SVG.
161 * @param string $spatial GIS LINESTRING object
162 * @param string $label Label for the GIS LINESTRING object
163 * @param int[] $color Color for the GIS LINESTRING object
164 * @param ScaleData $scaleData Array containing data related to scaling
166 * @return string the code related to a row in the GIS dataset
168 public function prepareRowAsSvg(string $spatial, string $label, array $color, ScaleData
$scaleData): string
172 'id' => $label . $this->getRandomId(),
173 'class' => 'linestring vector',
175 'stroke' => sprintf('#%02x%02x%02x', ...$color),
179 // Trim to remove leading 'LINESTRING(' and trailing ')'
180 $linestring = mb_substr($spatial, 11, -1);
181 $pointsArr = $this->extractPoints1d($linestring, $scaleData);
183 $row = '<polyline points="';
184 foreach ($pointsArr as $point) {
185 $row .= $point[0] . ',' . $point[1] . ' ';
189 foreach ($lineOptions as $option => $val) {
190 $row .= ' ' . $option . '="' . $val . '"';
199 * Prepares JavaScript related to a row in the GIS dataset
200 * to visualize it with OpenLayers.
202 * @param string $spatial GIS LINESTRING object
203 * @param int $srid Spatial reference ID
204 * @param string $label Label for the GIS LINESTRING object
205 * @param int[] $color Color for the GIS LINESTRING object
207 * @return string JavaScript related to a row in the GIS dataset
209 public function prepareRowAsOl(string $spatial, int $srid, string $label, array $color): string
211 $strokeStyle = ['color' => $color, 'width' => 2];
213 $style = 'new ol.style.Style({'
214 . 'stroke: new ol.style.Stroke(' . json_encode($strokeStyle) . ')';
216 $textStyle = ['text' => $label];
217 $style .= ', text: new ol.style.Text(' . json_encode($textStyle) . ')';
222 // Trim to remove leading 'LINESTRING(' and trailing ')'
223 $wktCoordinates = mb_substr($spatial, 11, -1);
224 $olGeometry = $this->toOpenLayersObject(
225 'ol.geom.LineString',
226 $this->extractPoints1d($wktCoordinates, null),
230 return $this->addGeometryToLayer($olGeometry, $style);
234 * Generate the WKT with the set of parameters passed by the GIS editor.
236 * @param mixed[] $gisData GIS data
237 * @param int $index Index into the parameter object
238 * @param string $empty Value for empty points
240 * @return string WKT with the set of parameters passed by the GIS editor
242 public function generateWkt(array $gisData, int $index, string $empty = ''): string
244 $dataRow = $gisData[$index]['LINESTRING'] ??
null;
245 $noOfPoints = max(2, $dataRow['data_length'] ??
0);
248 /** @infection-ignore-all */
249 for ($i = 0; $i < $noOfPoints; $i++
) {
250 $wktPoints[] = $this->getWktCoord($dataRow[$i] ??
null, $empty);
253 return 'LINESTRING(' . implode(',', $wktPoints) . ')';
257 * Generate coordinate parameters for the GIS data editor from the value of the GIS column.
259 * @param string $wkt Value of the GIS column
261 * @return mixed[] Coordinate params for the GIS data editor from the value of the GIS column
263 protected function getCoordinateParams(string $wkt): array
265 // Trim to remove leading 'LINESTRING(' and trailing ')'
266 $linestring = mb_substr($wkt, 11, -1);
267 $pointsArr = $this->extractPoints1d($linestring, null);
269 $noOfPoints = count($pointsArr);
270 $coords = ['data_length' => $noOfPoints];
271 /** @infection-ignore-all */
272 for ($i = 0; $i < $noOfPoints; $i++
) {
273 $coords[$i] = ['x' => $pointsArr[$i][0], 'y' => $pointsArr[$i][1]];
279 protected function getType(): string