0

別の質問を作成しました(現在地が移動する地図(静止画像ファイル)を表示する方法

しかし、それには 2 つの質問が含まれているため、分離する必要があります。

人を目的地まで案内できるプロトタイプを作ろうとしています。

  • 場所は数階建ての広い建物です。
  • 地図(静止画)を取得・取得できます。例: 現在地:1F 目的地:5F; 1階、2階…5階の静止画(5枚の画像ファイル)を取得できます。

シナリオ:

  1. アプリケーションを開始する
  2. 現在地を入力 (または現在地を使用して自動的に設定される場合があります) & 目的地
  3. 検索ルートボタンをクリックして、使用する地図(静止画)を検索し、現在地と目的地をマークします
  4. 目的地への移動/移動時に現在地を更新する

問題: WiFi/セル タワー/IP アドレスを介して現在の位置座標を取得できますが、それを静止画像に入れて現在の位置をマークする方法がわかりません。

概念/アイデアを共有するか、コード スニペットを含めますか。私の論文に大いに役立ちます。

正しい方向へのガイダンスをいただければ幸いです。


アップデート

実際の、期待される出力、テスト ケースを含む実際の例 (ここにあるコードの一部は、mapsforge から取得したものです)

メルカトル投影クラス.java

/**
 * A performance optimized implementation of the spherical Mercator projection.
 */
class MercatorProjectionClass {
    /**
     * Width and height of a map tile in pixel.
     */
    static final int TILE_SIZE = 256;

    /**
     * Converts a latitude coordinate (in degrees) to a pixel Y coordinate at a certain zoom level.
     * 
     * @param latitude
     *            the latitude coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the pixel Y coordinate of the latitude value.
     */
    static double latitudeToPixelY(double latitude, byte zoom) {
        double sinLatitude = Math.sin(latitude * (Math.PI / 180));
        return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * Math.PI))
                * ((long) TILE_SIZE << zoom);
    }

    /**
     * Converts a latitude coordinate (in degrees) to a tile Y number at a certain zoom level.
     * 
     * @param latitude
     *            the latitude coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the tile Y number of the latitude value.
     */
    static long latitudeToTileY(double latitude, byte zoom) {
        return pixelYToTileY(latitudeToPixelY(latitude, zoom), zoom);
    }

    /**
     * Converts a longitude coordinate (in degrees) to a pixel X coordinate at a certain zoom level.
     * 
     * @param longitude
     *            the longitude coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the pixel X coordinate of the longitude value.
     */
    static double longitudeToPixelX(double longitude, byte zoom) {
        return (longitude + 180) / 360 * ((long) TILE_SIZE << zoom);
    }

    /**
     * Converts a longitude coordinate (in degrees) to the tile X number at a certain zoom level.
     * 
     * @param longitude
     *            the longitude coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the tile X number of the longitude value.
     */
    static long longitudeToTileX(double longitude, byte zoom) {
        return pixelXToTileX(longitudeToPixelX(longitude, zoom), zoom);
    }

    /**
     * Converts a pixel X coordinate at a certain zoom level to a longitude coordinate.
     * 
     * @param pixelX
     *            the pixel X coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the longitude value of the pixel X coordinate.
     */
    static double pixelXToLongitude(double pixelX, byte zoom) {
        return 360 * ((pixelX / ((long) TILE_SIZE << zoom)) - 0.5);
    }

    /**
     * Converts a pixel X coordinate to the tile X number.
     * 
     * @param pixelX
     *            the pixel X coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the tile X number.
     */
    static long pixelXToTileX(double pixelX, byte zoom) {
        return (long) Math.min(Math.max(pixelX / TILE_SIZE, 0), Math.pow(2, zoom) - 1);
    }

    /**
     * Converts a pixel Y coordinate at a certain zoom level to a latitude coordinate.
     * 
     * @param pixelY
     *            the pixel Y coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the latitude value of the pixel Y coordinate.
     */
    static double pixelYToLatitude(double pixelY, byte zoom) {
        double y = 0.5 - (pixelY / ((long) TILE_SIZE << zoom));
        return 90 - 360 * Math.atan(Math.exp(-y * (2 * Math.PI))) / Math.PI;
    }

    /**
     * Converts a pixel Y coordinate to the tile Y number.
     * 
     * @param pixelY
     *            the pixel Y coordinate that should be converted.
     * @param zoom
     *            the zoom level at which the coordinate should be converted.
     * @return the tile Y number.
     */
    static long pixelYToTileY(double pixelY, byte zoom) {
        return (long) Math.min(Math.max(pixelY / TILE_SIZE, 0), Math.pow(2, zoom) - 1);
    }

    private static final byte ZOOM_LEVEL = 14;

    /**
     * @param args
     */
    public static void main(String[] args) {
        // Pixel Coordinate of Chicago,IL
        double pixel_y = 1559345;
        double pixel_x = 1075954;
        // Lat Lng of Chicago,IL
        double lat_y = 41.850033;
        double lng_x = -87.65005229999997; 

        testPixelXYToLatitude(pixel_y, pixel_x, lat_y, lng_x);
        testLatLngToPixelXY(pixel_y, pixel_x, lat_y, lng_x);
    }

    private static void testPixelXYToLatitude(
            double pixel_y, double pixel_x, 
            double lat_y, double lng_x) {

        double actual_lat_y = MercatorProjectionClass.pixelYToLatitude(pixel_y, ZOOM_LEVEL);
        double actual_lng_x = MercatorProjectionClass.pixelXToLongitude(pixel_x, ZOOM_LEVEL);

        String expectedstr_lat_y = Double.toString(lat_y).substring(0, 5);
        String expectedstr_lng_x = Double.toString(lng_x).substring(0, 6);

        String actualstr_lat_y = Double.toString(actual_lat_y).substring(0, 5);
        String actualstr_lng_x = Double.toString(actual_lng_x).substring(0, 6);

        String result = (actualstr_lat_y.equals(expectedstr_lat_y) && actualstr_lng_x.equals(expectedstr_lng_x))?"PASSED":"FAILED"; 
        System.out.println("PixelXYToLatitude test result:" + result);
    }

    private static void testLatLngToPixelXY(
            double pixel_y, double pixel_x, 
            double lat_y, double lng_x) {

        double actual_pixel_y = MercatorProjectionClass.latitudeToPixelY(lat_y, ZOOM_LEVEL);
        double actual_pixel_x = MercatorProjectionClass.longitudeToPixelX(lng_x, ZOOM_LEVEL);

        String expectedstr_pixel_y = Integer.toString((Double.valueOf(pixel_y).intValue()));
        String expectedstr_pixel_x = Integer.toString((Double.valueOf(pixel_x).intValue()));

        String actualstr_pixel_y = Integer.toString(Double.valueOf(actual_pixel_y).intValue());
        String actualstr_pixel_x = Integer.toString(Double.valueOf(actual_pixel_x).intValue());

        String result = (actualstr_pixel_y.equals(expectedstr_pixel_y) && actualstr_pixel_x.equals(expectedstr_pixel_x))?"PASSED":"FAILED"; 
        System.out.println("LatLngToPixelXY test result:" + result);
    }
}

上記のコードの出力:

  • PixelXYToLatitude テスト結果:PASSED
  • LatLngToPixelXY テスト結果:PASSED

LatLng を Pixel に変換するための投影クラスが既にあります。私の問題は、上記のクラスを使用して、特定の LatLng の静止画像にマークを付ける方法です。

これが私の静止画像です(シカゴ、イリノイ州):

これが私の静止画像です(シカゴ、イリノイ州)

マークを付けたい(これは例ですが、後でバルーンを小さなポインターに変更する必要があります)

目印をつけたい(ここでは例ですが、吹き出しをポインタに変更)

4

1 に答える 1

1

私が理解したことから、あなたはここでいくつかの問題に直面しています。

  • オフライン タイルでマップ コントローラーを使用する

  • 現在地を地図上にマークする

  • ユーザーをポイント A からポイント B にルーティングする


マップコントローラー

基本的に、Android のロケーション プロバイダーはアプリケーションにいくつかのグローバル ポジショニング座標 (経度と緯度) を提供し、その背後に背景を配置して、ユーザーが自分のロケーションを視覚的に把握できるようにします。そこに静止画像を配置するというあなたの考えは正しいですが、私が提案する修正 (これはすべての商用または非商用の製品で機能する方法です) は、大きな画像を小さな部分に分割することです。コントローラーは大きな画像をメモリにロードする必要はありません。512 x 512 は妥当なサイズのように思えます (Google マップは 256 x 256 を使用します)。これらの大きな画像のチャンクはタイルと呼ばれます。

Google マップでは、オフライン タイルを使用することはできません。OSMDroid (これは最良のオープン ソースの代替手段です) を使用して Google マップでそれを行う方法についての投稿を書きました。また、ArcGIS (Android 用の無料のマップ コントローラー、商用マップ タイル; すべてがこのコントローラーで素晴らしいですが、私の論文プロジェクトには負荷が高すぎるという意見)。

したがって、ここで再現する手順は次のとおりです。

  • 大きなファイルを小さな部分にチャンク
  • タイルに名前を付ける方法を正確に知るために、大きな画像の端の正確な座標を見つけます(マップコントローラーは、ビューポートの一部をカバーするために必要なタイルを名前で見つけます)
  • 画像を使用してオフライン タイル プロバイダーを実装する

ロケーションプロバイダー

これは、私の意見では、最も難しい部分です。建物内のデバイスの正確な位置をどのように正確に見つけますか? GPS はある程度は役に立ちますが、建物の中では正確ではありません。ArcGIS は非常に優れたビルトイン ロケーション プロバイダーを提供します。他のソリューションでは、独自に実装する必要があります。この問題を克服できたら、ロケーション プロバイダーから提供された高度を使用してフロアを自動的に切り替えることもできます。

ルーティング

OSMDroid (ArcGIS も同様) を使用してルーティング ラインを表現するのはチョコレート ケーキです。ターン ポイントの配列を作成し、ある点から別の点まで線を引き、その線をマップに配置します。難しい部分は、ルーティング アルゴリズムを作成することです。頑張ってください!

于 2011-08-18T06:27:49.547 に答える