New file |
0,0 → 1,300 |
<?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érer |
while (($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 mille |
if ($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 multipolygone |
for ($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é administrative |
if ((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()); |
} |
} |