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

Algorithmes et structures de données Discussion :

Trouver si un point est dans un polygone


Sujet :

Algorithmes et structures de données

  1. #1
    Membre régulier Avatar de Mucho
    Inscrit en
    Décembre 2005
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 221
    Points : 109
    Points
    109
    Par défaut Trouver si un point est dans un polygone
    Bonjour, bonjour,

    pour trouver si un point est dans un polygone j'aimerai utilisé la méthode qui consiste a faire la somme des angles (voir ici pour explications) mais cet algorithme a pour but d'être implémenté en c++ et je me disais que calculer chaque angle doit prendre pas mal de temps pour beaucoup de polygones.

    Donc, je me demandais si il est possible d'utiliser cette méthode sans calculé complètement chaque angle mais avec des outils plus adapté au calcul par ordinateur (ie en utilisant des matrices ou produits scalaires, vectoriels).

  2. #2
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut
    Bonjour,

    cette question a déjà été posé plusieurs fois sur ce forum.

    Pour ma part, regarder le signe des angles est une très bonne méthode, que j'utilise dans le calcul d'enveloppes convexes...
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  3. #3
    Membre habitué Avatar de larnicebafteur
    Inscrit en
    Mai 2006
    Messages
    133
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 133
    Points : 131
    Points
    131
    S'il n'y a pas de solution, c'est qu'il n'y a pas de problème

  4. #4
    Membre régulier Avatar de Mucho
    Inscrit en
    Décembre 2005
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 221
    Points : 109
    Points
    109
    Par défaut
    Hum en fait non, le titre n'est peut être pas adapté, désolé,

    comme je le disais j'ai déjà la solution je voudrais savoir si il y a des manières efficaces de la réalisée. (cf premier message)

  5. #5
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut
    Bonjour,

    tu dois calculer autant d'angle que de points constituant le polygone. Donc tu es en O(n). C'est tout à fait correcte.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  6. #6
    Expert éminent

    Profil pro
    Fabricant et casseur d'avions
    Inscrit en
    Avril 2004
    Messages
    3 813
    Détails du profil
    Informations personnelles :
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Fabricant et casseur d'avions
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2004
    Messages : 3 813
    Points : 7 638
    Points
    7 638
    Par défaut
    A la limite, tu peux limiter le nombre de polygones à tester en utilisant par exemple un octree (si tu es en 3D, sinon tu fais l'équivalent en 2D, un quadtree).
    Tu testes ensuite dans quelle partie de l'octree se trouve ton point (plus facile et rapide à mon avis de tester si un point est dans un cube), et ensuite de tester uniquement les polygones de cette partie de l'octree.

    Sinon, en 2D, tu peux également définir une boite englobante de ton polygone (qui sera définie en même temps que le polygone, histoire de ne pas la calculer à chaque fois), et déjà tester si ton point est à l'intérieur. Si il y est, tu fais ton test sur les angles, sinon tu passes au polygone suivant.

    Et tu peux aussi coupler les deux, quadtree+boite englobante...
    "Errare humanum est, sed perseverare diabolicum"

    Ma page sur DVP.com

  7. #7
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut
    Bonjour,

    je ne vois pas comment l'octree ( ou le quadtree) peuvent aider efficacement.
    En revanche, la boite englobante pour ne tester que le polygone nécéssaire me semble une très bonne idée...
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  8. #8
    Expert éminent

    Profil pro
    Fabricant et casseur d'avions
    Inscrit en
    Avril 2004
    Messages
    3 813
    Détails du profil
    Informations personnelles :
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Fabricant et casseur d'avions
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2004
    Messages : 3 813
    Points : 7 638
    Points
    7 638
    Par défaut
    Citation Envoyé par ToTo13
    je ne vois pas comment l'octree ( ou le quadtree) peuvent aider efficacement.
    Si tu sais placer ton point dans l'octree (ou le quadtree), tu peux virer un certains nombre de polygones, non? Tous ceux qui ne sont pas dans cette région... Pas la peine de tester la boite englobante si tu sais que ton point est à 3 kilomètres de là...

    C'est le même problème qu'en affichage 3D, on ne va pas aller texturer les quads qui ne sont pas dans le champ de vision... (déjà qu'on les affiche pas...)
    "Errare humanum est, sed perseverare diabolicum"

    Ma page sur DVP.com

  9. #9
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    Voici un petit code en C qui doit apporter la réponse.
    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
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
     
     
     
    #define         Maxs(a, b)      (((a) > (b)) ? (a) : (b))
    #define         Mins(a, b)      (((a) < (b)) ? (a) : (b))
    #define         next(i)         (i+1) % np
    short np;
    struct Crd  Sommets[Max_Sommets];
    struct Crd S1[Max_Sommets+1];
    static short Where_do_we_have_to_insert_point ( double Px, double Py )
       {
       short n1, i_next;
       double D1, D2, d2;
       double P1=1e100;
       for ( short i=0; i < np; i++)
          {
          i_next = next(i);
          // doite allant du point i au point i_next
          double dx, dy;
          dx = Sommets[i_next].x-Sommets[i].x;
          dy = Sommets[i_next].y-Sommets[i].y;
          if ( fabs(dx) < 1e-40) // dx=0 => droite verticale
             {
             double Ud = 0; // on suppose le point entre Yi et Yi_next
             if ( Py > Maxs( Sommets[i_next].y,Sommets[i].y))
                Ud = Py - Maxs( Sommets[i_next].y,Sommets[i].y); // correction si trop haut
             else
             if ( Py < Mins( Sommets[i_next].y,Sommets[i].y))   // correction si trop bas
                Ud = Mins( Sommets[i_next].y,Sommets[i].y) - Ud;
             d2 = sqr(Sommets[i].x-Px) + sqr(Ud);
             }
          else
          if ( fabs(dy) < 1e-40) // dy=0 => droite horizontale
             {
             double Ud = 0;  // on suppose le point ente Xi et Xi_next
             if ( Px > Maxs( Sommets[i_next].x,Sommets[i].x) )
                Ud = Px - Maxs( Sommets[i_next].x,Sommets[i].x); // correction trop à droite
             else
             if ( Px < Mins( Sommets[i_next].x,Sommets[i].x))   //correction trop à gauche
                Ud = Mins( Sommets[i_next].x,Sommets[i].x) - Ud;
             d2 = sqr(Sommets[i].y-Py) + sqr(Ud);
             }
          else // droite oblique y= px + q
             {
             double p, q, al, ax, ay;
             p = dy / dx;
             q = Sommets[i].y - p*Sommets[i].x;
             d2 =sqr(Py - p*Px - q) / (1+ sqr(p)); // distance^2 point droite si elle etait non bornée
             //Point A => A' tel que AA' orthogonal au segment (Pi,Pinext)
             // A' = (Px+al, Py-al/p)
             // si A' est sur la droite (Pi,Pinext) alors
             // Py-al/p= p*(Px+al) + q => al(p+1/p) = Py-q-p*Px
             al = (Py - q - p*Px) / (p + 1/p);  // droite oblique => p !=0 et p != infini, p+1/p toujours !=0 dans R
             // d'où A'(ax,ay)
             ax = Px + al;
             ay = Py - al/p;
             // A' est il entre les 2 extremitées du segment?
             if ((ax-Sommets[i].x)*(ax-Sommets[i_next].x) + (ay-Sommets[i].y)*(ay-Sommets[i_next].y) > 0)
                {
                // produit scalaire > 0 => A' hors de Pi, Pi_next    ( angle =0 => cos=1)
                D1 = sqr(ax - Sommets[i].x) + sqr(ay-Sommets[i].y);
                D2 = sqr(ax - Sommets[i_next].x) + sqr(ay-Sommets[i_next].y);
                d2 += Mins(D1,D2);  // correctif à d2
                }
             }
     
          if ( d2 < P1 )
             {
             P1=d2;
             n1 = i;
             }
          }
       return
          n1;     // on insere entre n1 & n1+1  % np
       }
    double area ( bool b , double Px, double Py)
       {
       if (b)
          {
          double d2 = 0;
          for ( short i=0; i < np; i++)
             d2 += (Sommets[i].y + Sommets[(i+1) % np].y ) * ( Sommets[i].x-Sommets[(i+1)%np].x);
          return
             fabs(d2) / 2;
          }
       else
          {
          short n1;
          n1 = Where_do_we_have_to_insert_point(Px, Py);
          // le point entré est le plus proche du seg  n1, (n1+1)%np)
          if ( n1 >=0 )
          for (short i=0; i <= n1; i++ )
             S1[i] = Sommets[i];
          S1[n1+1].x = Px;
          S1[n1+1].y = Py;
          if ( n1 < np-1 )
          for (short i=n1+1; i < np; i++ )
             S1[i+1] = Sommets[i];
          double d2 = 0;
          for ( short i=0; i <= np; i++)
             d2 += (S1[i].y + S1[(i+1) % (np+1)].y ) * ( S1[i].x-S1[(i+1)%(np+1)].x);
          return
             fabs(d2) / 2;
          }
       }
    double Aire_Polygone(void) // Sommets[0..np-1].x et .y
       {
       double A = area(true,0,0);
       return A;
       }
    bool Inside(double X, double Y) // Sommets[0..np-1].x et .y, on teste le point (X,Y)
       {
       double A = area (false,X, Y);
       double B = Aire_Polygone();
       return
          A <  B;
       }

    Ce qui est le "+ délicat" est d'insérer le point à tester au bon endroit de la liste.
    Pour le reste il n'y a que quelques aditions et multiplications.

    Si on calcul avec des angles, le 1er point reste toujours le même, mais la 2ème phase est certainement plus coûteuse en calculs.



    Petit ajout : J'avais oublié de mettre le fichier .h associé !! <15-09-06>


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    #define Max_Sommets 1000    /* on pourrait imaginer des tableaux dynamiques */
    #define sqr(a)   ((a) * (a))     /* pour a^2 */
    struct Crd   /* coordonnées x,y d'1 point */
       {
       double x,y ;
       };

  10. #10
    Membre régulier Avatar de Mucho
    Inscrit en
    Décembre 2005
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 221
    Points : 109
    Points
    109
    Par défaut
    merci j.p.mignot

    effectivement ca a l'air d'etre ca que je cherchais



    Sinon pour les (quad ou) octree et pour les bounding boxs, effectivement ce sont des solutions que j'avais adoptées et qui sont très efficaces mais ca ne correspondait pas à ma question, en tout cas merci quand même.

  11. #11
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Points : 754
    Points
    754
    Par défaut
    1- vérifier le code : je l'ai écrit 'à la volée'.
    2- Il n'est pas optimisé ( dans différence des aires par intégration de y.dx, un grand nombre d'éléments s'annihilent par 2 ). De même des distances (^2) sont susceptibles d'être calculées 2 fois.
    3- L'algorithme devient faux pour les polygones croisés. Cette situation n'est pas testée

Discussions similaires

  1. [3D] Comment savoir si un point est dans mon champ de vision
    Par patmaba dans le forum Développement 2D, 3D et Jeux
    Réponses: 10
    Dernier message: 04/11/2018, 13h20
  2. Réponses: 14
    Dernier message: 05/04/2012, 14h16
  3. [JavaScript] [Google Maps]Tester si un point est dans un Polygone
    Par NoSmoking dans le forum Contribuez
    Réponses: 1
    Dernier message: 08/08/2011, 17h48
  4. Savoir si un point est dans un polygone.
    Par poly128 dans le forum Langage
    Réponses: 8
    Dernier message: 18/11/2008, 09h34
  5. Savoir si un point est dans la zone affiché
    Par nicoenz dans le forum OpenGL
    Réponses: 6
    Dernier message: 08/12/2006, 15h59

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