0

我创建了另一个问题(如何显示具有移动当前位置的地图(静止图像文件)

但它包含 2(两个)问题,所以我需要将其分开。

我正在尝试创建一个可以引导一个人到达目的地的原型。

  • 地方是一栋有几层楼的宽敞建筑。
  • 我可以获取/检索地图(静止图像)。例如当前:1F 目的地:5F;所以我可以得到1楼、2楼...5楼的静止图像(5个图像文件)。

设想:

  1. 启动应用程序
  2. 输入当前位置(或使用当前位置自动设置)和目的地
  3. 单击搜索路线按钮以搜索要使用的地图(静止图像)并标记当前位置和目的地
  4. 移动/前往目的地时更新当前位置

问题: 我可以通过 WiFi/基站/IP 地址获取当前位置坐标,但不知道如何将其放入静止图像中以标记当前位置。

您会分享概念/想法还是包含代码片段。对我的论文有很大帮助。

感谢任何有关正确方向的指导。


更新

带有实际、预期输出、测试用例的实际示例 (此处的代码包来自 mapsforge)

MercatorProjectionClass.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 听起来是一个合理的尺寸(谷歌地图使用 256 x 256)。这些较大的图像块称为图块。

使用 Google 地图,无法使用离线图块。我已经写了一篇关于如何使用OSMDroid(这是最好的开源替代品)的谷歌地图和ArcGIS的另一篇文章(Android 的免费地图控制器,商业地图图块;这个控制器的一切都很棒,但在我的认为它对于论文项目来说太重了)。

因此,这里重现的步骤是:

  • 将大文件分块成更小的部分
  • 找到大图像边缘的确切坐标以准确了解如何命名图块(地图控制器通过名称查找覆盖视口一部分所需的图块)
  • 使用您的图像实现离线磁贴提供程序

位置提供者

在我看来,这是最难的部分。您将如何准确地找到设备在建筑物中的确切位置?GPS可以在一定程度上有所帮助,但无论如何它在建筑物中并不精确。ArcGIS 为您提供了一个非常好的内置位置提供程序,在任何其他解决方案上您都必须自己实现它。一旦您设法克服了这个问题,您还可以使用位置提供商提供的高度在楼层之间自动切换。

路由

用 OSMDroid(好吧,ArcGIS 也是如此)表示一条路线是一块巧克力蛋糕:创建一个转折点数组,从一个点画一条线到另一个点,然后将该线放在地图上。困难的部分是创建一个路由算法,祝你好运!

于 2011-08-18T06:27:49.547 回答