Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- define('DB_HOST', 'localhost');
- define('DB_NAME', 'trains_geo');
- define('DB_USER', 'root');
- define('DB_PASSWORD', '');
- define('DB_ENCODING', 'utf8');
- define('DB_CHARSET', 'utf8');
- class DbConnect {
- private $db_host = DB_HOST;
- private $db_name = DB_NAME;
- private $db_user = DB_USER;
- private $db_password = DB_PASSWORD;
- private $db_encoding = DB_ENCODING;
- private $db_charset = DB_CHARSET;
- /**
- * PDO instance
- * @var PDO
- */
- private $pdo = null;
- /**
- * Open the database connection
- */
- public function __construct() {
- // open database connection
- $conStr = sprintf("mysql:host=%s;dbname=%s;encoding:%s;charset=%s;", $this->db_host, $this->db_name, $this->db_encoding, $this->db_charset);
- try {
- $this->pdo = new PDO($conStr, $this->db_user, $this->db_password);
- $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- } catch (PDOException $e) {
- echo $e->getMessage();
- }
- }
- public function getPdo() {
- return $this->pdo;
- }
- /**
- * close the database connection
- */
- public function __destruct() {
- // close the database connection
- $this->pdo = null;
- }
- }
- class DrawMapStructure {
- private $pdo = null;
- private $spatialDataPolylines = array();
- private $spatialDataStationsPoints = array();
- private $spatialDataCurrentConnectionLine = array();
- private $spatialDataCurrentConnectionSpatialLine = array();
- private $stationSpiderLines = array();
- private $distances = array();
- private $simplePathStations = array();
- private $stationLineIntersects = array();
- private $lastCheckedLineIds = array();
- private $floatPrecision = 10;
- private $lineId = 0;
- private $checkSLI = true;
- public $dijkstrasRouteEngine = array();
- private $SRP = array();
- public $totalCost;
- public function __construct() {
- $dbConnect = new DbConnect();
- $this->pdo = $dbConnect->getPdo();
- }
- public function getRailwaysPolylines() {
- $sql = 'SELECT `id`, ST_AsGeoJSON(`line`, :floatPrecision) AS `line` FROM `connections`';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
- $stmt->execute();
- while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->spatialDataPolylines[$row['id']] = json_decode($row['line'], true);
- }
- return $this->spatialDataPolylines;
- }
- public function getStationsPoints() {
- $sql = 'SELECT `id`, `name`, ST_AsGeoJSON(`point`, :floatPrecision) AS `point` FROM `stations`';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
- $stmt->execute();
- while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->spatialDataStationsPoints[$row['id']] = json_decode($row['point'], true);
- $this->spatialDataStationsPoints[$row['id']]['name'] = $row['name'];
- }
- return $this->spatialDataStationsPoints;
- }
- public function getStationPoint($stationId, $stationPointJSON = false) {
- if($stationPointJSON) {
- $sql = 'SELECT ST_AsGeoJSON(`point`, :floatPrecision) AS `pointJSON` FROM `stations` WHERE `id`=:id';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
- $stmt->bindParam(':id', $stationId, PDO::PARAM_INT);
- $stmt->execute();
- return json_decode($stmt->fetch(PDO::FETCH_ASSOC)['pointJSON'], true);
- } else {
- $sql = 'SELECT `point` FROM `stations` WHERE `id`=:id';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindParam(':id', $stationId, PDO::PARAM_INT);
- $stmt->execute();
- return $stmt->fetch(PDO::FETCH_ASSOC)['point'];
- }
- }
- public function getCurrentConnectionLine($beginStationId, $endStationId) {
- $sql = 'SELECT s.`id` AS `station_id`, s.`name`, c.`id` AS `line_id`, ST_AsGeoJSON(c.`line`, :floatPrecision) AS `currentLineSpatialJSONData`
- FROM `connections` c
- JOIN `stations` s ON (ST_Intersects(s.`point`, c.`line`) = 1)
- WHERE (ST_INTERSECTS(c.`line`, :station1)
- OR ST_INTERSECTS(c.`line`, :station2))
- GROUP BY c.`id`';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
- $stmt->bindValue(':station1', $this->getStationPoint($beginStationId));
- $stmt->bindValue(':station2', $this->getStationPoint($endStationId));
- $stmt->execute();
- while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->spatialDataCurrentConnectionLine[$row['line_id']] = json_decode($row['currentLineSpatialJSONData'], true);
- }
- return $this->spatialDataCurrentConnectionLine;
- }
- public function getDistanceLineOfTwoStations($s1, $s2) {
- $sql = 'SELECT
- ST_Length(
- ST_LineStringFromWKB(
- LineString(
- (SELECT `point` FROM `stations` WHERE `id` = :s1Id),
- (SELECT `point` FROM `stations` WHERE `id` = :s2Id)
- )
- )
- ) AS `distance`';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindValue(':s1Id', $s1, PDO::PARAM_INT);
- $stmt->bindValue(':s2Id', $s2, PDO::PARAM_INT);
- $stmt->execute();
- $row = $stmt->fetch(PDO::FETCH_ASSOC);
- return $row['distance'];
- }
- public function getStationSpiderLines($stationId, $getDistanceOnly = false) {
- if(count($this->simplePathStations) === 0) {
- $this->simplePathStations[] = $stationId;
- }
- $sql = 'SELECT
- `id`,
- ST_AsGeoJSON(`point`, :floatPrecision) AS `secondpoint`,
- ST_Length(
- ST_LineStringFromWKB(
- LineString(
- `point`,
- (SELECT `point` FROM `stations` WHERE `id` = :stationId)
- )
- )
- )
- AS `distance`,
- (SELECT ST_AsGeoJSON(`point`, :floatPrecision) FROM `stations` WHERE `id` = :stationId) AS `firstpoint`
- FROM `stations`
- WHERE `id` <> :stationId
- ORDER BY `distance`';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
- $stmt->bindValue(':stationId', $stationId, PDO::PARAM_INT);
- $stmt->execute();
- $this->distances = [];
- $this->stationSpiderLines = [];
- if($getDistanceOnly) {
- while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->distances[$row['id']] = $row['distance'];
- }
- return $this->distances;
- }
- while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->stationSpiderLines['secondpoint'][] = json_decode($row['secondpoint'], true);
- $this->stationSpiderLines['firstpoint'] = json_decode($row['firstpoint'], true);
- }
- return $this->stationSpiderLines;
- }
- public function checkStationLineIntersects($stationId) {
- $this->stationLineIntersects = [];
- $sql = 'SELECT `id` FROM `connections` WHERE ST_INTERSECTS((SELECT `point` FROM `stations` WHERE `id` = :stationId), `line`)';
- $stmt = $this->pdo->prepare($sql);
- $stmt->bindValue(':stationId', $stationId, PDO::PARAM_INT);
- $stmt->execute();
- while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->stationLineIntersects[] = $row['id'];
- }
- return $this->stationLineIntersects;
- }
- public function getSimplePath($distances, $targetStationId) {
- //var_dump($distances);
- $this->lastCheckedLineIds = $this->checkStationLineIntersects(end($this->simplePathStations));
- //var_dump($this->lastCheckedLineIds);
- foreach($distances as $key => $val) {
- // echo 'key:';
- // var_dump($this->checkStationLineIntersects($key));
- // echo 'last:';
- // var_dump($this->lastCheckedLineIds[0]);
- //if($this->checkStationLineIntersects($key)[0] != $this->lastCheckedLineIds[$this->lineId]) {
- /*var_dump($key.' > '.$targetStationId);
- var_dump($this->getDistanceLineOfTwoStations($key, $targetStationId));
- var_dump($distances[$targetStationId]);
- var_dump($distances);*/
- if(!in_array($this->lastCheckedLineIds[$this->lineId], $this->checkStationLineIntersects($key)) && $this->checkSLI === true ) {
- echo 'stacja '.$key.' poza linią numer '.$this->lastCheckedLineIds[$this->lineId].'</br>';
- $this->lineId = 0;
- continue;
- } elseif(($val < $distances[$targetStationId] && $this->getDistanceLineOfTwoStations($key, $targetStationId) < $distances[$targetStationId]) || count($this->checkStationLineIntersects($key)) > 1) {
- if(count($this->checkStationLineIntersects($key)) > 1) {
- echo 'zmiana linii po dotarciu do = '.$key.'</br>';
- //$this->lineId++;
- $this->checkSLI = false;
- } else {
- $this->checkSLI = true;
- }
- echo 'wybrana = '.$key. ' val = '.$val.'</br>';
- $this->simplePathStations[] = $key;
- $this->getSimplePath($this->getStationSpiderLines($key, true), $targetStationId);
- return;
- } elseif($key == $targetStationId) {
- echo 'dotarłem do ostatniej ('.$key.')</br>';
- $this->simplePathStations[] = $key;
- var_dump($this->simplePathStations);
- return;
- } else {
- echo 'pominięta = '.$key.'</br>';
- }
- }
- }
- public function dijkstras($from) {
- $unvisitedStations = ['a','b','c','d','e','f','g','h','i'];
- if($unvisitedStations[0] != $from) {
- // unset "from station" from unvisited array
- unset($unvisitedStations[array_search($from, $unvisitedStations)]);
- // prepend "from station" to the beginning of an unvisited array
- array_unshift($unvisitedStations, $from);
- }
- //var_dump($unvisitedStations);
- $visitedStations = [];
- $minCost = 0;
- $costs = [];
- $distancesTempArr = [
- ['a', 'b', 5],
- ['b', 'c', 4],
- ['c', 'd', 2],
- ['d', 'e', 1],
- ['d', 'f', 7],
- ['f', 'g', 6],
- ['f', 'i', 12],
- ['e', 'i', 11],
- ['g', 'i', 5],
- ['g', 'h', 2]
- ];
- //var_dump($distancesTempArr);
- foreach ($unvisitedStations as $init => $station) {
- // find and set min cost
- if(count($costs) > 0) {
- $minCost = min($costs);
- $station = array_keys($costs, min($costs))[0];
- }
- // clean costs
- var_dump($costs);
- $costs = [];
- // push current station into visited
- $visitedStations[] = $station;
- $this->dijkstrasRouteEngine[$init]['visited'] = $visitedStations;
- // unset current station from unvisited
- unset($unvisitedStations[array_search($station, $unvisitedStations)]);
- $this->dijkstrasRouteEngine[$init]['unvisited'] = $unvisitedStations;
- // foreach for create analyze schema
- $analyze = [];
- foreach ($unvisitedStations as $keyStation => $indexStation) {
- // foreach simple lines (A-B)
- foreach ($distancesTempArr as $distancesIndex => $pointsDistances) {
- // if A-B OR B-A in current then...
- if(($pointsDistances[0] == $station && $pointsDistances[1] == $indexStation) || ($pointsDistances[1] == $station && $pointsDistances[0] == $indexStation)) {
- //var_dump('znalazłem '.$station.'-'.$indexStation.' w '.$distancesIndex.', długość to '.$distancesTempArr[$distancesIndex][2].' dodana z poprzedniej to '.$minCost);
- // found nearest point
- $cost = $distancesTempArr[$distancesIndex][2] + $minCost;
- if($init == 0) {
- $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
- $costs[$indexStation] = $cost;
- break;
- }
- } else {
- // infinity cost
- // if($init > 0 && $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'] != 'infinity') {
- // $cost = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'];
- // }
- // else
- $cost = 'infinity';
- $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
- }
- //var_dump($station.' | '.$indexStation.' | '.$this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'].' | '.$cost);
- // skip first cycle
- if($init > 0) {
- //$cost = $distancesTempArr[$distancesIndex][2] + $minCost;
- $previousCost = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'];
- //var_dump($init.' / '.$indexStation.' = '.$previousCost .' <> '.$station.' = '. $cost);
- //var_dump($previousCost.' = '.$cost);
- if($previousCost == 'infinity' && $cost == 'infinity') {
- //$cost = $distancesTempArr[$distancesIndex][2] + $minCost;
- $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
- //$costs[] = $cost;
- //break;
- } elseif($previousCost == 'infinity' && $cost != 'infinity') {
- $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
- $costs[$indexStation] = $cost;
- break;
- } elseif($previousCost != 'infinity' && $cost == 'infinity') {
- $analyze[$indexStation] = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation];
- $costs[$indexStation] = $previousCost;
- //break;
- } elseif($previousCost != 'infinity' && $cost != 'infinity') {
- echo 'porównałem dwie liczby';
- if($cost <= $previousCost) {
- $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
- $costs[$indexStation] = $cost;
- break;
- } else {
- $analyze[$indexStation] = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation];
- $costs[$indexStation] = $previousCost;
- break;
- }
- }
- }
- }
- }
- // -- OLD COSTS PLACE --
- // set current
- $this->dijkstrasRouteEngine[$init]['current'] = $station;
- // set unvisited to analyze
- $this->dijkstrasRouteEngine[$init]['analyze'] = $analyze;
- }
- //var_dump($this->dijkstrasRouteEngine);
- //return $this->dijkstrasRouteEngine;
- }
- public function getShortestRoutePath($from, $to, $toReference = null) {
- $toArray = [];
- // in first method init reference "to station" is null - use "to", clear SRP
- if($toReference == null) {
- $this->dijkstras($from);
- $this->SRP = [];
- $this->totalCost = null;
- $toReference = $to;
- }
- // walk on dijkstras route engine array to determine backwards SRP step by step
- foreach ($this->dijkstrasRouteEngine as $key => $init) {
- foreach ($init['analyze'] as $station => $analyzeField) {
- if($station == $toReference)
- $toArray[] = $analyzeField;
- if($station == $to)
- $this->totalCost = $analyzeField['cost'];
- }
- }
- if(count($toArray) > 0) {
- $previousStation = $this->SRP[] = end($toArray)['station'];
- // references on station to set route backwards
- $this->getShortestRoutePath($from, $to, $previousStation);
- return $this->SRP;
- }
- // prepend "to station" to the beginning of an SRP array
- array_unshift($this->SRP, $to);
- // reverse SRP
- $this->SRP = array_reverse($this->SRP);
- // final SRP return
- return $this->SRP;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement