Android WMS地图库
Android WMS map library
目前我正在使用 Geoserver 中的地图。我想在 android 中以 WMS 格式显示地图。我见过 openscales、mapsforge、osm-droid。哪些 android 地图库最适合处理 WMS、WFS 图层?它们的优缺点是什么?
我不为 WMS 使用特定的库,因为我不喜欢它们(对于特定的情况来说太复杂了,在我的情况下是非标准情况),所以我创建了我的 class 来管理它.例如,在地图上显示 WMS 只是简单地覆盖 URLTileProvider:
/*
* Copyright [2015] Nicola Dorigatti
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.dorigatti.android.editing.wms;
import com.google.android.gms.maps.model.UrlTileProvider;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
public abstract class WMSTileProvider extends UrlTileProvider {
// Web Mercator n/w corner of the map.
private static final double[] TILE_ORIGIN = { -20037508.34789244, 20037508.34789244 };
// array indexes for that data
private static final int ORIG_X = 0;
private static final int ORIG_Y = 1; // "
// Size of square world map in meters, using WebMerc projection.
private static final double MAP_SIZE = 20037508.34789244 * 2;
// array indexes for array to hold bounding boxes.
protected static final int MINX = 0;
protected static final int MAXX = 1;
protected static final int MINY = 2;
protected static final int MAXY = 3;
// cql filters
private String cqlString = "";
// Construct with tile size in pixels, normally 256, see parent class.
public WMSTileProvider(int x, int y) {
super(x, y);
}
@SuppressWarnings("deprecation")
protected String getCql() {
try {
return URLEncoder.encode(cqlString, Charset.defaultCharset().name());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return URLEncoder.encode(cqlString);
}
}
public void setCql(String c) {
cqlString = c;
}
// Return a web Mercator bounding box given tile x/y indexes and a zoom
// level.
protected 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;
}
}
他们将图层管理为:
/*
* Copyright [2015] Nicola Dorigatti
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.dorigatti.android.editing.wms;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import it.dorigatti.android.editing.dto.WMSLayerInfo;
public class TileProviderFactory {
public static WMSTileProvider getWMSTileProviderByName(String layerName) {
final String OSGEO_WMS = "YOURGEOSERVER/gwc/service/wms/?"
+ "LAYERS=" + layerName
+ "&FORMAT=image/png8&"
+ "PROJECTION=EPSG:3857&"
+ "TILEORIGIN=lon=-20037508.34,lat=-20037508.34&"
+ "TILESIZE=w=256,h=256"
+ "&MAXEXTENT=-20037508.34,-20037508.34,20037508.34,20037508.34&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&SRS=EPSG:3857"
+ "&BBOX=%f,%f,%f,%f&WIDTH=256&HEIGHT=256";
return new WMSTileProvider(256, 256) {
@Override
public synchronized URL getTileUrl(int x, int y, int zoom) {
final double[] bbox = getBoundingBox(x, y, zoom);
String s = String.format(Locale.US, OSGEO_WMS, bbox[MINX], bbox[MINY], bbox[MAXX], bbox[MAXY]);
try {
return new URL(s);
} catch (MalformedURLException e) {
throw new AssertionError(e);
}
}
};
}
}
对于 WFS 服务,我开发了一个小型库,它使用 GeoJSON 作为数据 download/upload。 XML 不适合 android 并且 WFS 太宽无法支持所有内容,所以我只是根据需要实现了它。
请注意,geoserver 在某些情况下与 WFS v2 存在一些问题,我不得不切换到 WFS 1.1。
目前我正在使用 Geoserver 中的地图。我想在 android 中以 WMS 格式显示地图。我见过 openscales、mapsforge、osm-droid。哪些 android 地图库最适合处理 WMS、WFS 图层?它们的优缺点是什么?
我不为 WMS 使用特定的库,因为我不喜欢它们(对于特定的情况来说太复杂了,在我的情况下是非标准情况),所以我创建了我的 class 来管理它.例如,在地图上显示 WMS 只是简单地覆盖 URLTileProvider:
/*
* Copyright [2015] Nicola Dorigatti
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.dorigatti.android.editing.wms;
import com.google.android.gms.maps.model.UrlTileProvider;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
public abstract class WMSTileProvider extends UrlTileProvider {
// Web Mercator n/w corner of the map.
private static final double[] TILE_ORIGIN = { -20037508.34789244, 20037508.34789244 };
// array indexes for that data
private static final int ORIG_X = 0;
private static final int ORIG_Y = 1; // "
// Size of square world map in meters, using WebMerc projection.
private static final double MAP_SIZE = 20037508.34789244 * 2;
// array indexes for array to hold bounding boxes.
protected static final int MINX = 0;
protected static final int MAXX = 1;
protected static final int MINY = 2;
protected static final int MAXY = 3;
// cql filters
private String cqlString = "";
// Construct with tile size in pixels, normally 256, see parent class.
public WMSTileProvider(int x, int y) {
super(x, y);
}
@SuppressWarnings("deprecation")
protected String getCql() {
try {
return URLEncoder.encode(cqlString, Charset.defaultCharset().name());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return URLEncoder.encode(cqlString);
}
}
public void setCql(String c) {
cqlString = c;
}
// Return a web Mercator bounding box given tile x/y indexes and a zoom
// level.
protected 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;
}
}
他们将图层管理为:
/*
* Copyright [2015] Nicola Dorigatti
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.dorigatti.android.editing.wms;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import it.dorigatti.android.editing.dto.WMSLayerInfo;
public class TileProviderFactory {
public static WMSTileProvider getWMSTileProviderByName(String layerName) {
final String OSGEO_WMS = "YOURGEOSERVER/gwc/service/wms/?"
+ "LAYERS=" + layerName
+ "&FORMAT=image/png8&"
+ "PROJECTION=EPSG:3857&"
+ "TILEORIGIN=lon=-20037508.34,lat=-20037508.34&"
+ "TILESIZE=w=256,h=256"
+ "&MAXEXTENT=-20037508.34,-20037508.34,20037508.34,20037508.34&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&SRS=EPSG:3857"
+ "&BBOX=%f,%f,%f,%f&WIDTH=256&HEIGHT=256";
return new WMSTileProvider(256, 256) {
@Override
public synchronized URL getTileUrl(int x, int y, int zoom) {
final double[] bbox = getBoundingBox(x, y, zoom);
String s = String.format(Locale.US, OSGEO_WMS, bbox[MINX], bbox[MINY], bbox[MAXX], bbox[MAXY]);
try {
return new URL(s);
} catch (MalformedURLException e) {
throw new AssertionError(e);
}
}
};
}
}
对于 WFS 服务,我开发了一个小型库,它使用 GeoJSON 作为数据 download/upload。 XML 不适合 android 并且 WFS 太宽无法支持所有内容,所以我只是根据需要实现了它。 请注意,geoserver 在某些情况下与 WFS v2 存在一些问题,我不得不切换到 WFS 1.1。