0

Ich verwende den CanvasTileProvider in Google Maps Android v2.Kachelbezeichnung Google Maps: Entfernung zu Bildschirmdimensionen umwandeln

Ich kann lat lange Punkte auf Bildschirm Pixel konvertieren.

Allerdings möchte ich eine Methode erstellen, um eine Entfernung auf Bildschirm Pixel zu konvertieren. Dadurch kann ich einen Kreis mit x-Radius zeichnen. Kann mir jemand helfen?

Der Code unten habe ich abgeschlachtet und modifiziert von woanders so gut an den ursprünglichen Autor.

/** 
* Converts between LatLng coordinates and the pixels inside a tile. 
*/ 
public class TileProjection { 

    public int x; 
    public int y; 
    private int zoom; 
    private int TILE_SIZE; 

    private DoublePoint pixelOrigin_; 
    private double pixelsPerLonDegree_; 
    private double pixelsPerLonRadian_; 

    TileProjection(int tileSize, int x, int y, int zoom) { 
     this.TILE_SIZE = tileSize; 
     this.x = x; 
     this.y = y; 
     this.zoom = zoom; 
     pixelOrigin_ = new DoublePoint(TILE_SIZE/2, TILE_SIZE/2); 
     pixelsPerLonDegree_ = TILE_SIZE/360d; 
     pixelsPerLonRadian_ = TILE_SIZE/(2 * Math.PI); 
    } 

    /** 
    * Get the dimensions of the Tile in LatLng coordinates 
    */ 
    public LatLngBounds getTileBounds() { 
     DoublePoint tileSW = new DoublePoint(x * TILE_SIZE, (y + 1) * TILE_SIZE); 
     DoublePoint worldSW = pixelToWorldCoordinates(tileSW); 
     LatLng SW = worldCoordToLatLng(worldSW); 
     DoublePoint tileNE = new DoublePoint((x + 1) * TILE_SIZE, y * TILE_SIZE); 
     DoublePoint worldNE = pixelToWorldCoordinates(tileNE); 
     LatLng NE = worldCoordToLatLng(worldNE); 
     return new LatLngBounds(SW, NE); 
    } 

    /** 
    * Calculate the pixel coordinates inside a tile, relative to the left upper 
    * corner (origin) of the tile. 
    */ 
    public PointF latLngToPoint(LatLng latLng) { 
     DoublePoint result = new DoublePoint(1, 1); 
     // Log.d("Aero","x " + String.valueOf(x)); 
     // Log.d("Aero","y " + String.valueOf(y)); 

     latLngToWorldCoordinates(latLng, result); 
     worldToPixelCoordinates(result, result); 
     result.x -= x * TILE_SIZE; 

     int numTiles = 1 << zoom; 
     if (latLng.longitude < 0) { 
      result.x = result.x + (numTiles * TILE_SIZE); 
     } 

     result.y -= y * TILE_SIZE; 
     return new PointF((float) result.x, (float) result.y); 
    }  

    private DoublePoint pixelToWorldCoordinates(DoublePoint pixelCoord) { 
     int numTiles = 1 << zoom; 
     DoublePoint worldCoordinate = new DoublePoint(pixelCoord.x/numTiles, 
       pixelCoord.y/numTiles); 
     return worldCoordinate; 
    } 

    /** 
    * Transform the world coordinates into pixel-coordinates relative to the 
    * whole tile-area. (i.e. the coordinate system that spans all tiles.) 
    * <p/> 
    * <p/> 
    * Takes the resulting point as parameter, to avoid creation of new objects. 
    */ 
    private void worldToPixelCoordinates(DoublePoint worldCoord, DoublePoint result) { 
     int numTiles = 1 << zoom; 
     result.x = worldCoord.x * numTiles; 
     result.y = worldCoord.y * numTiles; 
    } 

    private LatLng worldCoordToLatLng(DoublePoint worldCoordinate) { 
     DoublePoint origin = pixelOrigin_; 
     double lng = (worldCoordinate.x - origin.x)/pixelsPerLonDegree_; 
     double latRadians = (worldCoordinate.y - origin.y) 
       /-pixelsPerLonRadian_; 
     double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians)) 
       - Math.PI/2); 
     return new LatLng(lat, lng); 
    } 

    /** 
    * Get the coordinates in a system describing the whole globe in a 
    * coordinate range from 0 to TILE_SIZE (type double). 
    * <p/> 
    * Takes the resulting point as parameter, to avoid creation of new objects. 
    */ 
    private void latLngToWorldCoordinates(LatLng latLng, DoublePoint result) { 
     DoublePoint origin = pixelOrigin_; 

     result.x = origin.x + latLng.longitude * pixelsPerLonDegree_; 


     // Truncating to 0.9999 effectively limits latitude to 89.189. This is 
     // about a third of a tile past the edge of the world tile. 
     double siny = bound(Math.sin(Math.toRadians(latLng.latitude)), -0.9999, 
       0.9999); 
     result.y = origin.y + 0.5 * Math.log((1 + siny)/(1 - siny)) 
       * -pixelsPerLonRadian_; 
    } 

    ; 

    /** 
    * Return value reduced to min and max if outside one of these bounds. 
    */ 
    private double bound(double value, double min, double max) { 
     value = Math.max(value, min); 
     value = Math.min(value, max); 
     return value; 
    } 

    /** 
    * A Point in an x/y coordinate system with coordinates of type double 
    */ 
    public static class DoublePoint { 
     double x; 
     double y; 

     public DoublePoint(double x, double y) { 
      this.x = x; 
      this.y = y; 
     } 
    } 

} 

Dies ist, was ich verwende vorschlage:

public Double MetersToPixels(LatLng latLng, Double distance){ 
    double tileScale = TILE_SIZE/256; 
    double pixelsPerMeter =1/(156543.03392 * Math.cos(latLng.latitude * Math.PI/180)/Math.pow(2, zoom)) * tileScale; 
    return pixelsPerMeter * distance; 
} 

Antwort

1

Zunächst sollten Sie sich bewusst sein die Tatsache, dass ein Kreis auf der Oberfläche der Erde auf der Karte nicht genau ein Kreis . Aber wenn Sie diese Ungenauigkeit ignorieren, müssen Sie nur einen LatLng-Punkt im 25-nm-Abstand erstellen und dann die latLngToPoint-Methode verwenden, um die Pixel zu erhalten. Vergleicht man sie mit den Pixeln der Mitte, erhält man den Radius. Zum Erstellen einer LatLng in einer bestimmten Entfernung siehe die Antwort auf diese SO question (Methode verschieben)

+0

Vielen Dank für Ihre Hilfe, habe ich Ihre Antwort/Link überprüft und es ergibt Sinn. Bevor Sie jedoch einen Code veröffentlicht haben, sollten Sie sich den Code am Ende der bearbeiteten Frage ansehen und mir sagen, ob Sie das für richtig halten. Es scheint mir zu funktionieren. – Reafidy

+0

Hi Reafidy, es ist schon eine Weile her, dass ich tief darin war. So kann ich nicht aus der Box beurteilen, ob deine Formel o.k. oder nicht. Aber ich denke, wenn man die y-Entfernung (Nord-Süd) berechnet, sollte man unabhängig vom latLng selbst sein, da der Nord-Süd-Perimeter immer die gleiche Länge hat, während der Ost-West-Perimeter vom Breitengrad abhängt. Da Sie den Breitengrad in Ihrer Formel haben, scheint es, dass Sie die Ost-West-Entfernung berechnen. (Wie gesagt, kann antworten. Ein genauer Kreis auf der Erde wird kein genauer Kreis auf der Karte sein und umgekehrt) – user2808624