osmdroid 中使用ArcgisServer地圖服務(wù)

osmdroid

osmdroid是一個(gè)開源項(xiàng)目,其目的是提供比安卓原生的MapView更為強(qiáng)大的地圖組件庫。osmdroid支持多種在線或者離線的瓦片地圖源以及地圖覆蓋管理器,用于繪制圖標(biāo)、幾何圖形以及GPS定位。

osmdroid相比于Android原生MapView的優(yōu)勢(shì)在于其豐富的瓦片地圖源和地圖覆蓋管理器了。相比于Arcgis Android Runtime SDK這種專業(yè)的GIS開發(fā)包在功能上的劣勢(shì)非常明顯,但也有其優(yōu)勢(shì)也很明顯——輕量。一個(gè)使用了Arcgis Android Runtime SDK的APP,如果完整支持arm64-v8a、armeabi-v7a、armeabi、x86的話,apk文件至少60M,僅支持armeabi-v7a也在30M以上,而使用osmdroid的APP的APK通常只有幾M。

ArcgisServer的地圖服務(wù)

Arcgis可以說是GIS領(lǐng)域最強(qiáng)大的軟件,沒有之一。Esri公司也是一家值得尊重的公司,一直在致力于GIS領(lǐng)域新技術(shù)的開發(fā)以及Arcgis和互聯(lián)網(wǎng)新科技的融合。ArcgisServer提供了目前市場(chǎng)上最強(qiáng)大最豐富的的GIS領(lǐng)域的服務(wù),包括地圖服務(wù),瓦片服務(wù),矢量切片服務(wù),要素服務(wù),分析服務(wù),幾何網(wǎng)絡(luò)服務(wù)等等等。

osmdroid主要是一個(gè)MapView,矢量切片這種新技術(shù)完全不支持,瓦片服務(wù)本來就支持,只有地圖服務(wù),osmdroid原本不支持,但有潛力。這里說的潛力,是因?yàn)锳rcgis的地圖服務(wù)是通過export接口返回的一張圖片,在數(shù)據(jù)源上與瓦片地圖沒有區(qū)別。

以瓦片的形式請(qǐng)求地圖服務(wù)

在ArcgisServer地圖服務(wù)的地圖請(qǐng)求鏈接一般形式如下:http://192.168.1.28:6080/arcgis/rest/services/NHCT/MapServer/export?bbox=114.36767578125,30.519681272749406,114.3731689453125,30.524413269923976&bboxSR=4326&size=256,256&format=png24&transparent=true&dpi=96&f=image,其中bbox表示請(qǐng)求的地圖的范圍,size表示請(qǐng)求的圖片的大小,format表示請(qǐng)求的圖片的格式,transparent表示沒有數(shù)據(jù)的部分是否透明,如果format不為png時(shí),transparent參數(shù)無效。f表示以圖片的形式返回,另外還有json和html的形式。

我們要以瓦片的形式請(qǐng)求地圖服務(wù),重點(diǎn)就在算出每個(gè)請(qǐng)求瓦片的bbox,其邏輯代碼如下。

public static BoundingBox tile2boundingBox(final int x, final int y, final int zoom) 
{
    BoundingBox bb = new BoundingBox(tile2lat(y, zoom), tile2lon(x + 1, zoom), tile2lat(y + 1, zoom), tile2lon(x, zoom));
    return bb;
}

public static double tile2lon(int x, int z) {
    return x / Math.pow(2.0, z) * 360.0 - 180;
}

public static double tile2lat(int y, int z) {
    double n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z);
    return Math.toDegrees(Math.atan(Math.sinh(n)));
}

當(dāng)然如果是莫卡托投影的,就不是經(jīng)緯度了

public  double[] getBoundingBox(int x, int y, int zoom) {
    double tileSize = MAP_SIZE / Math.pow(2, zoom);
    double minx = TILE_ORIGIN[ORIG_X] + x * tileSize;
    double maxx = TILE_ORIGIN[ORIG_X] + (x + 1) * tileSize;
    double miny = TILE_ORIGIN[ORIG_Y] - (y + 1) * tileSize;
    double maxy = TILE_ORIGIN[ORIG_Y] - y * tileSize;

    double[] bbox = new double[4];
    bbox[MINX] = minx;
    bbox[MINY] = miny;
    bbox[MAXX] = maxx;
    bbox[MAXY] = maxy;

    return bbox;
}

然后照著請(qǐng)求瓦片一樣請(qǐng)求就可以了

@Override
public String getTileURLString(long pMapTileIndex) {
    String baseUrl = getBaseUrl();
    if (forceHttps)
        baseUrl = baseUrl.replace("http://", "https://");
    if (forceHttp)
        baseUrl = baseUrl.replace("https://", "http://");
    StringBuilder sb = new StringBuilder(baseUrl);
    if (!baseUrl.endsWith("/"))
        sb.append("/");
    sb.append("export?").append("bbox=");
    if (srs.equals("EPSG:900913")) {
        double[] bbox = getBoundingBox(MapTileIndex.getX(pMapTileIndex), MapTileIndex.getY(pMapTileIndex), MapTileIndex.getZoom(pMapTileIndex));
        sb.append(bbox[MINX]).append(",");
        sb.append(bbox[MINY]).append(",");
        sb.append(bbox[MAXX]).append(",");
        sb.append(bbox[MAXY]);
    } else {
        BoundingBox boundingBox = tile2boundingBox(MapTileIndex.getX(pMapTileIndex), MapTileIndex.getY(pMapTileIndex), MapTileIndex.getZoom(pMapTileIndex));
        sb.append(boundingBox.getLonWest()).append(",");
        sb.append(boundingBox.getLatSouth()).append(",");
        sb.append(boundingBox.getLonEast()).append(",");
        sb.append(boundingBox.getLatNorth());
    }
    sb.append("&bboxSR=").append(srs.replace("EPSG:","")).append("&size=").append(getTileSizePixels()).append(",").append(getTileSizePixels());
    sb.append("&format=png24").append("&transparent=true").append("&dpi=96").append("&f=image");
    String str = sb.toString();
    return str;
}

這個(gè)思路不是我的,而是在osmdroid中自帶一個(gè)osmdroid-wms的子項(xiàng)目,我心想WMS和ArcgisServer的地圖服務(wù)原理一致,前者可以后者當(dāng)然也可以,所以就仔細(xì)閱讀了一下osmdroid-wms的源碼,參照WMSTileSource類寫了一個(gè)ArcgisServer地圖服務(wù)的DataSource,核心代碼就是上面那些了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容