Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 880 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
/**
 * Exemple de lancement du script :
 * /opt/lampp/bin/php cli.php osm/parseur_osm -a compter -f "/home/jpm/Stockage/osm/languedoc-roussillon-communes.osm"
 *
 */
class ParseurOsm extends Script {

        private $communes = array();
        private $relations_communes = array();
        private $relation_a_chemins = array();
        private $chemin_a_noeuds = array();
        private $noeuds = array();
        private $pas = 10000;
        private $pas_commune = 1000;

        protected $parametres_autorises = array(
                '-f' => array(true, null, 'Chemin du fichier osm à analyser'),
                '-m' => array(false, 'auto', 'Mode «auto» ou «manuel». En manuel, les compteurs dans les boucles sont affichés.'));

        public function executer() {
                $this->bdd = new Bdd();

                // Lancement de l'action demandée
                $cmd = $this->getParametre('a');
            switch ($cmd) {
                case 'analyser' :
                                $this->lireFichierOsm();
                                break;
                        case 'ordre' :
                                $this->ordonnerWays();
                                break;
                        case 'polygone' :
                                $this->remplirPolygone();
                                break;
                        case 'zero' :
                                $this->remettreOrdreAZero();
                                break;
                        case 'ordonnerPolygoneInc' :
                                $this->relationsPolygoneIncomplet(1, 0);
                                break;
                        case 'remplirPolygoneInc' :
                                $this->remplirCommunesPolygoneIncomplet();
                                break;
                        case 'renommer' :
                                $this->renommerEnPolygoneIncomplet();
                                break;
                        case 'centre' :
                                $this->centroid();
                                break;
                        default :
                                $this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));
                }
    }


    /**
         * Lit le fichier OSM et lance l'analyse des noeuds xml en fonction de leur type.
         */
        private function lireFichierOsm() {
                $lecteur = new XMLReader();
                if ($lecteur->open($this->getParametre('f'))) {
                        $dom = new DomDocument();
                        while ($lecteur->read()) {
                                if ($lecteur->nodeType == XMLREADER::ELEMENT) {
                                        if ($lecteur->localName == 'relation') {
                                                $relation = $lecteur->expand();
                                                $this->analyserRelation($relation);

                                                if (count($this->relation_a_chemins) > $this->pas) {
                                                        $this->insererRelationAChemins();
                                                }
                                                if (count($this->relations_communes) > $this->pas_commune) {
                                                        $this->insererRelationsCommunes();
                                                }
                                        } else if ($lecteur->localName == 'way') {
                                                $way = $lecteur->expand();
                                                $this->analyserWay($way);

                                                if (count($this->chemin_a_noeuds) > $this->pas) {
                                                        $this->insererCheminANoeuds();
                                                }
                                        } else if ($lecteur->localName == 'node') {
                                                $node = $lecteur->expand();
                                                $this->analyserNode($node);
                                                if (count($this->noeuds) > $this->pas) {
                                                        $this->insererNoeuds();
                                                }
                                        }
                                }
                                if (count($this->noeuds) > $this->pas) {
                                        $this->insererNoeuds();
                                        $this->insererCheminANoeuds();
                                }
                                if ($this->getParametre('m') == 'manuel') {
                                        $this->afficherAvancement("Analyse de la ligne du fichier OSM : ", 1);
                                }
                        }
                        $this->insererRelationsCommunes();
                        $this->insererRelationAChemins();
                        $this->insererCheminANoeuds();
                        $this->insererNoeuds();
                } else {
                        $e = "Impossible d'ouvrir le fichier osm : %s";
                        $this->traiterErreur($e, array($this->getParametre('f')));
                }
        }

        /**
         * Récupère l'id commune, nom commune et le code INSEE et remplie la table `CommuneOSM`
         */
        private function analyserRelation($relation) {
                $relation_id = $this->proteger($relation->getAttribute('id'));
                $chemins = $relation->getElementsByTagName('member');
                foreach ($chemins as $chemin) {
                        if ($chemin->getAttribute('type') == 'way') { //écarter le noeud centrale
                                $chemin_id = $this->proteger($chemin->getAttribute('ref'));
                                $role = $this->proteger($chemin->getAttribute('role'));//role: null, inner, outer, exclave et enclave.
                                $this->relation_a_chemins[] = array($relation_id, $chemin_id, $role);
                        }
                }
                $commune_nom = null;
                $commune_insee = null;
                $tags = $relation->getElementsByTagName('tag');
                foreach ($tags as $tag) {
                        $tag_cle = $tag->getAttribute('k');
                        $tag_val = $tag->getAttribute('v');
                        switch ($tag_cle) {
                                case 'name' :
                                        $commune_nom = $this->proteger($tag_val);
                                        break;
                                case 'ref:INSEE' :
                                        $commune_insee = $this->proteger($tag_val);
                                        break;
                        }
                        if (!is_null($commune_nom) && !is_null($commune_insee)) {
                                $this->relations_communes[] = array($relation_id, $commune_nom, $commune_insee);
                                if (!isset($this->communes[$commune_insee])) {
                                        $this->communes[$commune_insee] = $relation_id;
                                } else {
                                        $e = "La relation #%s contient déjà le tag ref:INSEE avec la valeur %s.".
                                                "Veuillez corriger la carte OSM.";
                                        $this->traiterErreur($e, array($this->communes[$commune_insee], $commune_insee, $relation_id));
                                }
                                break;
                        }
                }
        }

        /**
         * Récupère l'id_way et tous les id_node de chaque way et remplie la table `osm_chemin_a_noeuds`
         */
        private function analyserWay($way) {
                $chemin_id = $this->proteger($way->getAttribute('id'));
                $ordre = 0;
                $noeuds = $way->getElementsByTagName('nd');
                $chemin_a_noeuds = array();
                foreach ($noeuds as $noeud) {
                        $noeud_id = $this->proteger($noeud->getAttribute('ref'));
                        $ordre++;
                $this->chemin_a_noeuds[] = array($chemin_id, $noeud_id, $ordre);
                }
        }

        /**
         * Fonction qui récupère tous les l'id_node et les valeurs(Lat/Lon) correspondantes et remplie la table `osm_noeuds`
         */
        private function analyserNode($node) {
                $noeud_id = $this->proteger($node->getAttribute('id'));
                $lat = $this->proteger($node->getAttribute('lat'));
                $lon = $this->proteger($node->getAttribute('lon'));
                $this->noeuds[] = array($noeud_id, $lat, $lon);
        }

        private function insererRelationsCommunes() {
                $requete =      'INSERT INTO osm_relations (id_relation, nom, code_insee) '.
                                        'VALUES '.$this->creerValuesMultiple($this->relations_communes);
                $this->inserer($requete);
                $this->relations_communes = array();
        }

        private function insererRelationAChemins() {
                $requete =      'INSERT INTO osm_relation_a_chemins (id_relation, id_chemin, role) '.
                                        'VALUES '.$this->creerValuesMultiple($this->relation_a_chemins);
                $this->inserer($requete);
                $this->relation_a_chemins = array();
        }

        private function insererCheminANoeuds() {
                $requete =      'INSERT INTO osm_chemin_a_noeuds (id_chemin, id_noeud, ordre) '.
                                        'VALUES '.$this->creerValuesMultiple($this->chemin_a_noeuds);
                $this->inserer($requete);
                $this->chemin_a_noeuds = array();
        }

        private function insererNoeuds() {
                $requete = 'INSERT INTO osm_noeuds (id_noeud, lat, `long`) '.
                           'VALUES '.$this->creerValuesMultiple($this->noeuds);
                $this->inserer($requete);
                $this->noeuds = array();
        }

        /**
         * Fonction qui rajoute l'ordre et le sens de chaque way d'une relation dans la table `osm_relation_a_chemins`
         * ALGO:
         * -On fait un select de toutes les ways d'une relation.
         * -On fait un count sur le tableau ways resutlant.
         * -On met l'ordre du premier Way à 0.
         * -On met : Actuelway = id_premier_way
         * -Select dans table nodes, les nodes du way actuel
         * -On prend le dernier noeud
         * -On met : ActuelNoeud = id_dernier_noeud
         * -Boucle for (i = 0; i < count(tabeau_way); i++) { sur le nombre de ways
         *              -On sélectionne id_way suivant qui contient le dernier_noeud du précédent
         *              (En écartant l'id_way déja existant )
         *              -On recherche les noeuds du nouveau way
         *              -On teste sur les extrémités du way précédent(dernier noeud) et suivant(premier noeud)
         *              -si égalité: $nombrePolygone=1;
         *                      -sens:directe
         *                      -ordre++
         *                      -ActuelNoeud = id_dernier_noeud
         *              sinon
         *                      -sens:indirecte
         *              -ordre++
         *                      -ActuelNoeud = id_premier_noeud
         * }
         */
        private function ordonnerWays() {
                $requete = 'SELECT DISTINCT id_relation '.
                                        'FROM osm_relation_a_chemins ';
        $relations = $this->bdd->recupererTous($requete);
        foreach ($relations as $relation) {
                $idRelation = $relation['id_relation'];
                        $requete =      'SELECT id_chemin '.
                                        'FROM osm_relation_a_chemins '.
                                        "WHERE id_relation = $idRelation";
                        $ways = $this->bdd->recupererTous($requete);
                $nombreWays = count($ways);
                        // premier élément du tableau
                $idPremierWay = $ways[0]['id_chemin'];
                        $wayActuel  = $idPremierWay;
                        $requete = 'UPDATE  osm_relation_a_chemins '.
                                                'SET  ordre =  0,  sens =  "directe" '.
                                                "WHERE  id_relation = $idRelation ".
                                                "AND  id_chemin = $wayActuel ";
                        $this->inserer($requete);
                        // selection dernier noeud
                        $requete = 'SELECT id_noeud '.
                                                'FROM osm_chemin_a_noeuds '.
                                                "WHERE id_chemin = $wayActuel ORDER BY ordre";
                        $nodes = $this->bdd->recupererTous($requete);
                        $nombreNodes = count($nodes);
                        $dernierNoeud = $nodes[$nombreNodes - 1]['id_noeud'];
                        $noeudActuel = $dernierNoeud;
                        for ($ordre = 1; $ordre < $nombreWays; $ordre++) {
                                //selectionner le way qui possède le dernier noeud du précédent way et écarter l'actuel
                                $requete = 'SELECT WN.id_chemin '.
                                                        'FROM osm_relation_a_chemins AS RW LEFT JOIN osm_chemin_a_noeuds AS WN ON (RW.id_chemin = WN.id_chemin) '.
                                                        "WHERE WN.id_noeud = $noeudActuel ".
                                                        "AND WN.id_chemin != $wayActuel ".
                                                        "AND RW.id_relation = $idRelation ";
                                $ways = $this->bdd->recupererTous($requete);
                                if (isset($ways[0])) {
                                        $wayActuel =  $ways[0]['id_chemin'];
                                        $requete = 'SELECT id_noeud '.
                                                                'FROM osm_chemin_a_noeuds '.
                                                                "WHERE id_chemin = $wayActuel ORDER BY ordre ";
                                        $nodes = $this->bdd->recupererTous($requete);
                                        $nombreNodes = count($nodes);
                                        if ( strcmp($nodes[0]['id_noeud'], $noeudActuel ) == 0 ) {
                                                $requete = 'UPDATE osm_relation_a_chemins '.
                                                                        "SET ordre = '$ordre', sens = 'directe' ".
                                                                        "WHERE id_relation = $idRelation ".
                                                                        "AND id_chemin = $wayActuel ";
                                                $this->inserer($requete);
                                                $noeudActuel = $nodes[$nombreNodes-1]['id_noeud'];
                                        } else {
                                                $requete = 'UPDATE osm_relation_a_chemins '.
                                                                        "SET ordre = '$ordre', sens = 'indirecte' ".
                                                                        "WHERE id_relation = $idRelation ".
                                                                        "AND id_chemin = $wayActuel";
                                                $this->inserer($requete);
                                                $noeudActuel = $nodes[0]['id_noeud'];
                                        }
                                }
                        }
        }
        }

        /**
         * 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`
         */
        private function remplirPolygone() {
                $polygone = array();
                $idNodes = array();
                $String = '';
        $requete = 'SELECT id_relation, nom, code_insee FROM osm_relations ';
        $relations = $this->bdd->recupererTous($requete);
        foreach ($relations as $relation) {
                $idCommune = $relation['id_relation'];
                        $nomCommune = $relation['nom'];
                $INSEE = $relation['code_insee'];
                $requete = 'SELECT id_chemin FROM osm_relation_a_chemins '.
                                        "WHERE id_relation = $idCommune ".
                                        'ORDER BY ordre';
                        $ways = $this->bdd->recupererTous($requete);
                    foreach ($ways as $way) {
                        $idWay = $way['id_chemin'];
                        $requeteSensWay= "SELECT sens FROM osm_relation_a_chemins WHERE id_relation = $idCommune
                                                         AND id_chemin = $idWay";
                                $sens = $this->bdd->recupererTous($requeteSensWay);
                        $requeteNodes = "SELECT id_noeud FROM osm_chemin_a_noeuds WHERE id_chemin= $idWay ORDER BY ordre ";
                                $nodes = $this->bdd->recupererTous($requeteNodes);
                                if($sens[0]['sens'] == "directe") {
                                foreach ($nodes as $node) {
                                                $idNodes[] = $node['id_noeud'];
                                }
                                $noeuds = implode(", ", $idNodes);
                                //requête IN qui gère l'ordre des noeuds de chaque way (CAS ASC)
                                        $requeteLatitudeLongitude = 'SELECT NLL.id_noeud, NLL.lat, NLL.`long` '.
                                                                                                'FROM osm_chemin_a_noeuds WN, osm_noeuds NLL '.
                                                                                                "WHERE NLL.id_noeud IN ($noeuds) ".
                                                                                                'AND WN.id_noeud = NLL.id_noeud '.
                                                                                                "AND WN.id_chemin = $idWay ORDER BY WN.ordre ASC";
                                        unset($noeuds);
                                        unset($idNodes);
                                        $LatLons = $this->bdd->recupererTous($requeteLatitudeLongitude);
                                foreach ($LatLons as $LatLon) {
                                                $Latitude = $LatLon['lat'];
                                                    $Longitude = $LatLon['long'];
                                                        $String = "$Latitude $Longitude";
                                                        $polygone[] = $String;
                                }
                                } else {
                                        foreach ($nodes as $node) {
                                                $idNodes[] = $node['id_noeud'];
                                }
                                $noeuds = implode(", ", $idNodes);
                                //requête IN qui gère l'ordre des noeuds de chaque way (CAS DESC)
                                $requeteLatitudeLongitude = 'SELECT NLL.id_noeud, NLL.lat, NLL.`long` '.
                                                                                    'FROM osm_chemin_a_noeuds WN ,osm_noeuds NLL '.
                                                                                    "WHERE NLL.id_noeud IN ($noeuds) ".
                                                                                    'AND WN.id_noeud = NLL.id_noeud '.
                                                                                    "AND WN.id_chemin = $idWay ORDER BY WN.ordre DESC";
                                        unset($noeuds);
                                        unset($idNodes);
                                        $LatLons = $this->bdd->recupererTous($requeteLatitudeLongitude);
                                        foreach ($LatLons as $LatLon) {
                                        $Latitude = $LatLon['lat'];
                                                $Longitude = $LatLon['long'];
                                                $String = "$Latitude $Longitude";
                                        $polygone[] = $String;
                                        }
                                }
            }
                        $this->etatPolygone($polygone, $idCommune, $nomCommune, $INSEE);
                        unset($separationVirgule);
                                unset($requeteNodes);
                                unset($String);
                                unset($polygone);
                }
        }

        private function etatPolygone($polygone, $idCommune, $nomCommune, $INSEE) {
                        $separationVirgulePolygone = implode(', ', $polygone);
                        $nomCommuneProtege = $this->bdd->proteger($nomCommune);
                        $InseeProtege = $this->bdd->proteger($INSEE);
                        if ($polygone[0] == $polygone[count($polygone)-1]) { //test sur début et fin du polygone
                                //requête replace pour gérer la mise à jour à la suite
                                $requete = 'REPLACE INTO osm_communes (id_relation, nom, code_insee, polygon, note ) '.
                                                   "VALUES ($idCommune, $nomCommuneProtege, $InseeProtege, ".
                                                   "POLYFROMTEXT('MULTIPOLYGON ((($separationVirgulePolygone)))'),'Polygone complet');";
                        } else {
                                $requete = 'REPLACE INTO osm_communes (id_relation, nom, code_insee, polygon, note ) '.
                                                   "VALUES ($idCommune, $nomCommuneProtege, $InseeProtege, ".
                                                   "POLYFROMTEXT('MULTIPOLYGON ((($separationVirgulePolygone)))'),'Polygone incomplet');";
                        }
                        $this->inserer($requete);
        }

        //Fonction qui remet à zéro l'ordre des ways des communes des polygones incomplets fait précédement
        private function remettreOrdreAZero() {
                $requeteRelations = "SELECT id_relation FROM osm_communes WHERE note LIKE 'Polygone incomplet'";
        $relations = $this->bdd->recupererTous($requeteRelations);
        foreach ($relations as $relation) {
                $idRelation = $relation['id_relation'];
                $requeteWays = "SELECT id_chemin FROM osm_relation_a_chemins WHERE id_relation= $idRelation";
                        $ways = $this->bdd->recupererTous($requeteWays);
                        foreach ($ways as $way) {
                                $idWay = $way['id_chemin'];
                                $this-> inserer('UPDATE osm_relation_a_chemins SET ordre = NULL '.
                                                                "WHERE id_relation = $idRelation AND id_chemin = $idWay ;");
                        }
                }

        }

        /**
         * Fonction qui récupère les relations des polygones incomplets et appelle pour chaque relation la fonction
         * ordonnerPolygoneIncomplet($ordre,$tour,$idRelation,$nombrePolygone)
         */
        private function relationsPolygoneIncomplet($ordre, $tour) {
                $nombrePolygone = 1;
                $requeteRelations = "SELECT id_relation FROM osm_communes WHERE note LIKE 'Polygone incomplet'";
                $relations = $this->bdd->recupererTous($requeteRelations);
            foreach ($relations as $relation) {
                        $nombrePolygone = 1;
                $idRelation = $relation['id_relation'];
                $this->ordonnerPolygoneIncomplet($ordre,$tour,$idRelation,$nombrePolygone);
            }
        }

        /**
         * 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 ordonnerPolygoneIncomplet($ordre, $tour, $idRelation, $nombrePolygone) {
                $requeteWays = 'SELECT id_chemin FROM osm_relation_a_chemins '.
                                                "WHERE id_relation = $idRelation AND ordre = 'NULL'";
                $ways = $this->bdd->recupererTous($requeteWays);
                $tempWays = $ways;
                $nombreWays = count($ways);
                // premier élément du tableau
        $idPremierWay = $ways[0]['id_chemin'];
                $wayActuel = $idPremierWay;
                $this-> inserer('UPDATE osm_relation_a_chemins '.
                                                 "SET ordre = $ordre, sens = 'directe', nbre_poly = $nombrePolygone ".
                                                 "WHERE id_relation = $idRelation ".
                                                 "AND id_chemin = $wayActuel ;");
                //selection dernier noeud
                $requeteNodes = "SELECT id_noeud FROM osm_chemin_a_noeuds WHERE id_chemin = $wayActuel ORDER BY ordre;";
                $nodes = $this->bdd->recupererTous($requeteNodes);
                $nombreNodes = count($nodes);
                $premierNoeud = $nodes[0]['id_noeud'];
                $dernierNoeud = $nodes[$nombreNodes-1]['id_noeud'];
                $noeudActuel = $dernierNoeud;
                $tour++;
                //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) < count($tempWays))) {
                        //select le way qui possède le dernier noeud du précédent way et écarter l'actuel
                        $nombrePolygone;
                        $ordre++;
                        //select des ways qui n'ont pas été ordonnés: on obtient à chaque itération les ways qui restent à ordonner
                        $requeteWays = 'SELECT WN.id_chemin FROM (osm_chemin_a_noeuds WN, osm_relation_a_chemins RW) '.
                                                   "WHERE WN.id_noeud = $noeudActuel AND WN.id_chemin != $wayActuel ".
                                                   "AND RW.id_chemin = WN.id_chemin AND RW.id_relation = $idRelation ".
                                                   "AND RW.ordre = 'NULL' ;";
                        $ways = $this->bdd->recupererTous($requeteWays);

                        if (isset($ways[0])) {
                                $wayActuel = $ways[0]['id_chemin'];
                                $requeteNodes = "SELECT id_noeud FROM osm_chemin_a_noeuds WHERE id_chemin = $wayActuel ORDER BY ordre;";
                                $nodes = $this->bdd->recupererTous($requeteNodes);
                                $nombreNodes = count($nodes);
                                if (strcmp($nodes[0]['id_noeud'], $noeudActuel ) == 0) {
                                        $this-> inserer("UPDATE osm_relation_a_chemins SET ordre = '$ordre', sens = 'directe', ".
                                                                        "nbre_poly = $nombrePolygone ".
                                                                        "WHERE osm_relation_a_chemins.id_relation = $idRelation ".
                                                                "AND osm_relation_a_chemins.id_chemin = $wayActuel");
                                        $noeudActuel = $nodes[$nombreNodes-1]['id_noeud'];
                                } else {
                                        $this-> inserer('UPDATE osm_relation_a_chemins '.
                                                                        "SET ordre = '$ordre', sens = 'indirecte', ".
                                                                        "nbre_poly = $nombrePolygone ".
                                                                "WHERE id_relation = $idRelation ".
                                                                "AND id_chemin = $wayActuel");
                                        $noeudActuel = $nodes[0]['id_noeud'];
                                }
                        }
                }
                $ordre = 1000 * $tour; //différencier chaque polygone: pour chaque polygone on a un multiple de mille
                $requeteCount = "SELECT ordre FROM osm_relation_a_chemins WHERE id_relation = $idRelation AND ordre = 0";
                $count = $this->bdd->recupererTous($requeteCount);
                if ((count($count)) != 0) { // s'ils en restent des ways à gérer
                        $nombrePolygone++;
                        //appelle de la fonction récursive
                        $this->ordonnerPolygoneIncomplet($ordre, $tour, $idRelation, $nombrePolygone);
                }
        }

        /**
         * Fonction qui récupère les relations des polygones incomplets et appelle pour chaque relation la fonction
         * remplirPolygoneIncomplet($idRelation);
         */
        private function remplirCommunesPolygoneIncomplet() {
                $nombrePolygone = 1;
                $requeteRelations = "SELECT id_relation FROM osm_communes WHERE note LIKE 'Polygone incomplet'";
                $relations = $this->bdd->recupererTous($requeteRelations);
            foreach ($relations as $relation) {
                        $idRelation = $relation['id_relation'];
                                $this->remplirPolygoneIncomplet($idRelation);//appel de la fonction avec comme paramètre ID-commune
            }
        }

        /**
         * 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é et appelle la fonction
         * etatMultiPolygone($multiPolygone, $idCommune) qui remplie le Multipolygone de la commune correspondante
         */
        private function remplirPolygoneIncomplet($idCommune) {
                $polygone = array();
                $multiPolygone = array();//tableau multipolygone qui contient tous les polygones d'un multipolygone
                $idNodes = array();
                $roles = array();//tableau roles qui contient les roles des ways
                $String = "";
                //sélectionner le nombre de polygones qui existe dans un multipolygone
                $requete = 'SELECT MAX(nbre_poly) AS nbre_poly '.
                                        'FROM osm_relation_a_chemins '.
                                        "WHERE id_relation = $idCommune";
        $nombrePolygone = $this->bdd->recupererTous($requete);
        $nbPoly = $nombrePolygone[0]['nbre_poly'];
                for ($tour = 1; $tour <= $nbPoly; $tour++) {//boucle for qui parcourt chaque polygone du multipolygone
                $requeteWays =  'SELECT id_chemin FROM osm_relation_a_chemins '.
                                                "WHERE id_relation = $idCommune ".
                                                        "AND nbre_poly = $tour ORDER BY ordre";
                    $ways = $this->bdd->recupererTous($requeteWays);
                    foreach ($ways as $way) {
                        $idWay = $way['id_chemin'];
                                $requeteSensWay = 'SELECT sens FROM osm_relation_a_chemins '.
                                                                  "WHERE id_relation = $idCommune ".
                                                          "AND id_chemin = $idWay";//sélection de l'orientation du way
                        $sens= $this->bdd->recupererTous($requeteSensWay);
                        $requeteNodes = "SELECT id_noeud FROM osm_chemin_a_noeuds WHERE id_chemin= $idWay ORDER BY ordre";
                                $nodes = $this->bdd->recupererTous($requeteNodes);
                        if ($sens[0]['sens'] == "directe") {//test sur le sens des ways
                                foreach ($nodes as $node) {
                                                $idNodes[] = $node['id_noeud'];
                                }
                                $noeuds = implode(", ", $idNodes);
                                //requête IN qui gère l'ordre des noeuds de chaque way (CAS ASC)
                                        $requeteLatitudeLongitude = 'SELECT NLL.id_noeud, NLL.lat, NLL.`long` '.
                                                                                                'FROM osm_chemin_a_noeuds WN, osm_noeuds NLL '.
                                                                                                "WHERE NLL.id_noeud IN ($noeuds) ".
                                                                                                'AND WN.id_noeud = NLL.id_noeud '.
                                                                                                "AND WN.id_chemin= $idWay ORDER BY WN.ordre ASC";
                                        unset($noeuds);
                                        unset($idNodes);
                                        $LatLons = $this->bdd->recupererTous($requeteLatitudeLongitude);
                                foreach ($LatLons as $LatLon) {
                                        $Latitude = $LatLon['lat'];
                                            $Longitude = $LatLon['long'];
                                                $String = "$Latitude $Longitude";
                                                $polygone[] = $String;
                                        }
                                } else {
                                        foreach ($nodes as $node) {
                                                $idNodes[] = $node['id_noeud'];
                                }
                                $noeuds = implode(", ", $idNodes);
                                //requête IN qui gère l'ordre des noeuds de chaque way (CAS DESC)
                                $requeteLatitudeLongitude = 'SELECT NLL.id_noeud, NLL.lat, NLL.`long` '.
                                                                                                'FROM osm_chemin_a_noeuds WN, osm_noeuds NLL '.
                                                                                                "WHERE NLL.id_noeud IN ($noeuds) ".
                                                                                                'AND WN.id_noeud = NLL.id_noeud '.
                                                                                                "AND WN.id_chemin= $idWay ORDER BY WN.ordre DESC";
                                        unset($noeuds);
                                        unset($idNodes);
                                        $LatLons = $this->bdd->recupererTous($requeteLatitudeLongitude);
                                        foreach ($LatLons as $LatLon) {
                                        $Latitude = $LatLon['lat'];
                                                $Longitude = $LatLon['long'];
                                                $String = "$Latitude $Longitude";
                                        $polygone[] = $String;
                                        }
                                }
                        }
                        $requeteRole = 'SELECT DISTINCT role '.
                                                   'FROM  osm_relation_a_chemins '.
                                                   "WHERE id_relation = $idCommune ".
                                                   "AND nbre_poly = $tour ";
                        $role = $this->bdd->recupererTous($requeteRole);
                        $role = $role[0]['role'];
                        $separationVirgulePolygone = implode(", ", $polygone);
                $multiPolygone[] = $separationVirgulePolygone;
                $roles[] = $role;
                        unset($separationVirgulePolygone);
                        unset($polygone);
                }
                        $this->etatMultiPolygone($multiPolygone, $roles, $idCommune, $nbPoly);//appel de la fonction de remplissage
        }

        /**
         * Remplie le champ polygone à partir du tableau MultiPolygone
         */
        private function etatMultiPolygone($multiPolygone, $roles, $idCommune, $nbPoly) {
                $note = $this->proteger('Polygone complet');
                if ($nbPoly == 2 && ((in_array('inner', $roles)) || (in_array('enclave', $roles)))) {//cas Outer Inner à deux polygones
                        $multiPoly = implode('),(', $multiPolygone);
                        $requete = 'UPDATE osm_communes '.
                                                "SET polygon = MPOLYFROMTEXT('MULTIPOLYGON((($multiPoly)))'), ".
                                        "note = $note ".
                                        "WHERE id_relation = $idCommune ";
                        $this->inserer($requete);
                }
                if ((in_array('inner', $roles)) || (in_array('enclave', $roles)) != 1) { //tous les autres cas
                        $multiPoly = implode(')),((', $multiPolygone);
                        $requete = 'UPDATE osm_communes '.
                                                "SET polygon = MPOLYFROMTEXT('MULTIPOLYGON((($multiPoly)))'), ".
                                "note = $note ".
                                "WHERE id_relation = $idCommune ";
                        $this->inserer($requete);
                }
        }

        /**
         * Renomme la note des polygones vides d'un polygone complet en polygone incomplet
         */
        private function renommerEnPolygoneIncomplet() {
                $requete = 'SELECT id_relation, ASTEXT(polygon) AS poly '.
                                        'FROM osm_communes ';
                $etatPolygones = $this->bdd->recupererTous($requete);
                foreach ($etatPolygones as $etatPolygone ) {
                        if (isset($etatPolygone['poly']) == 0) {//test si le polygone est vide
                                $idCommune = $this->proteger($etatPolygone['id_relation']);
                                $note = $this->proteger('Polygone incomplet');
                                $requete = 'UPDATE osm_communes '.
                                                        "SET note = $note ".
                                                        "WHERE id_relation = $idCommune ";
                                $this->inserer($requete);
                        }
                }
        }


        /**
         * Récupère le point centre de chaque polygone et remplie la colonne "centre"
         */
        private function centroid() {
                $requete = 'SELECT id_relation, ASTEXT(polygon) AS poly '.
                                        'FROM osm_communes ';
                $communes = $this->bdd->recupererTous($requete);
                foreach ($communes as $commune) {
                        $multipolygone = $commune['poly'];
                        $requete = "SELECT ASTEXT(CENTROID(MPOLYFROMTEXT('$multipolygone'))) AS centre ";
                        $point = $this->bdd->recupererTous($requete);
                $centre = $this->proteger($point[0]['centre']);
                $idCom = $this->proteger($commune['id_relation']);
                $requete = 'UPDATE osm_communes '.
                                        "SET centre = POINTFROMTEXT($centre) ".
                                        "WHERE id_relation = $idCom ";
                $this->inserer($requete);
                }
        }

        private function creerValuesMultiple($donnees) {
                $values = array();
                foreach ($donnees as $donnee) {
                        $values[] = implode(',', $donnee);
                }
                $values_chaine = '('.implode('),(', $values).')';
                return $values_chaine;
        }

        private function inserer($requete) {
                $this->bdd->requeter($requete);
        }

        private function proteger($chaine) {
                return $this->bdd->proteger($chaine);
        }

}
?>