9 votes

Trier la liste de lon \lat points, commencez par le plus proche

J'ai la localisation du GPS (lon_base, lat_base). Je dispose d'une liste de lieux (lon1, lat1|lon2, lat2|lon3, lat3...). Cette liste est très longue et se trouve dans le monde entier.

Mes questions sont les suivantes : 1. Comment puis-je obtenir de cette liste uniquement les lon \lat qui se trouvent à un kilomètre de ma base longue. \lat_base ? 2. Comment les trier du plus proche au plus éloigné ?

Merci d'avance !

20voto

Niels Points 742
public static List<Location> sortLocations(List<Location> locations, final double myLatitude,final double myLongitude) {
    Comparator comp = new Comparator<Location>() {
        @Override
        public int compare(Location o, Location o2) {
            float[] result1 = new float[3];
            android.location.Location.distanceBetween(myLatitude, myLongitude, o.Lat, o.Long, result1);
            Float distance1 = result1[0];

            float[] result2 = new float[3];
            android.location.Location.distanceBetween(myLatitude, myLongitude, o2.Lat, o2.Long, result2);
            Float distance2 = result2[0];

            return distance1.compareTo(distance2);
        }
    };

    Collections.sort(locations, comp);
    return locations;
}

où la liste des emplacements est une liste contenant votre propre classe d'emplacement, et non la classe Android.location.Location.

7voto

ChrisJ Points 3531

Vous pouvez utiliser le distance du grand cercle pour calculer la distance entre deux points dont vous connaissez les coordonnées de latitude-longitude. Le site formules sont assez faciles à coder :

static double distance(double fromLat, double fromLon, double toLat, double toLon) {
    double radius = 6378137;   // approximate Earth radius, *in meters*
    double deltaLat = toLat - fromLat;
    double deltaLon = toLon - fromLon;
    double angle = 2 * Math.asin( Math.sqrt(
        Math.pow(Math.sin(deltaLat/2), 2) + 
        Math.cos(fromLat) * Math.cos(toLat) * 
        Math.pow(Math.sin(deltaLon/2), 2) ) );
    return radius * angle;
}

4voto

Travis Webb Points 5765

Vous voulez définir votre propre Comparator qui, en général, ressemble à quelque chose comme ça :

LonLat myHouse = /* whatever */ ;
Comparable comp = new Comparable () {
    LonLat a;
    int compareTo (Object b) {
        int aDist = calcDistance(a, myHouse) ;
        int bDist = calcDistance(b, myHouse) ;
        return aDist - bDist;
    }
};
myLonLatList.sort(lonLatList, comp);

donde calcDistance() calcule simplement la distance entre les deux points. Si vous êtes sur Android, je pense que Google Maps a une fonction quelque part dans leur API qui fera cela pour vous.

EDITAR : Vous voudrez votre calcDistance() pour ressembler à la fonction de ChrisJ distance fonction.

-tjw

1voto

Curd Points 4670

Vous pouvez utiliser l'approximation suivante (puisque 1 mile est beaucoup plus petit que le rayon de la terre) pour calculer les distances depuis votre base :

dx = cos(phi_base) * (theta - theta_base)
dy = phi - phi_base

dist = sqrt(dx*dx+dy*dy) 

avec : phi = latitude et theta = longitude

Le résultat est en unités de 60 milles nautiques si theta y phi sont données en degrés. Les résultats seront assez erronés pour les points dont la latitude est très différente de celle de votre base, mais cela n'a pas d'importance si vous voulez simplement savoir quels points se trouvent à environ 1 mile de votre base.

Pour la plupart des langages de programmation, vous devez convertir phi_base en radians (multiplier par pi/180) afin de l'utiliser pour les opérations suivantes cos() .

(Attention : Vous devez faire très attention si votre longitude de base est très proche de 180° ou -180°, mais ce n'est probablement pas le cas :-)

Utilisez les distances calculées comme clé de tri pour classer vos points.

Si vous devez être plus précis (par exemple si vous voulez connaître tous les points qui se trouvent à environ 2000 miles de votre domicile), vous devez utiliser la formule suivante Distance du grand cercle pour calculer la distance exacte de deux points sur une sphère.

1voto

Roger Alien Points 802

Selon cette lien J'ai créé une méthode de travail. La réponse ci-dessus était fausse, car elle ne convertit pas les degrés lat/lng en radians.

    private double getDistance(double fromLat, double fromLon, double toLat, double toLon){
        double radius = 6371;   // Earth radius in km
        double deltaLat = Math.toRadians(toLat - fromLat);
        double deltaLon = Math.toRadians(toLon - fromLon);
        double lat1 = Math.toRadians(fromLat);
        double lat2 = Math.toRadians(toLat);
        double aVal = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
            Math.sin(deltaLon/2) * Math.sin(deltaLon/2) * Math.cos(lat1) * Math.cos(lat2);
        double cVal = 2*Math.atan2(Math.sqrt(aVal), Math.sqrt(1-aVal));  

        double distance = radius*cVal;
        Log.d("distance","radius * angle = " +distance);
        return distance;
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X