Rev 1058 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** Réparation des polygones incomplets :** Exemple de lancement du script :* /opt/lampp/bin/php -d memory_limit=8000M cli.php osm -a ordonnerPolygoneInc -m manuel -v 3** /opt/lampp/bin/php -d memory_limit=8000M cli.php osm -a remplirPolygoneInc -m manuel -v 3** /opt/lampp/bin/php -d memory_limit=8000M cli.php osm -a renommer -m manuel -v 3**/class PolygoneReparateur {private $conteneur;private $bdd;private $messages;private $mode;public function __construct($conteneur) {$this->conteneur = $conteneur;$this->bdd = $this->conteneur->getBdd();$this->messages = $this->conteneur->getMessages();$this->mode = $this->conteneur->getParametre('m');}/*** Fonction qui parcourt tous les ways les noeuds de chaque relation en prenant en considération l'ordre et* le sens de chaque ways concaténés ensemble (séparés par des virgules). Update du champ polygone de chaque* relation dans la table `osm_relations`*/public function executer() {// Lancement de l'action demandée$cmd = $this->conteneur->getParametre('a');switch ($cmd) {case 'ordonnerPolygoneInc' :$this->ordonnerRelationsAuPolygoneIncomplet();break;case 'remplirPolygoneInc' :$this->remplirRelationsAuPolygoneIncomplet();break;case 'renommer' :$this->renommerEnPolygoneIncomplet();break;default :$msgTpl = "Erreur : la commande '%s' n'est pas prise en compte par la classe %s !";$msg = sprintf($msgTpl, $cmd, get_class($this));throw new Exception($msg);}print "\n";// Pour ramener à la ligne en fin de script}/*** Fonction qui récupère les relations des polygones incomplets et appelle pour chaque relation la fonction* ordonnerPolygoneIncomplet($ordre,$tour,$idRelation,$nombrePolygone)*/private function ordonnerRelationsAuPolygoneIncomplet() {$relations = $this->getRelationsAuPolygoneIncomplet();foreach ($relations as $relation) {$idRelation = $relation['id_relation'];$this->ordonnerCheminsMultiPolygone($idRelation);if ($this->mode == 'manuel') {$this->messages->afficherAvancement("Réparation du polygone incomplet : ", 1);}}}/*** Fonction récursive qui exécute la même tâche que la fonction ordonnerWays() pour chaque polygone d'un* multipolygone et remplie le champ NbPoly dans la table `osm_relation_a_chemins` qui correspond au nombre de polygone fermé* dans le multipolygone*/private function ordonnerCheminsMultiPolygone($idRelation, $numPolygone = 1, $ordre = 1, $tour = 1) {$chemins = $this->getChemins($idRelation);$nbreCheminsTotal = count($chemins);// premier élément du tableau$idPremierChemin = $chemins[0]['id_chemin'];$idChemin = $idPremierChemin;$this->mettreAJourChemin($idRelation, $idPremierChemin, $ordre, 'directe', $numPolygone);//selection dernier noeud$nodes = $this->getNoeuds($idPremierChemin);$nombreNodes = count($nodes);$premierNoeud = $nodes[0]['id_noeud'];$dernierNoeud = $nodes[$nombreNodes - 1]['id_noeud'];$noeudActuel = $dernierNoeud;//Condition pour laquelle la boucle while continue à tourner; tant que le premier noeud du polygone n'est//égale au dernier et tant qu'il reste des ways à gérerwhile (($premierNoeud != $noeudActuel) && (($ordre % 1000) < $nbreCheminsTotal)) {//select le way qui possède le dernier noeud du précédent way et écarter l'actuel$ordre++;$chemins = $this->getCheminsAOrdonner($idRelation, $idChemin, $noeudActuel);if (isset($chemins[0])) {$idChemin = $chemins[0]['id_chemin'];$nodes = $this->getNoeuds($idChemin);$nombreNodes = count($nodes);if (strcmp($nodes[0]['id_noeud'], $noeudActuel ) == 0) {$sens = 'directe';$noeudActuel = $nodes[$nombreNodes-1]['id_noeud'];} else {$sens = 'indirecte';$noeudActuel = $nodes[0]['id_noeud'];}$this->mettreAJourChemin($idRelation, $idChemin, $ordre, $sens, $numPolygone);}}$ordre = 1000 * $tour; //différencier chaque polygone: pour chaque polygone on a un multiple de milleif ($this->getNombreChemins($idRelation) != 0) {//appelle de la méthode récursivement$this->ordonnerCheminsMultiPolygone($idRelation, ++$numPolygone, $ordre, ++$tour);}}private function getRelationsAuPolygoneIncomplet() {$requete = 'SELECT id_relation '.'FROM osm_communes '."WHERE notes = 'Polygone incomplet' ".' -- '.__FILE__.' : '.__LINE__;$relations = $this->bdd->recupererTous($requete);return $relations;}private function getChemins($idRelation) {$requete = 'SELECT id_chemin '.'FROM osm_relation_a_chemins '."WHERE id_relation = $idRelation "."AND ordre IS NULL ".' -- '.__FILE__.' : '.__LINE__;$chemins = $this->bdd->recupererTous($requete);return $chemins;}/*** Select des ways qui n'ont pas été ordonnés: on obtient à chaque itération les ways qui restent à ordonner*/private function getCheminsAOrdonner($idRelation, $idChemin, $idNoeud) {$requete = 'SELECT cn.id_chemin '.'FROM osm_relation_a_chemins AS rc '.' INNER JOIN osm_chemin_a_noeuds AS cn ON (rc.id_chemin = cn.id_chemin) '."WHERE cn.id_noeud = $idNoeud "."AND cn.id_chemin != $idChemin "."AND rc.id_relation = $idRelation "."AND rc.ordre IS NULL ".' -- '.__FILE__.' : '.__LINE__;$chemins = $this->bdd->recupererTous($requete);return $chemins;}private function getNoeuds($idChemin) {$requete = 'SELECT id_noeud '.'FROM osm_chemin_a_noeuds '."WHERE id_chemin = $idChemin ".'ORDER BY ordre '.' -- '.__FILE__.' : '.__LINE__;$noeuds = $this->bdd->recupererTous($requete);return $noeuds;}private function getNombreChemins($idRelation) {$requete = 'SELECT COUNT(id_chemin) AS nbre '.'FROM osm_relation_a_chemins '."WHERE id_relation = $idRelation ".'AND ordre = 0 '.' -- '.__FILE__.' : '.__LINE__;$infos = $this->bdd->recuperer($requete);return $infos['nbre'];}private function mettreAJourChemin($idRelation, $idChemin, $ordre, $sens, $nbrePoly) {$requete = 'UPDATE osm_relation_a_chemins '."SET ordre = '$ordre', sens = '$sens', num_poly = $nbrePoly "."WHERE id_relation = $idRelation "."AND id_chemin = $idChemin ".' -- '.__FILE__.' : '.__LINE__;$this->bdd->requeter($requete);}/*** Fonction qui récupère les relations des polygones incomplets et appelle pour chaque relation la fonction* remplirPolygoneIncomplet($idRelation);*/private function remplirRelationsAuPolygoneIncomplet() {$relations = $this->getRelationsAuPolygoneIncomplet();foreach ($relations as $relation) {$this->remplirPolygoneIncomplet($relation['id_relation']);if ($this->mode == 'manuel') {$this->messages->afficherAvancement("Création du polygone incomplet : ", 1);}}}/*** Fonction qui exécute la même tâche que la fonction remplirPolygone() pour chaque polygone d'un multipolygone* et renvoie un tableau MultiPolygone[] où chaque case contient un polygone fermé. Puis met à jour le polygone* de la commune.*/private function remplirPolygoneIncomplet($idRelation) {// Tableau multipolygone qui contient tous les polygones d'un multipolygone$multiPolygone = array();// Tableau roles qui contient les différents roles des chemins de la relation$roles = array();// Sélectionner le nombre de polygones qui existe dans un multipolygone$nbPoly = $this->getNombrePoly($idRelation);//boucle for qui parcourt chaque polygone du multipolygonefor ($numPoly = 1; $numPoly <= $nbPoly; $numPoly++) {$polygone = array();$chemins = $this->getCheminsParPolygone($idRelation, $numPoly);foreach ($chemins as $chemin) {$role = $chemin['role'];$roles[$role] = (isset($roles[$role])) ? $roles[$role]++ : 1;$noeuds = $this->getNoeudsPourCheminEtSens($chemin['id_chemin'], $chemin['sens']);$polygone = array_merge($polygone, $noeuds);}$multiPolygone[] = implode(', ', $polygone);}$this->mettreAJourMultiPolygone($multiPolygone, $roles, $idRelation, $nbPoly);}private function getNombrePoly($idRelation) {$requete = 'SELECT MAX(num_poly) AS num_poly '.'FROM osm_relation_a_chemins '."WHERE id_relation = $idRelation ".' -- '.__FILE__.' : '.__LINE__;$resultat = $this->bdd->recuperer($requete);return $resultat['num_poly'];}private function getCheminsParPolygone($idRelation, $numPoly) {$requete = 'SELECT id_chemin, sens, role '.'FROM osm_relation_a_chemins '."WHERE id_relation = $idRelation "."AND num_poly = $numPoly ".'ORDER BY ordre '.' -- '.__FILE__.' : '.__LINE__;$chemins = $this->bdd->recupererTous($requete);return $chemins;}private function getNoeudsPourCheminEtSens($idChemin, $sens) {$tri = ($sens == 'directe') ? 'ASC' : 'DESC';$requete = 'SELECT NLL.id_noeud, NLL.lat, NLL.`long` '.'FROM osm_chemin_a_noeuds AS WN '.' INNER JOIN osm_noeuds AS NLL ON (WN.id_noeud = NLL.id_noeud) '."WHERE WN.id_chemin = $idChemin "."ORDER BY WN.ordre $tri ".' -- '.__FILE__.' : '.__LINE__;$noeuds = $this->bdd->recupererTous($requete);$latLng = array();foreach ($noeuds as $noeud) {$latLng[] = $noeud['lat'].' '.$noeud['long'];}return $latLng;}/*** Remplie le champ polygone à partir du tableau MultiPolygone*/private function mettreAJourMultiPolygone($multiPolygone, $roles, $idRelation, $nbPoly) {// Présence d'une enclave contenue dans cette entité administrative mais qui appartient à une autre entité administrativeif ((isset($roles['inner']) || isset($roles['enclave']))) {if ($nbPoly == 2) {$multiPoly = implode('),(', $multiPolygone);} else {$multiPoly = null;$msgTpl = "La relation '%s' possède plus de 2 polygones de type enclaves.";$this->messages->traiterErreur($msgTpl, array($idRelation));}} else {// Tous les autres cas$multiPoly = implode(')),((', $multiPolygone);}if (isset($multiPoly)) {$this->mettreAJourCommune($idRelation, $multiPoly);}}private function mettreAJourCommune($idRelation, $multiPoly) {$requete = 'UPDATE osm_communes '."SET polygone = MPOLYFROMTEXT('MULTIPOLYGON((($multiPoly)))'), "."notes = 'Polygone complet' "."WHERE id_relation = $idRelation ".' -- '.__FILE__.' : '.__LINE__;$this->bdd->requeter($requete);}/*** Renomme la note des polygones vides d'un polygone complet en polygone incomplet*/private function renommerEnPolygoneIncomplet() {$requete = 'UPDATE osm_communes '."SET notes = 'Polygone incomplet' "."WHERE ASTEXT(polygone) IS NULL ".' -- '.__FILE__.' : '.__LINE__;$retour = $this->bdd->requeter($requete);$this->messages->traiterInfo("Nombre de polygones définis à incomplet : ".$retour->rowCount());}}