IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

transformer variable texte en tableau


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2018
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 76
    Par défaut transformer variable texte en tableau
    Bonjour

    Je cherche à utiliser une fonction qui teste si un point est à l'intérieur d'un polygone. Cette fonction fait appel à un tableau des coordonnées du polygone.
    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $polygon = array("5.386 45.930","5.374 45.936","5.372 45.943","5.344 45.950","5.386 45.930");
    Je récupère les coordonnées du polygone à partir d'un champ d'une base MySQL et je les mets en forme avec les bons séparateurs : coordonnées entourées de guillemets, espace entre longitude et latitude, virgule entre les couples de coordonnées.
    J'obtiens alors une variable $kml_commune qui contient apparemment les bonnes infos : quand je fais un echo $kml_commune, j'obtiens bien "5.386 45.930","5.374 45.936","5.372 45.943","5.344 45.950","5.386 45.930".

    Pour créer mon tableau $polygon, je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $polygon=explode(",",$kml_commune);
    Mais si je teste la fonction avec ce $polygon créé à partir de la variable, aucun point d'exemple n'est renvoyé alors que les mêmes exemples fonctionnent si je tape la chaîne en rentrant les valeurs manuellement dans le tableau.

    Quelque chose m'échappe mais je ne vois pas quoi !

    Merci d'avance pour votre aide

  2. #2
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 499
    Billets dans le blog
    1
    Par défaut
    Bonsoir, merci de donner le code complet et l'exemple manuel.

  3. #3
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2018
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 76
    Par défaut
    Voici le code de la fonction et de son appel

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    // fonctions
    class pointLocation {
        var $pointOnVertex = true; // Vérifier si le point est exactement sur un sommet ?
     
        function pointLocation() {
        }
     
            function pointInPolygon($point, $polygon, $pointOnVertex = true) {
            $this->pointOnVertex = $pointOnVertex;
     
            // Transformer chaque couple de coordonnées en un tableau de 2 valeurs (x et y)
            $point = $this->pointStringToCoordinates($point);
            $vertices = array(); 
            foreach ($polygon as $vertex) {
                $vertices[] = $this->pointStringToCoordinates($vertex); 
            }
     
            // Vérfier si le point est exactement sur un sommet
            if ($this->pointOnVertex == true and $this->pointOnVertex($point, $vertices) == true) {
                return "vertex";
            }
     
            // Vérifier si le point est dans le polygone ou sur le bord
            $intersections = 0; 
            $vertices_count = count($vertices);
     
            for ($i=1; $i < $vertices_count; $i++) {
                $vertex1 = $vertices[$i-1]; 
                $vertex2 = $vertices[$i];
                if ($vertex1['y'] == $vertex2['y'] and $vertex1['y'] == $point['y'] and $point['x'] > min($vertex1['x'], $vertex2['x']) and $point['x'] < max($vertex1['x'], $vertex2['x'])) { 
    			// Vérifier si le point est sur un bord horizontal
                    return "boundary";
                }
                if ($point['y'] > min($vertex1['y'], $vertex2['y']) and $point['y'] <= max($vertex1['y'], $vertex2['y']) and $point['x'] <= max($vertex1['x'], $vertex2['x']) and $vertex1['y'] != $vertex2['y']) { 
                    $xinters = ($point['y'] - $vertex1['y']) * ($vertex2['x'] - $vertex1['x']) / ($vertex2['y'] - $vertex1['y']) + $vertex1['x']; 
                    if ($xinters == $point['x']) { 
    				// Vérifier si le point est sur un bord (autre qu'horizontal)
                        return "boundary";
                    }
                    if ($vertex1['x'] == $vertex2['x'] || $point['x'] <= $xinters) {
                        $intersections++; 
                    }
                } 
            } 
            // Si le nombre de bords par lesquels on passe est impair, le point est dans le polygone. 
            if ($intersections % 2 != 0) {
                return "inside";
            } else {
                return "outside";
            }
        }
     
        function pointOnVertex($point, $vertices) {
            foreach($vertices as $vertex) {
                if ($point == $vertex) {
                    return true;
                }
            }
        }
     
        function pointStringToCoordinates($pointString) {
            $coordinates = explode(" ", $pointString);
            return array("x" => $coordinates[0], "y" => $coordinates[1]);
        }
    }
     
    // mise en forme du polygone pour Ambérieu
    // les coordonnées du polygone sont stockées dans la base MySQL sous un format que je ne peux pas changer, il est utilisé dans de nombreuses autres pages
    // d'où les 3 lignes ci-dessous qui reformatent les coordonnées au format correspondant à l'attente de la fonction
    $req_kml = mysql_query("SELECT kml from communes WHERE insee='01004'",$conn);
    $kml_commune=str_replace(" ",";",mysql_result($req_kml,0,"kml"));
    $kml_commune=str_replace(","," ",$kml_commune);
    $kml_commune='"'.str_replace(';','","',$kml_commune).'"';
    //echo "polygone Amberieu formaté : ".$kml_commune."<br>";
     
    // appel de la fonction
    $pointLocation = new pointLocation();
    $points = array("6.7 45.4","6.56 45.39","6.77 45.48","6.74 45.47","5.34 45.96");
    $polygon=explode(",",$kml_commune);
    foreach($points as $key => $point) {
        echo "point " . ($key+1) . " ($point): " . $pointLocation->pointInPolygon($point, $polygon) . "<br>";
    }
    Ce code renvoie "outside" pour les 5 points de mon exemple de tableau $points alors que le 5ème point est dans le polygone

    Si je remplace la ligne 80
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $polygon=explode(",",$kml_commune);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $polygon = array("5.386190824025674 45.930927620631998","5.37433362175824 45.93679872108094","5.372314932961313 45.943291506642979","5.344968809766297 45.950681267601539","5.341280890273498 45.948388288135007","5.327335447177313 45.95669381885147","5.33065840754396 45.974471972832923","5.337615969823886 45.984049105732254","5.34747373307215 45.982475822038559","5.378274484108938 45.974238488584945","5.396285345268097 45.978372251369102","5.396959702283464 45.981691335107854","5.413533405897647 45.978897797149479","5.408819757268224 45.942060791465344","5.3942627999284 45.939901273042416","5.386190824025674 45.930927620631998");
    qui sont les valeurs que la requete extrait de la base MySQL, la fonction renvoie bien "inside" pour le 5ème point

  4. #4
    Membre Expert
    Avatar de laurentSc
    Homme Profil pro
    Webmaster débutant perpétuel !
    Inscrit en
    Octobre 2006
    Messages
    10 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster débutant perpétuel !
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2006
    Messages : 10 499
    Billets dans le blog
    1
    Par défaut
    désolé, mon wampserver est en PHP7 et la fonction mysql_query a été supprimée et j'ai pas le courage de tout convertir en PDO (de plus, il faudrait aussi la bdd).
    Pour déboguer, je mettrais un var_dump($polygon); après la ligne 80 (si tu ne l'as pas déjà fait)

  5. #5
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2018
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 76
    Par défaut
    Je n'avais pas essayé le var_dump : il montre que mes str_replace encadrait les coordonnées de guillemets qui étaient ensuite doublés (par le explode, je pense)
    J'ai supprimé de la ligne 74 les ajouts de guillemets et ça semble fonctionner.
    Je teste la suite demain mais déjà, un grand merci pour l'idée !

  6. #6
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    salut,

    j'ai repris ton code avec une version plus actuelle PHP 7+
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    // fonctions
    class PointLocation
    {
        private $point_on_vertex = true; // Vérifier si le point est exactement sur un sommet ?
     
        public function pointInPolygon($point, $polygon, bool $point_on_vertex = true)
        {
            $this->point_on_vertex = $point_on_vertex;
     
            [$x, $y] = explode(' ', $point);
     
            $vertices = [];
            foreach ($polygon as $vertex) {
                $vertices[] = array_combine(['x', 'y'], explode(' ', $vertex));
            }
     
            // Vérfier si le point est exactement sur un sommet
            if ($this->point_on_vertex) {
                foreach ($vertices as list($vx, $vy)) {
                    if (($x === $vx) && ($y === $vy)) {
                        return 'vertex';
                    }
                }
            }
     
            // Vérifier si le point est dans le polygone ou sur le bord
            $intersections = 0;
            $vertices_count = count($vertices);
     
            for ($i = 1 ; $i < $vertices_count ; ++$i) {
                $v1 = $vertices[$i-1];
                $v2 = $vertices[$i];
     
                if ($v1['y'] === $v2['y'] && $v1['y'] === $y && $x > min($v1['x'], $v2['x']) && $x < max($v1['x'], $v2['x'])) {
                    // Vérifier si le point est sur un bord horizontal
                    return 'boundary';
                }
     
                if ($y > min($v1['y'], $v2['y']) && $y <= max($v1['y'], $v2['y']) && $x <= max($v1['x'], $v2['x']) && $v1['y'] != $v2['y']) {
                    $xinters = ($y - $v1['y']) * ($v2['x'] - $v1['x']) / ($v2['y'] - $v1['y']) + $v1['x'];
                    if ($xinters === $x) {
                        // Vérifier si le point est sur un bord (autre qu'horizontal)
                        return 'boundary';
                    }
                    if ($v1['x'] == $v2['x'] || $x <= $xinters) {
                        ++$intersections;
                    }
                }
            }
            // Si le nombre de bords par lesquels on passe est impair, le point est dans le polygone.
            return ($intersections % 2 === 0) ? 'outside' : 'inside';
        }
    }
    et chez moi voici ce que j'obtiens :
    Pour ce jeu de paramètres en entrée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $pointLocation = new PointLocation();
    $kml_commune   = '"5.386 45.930","5.374 45.936","5.372 45.943","5.344 45.950","5.386 45.930"';
    $points        = ["6.7 45.4","6.56 45.39","6.77 45.48","6.74 45.47","5.34 45.96"];
    $polygon       = explode(',', $kml_commune);
    point 1 (6.7 45.4): outside<br>point 2 (6.56 45.39): outside<br>point 3 (6.77 45.48): outside<br>point 4 (6.74 45.47): outside<br>point 5 (5.34 45.96): outside<br>
    Pour ce jeu de paramètres en entrée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $pointLocation = new PointLocation();
    $kml_commune   = '"5.386 45.930","5.374 45.936","5.372 45.943","5.344 45.950","5.386 45.930"';
    $points        = ["6.7 45.4","6.56 45.39","6.77 45.48","6.74 45.47","5.34 45.96"];
    $polygon = [
        '5.386190824025674 45.930927620631998',
        '5.37433362175824 45.93679872108094',
        '5.372314932961313 45.943291506642979',
        '5.344968809766297 45.950681267601539',
        '5.341280890273498 45.948388288135007',
        '5.327335447177313 45.95669381885147',
        '5.33065840754396 45.974471972832923',
        '5.337615969823886 45.984049105732254',
        '5.34747373307215 45.982475822038559',
        '5.378274484108938 45.974238488584945',
        '5.396285345268097 45.978372251369102',
        '5.396959702283464 45.981691335107854',
        '5.413533405897647 45.978897797149479',
        '5.408819757268224 45.942060791465344',
        '5.3942627999284 45.939901273042416',
        '5.386190824025674 45.930927620631998'
    ];
    point 1 (6.7 45.4): outside<br>point 2 (6.56 45.39): outside<br>point 3 (6.77 45.48): outside<br>point 4 (6.74 45.47): outside<br>point 5 (5.34 45.96): inside<br>
    Les points de ton polygone diffèrent d'un jeu à l'autre alors la différence de résultat n'est pas aberrante.

  7. #7
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2018
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 76
    Par défaut
    Merci pour ce test.
    Dans mon premier exemple, j'avais simplifié un peu le polygone pour ne pas alourdir mais, dans le second, il s'agit bien des coordonnées réelles du polygone qui représente la commune d'Ambérieu.
    Le point 5 était bien à l'intérieur du polygone (plein centre ville) mais la fonction renvoyait quand même "outside"
    Comme je l'ai vu hier soir avec le var_dump, sur les conseils de Laurent, ça venait sans doute du "str_replace" ou j'ajoutais des guillemets, ce qui rendait le polygone invalide et tous les points étaient outside
    Désormais ça marche bien
    Merci à tous les deux

  8. #8
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    par contre garde ma version de code, l'autre est méchamment obsolète.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WD-MAC 2011] Transformer texte en tableau
    Par Marco777 dans le forum Word
    Réponses: 3
    Dernier message: 27/04/2013, 01h37
  2. Transformer addresse mac texte en tableau d'octets
    Par dedibox26 dans le forum Débuter
    Réponses: 3
    Dernier message: 20/05/2010, 17h34
  3. [MySQL] transformer full text en tableau
    Par gtraxx dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 06/08/2009, 11h38
  4. Transformation d'un tableau html en CSS
    Par titou250 dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 27/09/2005, 16h55
  5. Réponses: 1
    Dernier message: 28/03/2005, 12h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo