9
votes

Trouver des points contenus dans un chemin d'Android

Y a-t-il une raison pour laquelle ils ont décidé de ne pas ajouter la méthode Contient (pour le chemin) dans Android?

Je veux savoir quels points j'ai sur un chemin et espéraient que c'était plus facile que voir ici:

Comment puis-je dire si Un chemin fermé contient un point donné?

serait-il préférable pour moi de créer une arrayliste et d'ajouter les entiers dans le tableau? (Je ne vérifie que les points une fois dans une déclaration de contrôle) c'est-à-dire. si (myPath.Contains (x, y)

Jusqu'à présent, mes options sont:

  • en utilisant une région
  • en utilisant une arrayliste
  • Extension de la classe
  • Votre suggestion

    Je suis juste à la recherche de la manière la plus efficace que je devrais y aller à ce sujet


4 Réponses :


14
votes

Je suis venu contre ce même problème il y a un peu de temps, et après une recherche, j'ai trouvé que ceci comme la meilleure solution.

Java a un Polygon code> classe avec un contient () code> méthode qui rendrait les choses vraiment simples. Malheureusement, la classe java.awt.polygon code> n'est pas prise en charge dans Android. Cependant, j'ai pu trouver quelqu'un qui a écrit un classe équivalente . p>

Je ne pense pas que vous puissiez obtenir les points individuels qui constituent le chemin de la trajectoire Android PATH CODE> , vous devrez donc stocker les données de manière différente. p>

La classe utilise un algorithme de numéro de passage pour déterminer si le point est à l'intérieur de la liste de points donnée. P>

/**
 * Minimum Polygon class for Android.
 */
public class Polygon
{
    // Polygon coodinates.
    private int[] polyY, polyX;

    // Number of sides in the polygon.
    private int polySides;

    /**
     * Default constructor.
     * @param px Polygon y coods.
     * @param py Polygon x coods.
     * @param ps Polygon sides count.
     */
    public Polygon( int[] px, int[] py, int ps )
    {
        polyX = px;
        polyY = py;
        polySides = ps;
    }

    /**
     * Checks if the Polygon contains a point.
     * @see "http://alienryderflex.com/polygon/"
     * @param x Point horizontal pos.
     * @param y Point vertical pos.
     * @return Point is in Poly flag.
     */
    public boolean contains( int x, int y )
    {
        boolean oddTransitions = false;
        for( int i = 0, j = polySides -1; i < polySides; j = i++ )
        {
            if( ( polyY[ i ] < y && polyY[ j ] >= y ) || ( polyY[ j ] < y && polyY[ i ] >= y ) )
            {
                if( polyX[ i ] + ( y - polyY[ i ] ) / ( polyY[ j ] - polyY[ i ] ) * ( polyX[ j ] - polyX[ i ] ) < x )
                {
                    oddTransitions = !oddTransitions;          
                }
            }
        }
        return oddTransitions;
    }  
}


6 commentaires

Que ferait-on s'ils ne sont pas incertains du nombre de côtés, le polygone a?


Le nombre de côtés peut facilement être déduit du nombre de points. Un rectangle a 4 points et 4 côtés. Un triangle a 3 points et 3 côtés. Les polygones dessinés par des chemins continus ont le même nombre de côtés et de points, de sorte que si votre chemin a des points "n", il a aussi des côtés "n".


Impressionnant, je suis content de pouvoir aider. Cette solution m'a sauvé une tonne de problèmes il y a quelques semaines également.


Oui, c'est plutôt étrange qu'ils laissaient la méthode de la contient. Néanmoins, je suis content que tu m'as sauvé une tonne de temps avec la classe. À votre santé!


C'était très utile. Si vous êtes intéressé, j'ai trouvé des informations sur le numéro de croisement et les algorithmes de numéro d'enroulement (que j'ai trouvé très informatif) ici: Softsurfer.com/archive/algorithm_0103/algorithm_0103.htm


... et votre réponse m'a également sauvé une bonne quantité de temps. Merci, théisenp!



7
votes

essayé l'autre réponse, mais cela a donné un résultat erroné pour mon cas. Je n'ai pas pris la peine de trouver la cause exacte, mais a fait ma propre traduction directe de l'algorithme sur: http://www.ecse.ripi.edu/homepages/wrf/research/short_notes/pnpoly.html

Le code lit: P>

/**
 * Minimum Polygon class for Android.
 */
public class Polygon
{
    // Polygon coodinates.
    private int[] polyY, polyX;

    // Number of sides in the polygon.
    private int polySides;

    /**
     * Default constructor.
     * @param px Polygon y coods.
     * @param py Polygon x coods.
     * @param ps Polygon sides count.
     */
    public Polygon( int[] px, int[] py, int ps )
    {
        polyX = px;
        polyY = py;
        polySides = ps;
    }

    /**
     * Checks if the Polygon contains a point.
     * @see "http://alienryderflex.com/polygon/"
     * @param x Point horizontal pos.
     * @param y Point vertical pos.
     * @return Point is in Poly flag.
     */
    public boolean contains( int x, int y )
    {
        boolean c = false;
        int i, j = 0;
        for (i = 0, j = polySides - 1; i < polySides; j = i++) {
            if (((polyY[i] > y) != (polyY[j] > y))
                && (x < (polyX[j] - polyX[i]) * (y - polyY[i]) / (polyY[j] - polyY[i]) + polyX[i]))
            c = !c;
        }
        return c;
    }  
}


3 commentaires

Thnx mate. M'a sauvé beaucoup de problèmes. J'étais en train de mettre en œuvre @theisenp réponse, mais ce n'était pas jusqu'à mes attentes. +1 pour vous.


Qu'en est-il du chemin avec l'arc? L'algorithme utilise Vertex Array. Il ne semble pas que cela ne semble pas considérer le cas lorsque le chemin contient un arc ou, plus en général, une partie circulaire du trajet.


Merci beaucoup pour cette contribution.



7
votes

Je voudrais juste commenter sur @theisenp Réponse: le code comporte des tableaux entier et si vous regardez sur la page Web de la description d'algorithme, il met en garde contre l'utilisation d'entiers au lieu d'un point flottant.

J'ai copié votre code ci-dessus et cela semblait fonctionner correctement, à l'exception des cas d'angle lorsque je faisais des lignes qui ne se sont pas bien connues à elles-mêmes.

En changeant tout sur Point flottant, je me suis débarrassé de ce bogue.


1 commentaires

Merci mon pote. Je faisais également face au même problème de précision et de lecture de votre commentaire a fait que le travail merci. u r obtenir un +1 :)



1
votes

En complétude, je veux faire quelques notes ici:

à partir de API 19, il y a un Opération d'intersection pour les chemins. Vous pouvez créer un très petit chemin carré autour de votre point de test, l'intersecter avec le chemin et voir si le résultat est vide ou non.

Vous pouvez convertir des chemins vers des régions et faire un Contient () Opération. Cependant, les régions fonctionnent dans des coordonnées entière et je pense qu'ils utilisent des coordonnées transformées (pixels), vous devrez donc travailler avec cela. Je soupçonne également que le processus de conversion est informellement intensif de calcul.

L'algorithme de croisement de bord que Hans posté est bon et rapide, mais vous devez faire très attention à certains cas de coin comme lorsque le rayon passe directement à travers Un sommet ou coupe un bord horizontal, ou lorsque l'erreur arrondi est un problème, ce qu'elle est toujours.

le Numéro d'enroulement est une preuve très imbuleuse, mais implique beaucoup de trigle et est calculé en calcul.

Ce document par Dan Dimanche donne un algorithme hybride aussi précis que le numéro d'enroulement, mais aussi simple que l'algorithme de coulée de rayons. Ça m'a explosé à quel point c'était élégant.

Mon code

Ceci est un code que j'ai écrit récemment en Java, qui gère un chemin à partir de deux segments de ligne et arcs. (Également cercles, mais ce sont des chemins complets seuls, il est donc en quelque sorte un cas dégénéré.) xxx


modifier: par demande, ajoutant un exemple de code utilise ceci. xxx


3 commentaires

Pouvez-vous s'il vous plaît fournir un exemple comment utiliser votre bibliothèque correctement avec l'exemple de l'ARC, on dirait que je vais faire quelque chose de mal. En fait, pas sûr de quoi envoyer X0, Y0, X1, Y0. Est-ce top, bas, gauche, points de droite de RecF Obj? (NEWBIE Android)


Oui, Android spécifie les arcs en spécifiant les limites de l'ellipse, puis spécifiant les angles de début et de fin. J'ai des notes sur cette question à efalk.org/docs/android/graphics_0.html #Arcto


Vous pouvez donner un exemple de comment l'utiliser? @Shp êtes-vous compris?