Advertisement
Guest User

Untitled

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