Il Bar dell'Ingegneria

Algoritmi: Punto interno o esterno ad un poligono

« Older   Newer »
 
  Share  
.
  1.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    Si hai ragione di dubitare, ma in realtà quel codice li è già collaudato da alcuni anni e funziona a dovere.
    In realtà le semirette utilizzate sono quattro, due orizzontali e due verticali e con la logica di controllo finale vengono considerati anche i casi particolari da te segnalati.
    provare per credere.

    Edited by texitaliano64 - 26/4/2013, 09:14
     
    Top
    .
  2.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (texitaliano64 @ 26/4/2013, 00:20) 
    Si hai ragione di dubitare, ma in realtà quel codice li è già collaudato da alcuni anni e funziona a dovere.
    In realtà le semirette utilizzate sono quattro, due orizzontali e due verticali e con la logica di controllo finale vengono considerati anche i casi particolari da te segnalati.
    provare per credere.

    Nell'ultimo esempio che ho riportato, sono riportate le quattro semirette a cui ti riferisci e per tutte e quattro si contano 2 intersezioni, essendo pari, la funzione dovrebbe restituire come risultato "punto esterno" [ed invece è interno]

    Se tu dici che funziona ed è testato da anni, posso solo farne motivo di fede, ma...
     
    Top
    .
  3.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    Allego uno screen shot autentico, e non frutto di fotoritocco, dell'applicazione che ne fa uso.

    Uploaded with ImageShack.us

    Edited by texitaliano64 - 22/11/2013, 19:59
     
    Top
    .
  4.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    Codice di un algoritmo simile a quanto già visto trovato nel web di nome Inside.c

    CODICE
    #define ZERO     1e-8
    #define PERTURB  1e-6

    #define P_ABS(x) (((x) > 0) ? (x) : (-(x)))

    /*
    * This function determines, whether the 'node' lies inside or
    * outside of the polygon, which is given in 'list'.
    * There 'n' nodes in 'list'.
    * The coordinates are given in 'Coords'.
    *
    * The function assumes, that there are no two nodes which are as
    * close to each other as PERTURB !!!
    *
    * It uses the ray-tracing method. From the given node it draws a
    * horizontal line to the right. It counts how many intersection
    * occurs. If a node would lie exactly on the ray, then the node
    * is moved up a little bit (perturbed). If the 'TO_BE_SURE_CHECK'
    * macro is defined the function will check that the length of the
    * boundary edges are bigger than the perturbation value 'PERTURB'.
    * This check is for the insane. :-)
    *
    * Returns:  1 - node is inside
    *           0 - node is outside
    *          -1 - node is part of the list, better to chooose another node
    */

    int Check2DNodeInside(double **Coords, int n, int *list,
                         int node, double x, double y)
    {
     int    j;
     double a, b; /* parameters of the line which is formed by an edge */
     double ix;   /* x coord. of the intersection point of a segment and the ray */
     double px, py, cx, cy; /* segment nodes, previous, current */
     int    ci; /* counts intersections */
     
     /* start with the last node */
     px = Coords[list[n-1]-1][0];
     py = Coords[list[n-1]-1][1];

     /* nodes are identical */
     if(P_ABS(y-py) < ZERO && P_ABS(x-px) < ZERO)
       return 1;

     /* check whether the node lies on the trace exactly */
     if(P_ABS(y-py) < ZERO)
     {
       /* then we have to perturb it */
       py += PERTURB;
     }

     ci = 0;
     for(j = 0; j < n; j++)
     {
       /* if the nodes are identical, quit */
       if(node == list[j])
         break;

       cx = Coords[list[j]-1][0];
       cy = Coords[list[j]-1][1];

    #ifdef TO_BE_SURE_CHECK
       {
         double ll;
         ll = sqrt((cx - px)*(cx - px) + (cy - py)*(cy - py));
         if(ll <= PERTURB)
           e_GeneralError("Check2DNodeInside: Boundary edge is smaller than PERTURB !");
       }
    #endif

       /* nodes are identical */
       if(P_ABS(y-py) < ZERO && P_ABS(x-px) < ZERO)
         return 1;

       /* check whether current node lies on the trace exactly */
       if(P_ABS(y-cy)  < ZERO)
       {
         /* then we have to perturb it */
         cy += PERTURB;
       }
         
       /* vertical line ? */
       if(P_ABS(cx-px) > ZERO) /* no */
       {
         /* horizontal line ? */
         if(P_ABS(cy-py) > ZERO) /* no, general case */
         {
           a = (cy-py) / (cx-px);
           b = cy - a * cx;
           ix = (y - b) / a;
         }
         else /* yes */
         {
           /* side is horizontal there cannot be intersection then */
           ix = x-1;
         }
       }
       else /* yes */
       {
         ix = cx;
       }
         
       /* only nodes on the left hand side are counted */
       if(ix > x)
       {
         /* this is the general case */
         if(   ((py < y) && (y < cy))
            || ((cy < y) && (y < py)) )
         {
           ci++;
         }
       }
         
       px = cx;
       py = cy;
     }

     if(j == n)
     {
       return(ci % 2);
     }
     else
       return -1;
    }
     
    Top
    .
  5.     +1   -1
     
    .
    Avatar

    Junior Member

    Group
    Member
    Posts
    6
    Reputation
    0

    Status
    Offline
    Ciao, rileggevo questa interessante discussione e quella del 2006.
    Il mio obiettivo è quello di scrivere un codice in excel che i consenta, data una serie di punti di coordinate note (lat. e long.) di capire se ognuno di questi appartenga ad un dato poligono definito da N vertici di coordinate note.
    Leggevo che qualcuno aveva già implementato in excel un problema del genere. Potreste aiutarmi?
    Grazie
     
    Top
    .
  6.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    304
    Reputation
    0

    Status
    Offline
    CITAZIONE (afazio @ 21/8/2012, 12:07) 
    (IMG:http://imageshack.us/a/img507/7946/inside001.jpg)


    RIleggendo questo vecchio ed appassionate topic ( https://bar-ingegneria.forumfree.it/?t=8970619 ) risalente a qualche anno fa (giugno del 2006), mi sono ricordato di aver letto in questi giorni una pagina di Paul Bourke dove è riportato l'algoritmo che risolve la questione.

    http://paulbourke.net/geometry/insidepoly/

    Prendendo lo spunto da questo algoritmo ho anche pensato di scrivere un codice minimo in VBA per autocad per stabilire se un punto è interno o esterno ad un poligono sfruttando una particolare funzione di alcuni oggetti grafici di Autocad

    Il link alla pagina dovrebbe essere il seguente:

    http://paulbourke.net/geometry/polygonmesh/

    Il precedente potrebbe essere obsoleto. Ciao
     
    Top
    .
  7.     +1   -1
     
    .
    Avatar

    Junior Member

    Group
    Member
    Posts
    6
    Reputation
    0

    Status
    Offline
    Ringraziandoti per l'articolo, ti chiedo se fosse possibile recuperare l'esempio in excel fornito nell'ambito della discussione al seguente link https://bar-ingegneria.forumfree.it/?t=8970619&st=15.
    Infatti l'esempio dovrebbe essere scaricabile ma il link fornito in quella discussione del 2006 risulta non essere più attivo.
     
    Top
    .
21 replies since 21/8/2012, 11:07   4906 views
  Share  
.