需求
遇到一个需求,需要在osmdroid地图中支持点击查询,查询所点击的地图图斑信息。
理论
地图服务geoserver支持WFS服务,用于地图查询
omdroid没有找到相关支持,所以手写了一个对wfs服务的调用调用分析
实现
自定义一个EventsOverlay类,继承自Overlay,用于接收地图的点击事件并分析点击的坐标位置
在获取的坐标位置生成一个小小的polygon进行图斑查询
手动拼接xml参数,返回结果拼接为polygon加载到地图上
代码
public class MainMapEventsOverlay extends Overlay {
private static String TAG = "osmdroid-overlay";
public Context context;
public MapView mv;
public String layer = null;
public String srs;
public int polygonFillColor;
public int polygonOutlineWith;
public int polygonOutlineColor;
public JSONObject properties;
private String par = "";
private List<Polygon> listPolygon = new ArrayList<>();
private Handler handler;
@Override
public boolean onSingleTapConfirmed(MotionEvent e, MapView mv) {
Projection proj = mv.getProjection();//获得投影对象
GeoPoint gp = (GeoPoint) proj.fromPixels(((Float) e.getX()).intValue(), ((Float) e.getY()).intValue());//坐标转换
Log.d(TAG, gp.toString());
//没有图层时不查询
if (layer == null) {
return true;
}
par = "<GetFeature " +
"xmlns=\"http://www.opengis.net/wfs\" service=\"WFS\" version=\"1.1.0\" outputFormat=\"application/json\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xsi:schemaLocation=\"http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd\">" +
"<Query typeName=\"" + layer + "\" srsName=\"" + srs + "\" xmlns:sde=\"http://geoserver.sf.net\">" +
"<Filter xmlns=\"http://www.opengis.net/ogc\">" +
"<Intersects>" +
"<PropertyName>geom</PropertyName>" +
"<Polygon xmlns=\"http://www.opengis.net/gml\">" +
"<exterior><LinearRing><posList srsDimension=\"2\">" +
"" + gp.getLongitude() + " " + gp.getLatitude() + " " +
"" + (gp.getLongitude() + 0.0000001) + " " + gp.getLatitude() + " " +
"" + gp.getLongitude() + " " + (gp.getLatitude() + 0.0000001) + " " +
"" + gp.getLongitude() + " " + gp.getLatitude() + "" +
//"117.32810497283936 39.11452531814575 117.3310661315918 39.10838842391968 117.3391342163086 39.11684274673462 117.32810497283936 39.11452531814575" +
"</posList>" +
"</LinearRing>" +
"</exterior>" +
"</Polygon>" +
"</Intersects></Filter></Query></GetFeature>";
Log.d(TAG, par);
for (int i = 0; i < listPolygon.size(); i++) {
mv.getOverlays().remove(listPolygon.get(i));
}
listPolygon.clear();
properties = null;
MyThreadRunnable myThreadRunnable = new MyThreadRunnable();
Thread thread = new Thread(myThreadRunnable);
thread.start();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
for (int i = 0; i < listPolygon.size(); i++) {
mv.getOverlays().add(listPolygon.get(i));
}
mv.invalidate();//重绘地图
break;
}
super.handleMessage(msg);
}
};
mv.invalidate();//重绘地图
return true;
}
public void clear() {
for (int i = 0; i < listPolygon.size(); i++) {
mv.getOverlays().remove(listPolygon.get(i));
}
listPolygon.clear();
mv.invalidate();//重绘地图
}
//创建线程方式二
class MyThreadRunnable implements Runnable {
@Override
public void run() {
try {
URL url = new URL("https://www.hotworld.com.cn:1122/geoserver/wfs");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(30000); //设置连接超时时间
httpURLConnection.setDoInput(true); //打开输入流,以便从服务器获取数据
httpURLConnection.setDoOutput(true); //打开输出流,以便向服务器提交数据
httpURLConnection.setRequestMethod("POST"); //设置以Post方式提交数据
httpURLConnection.setUseCaches(false); //使用Post方式不能使用缓存
//设置请求体的类型是文本类型
httpURLConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
//设置请求体的长度
httpURLConnection.setRequestProperty("Content-Length", par.length() + "");
//获得输出流,向服务器写入数据
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(par.getBytes("UTF-8"));
int response = httpURLConnection.getResponseCode(); //获得服务器的响应码
if (response == HttpURLConnection.HTTP_OK) {
InputStream inptStream = httpURLConnection.getInputStream();
//return dealResponseResult(inptStream); //处理服务器的响应结果
}
StringBuffer buffer = new StringBuffer();
// 从输入流读取返回内容
InputStream inputStream = httpURLConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
JSONTokener jsonTokener = new JSONTokener(buffer.toString());
JSONObject jsonObject = (JSONObject) jsonTokener.nextValue();
JSONArray features = jsonObject.getJSONArray("features");
for (int i = 0; i < features.length(); i++) {
JSONObject feature = features.getJSONObject(i);
JSONObject geometry = feature.getJSONObject("geometry");
switch (geometry.getString("type")) {
case "MultiPolygon": {
Polygon polygon = new Polygon();
JSONArray coods = geometry.getJSONArray("coordinates").getJSONArray(0);
for (int holeIndex = 0; holeIndex < coods.length(); holeIndex++) {
List<GeoPoint> listPoints = new ArrayList<>();
for (int pointIndex = 0; pointIndex < coods.getJSONArray(holeIndex).length(); pointIndex++) {
JSONArray point = coods.getJSONArray(holeIndex).getJSONArray(pointIndex);
GeoPoint geoPoint = new GeoPoint(point.getDouble(1), point.getDouble(0));
listPoints.add(geoPoint);
}
if (holeIndex == 0) {
polygon.setPoints(listPoints);
} else {
polygon.getHoles().add(listPoints);
}
}
polygon.getFillPaint().setColor(polygonFillColor);
polygon.getOutlinePaint().setColor(polygonOutlineColor);
polygon.setStrokeWidth(polygonOutlineWith);
listPolygon.add(polygon);
}
break;
case "Polygon": {
Polygon polygon = new Polygon();
JSONArray coods = geometry.getJSONArray("coordinates").getJSONArray(0);
List<GeoPoint> listPoints = new ArrayList<>();
for (int pointIndex = 0; pointIndex < coods.length(); pointIndex++) {
JSONArray point = coods.getJSONArray(pointIndex);
GeoPoint geoPoint = new GeoPoint(point.getDouble(1), point.getDouble(0));
listPoints.add(geoPoint);
}
polygon.setPoints(listPoints);
polygon.getFillPaint().setColor(polygonFillColor);
polygon.getOutlinePaint().setColor(polygonOutlineColor);
polygon.setStrokeWidth(polygonOutlineWith);
listPolygon.add(polygon);
}
break;
}
//获取属性信息与其他关联或者显示
properties = feature.getJSONObject("properties");
}
Message message = new Message();
message.what = 0;
handler.sendMessage(message);
Log.d(TAG, buffer.toString());
} catch (Exception ex) {
Log.d(TAG, ex.toString());
}
}
}
}
应用
//点击查询图层
mainMapEventsOverlay = new MainMapEventsOverlay();
mainMapEventsOverlay.context = this;
mainMapEventsOverlay.mv = mMapView;
mainMapEventsOverlay.layer = "sde:ZFJCDL_XZDL";
mainMapEventsOverlay.srs = "EPSG:4326";
//渲染查询结果样式
mainMapEventsOverlay.polygonFillColor = getColor(R.color.color_polygon_wtj);
mainMapEventsOverlay.polygonOutlineWith = 1;
mainMapEventsOverlay.polygonOutlineColor = getColor(R.color.color_polygon_line);
mMapView.getOverlays().add(mainMapEventsOverlay);