biale_plamy_class.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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 = 40;
  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+60);
  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+60);
  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;
  53. private $punktyAdresoweTable = null, $drogiTable = null;
  54. private $joins_asText = array(), $ways_asText = array(), $xpoints_asText = array(), $points_asText = array(), $przylacza_asText = array();
  55. private $ways2drogi = array(), $ways2joins = array(), $joins2ways = array(), $points2xpoints = array(), $xpoints2points = array(), $przylacza2joins = array(), $przylacza2points = array();
  56. public function __construct($punktyAdresoweTable, $drogiTable) {
  57. $this->punktyAdresoweTable = $punktyAdresoweTable;
  58. $this->drogiTable = $drogiTable;
  59. }
  60. public function enableShowProgress() {
  61. $this->showProgress = true;
  62. }
  63. public function disableShowProgress() {
  64. $this->showProgress = false;
  65. }
  66. private $dataArrays = array('joins_asText', 'ways_asText', 'xpoints_asText', 'points_asText', 'przylacza_asText',
  67. 'ways2drogi', 'ways2joins', 'joins2ways', 'points2xpoints', 'xpoints2points', 'przylacza2joins', 'przylacza2points');
  68. public function saveCache() {
  69. foreach ($this->dataArrays as $array) if ($this->$array) {
  70. if ($this->showProgress) $progress = new showProgress("Saving {$array}");
  71. file_put_contents('/tmp/save_'.$array.'.txt', serialize($this->$array));
  72. if ($this->showProgress) $progress->stop();
  73. }
  74. }
  75. public function saveXML() {
  76. function array_to_xml($data, &$xml_data) {
  77. foreach ($data as $key => $value) {
  78. $key_ = "";
  79. if (is_numeric($key)) $key_ = 'item';
  80. if (is_array($value)) {
  81. $subnode = $xml_data->addChild($key_);
  82. $subnode->addAttribute('id', $key);
  83. array_to_xml($value, $subnode);
  84. } else {
  85. $subnode = $xml_data->addChild("$key_", htmlspecialchars("$value"));
  86. if (is_numeric($key)) $subnode->addAttribute('id', $key);
  87. }
  88. }
  89. }
  90. foreach ($this->dataArrays as $array) if ($this->$array) {
  91. if ($this->showProgress) $progress = new showProgress("Generating XML for {$array}");
  92. $xml = new SimpleXMLElement("<?xml version=\"1.0\"?><{$array}></{$array}>");
  93. array_to_xml($this->$array, $xml);
  94. $xml->asXML("{$array}.xml");
  95. if ($this->showProgress) $progress->stop();
  96. }
  97. }
  98. public function loadCache() {
  99. try {
  100. foreach ($this->dataArrays as $array) if (file_exists('/tmp/save_'.$array.'.txt')) {
  101. if ($this->showProgress) $progress = new showProgress("Loading {$array}");
  102. $this->$array = unserialize(file_get_contents('/tmp/save_'.$array.'.txt'));
  103. if ($this->showProgress) $progress->stop();
  104. }
  105. } catch (Exception $e) {
  106. throw new Exception ($e->getMessage());
  107. }
  108. }
  109. private function saveDB($src, $dst) {
  110. try {
  111. if ($this->showProgress) $progress = new showProgress("Saving points table");
  112. DB::getPDO()->query("truncate table `{$dst}`");
  113. $result = DB::getPDO()->fetchall("show fields from `{$src}`");
  114. foreach ($result as $col) $cols[] = "`{$col['Field']}`";
  115. $query = "insert into `{$dst}` (".implode(", ", $cols).") select * from `{$src}`";
  116. DB::getPDO()->query($query);
  117. if ($this->showProgress) $progress->stop();
  118. } catch (Exception $e) {
  119. throw new Exception ($e->getMessage());
  120. }
  121. }
  122. public function savePointsTable($dst) {
  123. if (!$this->getSourceData) $this->getSourceData();
  124. if ($this->xpoints2points) $this->updateTemporaryPointsTable();
  125. $this->saveDB("_temp_punkty_adresowe", $dst);
  126. }
  127. public function saveWaysTable($dst) {
  128. if (!$this->createTemporaryWaysTable) $this->createTemporaryWaysTable();
  129. $this->saveDB("_temp_ways", $dst);
  130. }
  131. public function saveJoinsTable($dst) {
  132. if (!$this->createTemporaryJoinsTable) $this->createTemporaryJoinsTable();
  133. $this->saveDB("_temp_joins", $dst);
  134. }
  135. public function savePrzylaczaTable($dst) {
  136. if (!$this->createTemporaryPrzylaczaTable) $this->createTemporaryPrzylaczaTable();
  137. $this->saveDB("_temp_przylacza", $dst);
  138. }
  139. private function arrayFrom1() {
  140. $array = array('');
  141. unset($array[0]);
  142. return $array;
  143. }
  144. private function pointsDistance($a, $b) {
  145. $line = new LineString(array($a, $b));
  146. return $line->length();
  147. }
  148. private function getSourceData() {
  149. try {
  150. if ($this->showProgress) $progress = new showProgress("Loading source data from database");
  151. DB::getPDO()->query("create temporary table `_temp_punkty_adresowe` select * from `{$this->punktyAdresoweTable}`");
  152. DB::getPDO()->query("create temporary table `_temp_drogi` select * from `{$this->drogiTable}` where numpoints(the_geom)>1");
  153. DB::getPDO()->query("create index `ID` on `_temp_punkty_adresowe` (`ID`)");
  154. DB::getPDO()->query("create index `ID` on `_temp_drogi` (`ID`)");
  155. $this->getSourceData = true;
  156. if ($this->showProgress) $progress->stop();
  157. } catch (Exception $e) {
  158. throw new Exception($e->getMessage());
  159. }
  160. }
  161. private function generatePoints() {
  162. try {
  163. if (!$this->getSourceData) $this->getSourceData();
  164. if ($this->showProgress) $progress = new showProgress("Generating points");
  165. $result = DB::getPDO()->query("select `ID`, astext(`the_geom`) as `point_asText` from `_temp_punkty_adresowe`");
  166. foreach ($result as $row) $points_asText[$row['ID']] = $row['point_asText'];
  167. $this->points_asText = $points_asText;
  168. if ($this->showProgress) $progress->stop();
  169. } catch (Exception $e) {
  170. throw new Exception($e->getMessage());
  171. }
  172. }
  173. private function createTemporaryWaysTable() {
  174. try {
  175. if ((!$this->ways_asText) || (!$this->ways2drogi)) throw new Exception("createTemporaryWaysTable() :: Ways not generated, use generateWays() first");
  176. DB::getPDO()->query("drop temporary table if exists `_temp_ways`");
  177. 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");
  178. if ($this->showProgress) $progress = new showProgress("Creating temporary ways table", count($this->ways_asText));
  179. foreach ($this->ways_asText as $way_key => $way_asText) {
  180. DB::getPDO()->query("insert into `_temp_ways` values ('{$way_key}', '{$this->ways2drogi[$way_key]}', LineFromText('{$way_asText}'))");
  181. if ($this->showProgress) $progress->step();
  182. }
  183. if ($this->showProgress) $progress->stop();
  184. $this->createTemporaryWaysTable = true;
  185. } catch (Exception $e) {
  186. throw new Exception ($e->getMessage);
  187. }
  188. }
  189. public function generateWays() {
  190. try {
  191. if (!$this->getSourceData) $this->getSourceData();
  192. $ways_asText = $this->arrayFrom1();
  193. $ways2drogi = $this->arrayFrom1();
  194. $result = DB::getPDO()->fetchall("select ID as droga_id, astext(the_geom) as multiway from `_temp_drogi`");
  195. if ($this->showProgress) $progress = new showProgress("Generating ways", count($result));
  196. foreach ($result as $row) {
  197. $multiway = Vendor_Geophp::load($row['multiway'], 'wkt');
  198. for ($i = 1; $i < $n = $multiway->numPoints(); $i++) {
  199. $way = new LineString(array($multiway->pointN($i), $multiway->pointN($i+1)));
  200. $ways_asText[] = $way->asText();
  201. $ways2drogi[] = $row['droga_id'];
  202. }
  203. if ($this->showProgress) $progress->step();
  204. }
  205. if ($this->showProgress) $progress->stop();
  206. $this->ways_asText = $ways_asText;
  207. $this->ways2drogi = $ways2drogi;
  208. $this->joins_asText = array();
  209. $this->ways2joins = array();
  210. $this->joins2ways = array();
  211. $this->xpoints_asText = array();
  212. $this->points2xpoints = array();
  213. $this->xpoints2points = array();
  214. } catch (Exception $e) {
  215. throw new Exception($e->getMessage());
  216. }
  217. }
  218. private function createTemporaryJoinsTable() {
  219. try {
  220. if (!$this->joins_asText) throw new Exception("createTemporaryJoinsTable() :: Joins not generated, use generateJoins() first");
  221. DB::getPDO()->query("drop temporary table if exists `_temp_joins`");
  222. DB::getPDO()->query("create temporary table `_temp_joins` (`ID` int(11), `the_geom` point not null, index(`ID`), spatial index(`the_geom`)) ENGINE=MyISAM");
  223. if ($this->showProgress) $progress = new showProgress("Generating temporary joins table", count($this->joins_asText));
  224. foreach ($this->joins_asText as $join_key => $join_asText) {
  225. DB::getPDO()->query("insert into `_temp_joins` values ('{$join_key}', PointFromText('{$join_asText}'))");
  226. if ($this->showProgress) $progress->step();
  227. }
  228. if ($this->showProgress) $progress->stop();
  229. $this->createTemporaryJoinsTable = true;
  230. } catch (Exception $e) {
  231. throw new Exception ($e->getMessage());
  232. }
  233. }
  234. public function generateJoins() {
  235. try {
  236. if (!$this->ways_asText) throw new Exception("generateJoins() :: Ways not generated, use generateWays() first");
  237. $joins_asText = $this->arrayFrom1();
  238. $ways2joins = array();
  239. $joins2ways = array();
  240. if ($this->showProgress) $progress = new showProgress("Generating joins", count($this->ways_asText));
  241. foreach ($this->ways_asText as $way_key => $way_asText) {
  242. $way = Vendor_Geophp::load($way_asText, 'wkt');
  243. $points_asText = array($way->startPoint()->asText(), $way->endPoint()->asText());
  244. foreach ($points_asText as $point_asText) {
  245. if (!in_array($point_asText, $joins_asText)) {
  246. $join_key = array_push($joins_asText, $point_asText);
  247. $ways2joins[$way_key][] = $join_key;
  248. $joins2ways[$join_key][] = $way_key;
  249. }
  250. }
  251. if ($this->showProgress) $progress->step();
  252. }
  253. if ($this->showProgress) $progress->stop();
  254. $this->joins_asText = $joins_asText;
  255. $this->ways2joins = $ways2joins;
  256. $this->joins2ways = $joins2ways;
  257. } catch (Exception $e) {
  258. throw new Exception($e->getMessage());
  259. }
  260. }
  261. private function updateTemporaryPointsTable() {
  262. try {
  263. if ((!$this->points2xpoints) || (!$this->xpoints_asText)) throw new Exception("updateTemporaryPointsTable() :: Xpoints not generated, use generateXpoints() first");
  264. if (!$this->getSourceData) $this->getSourceData();
  265. if ($this->showProgress) $progress = new showProgress("Updating temporary points table", count($this->points2xpoints));
  266. foreach ($this->points2xpoints as $point_key => $xpoint_key) {
  267. DB::getPDO()->query("update `_temp_punkty_adresowe` set `the_geom_xpoint` = pointfromtext('{$this->xpoints_asText[$xpoint_key]}') where `ID` = '{$point_key}'");
  268. if ($this->showProgress) $progress->step();
  269. }
  270. if ($this->showProgress) $progress->stop();
  271. } catch (Exception $e) {
  272. throw new Exception($e->getMessage());
  273. }
  274. }
  275. public function generateXpoints() {
  276. try {
  277. if (!$this->ways_asText) throw new Exception("generateXpoints() :: Ways not generated, use generateWays() first");
  278. if (!$this->getSourceData) $this->getSourceData();
  279. if (!$this->createTemporaryWaysTable) $this->createTemporaryWaysTable();
  280. $xpoints_asText = $this->arrayFrom1();
  281. $result = DB::getPDO()->fetchall("select `ID`, astext(`the_geom`) as `point_asText` from `_temp_punkty_adresowe`");
  282. if ($this->showProgress) $progress = new showProgress("Generating xpoints", count($result));
  283. foreach ($result as $row) {
  284. 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");
  285. $way = Vendor_Geophp::load($this->ways_asText[$way_key], 'wkt');
  286. $a = $way->startPoint();
  287. $b = $way->endPoint();
  288. $p = Vendor_Geophp::load($row['point_asText'], 'wkt');
  289. if ($a->y() == $b->y()) {
  290. $xp = $p->x();
  291. $yp = $a->y();
  292. $deltaA = $p->x() - $a->x();
  293. $deltaB = $p->x() - $b->x();
  294. } else {
  295. if ($a->x() == $b->x()) {
  296. $xp = $a->x();
  297. $yp = $p->y();
  298. $a2 = 0;
  299. $b2 = $p->y();
  300. } else {
  301. $a1 = ($a->y() - $b->y()) / ($a->x() - $b->x());
  302. $b1 = $a->y() - $a1 * $a->x();
  303. $a2 = -1 / $a1;
  304. $b2 = $p->y() - $a2 * $p->x();
  305. $xp = ($b2 - $b1) / ($a1 - $a2);
  306. $yp = $a1 * $xp + $b1;
  307. }
  308. $deltaA = $a2 * $a->x() + $b2 - $a->y();
  309. $deltaB = $a2 * $b->x() + $b2 - $b->y();
  310. }
  311. if ($deltaA * $deltaB >= 0) { // punkt poza linia, ustalamy na blizszy koniec linii
  312. if (abs($deltaA) < abs($deltaB) ) $xpoint = $xpoint = $a;
  313. else $xpoint = $b;
  314. } else { // punkt w linii - trzeba podzielic linie na dwie
  315. $xpoint = new Point($xp, $yp);
  316. $wayA = new LineString(array($a, $xpoint));
  317. $wayB = new LineString(array($xpoint, $b));
  318. $this->ways_asText[$way_key] = $wayA->asText();
  319. $new_way_key = array_push($this->ways_asText, $wayB->asText());
  320. $this->ways2drogi[$new_way_key] = $this->ways2drogi[$way_key];
  321. DB::getPDO()->query("update `_temp_ways` set `the_geom` = linefromtext('{$wayA->asText()}') where `ID` = '{$way_key}'");
  322. DB::getPDO()->query("insert into `_temp_ways` values ('{$new_way_key}', '{$this->ways2drogi[$way_key]}', linefromtext('{$wayB->asText()}'))");
  323. }
  324. if (!($xpoint_key = array_search($xpoint->asText(), $xpoints_asText))) $xpoint_key = array_push($xpoints_asText, $xpoint->asText());
  325. $points2xpoints[$row['ID']] = $xpoint_key;
  326. $xpoints2points[$xpoint_key][] = $row['ID'];
  327. if ($this->showProgress) $progress->step();
  328. }
  329. if ($this->showProgress) $progress->stop();
  330. $this->xpoints_asText = $xpoints_asText;
  331. $this->points2xpoints = $points2xpoints;
  332. $this->xpoints2points = $xpoints2points;
  333. $this->generateJoins();
  334. $this->updateTemporaryPointsTable();
  335. } catch (Exception $e) {
  336. throw new Exception($e->getMessage());
  337. }
  338. }
  339. private function createTemporaryPrzylaczaTable() {
  340. try {
  341. if ((!$this->przylacza_asText) || (!$this->przylacza2joins) || (!$this->przylacza2points)) throw new Exception("createTemporaryPrzylaczaTable() :: Przylacza not generated, use generatePrzylacza() first");
  342. if ($this->showProgress) $progress = new showProgress("Generating temporary table przylacza", count($this->przylacza_asText));
  343. DB::getPDO()->query("drop temporary table if exists `_temp_przylacza`");
  344. 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");
  345. foreach ($this->przylacza_asText as $przylacze_key => $przylacze_asText) {
  346. $query = "insert into `_temp_przylacza` values ('{$przylacze_key}', '{$this->przylacza2points[$przylacze_key]}', '{$this->przylacza2joins[$przylacze_key]}', linefromtext('{$przylacze_asText}'))";
  347. DB::getPDO()->query($query);
  348. if ($this->showProgress) $progress->step();
  349. }
  350. if ($this->showProgress) $progress->stop();
  351. $this->createTemporaryPrzylaczaTable = true;
  352. } catch (Exception $e) {
  353. throw new Exception($e->getMessage());
  354. }
  355. }
  356. public function generatePrzylacza() {
  357. try {
  358. if ((!$this->points2xpoints) || (!$this->xpoints_asText)) throw new Exception("generatePrzylaczaTable() :: Xpoints not generated, use generateXpoints() first");
  359. if (!$this->joins_asText) throw new Exception("generatePrzylaczaTable() :: Joins not generated, use generateJoins() first");
  360. if (!$this->points_asText) $this->generatePoints();
  361. $przylacza_asText = $this->arrayFrom1();
  362. $przylacza2joins = $this->arrayFrom1();
  363. $przylacza2points = $this->arrayFrom1();
  364. if ($this->showProgress) $progress = new showProgress("Generating przylacza", count($this->points_asText));
  365. foreach ($this->points_asText as $point_key => $point_asText) {
  366. $xpoint_key = $this->points2xpoints[$point_key];
  367. $join_key = array_search($this->xpoints_asText[$xpoint_key], $this->joins_asText);
  368. $point = Vendor_Geophp::load($this->points_asText[$point_key], 'wkt');
  369. $xpoint = Vendor_Geophp::load($this->xpoints_asText[$xpoint_key], 'wkt');
  370. $przylacze = new Linestring(array($point, $xpoint));
  371. $przylacza_asText[] = $przylacze->asText();
  372. $przylacza2joins[] = $join_key;
  373. $przylacza2points[] = $point_key;
  374. if ($this->showProgress) $progress->step();
  375. }
  376. if ($this->showProgress) $progress->stop();
  377. $this->przylacza_asText = $przylacza_asText;
  378. $this->przylacza2joins = $przylacza2joins;
  379. $this->przylacza2points = $przylacza2points;
  380. } catch (Exception $e) {
  381. throw new Exception($e->getMessage());
  382. }
  383. }
  384. }
  385. $test = new bialePlamy("Rozdzielcza_test2_bzyk_punkty_adresowe", "Rozdzielcza_test2_bzyk_drogi");
  386. $test->enableShowProgress();
  387. $test->loadCache();
  388. //$test->generateWays();
  389. //$test->generateXpoints();
  390. //$test->generatePrzylacza();
  391. //$test->saveCache();
  392. $test->saveXML();
  393. //$test->saveWaysTable("Rozdzielcza_test2_bzyk_ways");
  394. //$test->saveJoinsTable("Rozdzielcza_test2_bzyk_joins");
  395. //$test->savePrzylaczaTable("Rozdzielcza_test2_bzyk_przylacza");