上一章我们以I查询为例讲述了在ArcGIS for Android里如何进行离线数据空间查询,通过ArcGIS 10.2以上的SDK里中QueryParamters类里设置查询参数,然后到对应空间数据库里查询即可。在了解如何空间查询以后,接下来我们以叠加分析为例说下ArcGIS for Android里如何进行离线数据的空间分析。
空间分析,顾名思义就是对空间数据进行分析,所以首先也是要进行空间查询,然后将查询结果用空间分析工具进行处理,最后再将处理后的结果进行归类统计。
相比起空间查询来,我们多用了空间分析工具,在ArcGIS for Android里空间分析工具都是放在GeometryEngine类里,我们看下官方文档里是怎么说的:
简要翻译下就是这个类里提供了一系列的方法来实现空间数据的运算。而这些方法名,如果对于ArcGIS比较熟的同学会发现,这就是ArcGIS里空间分析工具的名字,而且和这些工具使用的方法完全一样。我们以叠加分析为例,到时候就会用到Intersect叠加工具,用来处理得到两个矢量图形数据公共的部分。
不用多说,先上效果图以及空间分析时候的动态图,其中统计后的图表展示是用HelloChart完成。
再来看看代码如何实现的。
首先我们先划出需进行叠加分析的图形:
mMapView.setOnSingleTapListener(new OnSingleTapListener() { @Override public void onSingleTap(float v, float v1) { Point mPoint = mMapView.toMapPoint(v, v1);// 选择点 mPoints.add(mPoint);// 选择点加入点的集合 Graphic messurePoint = new Graphic(mPoint, mMarkerSymbol);// 点的要素初始化 messureLayer.addGraphic(messurePoint);// 点的要素添加到图层 if (mPoints.size() == 1) { messurePolygon.startPath(mPoints.get(0));// 设置面的初始点 } if (mPoints.size() > 1) { messureLayer.removeAll(); messurePolyline.setEmpty(); messurePolygon.lineTo(mPoint);// 连接到当前点击的点 messurePolygon.lineTo(mPoints.get(0));// 连接到初始点 for (int i = 0; i < mPoints.size() - 1; i++) { messureLine.setStart(mPoints.get(i)); messureLine.setEnd(mPoints.get(i + 1)); messurePolyline.addSegment(messureLine, true); messureLayer.addGraphic(new Graphic(mPoints.get(i), messureMarkerSymbol)); } messureLayer.addGraphic(new Graphic(mPoints.get(mPoints.size() - 1), messureMarkerSymbol)); messureLine.setStart(mPoint); messureLine.setEnd(mPoints.get(0)); messurePolyline.addSegment(messureLine, true); messureLineGraphic = new Graphic(messurePolyline, messureLineSymbol); messureAreaGraphic = new Graphic(messurePolygon, messureFillSymbol);// 初始化面的要素 messureLayer.addGraphic(messureAreaGraphic);// 将面的要素添加到图层 messureLayer.addGraphic(messureLineGraphic); messurePolygon.startPath(mPoint);// 将当前点设为初始点 } } });
这样我们就得到了名为一个messurePolygon的面,然后用这个面去进行空间查询:
mMapView.setOnLongPressListener(new OnLongPressListener() { @Override public boolean onLongPress(float v, float v1) { try { QueryParameters query = new QueryParameters(); query.setOutFields(new String[] { "*" });// 设置返回字段的数组 query.setGeometry(messurePolygon);// 设置空间几何对象 if (dataFeatureLayer == null) { return false; } else { FeatureTable mTable = dataFeatureLayer.getFeatureTable(); mTable.queryFeatures(query, new CallbackListener<FeatureResult>() { @Override public void onCallback(FeatureResult featureResul) { Landresult = getLandUseStatusAnalysisResultByPoints(featureResul); Message msg = new Message(); msg.what = ANALYSIS; handler.sendMessage(msg); } @Override public void onError(Throwable throwable) { } }); } } catch (Exception e) { Toast toast = Toast.makeText(MainActivity.this, "查寻异常", Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); } return false; } });
得到的结果我们首先会用叠加工具进行叠加处理,将处理的结果保存:
for (Object resultItem : featureResult) { Feature feature = (Feature) resultItem;// 遍历出一个结果 if (feature instanceof Feature) { Feature searchFeature = (Feature) feature; Map<String, Object> mQuerryString = feature.getAttributes(); Geometry mGeometry = GeometryEngine.intersect(searchFeature.getGeometry(), messurePolygon, mMapView.getSpatialReference()); PAnalysistItemInfo itemInfoTemp = new PAnalysistItemInfo(); mGeometry = GeometryEngine.geodesicDensifyGeometry(mGeometry, mMapView.getSpatialReference()); String dltype = getLandType("DLBM", mQuerryString).toString(); if (dltype.equals("")) { continue; } // 储存属性信息 itemInfoTemp.setDlName(mQuerryString.get("DLMC").toString()); String area1 = String.format("%.2f", Double.valueOf( GeometryEngine.geodesicArea(mGeometry, mMapView.getSpatialReference(), null)) * 0.0015); itemInfoTemp.setDlArea(area1); itemInfoTemp.setDlType(dltype); // 储存图形信息 Graphic mFeatureResultGraphic = new Graphic(mGeometry, pAnalysistSymbol); pointAnalysistGraphics.add(mFeatureResultGraphic); } }
然后就是归类统计了,这里举的例子是地类图斑的例子,根据图斑的属性按照农用地,建设用地和未利用地进行归类统计:
LandUseStatusItem item = new LandUseStatusItem(); item.AdmName = qsName; // 初始化 item.FarmLand = new FarmLand(); item.FarmLand.TotalNums = 0; item.FarmLand.TotalArea = 0.0; item.FarmLand.LandTypeMap = new HashMap<>(); item.FarmLand.GraphicList = new ArrayList<Graphic>(); item.BuildLand = new BuildLand(); item.BuildLand.TotalNums = 0; item.BuildLand.TotalArea = 0.0; item.BuildLand.LandTypeMap = new HashMap<>(); item.BuildLand.GraphicList = new ArrayList<Graphic>(); item.NoUseLand = new NoUseLand(); item.NoUseLand.TotalNums = 0; item.NoUseLand.TotalArea = 0.0; item.NoUseLand.LandTypeMap = new HashMap<>(); item.NoUseLand.GraphicList = new ArrayList<Graphic>(); item.GraphicList = new ArrayList<Graphic>(); // 归类计算 if (paList != null && !paList.isEmpty()) { for (PAnalysistItemInfo paItem : paList) { Double area = 0.0; Graphic graphic = null; try { area = Double.parseDouble(paItem.getDlArea()); graphic = paItem.getGraphic(); } catch (NumberFormatException e) { e.printStackTrace(); } item.GraphicList.add(graphic); if (paItem.getDlType().equals("农用地")) { item.FarmLand.TotalNums = item.FarmLand.TotalNums + 1; item.FarmLand.TotalArea = item.FarmLand.TotalArea + area; item.FarmLand.GraphicList.add(graphic); if (item.FarmLand.LandTypeMap.isEmpty()) { // 十二类无数据时处理 LandType landTypeItem = new LandType(); landTypeItem.TotalNums = 1; landTypeItem.TotalAreas = area; landTypeItem.LandTypeCode = ""; landTypeItem.LandTypeName = paItem.getDlName(); landTypeItem.Graphic = new ArrayList<Graphic>(); landTypeItem.Graphic.add(graphic); item.FarmLand.LandTypeMap.put(paItem.getDlName(), landTypeItem); } else { if (item.FarmLand.LandTypeMap.containsKey(paItem.getDlName())) { // 存在该类数据时处理 if (item.FarmLand.LandTypeMap.get(paItem.getDlName()) != null) { try { item.FarmLand.LandTypeMap .get(paItem.getDlName()).TotalNums = item.FarmLand.LandTypeMap .get(paItem.getDlName()).TotalNums + 1; item.FarmLand.LandTypeMap .get(paItem.getDlName()).TotalAreas = item.FarmLand.LandTypeMap .get(paItem.getDlName()).TotalAreas + area; item.FarmLand.LandTypeMap.get(paItem.getDlName()).Graphic.add(graphic); } catch (Exception e) { String ee = e.toString(); } } } else { // 已有十二类其他数据而没有该类时处理 LandType landTypeItem = new LandType(); landTypeItem.TotalNums = 1; landTypeItem.TotalAreas = area; landTypeItem.LandTypeCode = ""; landTypeItem.LandTypeName = paItem.getDlName(); landTypeItem.Graphic = new ArrayList<Graphic>(); landTypeItem.Graphic.add(graphic); item.FarmLand.LandTypeMap.put(paItem.getDlName(), landTypeItem); } } } else if (paItem.getDlType().equals("建设用地")) { item.BuildLand.TotalNums = item.BuildLand.TotalNums + 1; item.BuildLand.TotalArea = item.BuildLand.TotalArea + area; item.BuildLand.GraphicList.add(graphic); if (item.BuildLand.LandTypeMap.isEmpty()) { // 十二类无数据时处理 LandType landTypeItem = new LandType(); landTypeItem.TotalNums = 1; landTypeItem.TotalAreas = area; landTypeItem.LandTypeCode = ""; landTypeItem.LandTypeName = paItem.getDlName(); landTypeItem.Graphic = new ArrayList<Graphic>(); landTypeItem.Graphic.add(graphic); item.BuildLand.LandTypeMap.put(paItem.getDlName(), landTypeItem); } else { if (item.BuildLand.LandTypeMap.containsKey(paItem.getDlName())) { // 存在该类数据时处理 if (item.BuildLand.LandTypeMap.get(paItem.getDlName()) != null) { try { item.BuildLand.LandTypeMap .get(paItem.getDlName()).TotalNums = item.BuildLand.LandTypeMap .get(paItem.getDlName()).TotalNums + 1; item.BuildLand.LandTypeMap .get(paItem.getDlName()).TotalAreas = item.BuildLand.LandTypeMap .get(paItem.getDlName()).TotalAreas + area; item.BuildLand.LandTypeMap.get(paItem.getDlName()).Graphic.add(graphic); } catch (Exception e) { String ee = e.toString(); } } } else { // 已有十二类其他数据而没有该类时处理 LandType landTypeItem = new LandType(); landTypeItem.TotalNums = 1; landTypeItem.TotalAreas = area; landTypeItem.LandTypeCode = ""; landTypeItem.LandTypeName = paItem.getDlName(); landTypeItem.Graphic = new ArrayList<Graphic>(); landTypeItem.Graphic.add(graphic); item.BuildLand.LandTypeMap.put(paItem.getDlName(), landTypeItem); } } } else if (paItem.getDlType().equals("未利用地")) { item.NoUseLand.TotalNums = item.NoUseLand.TotalNums + 1; item.NoUseLand.TotalArea = item.NoUseLand.TotalArea + area; item.NoUseLand.GraphicList.add(graphic); if (item.NoUseLand.LandTypeMap.isEmpty()) { // 十二类无数据时处理 LandType landTypeItem = new LandType(); landTypeItem.TotalNums = 1; landTypeItem.TotalAreas = area; landTypeItem.LandTypeCode = ""; landTypeItem.LandTypeName = paItem.getDlName(); landTypeItem.Graphic = new ArrayList<Graphic>(); landTypeItem.Graphic.add(graphic); item.NoUseLand.LandTypeMap.put(paItem.getDlName(), landTypeItem); } else { if (item.NoUseLand.LandTypeMap.containsKey(paItem.getDlName())) { // 存在该类数据时处理 if (item.NoUseLand.LandTypeMap.get(paItem.getDlName()) != null) { try { item.NoUseLand.LandTypeMap .get(paItem.getDlName()).TotalNums = item.NoUseLand.LandTypeMap .get(paItem.getDlName()).TotalNums + 1; item.NoUseLand.LandTypeMap .get(paItem.getDlName()).TotalAreas = item.NoUseLand.LandTypeMap .get(paItem.getDlName()).TotalAreas + area; item.NoUseLand.LandTypeMap.get(paItem.getDlName()).Graphic.add(graphic); } catch (Exception e) { String ee = e.toString(); } } } else { // 已有十二类其他数据而没有该类时处理 LandType landTypeItem = new LandType(); landTypeItem.TotalNums = 1; landTypeItem.TotalAreas = area; landTypeItem.LandTypeCode = ""; landTypeItem.LandTypeName = paItem.getDlName(); landTypeItem.Graphic = new ArrayList<Graphic>(); landTypeItem.Graphic.add(graphic); item.NoUseLand.LandTypeMap.put(paItem.getDlName(), landTypeItem); } } } } }
最后就是将统计的结果在前端展示出来,具体的代码我就不贴了。demo资源我上传在:http://download.csdn.net/detail/bit_kaki/9919120。有兴趣的可以自己下载看看