biale_plamy_class.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. <?php
  2. $_SERVER['SERVER_NAME'] = 'biuro.biall-net.pl';
  3. //when used in /Library/Server/Web/Data/Sites/bzyk-biale-plamy-php-temp/SE/dev on biuro.biall-net.pl
  4. if( file_exists ( "../../se-lib/bootstrap.php"))
  5. require("../../se-lib/bootstrap.php");
  6. //when used in in native SE
  7. else require("../../../../SE-production-git/SE/se-lib/bootstrap.php");
  8. Lib::loadClass("Vendor_Geophp");
  9. class showProgress {
  10. private $startTime;
  11. private $i = 0, $l = 0, $left = 0, $diff = 0, $n, $msg;
  12. private $strlen = 50;
  13. public function __construct($msg, $n = null) {
  14. $this->msg = str_pad($msg, $this->strlen);
  15. echo "{$this->msg}: 0%";
  16. $this->n = $n;
  17. list($usec, $sec) = explode(" ", microtime());
  18. $this->startTime = $sec + $usec;
  19. }
  20. public function step($int = 1) {
  21. if ($this->n) {
  22. $this->i += $int;
  23. $p = floor(100 * $this->i / $this->n);
  24. list($usec, $sec) = explode(" ", microtime());
  25. $curTime = $sec + $usec;
  26. $diff = $curTime - $this->startTime;
  27. $left = floor((($this->n / $this->i) - 1) * $diff);
  28. $diff = floor($diff);
  29. if ($p > $this->l || $left != $this->left || $diff != $this->diff) {
  30. $this->l = $p;
  31. $this->diff = $diff;
  32. $this->left = $left;
  33. if ($left > 59) $left = floor($left / 60) . "m " . ($left % 60);
  34. if ($diff > 59) $diff = floor($diff / 60) . "m " . ($diff % 60);
  35. echo "\r".str_pad("", $this->strlen+70);
  36. echo "\r{$this->msg}: {$p}% (elapsed {$diff}s, estimated remaining {$left}s)";
  37. }
  38. }
  39. }
  40. public function stop() {
  41. list($usec, $sec) = explode(" ", microtime());
  42. $curTime = $sec + $usec;
  43. $diff = $curTime - $this->startTime;
  44. $diff = floor($diff);
  45. if ($diff > 59) $diff = floor($diff / 60) . "m " . ($diff % 60);
  46. echo "\r".str_pad("", $this->strlen+70);
  47. echo "\r{$this->msg}: OK (done in {$diff}s)\n";
  48. }
  49. }
  50. class bialePlamy {
  51. private $showProgress = false;
  52. private $getSourceData = false, $createTemporaryWaysTable = false, $createTemporaryJoinsTable = false, $createTemporaryPrzylaczaTable = false, $readyForFindWay = false, $createTemporaryLongWaysTable = false;
  53. private $punktyAdresoweTable = null, $drogiTable = null;
  54. private $drogi_asText = array(), $joins_asText = array(), $ways_asText = array(), $xpoints_asText = array(), $points_asText = array(), $przylacza_asText = array(), $waysLengths = array(), $longWays_asText = array();
  55. private $ways2drogi = array(), $drogi2ways = array(), $ways2joins = array(), $joins2ways = array(), $points2xpoints = array(), $xpoints2points = array(), $przylacza2joins = array(), $przylacza2points = array(), $points2joins = array();
  56. public function __construct($sourceTables) {
  57. $tables = array('pointsTable' => 'punktyAdresoweTable', 'origWaysTable' => 'drogiTable');
  58. try {
  59. if (!is_array($sourceTables)) throw new Exception("bialePlamy :: Wrong parameters");
  60. foreach ($tables as $arg => $table) {
  61. if (!isset($sourceTables[$arg])) throw new Exception("bialePlamy :: Missing parameter {$arg}");
  62. $this->$table = $sourceTables[$arg];
  63. }
  64. } catch (Exception $e) {
  65. throw $e;
  66. }
  67. }
  68. public function enableShowProgress() {
  69. $this->showProgress = true;
  70. }
  71. public function disableShowProgress() {
  72. $this->showProgress = false;
  73. }
  74. private $dataArrays = array('drogi_asText', 'joins_asText', 'ways_asText', 'xpoints_asText', 'points_asText', 'przylacza_asText', 'waysLengths', 'longWays_asText',
  75. 'ways2drogi', 'drogi2ways', 'ways2joins', 'joins2ways', 'points2xpoints', 'xpoints2points', 'przylacza2joins', 'przylacza2points', 'points2joins');
  76. public function saveCache($prefix = '') {
  77. if (!preg_match("/^[[:alnum:]]*$/", $prefix)) throw new Exception("saveCache() :: prefix error");
  78. if ($prefix) $prefix .= "_";
  79. foreach ($this->dataArrays as $array) if ($this->$array) {
  80. if ($this->showProgress) $progress = new showProgress("Saving {$array}");
  81. file_put_contents('/tmp/save_'.$prefix.$array.'.txt', serialize($this->$array));
  82. if ($this->showProgress) $progress->stop();
  83. }
  84. }
  85. public function saveXML() {
  86. function array_to_xml($data, &$xml_data) {
  87. foreach ($data as $key => $value) {
  88. $key_ = "";
  89. if (is_numeric($key)) $key_ = 'item';
  90. if (is_array($value)) {
  91. $subnode = $xml_data->addChild($key_);
  92. $subnode->addAttribute('id', $key);
  93. array_to_xml($value, $subnode);
  94. } else {
  95. $subnode = $xml_data->addChild("$key_", htmlspecialchars("$value"));
  96. if (is_numeric($key)) $subnode->addAttribute('id', $key);
  97. }
  98. }
  99. }
  100. foreach ($this->dataArrays as $array) if ($this->$array) {
  101. if ($this->showProgress) $progress = new showProgress("Generating XML for {$array}");
  102. $xml = new SimpleXMLElement("<?xml version=\"1.0\"?><{$array}></{$array}>");
  103. array_to_xml($this->$array, $xml);
  104. $xml->asXML("{$array}.xml");
  105. if ($this->showProgress) $progress->stop();
  106. }
  107. }
  108. public function printArray($array) {
  109. if (isset($this->$array) && is_array($this->$array)) {
  110. return print_r($this->$array, true);
  111. } else return null;
  112. }
  113. public function saveArrays() {
  114. foreach ($this->dataArrays as $array) if ($this->$array) {
  115. if ($this->showProgress) $progress = new showProgress("Saving array {$array} to file");
  116. file_put_contents("/tmp/array_{$array}.txt", $this->printArray($array));
  117. if ($this->showProgress) $progress->stop();
  118. }
  119. }
  120. public function loadCache($prefix = '') {
  121. try {
  122. if (!preg_match("/^[[:alnum:]]*$/", $prefix)) throw new Exception("saveCache() :: prefix error");
  123. if ($prefix) $prefix .= "_";
  124. foreach ($this->dataArrays as $array) if (file_exists('/tmp/save_'.$prefix.$array.'.txt')) {
  125. if ($this->showProgress) $progress = new showProgress("Loading {$array}");
  126. $this->$array = unserialize(file_get_contents('/tmp/save_'.$prefix.$array.'.txt'));
  127. if ($this->showProgress) $progress->stop();
  128. }
  129. } catch (Exception $e) {
  130. throw $e;
  131. }
  132. }
  133. private function saveDB($src, $dst) {
  134. try {
  135. if ($this->showProgress) $progress = new showProgress("Saving table {$dst}");
  136. DB::getPDO()->query("truncate table `{$dst}`");
  137. $result = DB::getPDO()->fetchall("show fields from `{$src}`");
  138. foreach ($result as $col) $cols[] = "`{$col['Field']}`";
  139. $query = "insert into `{$dst}` (".implode(", ", $cols).") select * from `{$src}`";
  140. DB::getPDO()->query($query);
  141. if ($this->showProgress) $progress->stop();
  142. } catch (Exception $e) {
  143. throw $e;
  144. }
  145. }
  146. public function savePointsTable($dst) {
  147. if (!$this->getSourceData) $this->getSourceData();
  148. if ($this->xpoints2points) $this->updateTemporaryPointsTable();
  149. $this->saveDB("_temp_punkty_adresowe", $dst);
  150. }
  151. public function saveWaysTable($dst) {
  152. if (!$this->createTemporaryWaysTable) $this->createTemporaryWaysTable();
  153. $this->saveDB("_temp_ways", $dst);
  154. }
  155. public function saveJoinsTable($dst) {
  156. if (!$this->createTemporaryJoinsTable) $this->createTemporaryJoinsTable();
  157. $this->saveDB("_temp_joins", $dst);
  158. }
  159. public function savePrzylaczaTable($dst) {
  160. if (!$this->createTemporaryPrzylaczaTable) $this->createTemporaryPrzylaczaTable();
  161. $this->saveDB("_temp_przylacza", $dst);
  162. }
  163. public function saveLongWaysTable($dst) {
  164. if (!$this->createTemporaryLongWaysTable) $this->createTemporaryLongWaysTable();
  165. $this->saveDB("_temp_long_ways", $dst);
  166. }
  167. private function arrayFrom1() {
  168. $array = array('');
  169. unset($array[0]);
  170. return $array;
  171. }
  172. private function pointsDistance($a, $b) {
  173. $line = new LineString(array($a, $b));
  174. return $line->length();
  175. }
  176. private function getSourceData() {
  177. try {
  178. if ($this->showProgress) $progress = new showProgress("Loading source data from database");
  179. DB::getPDO()->query("create temporary table `_temp_punkty_adresowe` select * from `{$this->punktyAdresoweTable}` where the_geom is not null");
  180. DB::getPDO()->query("create temporary table `_temp_drogi` select * from `{$this->drogiTable}` where coalesce(numpoints(the_geom),0)>1");
  181. DB::getPDO()->query("create index `ID` on `_temp_punkty_adresowe` (`ID`)");
  182. DB::getPDO()->query("create index `ID` on `_temp_drogi` (`ID`)");
  183. $this->getSourceData = true;
  184. if ($this->showProgress) $progress->stop();
  185. } catch (Exception $e) {
  186. throw $e;
  187. }
  188. }
  189. private function generatePoints() {
  190. try {
  191. if (!$this->getSourceData) $this->getSourceData();
  192. if ($this->showProgress) $progress = new showProgress("Generating points");
  193. $result = DB::getPDO()->query("select `ID`, astext(`the_geom`) as `point_asText` from `_temp_punkty_adresowe`");
  194. foreach ($result as $row) $points_asText[$row['ID']] = $row['point_asText'];
  195. $this->points_asText = $points_asText;
  196. $this->readyForFindWay = false;
  197. if ($this->showProgress) $progress->stop();
  198. } catch (Exception $e) {
  199. throw $e;
  200. }
  201. }
  202. private function createTemporaryWaysTable() {
  203. try {
  204. if ((!$this->ways_asText) || (!$this->ways2drogi)) throw new Exception("createTemporaryWaysTable() :: Ways not generated, use generateWays() first");
  205. DB::getPDO()->query("drop temporary table if exists `_temp_ways`");
  206. DB::getPDO()->query("create temporary table `_temp_ways` (`ID` int(11), `droga_id` int(11), `the_geom` linestring not null, index(`ID`), index(`droga_id`), spatial index(`the_geom`)) ENGINE=MyISAM");
  207. if ($this->showProgress) $progress = new showProgress("Creating temporary ways table", count($this->ways_asText));
  208. foreach ($this->ways_asText as $way_key => $way_asText) {
  209. DB::getPDO()->query("insert into `_temp_ways` values ('{$way_key}', '{$this->ways2drogi[$way_key]}', LineFromText('{$way_asText}'))");
  210. if ($this->showProgress) $progress->step();
  211. }
  212. if ($this->showProgress) $progress->stop();
  213. $this->createTemporaryWaysTable = true;
  214. } catch (Exception $e) {
  215. throw $e;
  216. }
  217. }
  218. public function generateWaysLenghts() {
  219. try {
  220. if (!$this->ways_asText) $this->generateWays;
  221. if ($this->showProgress) $progress = new showProgress("Generating waysLengths", count($this->ways_asText));
  222. foreach ($this->ways_asText as $way_key => $way_asText) {
  223. $way = Vendor_Geophp::load($way_asText, 'wkt');
  224. $waysLengths[$way_key] = $way->greatCircleLength();
  225. if ($this->showProgress) $progress->step();
  226. }
  227. $this->waysLengths = $waysLengths;
  228. if ($this->showProgress) $progress->stop();
  229. } catch (Exception $e) {
  230. throw $e;
  231. }
  232. }
  233. public function generateWays() {
  234. try {
  235. if (!$this->getSourceData) $this->getSourceData();
  236. $ways_asText = $this->arrayFrom1();
  237. $ways2drogi = $this->arrayFrom1();
  238. $result = DB::getPDO()->fetchall("select ID as droga_id, astext(the_geom) as multiway from `_temp_drogi`");
  239. if ($this->showProgress) $progress = new showProgress("Generating ways", count($result));
  240. foreach ($result as $row) {
  241. $multiway = Vendor_Geophp::load($row['multiway'], 'wkt');
  242. for ($i = 1; $i < $n = $multiway->numPoints(); $i++) {
  243. $way = new LineString(array($multiway->pointN($i), $multiway->pointN($i+1)));
  244. $ways_asText[] = $way->asText();
  245. $ways2drogi[] = $row['droga_id'];
  246. $drogi2ways[$row['droga_id']][] = count($ways2drogi);
  247. }
  248. $drogi_asText[$row['droga_id']] = $multiway->asText();
  249. if ($this->showProgress) $progress->step();
  250. }
  251. if ($this->showProgress) $progress->stop();
  252. $this->ways_asText = $ways_asText;
  253. $this->ways2drogi = $ways2drogi;
  254. $this->drogi2ways = $drogi2ways;
  255. $this->drogi_asText = $drogi_asText;
  256. $this->joins_asText = array();
  257. $this->ways2joins = array();
  258. $this->joins2ways = array();
  259. $this->xpoints_asText = array();
  260. $this->points2xpoints = array();
  261. $this->xpoints2points = array();
  262. $this->readyForFindWay = false;
  263. $this->generateWaysLenghts();
  264. } catch (Exception $e) {
  265. throw $e;
  266. }
  267. }
  268. private function createTemporaryJoinsTable() {
  269. try {
  270. if (!$this->joins_asText) throw new Exception("createTemporaryJoinsTable() :: Joins not generated, use generateJoins() first");
  271. DB::getPDO()->query("drop temporary table if exists `_temp_joins`");
  272. DB::getPDO()->query("create temporary table `_temp_joins` (`ID` int(11), `the_geom` point not null, index(`ID`), spatial index(`the_geom`)) ENGINE=MyISAM");
  273. if ($this->showProgress) $progress = new showProgress("Generating temporary joins table", count($this->joins_asText));
  274. foreach ($this->joins_asText as $join_key => $join_asText) {
  275. DB::getPDO()->query("insert into `_temp_joins` values ('{$join_key}', PointFromText('{$join_asText}'))");
  276. if ($this->showProgress) $progress->step();
  277. }
  278. if ($this->showProgress) $progress->stop();
  279. $this->createTemporaryJoinsTable = true;
  280. } catch (Exception $e) {
  281. throw $e;
  282. }
  283. }
  284. public function generateJoins() {
  285. try {
  286. if (!$this->ways_asText) throw new Exception("generateJoins() :: Ways not generated, use generateWays() first");
  287. $joins_asText = $this->arrayFrom1();
  288. $ways2joins = array();
  289. $joins2ways = array();
  290. if ($this->showProgress) $progress = new showProgress("Generating joins", count($this->ways_asText));
  291. foreach ($this->ways_asText as $way_key => $way_asText) {
  292. $way = Vendor_Geophp::load($way_asText, 'wkt');
  293. $points_asText = array($way->startPoint()->asText(), $way->endPoint()->asText());
  294. foreach ($points_asText as $point_asText) {
  295. if (!($join_key=array_search($point_asText, $joins_asText))) $join_key = array_push($joins_asText, $point_asText);
  296. $ways2joins[$way_key][] = $join_key;
  297. $joins2ways[$join_key][] = $way_key;
  298. }
  299. if ($this->showProgress) $progress->step();
  300. }
  301. if ($this->showProgress) $progress->stop();
  302. $this->joins_asText = $joins_asText;
  303. $this->ways2joins = $ways2joins;
  304. $this->joins2ways = $joins2ways;
  305. $this->readyForFindWay = false;
  306. } catch (Exception $e) {
  307. throw $e;
  308. }
  309. }
  310. private function updateTemporaryPointsTable() {
  311. try {
  312. if ((!$this->points2xpoints) || (!$this->xpoints_asText)) throw new Exception("updateTemporaryPointsTable() :: Xpoints not generated, use generateXpoints() first");
  313. if (!$this->getSourceData) $this->getSourceData();
  314. if ($this->showProgress) $progress = new showProgress("Updating temporary points table", count($this->points2xpoints));
  315. foreach ($this->points2xpoints as $point_key => $xpoint_key) {
  316. DB::getPDO()->query("update `_temp_punkty_adresowe` set `the_geom_xpoint` = pointfromtext('{$this->xpoints_asText[$xpoint_key]}') where `ID` = '{$point_key}'");
  317. if ($this->showProgress) $progress->step();
  318. }
  319. if ($this->showProgress) $progress->stop();
  320. } catch (Exception $e) {
  321. throw $e;
  322. }
  323. }
  324. public function generateXpoints() {
  325. try {
  326. if (!$this->ways_asText) throw new Exception("generateXpoints() :: Ways not generated, use generateWays() first");
  327. if (!$this->getSourceData) $this->getSourceData();
  328. if (!$this->createTemporaryWaysTable) $this->createTemporaryWaysTable();
  329. $xpoints_asText = $this->arrayFrom1();
  330. $result = DB::getPDO()->fetchall("select `ID`, astext(`the_geom`) as `point_asText` from `_temp_punkty_adresowe`");
  331. if ($this->showProgress) $progress = new showProgress("Generating xpoints", count($result));
  332. foreach ($result as $row) {
  333. if (!($way_key = DB::getPDO()->fetchValue("select `ID` from (select w.`ID`, st_distance(p.`the_geom`, w.`the_geom`) as `distance` from `_temp_punkty_adresowe` p join `_temp_ways` w on p.`ID` = '{$row['ID']}' order by `distance` limit 1) as ways"))) throw new Exception("generateXpoints() :: błąd spójnosci danych - nie znaleziono najbliższej drogi");
  334. $way = Vendor_Geophp::load($this->ways_asText[$way_key], 'wkt');
  335. $a = $way->startPoint();
  336. $b = $way->endPoint();
  337. $p = Vendor_Geophp::load($row['point_asText'], 'wkt');
  338. if ($a->y() == $b->y()) {
  339. $xp = $p->x();
  340. $yp = $a->y();
  341. $deltaA = $p->x() - $a->x();
  342. $deltaB = $p->x() - $b->x();
  343. } else {
  344. if ($a->x() == $b->x()) {
  345. $xp = $a->x();
  346. $yp = $p->y();
  347. $a2 = 0;
  348. $b2 = $p->y();
  349. } else {
  350. $a1 = ($a->y() - $b->y()) / ($a->x() - $b->x());
  351. $b1 = $a->y() - $a1 * $a->x();
  352. $a2 = -1 / $a1;
  353. $b2 = $p->y() - $a2 * $p->x();
  354. $xp = ($b2 - $b1) / ($a1 - $a2);
  355. $yp = $a1 * $xp + $b1;
  356. }
  357. $deltaA = $a2 * $a->x() + $b2 - $a->y();
  358. $deltaB = $a2 * $b->x() + $b2 - $b->y();
  359. }
  360. if ($deltaA * $deltaB >= 0) { // punkt poza linia, ustalamy na blizszy koniec linii
  361. if (abs($deltaA) < abs($deltaB) ) $xpoint = $a;
  362. else $xpoint = $b;
  363. } else { // punkt w linii - trzeba podzielic linie na dwie
  364. $xpoint = new Point($xp, $yp);
  365. $wayA = new LineString(array($a, $xpoint));
  366. $wayB = new LineString(array($xpoint, $b));
  367. $this->ways_asText[$way_key] = $wayA->asText();
  368. $new_way_key = array_push($this->ways_asText, $wayB->asText());
  369. $this->ways2drogi[$new_way_key] = $this->ways2drogi[$way_key];
  370. $this->drogi2ways[$this->ways2drogi[$way_key]][] = $new_way_key;
  371. DB::getPDO()->query("update `_temp_ways` set `the_geom` = linefromtext('{$wayA->asText()}') where `ID` = '{$way_key}'");
  372. DB::getPDO()->query("insert into `_temp_ways` values ('{$new_way_key}', '{$this->ways2drogi[$way_key]}', linefromtext('{$wayB->asText()}'))");
  373. }
  374. if (!($xpoint_key = array_search($xpoint->asText(), $xpoints_asText))) $xpoint_key = array_push($xpoints_asText, $xpoint->asText());
  375. $points2xpoints[$row['ID']] = $xpoint_key;
  376. $xpoints2points[$xpoint_key][] = $row['ID'];
  377. if ($this->showProgress) $progress->step();
  378. }
  379. if ($this->showProgress) $progress->stop();
  380. $this->xpoints_asText = $xpoints_asText;
  381. $this->points2xpoints = $points2xpoints;
  382. $this->xpoints2points = $xpoints2points;
  383. $this->generateJoins();
  384. $this->updateTemporaryPointsTable();
  385. $this->generateWaysLenghts();
  386. $this->readyForFindWay = false;
  387. } catch (Exception $e) {
  388. throw $e;
  389. }
  390. }
  391. private function createTemporaryPrzylaczaTable() {
  392. try {
  393. if ((!$this->przylacza_asText) || (!$this->przylacza2joins) || (!$this->przylacza2points)) throw new Exception("createTemporaryPrzylaczaTable() :: Przylacza not generated, use generatePrzylacza() first");
  394. if ($this->showProgress) $progress = new showProgress("Generating temporary table przylacza", count($this->przylacza_asText));
  395. DB::getPDO()->query("drop temporary table if exists `_temp_przylacza`");
  396. DB::getPDO()->query("create temporary table `_temp_przylacza` (`ID` int(11), `points_id` int(11), `joins_id` int(11), `the_geom` linestring not null, index(`ID`)) ENGINE=MyISAM");
  397. foreach ($this->przylacza_asText as $przylacze_key => $przylacze_asText) {
  398. $query = "insert into `_temp_przylacza` values ('{$przylacze_key}', '{$this->przylacza2points[$przylacze_key]}', '{$this->przylacza2joins[$przylacze_key]}', linefromtext('{$przylacze_asText}'))";
  399. DB::getPDO()->query($query);
  400. if ($this->showProgress) $progress->step();
  401. }
  402. if ($this->showProgress) $progress->stop();
  403. $this->createTemporaryPrzylaczaTable = true;
  404. } catch (Exception $e) {
  405. throw $e;
  406. }
  407. }
  408. public function generatePrzylacza() {
  409. try {
  410. if ((!$this->points2xpoints) || (!$this->xpoints_asText)) throw new Exception("generatePrzylaczaTable() :: Xpoints not generated, use generateXpoints() first");
  411. if (!$this->joins_asText) throw new Exception("generatePrzylaczaTable() :: Joins not generated, use generateJoins() first");
  412. if (!$this->points_asText) $this->generatePoints();
  413. $przylacza_asText = $this->arrayFrom1();
  414. $przylacza2joins = $this->arrayFrom1();
  415. $przylacza2points = $this->arrayFrom1();
  416. if ($this->showProgress) $progress = new showProgress("Generating przylacza", count($this->points_asText));
  417. foreach ($this->points_asText as $point_key => $point_asText) {
  418. $xpoint_key = $this->points2xpoints[$point_key];
  419. $join_key = array_search($this->xpoints_asText[$xpoint_key], $this->joins_asText);
  420. $point = Vendor_Geophp::load($this->points_asText[$point_key], 'wkt');
  421. $xpoint = Vendor_Geophp::load($this->xpoints_asText[$xpoint_key], 'wkt');
  422. $przylacze = new Linestring(array($point, $xpoint));
  423. $przylacza_asText[] = $przylacze->asText();
  424. $przylacza2joins[] = $join_key;
  425. $przylacza2points[] = $point_key;
  426. $points2joins[$point_key] = $join_key;
  427. if ($this->showProgress) $progress->step();
  428. }
  429. if ($this->showProgress) $progress->stop();
  430. $this->przylacza_asText = $przylacza_asText;
  431. $this->przylacza2joins = $przylacza2joins;
  432. $this->przylacza2points = $przylacza2points;
  433. $this->points2joins = $points2joins;
  434. $this->readyForFindWay = false;
  435. } catch (Exception $e) {
  436. throw $e;
  437. }
  438. }
  439. private function checkDataForFindWay() {
  440. try {
  441. if (!$this->readyForFindWay) {
  442. if (!$this->ways_asText) {
  443. $this->generateWays();
  444. $this->generateXpoints();
  445. }
  446. if ((!$this->ways2joins) || (!$this->joins2ways)) $this->generateJoins();
  447. if (!$this->points_asText) $this->generatePoints();
  448. if (!$this->points2joins) $this->generatePrzylacza();
  449. $this->readyForFindWay = true;
  450. }
  451. } catch (Exception $e) {
  452. throw $e;
  453. }
  454. }
  455. public function findWay($joinA, $joinB, $path = array(), $joins = array()) {
  456. try {
  457. $this->checkDataForFindWay();
  458. if ($joinA == $joinB) {
  459. $joinsPath = array($joinB);
  460. foreach (array_reverse($path) as $way_key) {
  461. array_unshift($joinsPath, $this->ways2joins[$way_key][1 - array_search($joinsPath[0], $this->ways2joins[$way_key])]);
  462. }
  463. return $joinsPath;
  464. } else {
  465. $subPaths = array();
  466. foreach ($this->joins2ways[$joinA] as $way_key) {
  467. if (!in_array($way_key, $path)) {
  468. $new_join = $this->ways2joins[$way_key][1 - array_search($joinA, $this->ways2joins[$way_key])];
  469. if (!in_array($new_join, $joins)) {
  470. if ($subPath = $this->findWay($new_join, $joinB, array_merge($path, array($way_key)), array_merge($joins, array($new_join)))) {
  471. $subPaths[] = $subPath;
  472. }
  473. }
  474. }
  475. }
  476. if ($subPaths) {
  477. if (count($subPaths) == 1) return $subPaths[0];
  478. else {
  479. $shortestKey = 0;
  480. foreach ($subPaths as $key => $subPath) {
  481. $distance_cur = 0;
  482. foreach ($subPath as $way_key) {
  483. $way = Vendor_Geophp::load($this->ways_asText[$way_key], 'wkt');
  484. if ($way) $distance_cur += Vendor_Geophp::load($this->ways_asText[$way_key], 'wkt')->length();
  485. else $distance_cur += 999;
  486. }
  487. if (!$shortestKey || ($shortestKey && $distance_cur < $distance)) {
  488. $shortestKey = $key;
  489. $distance = $distance_cur;
  490. }
  491. }
  492. return $subPaths[$key];
  493. }
  494. }
  495. else {
  496. return null;
  497. }
  498. }
  499. } catch (Exception $e) {
  500. throw $e;
  501. }
  502. }
  503. function joins2lineString($joins_keys) {
  504. try {
  505. if (!$this->points_asText) $this->generatePoints();
  506. if ($joins_keys) {
  507. foreach ($joins_keys as $join_key) {
  508. $points[] = Vendor_Geophp::load($this->joins_asText[$join_key], 'wkt');
  509. }
  510. return new LineString($points);
  511. } else return null;
  512. } catch (Exception $e) {
  513. throw $e;
  514. }
  515. }
  516. private function createTemporaryLongWaysTable() {
  517. try {
  518. if (!$this->longWays_asText) throw new Exception("createTemporaryLongWaysTable() :: longWays not generated, use generateLongWays() first");
  519. DB::getPDO()->query("drop temporary table if exists `_temp_long_ways`");
  520. DB::getPDO()->query("create temporary table `_temp_long_ways` (`ID` int(11), `the_geom` linestring not null, index(`ID`), spatial index(`the_geom`)) ENGINE=MyISAM");
  521. if ($this->showProgress) $progress = new showProgress("Creating temporary longWays table", count($this->longWays_asText));
  522. foreach ($this->longWays_asText as $longWay_key => $longWay_asText) {
  523. DB::getPDO()->query("insert into `_temp_long_ways` values ('{$longWay_key}', LineFromText('{$longWay_asText}'))");
  524. if ($this->showProgress) $progress->step();
  525. }
  526. if ($this->showProgress) $progress->stop();
  527. $this->createTemporaryLongWaysTable = true;
  528. } catch (Exception $e) {
  529. throw $e;
  530. }
  531. }
  532. function generateLongWays() {
  533. try {
  534. if ((!$this->drogi2ways) || (!$this->drogi_asText)) $this->generateWays();
  535. if (!$this->joins_asText) $this->generateJoins();
  536. if ($this->showProgress) $progress = new showProgress("Generating longWays", count($this->drogi2ways));
  537. foreach ($this->drogi2ways as $droga_key => $ways_keys) {
  538. $droga = Vendor_Geophp::load($this->drogi_asText[$droga_key], 'wkt');
  539. $startPoint = $droga->startPoint();
  540. $endPoint = $droga->endPoint();
  541. $start_join_key = array_search($startPoint->asText(), $this->joins_asText);
  542. $end_join_key = array_search($endPoint->asText(), $this->joins_asText);
  543. $path = array($start_join_key);
  544. $last_join_key = $start_join_key;
  545. while (($last_join_key) != $end_join_key) {
  546. $next_join_key = 0;
  547. foreach ($this->joins2ways[$last_join_key] as $way_key) {
  548. if (in_array($way_key, $ways_keys)) {
  549. $next_join_key = $this->ways2joins[$way_key][1 - array_search($last_join_key, $this->ways2joins[$way_key])];
  550. if (!in_array($next_join_key, $path)) {
  551. $path[] = $next_join_key;
  552. $last_join_key = $next_join_key;
  553. }
  554. }
  555. }
  556. if (!$next_join_key) throw new Exception("generateLongWays() :: Błąd spójności danych");
  557. }
  558. $points = array();
  559. foreach ($path as $join_key) $points[] = Vendor_Geophp::load($this->joins_asText[$join_key], 'wkt');
  560. $longWay = new LineString($points);
  561. $longWays_asText[$droga_key] = $longWay->asText();
  562. if ($this->showProgress) $progress->step();
  563. }
  564. $this->longWays_asText = $longWays_asText;
  565. if ($this->showProgress) $progress->stop();
  566. } catch (Exception $e) {
  567. throw $e;
  568. }
  569. }
  570. }
  571. //$test = new bialePlamy(array("pointsTable"=>"Rozdzielcza_test2_bzyk_punkty_adresowe", "origWaysTable"=>"Rozdzielcza_test2_bzyk_drogi"));
  572. //$test->enableShowProgress();
  573. //$test->loadCache();
  574. //$test->generateWays();
  575. //$test->generateXpoints();
  576. //$test->generatePrzylacza();
  577. //$test->saveCache();
  578. //$test->saveXML();
  579. //$test->saveWaysTable("Rozdzielcza_test2_bzyk_ways");
  580. //$test->saveJoinsTable("Rozdzielcza_test2_bzyk_joins");
  581. //$test->savePrzylaczaTable("Rozdzielcza_test2_bzyk_przylacza");