Advertisement
Guest User

Untitled

a guest
Nov 1st, 2016
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.38 KB | None | 0 0
  1. <?php
  2. define('DB_HOST', 'localhost');
  3. define('DB_NAME', 'trains_geo');
  4. define('DB_USER', 'root');
  5. define('DB_PASSWORD', '');
  6. define('DB_ENCODING', 'utf8');
  7. define('DB_CHARSET', 'utf8');
  8.  
  9. class DbConnect {
  10.  
  11. private $db_host = DB_HOST;
  12. private $db_name = DB_NAME;
  13. private $db_user = DB_USER;
  14. private $db_password = DB_PASSWORD;
  15. private $db_encoding = DB_ENCODING;
  16. private $db_charset = DB_CHARSET;
  17.  
  18. /**
  19. * PDO instance
  20. * @var PDO
  21. */
  22. private $pdo = null;
  23.  
  24. /**
  25. * Open the database connection
  26. */
  27. public function __construct() {
  28. // open database connection
  29. $conStr = sprintf("mysql:host=%s;dbname=%s;encoding:%s;charset=%s;", $this->db_host, $this->db_name, $this->db_encoding, $this->db_charset);
  30.  
  31. try {
  32. $this->pdo = new PDO($conStr, $this->db_user, $this->db_password);
  33. $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  34. } catch (PDOException $e) {
  35. echo $e->getMessage();
  36. }
  37. }
  38.  
  39. public function getPdo() {
  40. return $this->pdo;
  41. }
  42.  
  43. /**
  44. * close the database connection
  45. */
  46. public function __destruct() {
  47. // close the database connection
  48. $this->pdo = null;
  49. }
  50.  
  51. }
  52.  
  53. class DrawMapStructure {
  54.  
  55. private $pdo = null;
  56. private $spatialDataPolylines = array();
  57. private $spatialDataStationsPoints = array();
  58. private $spatialDataCurrentConnectionLine = array();
  59. private $spatialDataCurrentConnectionSpatialLine = array();
  60. private $stationSpiderLines = array();
  61. private $distances = array();
  62. private $simplePathStations = array();
  63. private $stationLineIntersects = array();
  64. private $lastCheckedLineIds = array();
  65. private $floatPrecision = 10;
  66. private $lineId = 0;
  67. private $checkSLI = true;
  68. public $dijkstrasRouteEngine = array();
  69. private $SRP = array();
  70. public $totalCost;
  71.  
  72. public function __construct() {
  73. $dbConnect = new DbConnect();
  74. $this->pdo = $dbConnect->getPdo();
  75. }
  76.  
  77. public function getRailwaysPolylines() {
  78. $sql = 'SELECT `id`, ST_AsGeoJSON(`line`, :floatPrecision) AS `line` FROM `connections`';
  79. $stmt = $this->pdo->prepare($sql);
  80. $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
  81. $stmt->execute();
  82.  
  83. while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  84. $this->spatialDataPolylines[$row['id']] = json_decode($row['line'], true);
  85. }
  86.  
  87. return $this->spatialDataPolylines;
  88. }
  89.  
  90. public function getStationsPoints() {
  91. $sql = 'SELECT `id`, `name`, ST_AsGeoJSON(`point`, :floatPrecision) AS `point` FROM `stations`';
  92.  
  93. $stmt = $this->pdo->prepare($sql);
  94. $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
  95. $stmt->execute();
  96.  
  97. while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  98. $this->spatialDataStationsPoints[$row['id']] = json_decode($row['point'], true);
  99. $this->spatialDataStationsPoints[$row['id']]['name'] = $row['name'];
  100. }
  101.  
  102. return $this->spatialDataStationsPoints;
  103. }
  104.  
  105. public function getStationPoint($stationId, $stationPointJSON = false) {
  106. if($stationPointJSON) {
  107. $sql = 'SELECT ST_AsGeoJSON(`point`, :floatPrecision) AS `pointJSON` FROM `stations` WHERE `id`=:id';
  108.  
  109. $stmt = $this->pdo->prepare($sql);
  110. $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
  111. $stmt->bindParam(':id', $stationId, PDO::PARAM_INT);
  112. $stmt->execute();
  113.  
  114. return json_decode($stmt->fetch(PDO::FETCH_ASSOC)['pointJSON'], true);
  115. } else {
  116. $sql = 'SELECT `point` FROM `stations` WHERE `id`=:id';
  117.  
  118. $stmt = $this->pdo->prepare($sql);
  119. $stmt->bindParam(':id', $stationId, PDO::PARAM_INT);
  120. $stmt->execute();
  121.  
  122. return $stmt->fetch(PDO::FETCH_ASSOC)['point'];
  123. }
  124. }
  125.  
  126. public function getCurrentConnectionLine($beginStationId, $endStationId) {
  127. $sql = 'SELECT s.`id` AS `station_id`, s.`name`, c.`id` AS `line_id`, ST_AsGeoJSON(c.`line`, :floatPrecision) AS `currentLineSpatialJSONData`
  128. FROM `connections` c
  129. JOIN `stations` s ON (ST_Intersects(s.`point`, c.`line`) = 1)
  130. WHERE (ST_INTERSECTS(c.`line`, :station1)
  131. OR ST_INTERSECTS(c.`line`, :station2))
  132. GROUP BY c.`id`';
  133.  
  134. $stmt = $this->pdo->prepare($sql);
  135. $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
  136. $stmt->bindValue(':station1', $this->getStationPoint($beginStationId));
  137. $stmt->bindValue(':station2', $this->getStationPoint($endStationId));
  138. $stmt->execute();
  139.  
  140. while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  141. $this->spatialDataCurrentConnectionLine[$row['line_id']] = json_decode($row['currentLineSpatialJSONData'], true);
  142. }
  143.  
  144. return $this->spatialDataCurrentConnectionLine;
  145. }
  146.  
  147. public function getDistanceLineOfTwoStations($s1, $s2) {
  148. $sql = 'SELECT
  149. ST_Length(
  150. ST_LineStringFromWKB(
  151. LineString(
  152. (SELECT `point` FROM `stations` WHERE `id` = :s1Id),
  153. (SELECT `point` FROM `stations` WHERE `id` = :s2Id)
  154. )
  155. )
  156. ) AS `distance`';
  157.  
  158. $stmt = $this->pdo->prepare($sql);
  159. $stmt->bindValue(':s1Id', $s1, PDO::PARAM_INT);
  160. $stmt->bindValue(':s2Id', $s2, PDO::PARAM_INT);
  161. $stmt->execute();
  162.  
  163. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  164.  
  165. return $row['distance'];
  166. }
  167.  
  168. public function getStationSpiderLines($stationId, $getDistanceOnly = false) {
  169. if(count($this->simplePathStations) === 0) {
  170. $this->simplePathStations[] = $stationId;
  171. }
  172.  
  173. $sql = 'SELECT
  174. `id`,
  175. ST_AsGeoJSON(`point`, :floatPrecision) AS `secondpoint`,
  176. ST_Length(
  177. ST_LineStringFromWKB(
  178. LineString(
  179. `point`,
  180. (SELECT `point` FROM `stations` WHERE `id` = :stationId)
  181. )
  182. )
  183. )
  184. AS `distance`,
  185. (SELECT ST_AsGeoJSON(`point`, :floatPrecision) FROM `stations` WHERE `id` = :stationId) AS `firstpoint`
  186. FROM `stations`
  187. WHERE `id` <> :stationId
  188. ORDER BY `distance`';
  189.  
  190. $stmt = $this->pdo->prepare($sql);
  191. $stmt->bindParam(':floatPrecision', $this->floatPrecision, PDO::PARAM_INT);
  192. $stmt->bindValue(':stationId', $stationId, PDO::PARAM_INT);
  193. $stmt->execute();
  194.  
  195. $this->distances = [];
  196. $this->stationSpiderLines = [];
  197.  
  198. if($getDistanceOnly) {
  199. while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  200. $this->distances[$row['id']] = $row['distance'];
  201. }
  202.  
  203. return $this->distances;
  204. }
  205.  
  206. while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  207. $this->stationSpiderLines['secondpoint'][] = json_decode($row['secondpoint'], true);
  208. $this->stationSpiderLines['firstpoint'] = json_decode($row['firstpoint'], true);
  209. }
  210.  
  211. return $this->stationSpiderLines;
  212. }
  213.  
  214. public function checkStationLineIntersects($stationId) {
  215. $this->stationLineIntersects = [];
  216.  
  217. $sql = 'SELECT `id` FROM `connections` WHERE ST_INTERSECTS((SELECT `point` FROM `stations` WHERE `id` = :stationId), `line`)';
  218.  
  219. $stmt = $this->pdo->prepare($sql);
  220. $stmt->bindValue(':stationId', $stationId, PDO::PARAM_INT);
  221. $stmt->execute();
  222.  
  223. while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
  224. $this->stationLineIntersects[] = $row['id'];
  225. }
  226.  
  227. return $this->stationLineIntersects;
  228. }
  229.  
  230. public function getSimplePath($distances, $targetStationId) {
  231. //var_dump($distances);
  232. $this->lastCheckedLineIds = $this->checkStationLineIntersects(end($this->simplePathStations));
  233. //var_dump($this->lastCheckedLineIds);
  234.  
  235. foreach($distances as $key => $val) {
  236. // echo 'key:';
  237. // var_dump($this->checkStationLineIntersects($key));
  238. // echo 'last:';
  239. // var_dump($this->lastCheckedLineIds[0]);
  240. //if($this->checkStationLineIntersects($key)[0] != $this->lastCheckedLineIds[$this->lineId]) {
  241. /*var_dump($key.' > '.$targetStationId);
  242. var_dump($this->getDistanceLineOfTwoStations($key, $targetStationId));
  243. var_dump($distances[$targetStationId]);
  244. var_dump($distances);*/
  245.  
  246. if(!in_array($this->lastCheckedLineIds[$this->lineId], $this->checkStationLineIntersects($key)) && $this->checkSLI === true ) {
  247. echo 'stacja '.$key.' poza linią numer '.$this->lastCheckedLineIds[$this->lineId].'</br>';
  248. $this->lineId = 0;
  249. continue;
  250. } elseif(($val < $distances[$targetStationId] && $this->getDistanceLineOfTwoStations($key, $targetStationId) < $distances[$targetStationId]) || count($this->checkStationLineIntersects($key)) > 1) {
  251. if(count($this->checkStationLineIntersects($key)) > 1) {
  252. echo 'zmiana linii po dotarciu do = '.$key.'</br>';
  253. //$this->lineId++;
  254. $this->checkSLI = false;
  255. } else {
  256. $this->checkSLI = true;
  257. }
  258.  
  259. echo 'wybrana = '.$key. ' val = '.$val.'</br>';
  260. $this->simplePathStations[] = $key;
  261. $this->getSimplePath($this->getStationSpiderLines($key, true), $targetStationId);
  262. return;
  263. } elseif($key == $targetStationId) {
  264. echo 'dotarłem do ostatniej ('.$key.')</br>';
  265. $this->simplePathStations[] = $key;
  266. var_dump($this->simplePathStations);
  267. return;
  268. } else {
  269. echo 'pominięta = '.$key.'</br>';
  270. }
  271. }
  272. }
  273.  
  274. public function dijkstras($from) {
  275. $unvisitedStations = ['a','b','c','d','e','f','g','h','i'];
  276.  
  277. if($unvisitedStations[0] != $from) {
  278. // unset "from station" from unvisited array
  279. unset($unvisitedStations[array_search($from, $unvisitedStations)]);
  280.  
  281. // prepend "from station" to the beginning of an unvisited array
  282. array_unshift($unvisitedStations, $from);
  283. }
  284.  
  285. //var_dump($unvisitedStations);
  286.  
  287. $visitedStations = [];
  288. $minCost = 0;
  289. $costs = [];
  290. $distancesTempArr = [
  291. ['a', 'b', 5],
  292. ['b', 'c', 4],
  293. ['c', 'd', 2],
  294. ['d', 'e', 1],
  295. ['d', 'f', 7],
  296. ['f', 'g', 6],
  297. ['f', 'i', 12],
  298. ['e', 'i', 11],
  299. ['g', 'i', 5],
  300. ['g', 'h', 2]
  301. ];
  302.  
  303. //var_dump($distancesTempArr);
  304. foreach ($unvisitedStations as $init => $station) {
  305. // find and set min cost
  306. if(count($costs) > 0) {
  307. $minCost = min($costs);
  308. $station = array_keys($costs, min($costs))[0];
  309. }
  310.  
  311. // clean costs
  312. var_dump($costs);
  313. $costs = [];
  314.  
  315. // push current station into visited
  316. $visitedStations[] = $station;
  317. $this->dijkstrasRouteEngine[$init]['visited'] = $visitedStations;
  318.  
  319. // unset current station from unvisited
  320. unset($unvisitedStations[array_search($station, $unvisitedStations)]);
  321. $this->dijkstrasRouteEngine[$init]['unvisited'] = $unvisitedStations;
  322.  
  323. // foreach for create analyze schema
  324. $analyze = [];
  325.  
  326. foreach ($unvisitedStations as $keyStation => $indexStation) {
  327. // foreach simple lines (A-B)
  328. foreach ($distancesTempArr as $distancesIndex => $pointsDistances) {
  329. // if A-B OR B-A in current then...
  330. if(($pointsDistances[0] == $station && $pointsDistances[1] == $indexStation) || ($pointsDistances[1] == $station && $pointsDistances[0] == $indexStation)) {
  331. //var_dump('znalazłem '.$station.'-'.$indexStation.' w '.$distancesIndex.', długość to '.$distancesTempArr[$distancesIndex][2].' dodana z poprzedniej to '.$minCost);
  332. // found nearest point
  333. $cost = $distancesTempArr[$distancesIndex][2] + $minCost;
  334.  
  335. if($init == 0) {
  336. $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
  337. $costs[$indexStation] = $cost;
  338. break;
  339. }
  340. } else {
  341. // infinity cost
  342. // if($init > 0 && $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'] != 'infinity') {
  343. // $cost = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'];
  344. // }
  345. // else
  346. $cost = 'infinity';
  347.  
  348. $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
  349. }
  350. //var_dump($station.' | '.$indexStation.' | '.$this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'].' | '.$cost);
  351. // skip first cycle
  352. if($init > 0) {
  353. //$cost = $distancesTempArr[$distancesIndex][2] + $minCost;
  354. $previousCost = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation]['cost'];
  355. //var_dump($init.' / '.$indexStation.' = '.$previousCost .' <> '.$station.' = '. $cost);
  356. //var_dump($previousCost.' = '.$cost);
  357. if($previousCost == 'infinity' && $cost == 'infinity') {
  358.  
  359. //$cost = $distancesTempArr[$distancesIndex][2] + $minCost;
  360. $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
  361. //$costs[] = $cost;
  362. //break;
  363.  
  364. } elseif($previousCost == 'infinity' && $cost != 'infinity') {
  365.  
  366. $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
  367. $costs[$indexStation] = $cost;
  368. break;
  369.  
  370. } elseif($previousCost != 'infinity' && $cost == 'infinity') {
  371.  
  372. $analyze[$indexStation] = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation];
  373. $costs[$indexStation] = $previousCost;
  374. //break;
  375.  
  376. } elseif($previousCost != 'infinity' && $cost != 'infinity') {
  377. echo 'porównałem dwie liczby';
  378. if($cost <= $previousCost) {
  379. $analyze[$indexStation] = ['cost' => $cost, 'station' => $station, 'init' => $init];
  380. $costs[$indexStation] = $cost;
  381. break;
  382. } else {
  383. $analyze[$indexStation] = $this->dijkstrasRouteEngine[$init - 1]['analyze'][$indexStation];
  384. $costs[$indexStation] = $previousCost;
  385. break;
  386. }
  387. }
  388. }
  389. }
  390. }
  391.  
  392. // -- OLD COSTS PLACE --
  393.  
  394. // set current
  395. $this->dijkstrasRouteEngine[$init]['current'] = $station;
  396.  
  397. // set unvisited to analyze
  398. $this->dijkstrasRouteEngine[$init]['analyze'] = $analyze;
  399. }
  400.  
  401. //var_dump($this->dijkstrasRouteEngine);
  402. //return $this->dijkstrasRouteEngine;
  403. }
  404.  
  405. public function getShortestRoutePath($from, $to, $toReference = null) {
  406. $toArray = [];
  407.  
  408. // in first method init reference "to station" is null - use "to", clear SRP
  409. if($toReference == null) {
  410. $this->dijkstras($from);
  411. $this->SRP = [];
  412. $this->totalCost = null;
  413. $toReference = $to;
  414. }
  415.  
  416. // walk on dijkstras route engine array to determine backwards SRP step by step
  417. foreach ($this->dijkstrasRouteEngine as $key => $init) {
  418. foreach ($init['analyze'] as $station => $analyzeField) {
  419. if($station == $toReference)
  420. $toArray[] = $analyzeField;
  421.  
  422. if($station == $to)
  423. $this->totalCost = $analyzeField['cost'];
  424. }
  425. }
  426.  
  427. if(count($toArray) > 0) {
  428. $previousStation = $this->SRP[] = end($toArray)['station'];
  429.  
  430. // references on station to set route backwards
  431. $this->getShortestRoutePath($from, $to, $previousStation);
  432. return $this->SRP;
  433. }
  434.  
  435. // prepend "to station" to the beginning of an SRP array
  436. array_unshift($this->SRP, $to);
  437.  
  438. // reverse SRP
  439. $this->SRP = array_reverse($this->SRP);
  440.  
  441. // final SRP return
  442. return $this->SRP;
  443. }
  444. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement