本文通过一个简单的小Demo,向大家介绍如何使用ArcGIS Android API绘制点、线、面图形,并且测量线的长度和多边形的面积。
首先来看一下程序运行的效果图:
实现上述功能,首先需要向地图中添加一个GraphicsLayer,用来绘制Point、Polyline、Polygon等Graphic对象。其次需要监听地图的Touch事件,即继承MapOnTouchListener类。最后调用Line或Polyline对象的calculateLength2D方法计算长度,调用Polygon对象的calculateArea2D的方法计算面积。
主要代码如下:
在main.xml布局文件中添加MapView控件:<com.esri.android.map.MapView android:id="@+id/map" android:layout_width="fill_parent" android:layout_height="fill_parent" initExtent = "11575115, 3575676, 11596612, 3599415" />在主Activity类中(本例是MeasureTestActivity.java)定义需要用到的全局变量:
private MapView map; private GraphicsLayer drawLayer; private String strMapUrl="http://www.arcgisonline.cn/ArcGIS/rest/services/ChinaCities_Community_BaseMap_CHN/ChengDu_Community_BaseMap_CHN/MapServer"; private SimpleLineSymbol lineSymbol; private SimpleMarkerSymbol markerSymbol; private SimpleFillSymbol fillSymbol; private MapTouchListener mapTouchListener; 在MeasureTestActivity类的onCreate方法中获取地图,添加图层: map = (MapView)findViewById(R.id.map); ArcGISTiledMapServiceLayer baseMapLayer = new ArcGISTiledMapServiceLayer(strMapUrl); map.addLayer(baseMapLayer); drawLayer = new GraphicsLayer(); map.addLayer(drawLayer); 还是在MeasureTestActivity类的onCreate方法中,添加对地图touch事件的监听: mapTouchListener = new MapTouchListener(MeasureTestActivity.this, map); map.setOnTouchListener(mapTouchListener);其中MapTouchListener类继承自MapOnTouchListener类,主要用于监听地图上的touch事件,包括onSingleTap和onDoubleTap事件。onSingleTap用于绘制点、绘制当前线段(并计算长度)、绘制现有点构成的临时多边形(并计算当前面积);onDoubleTap用于结束绘制,并计算总长度和总面积。
class MapTouchListener extends MapOnTouchListener { private Geometry.Type geoType = null;//用于判定当前选择的几何图形类型 private Point ptStart = null;//起点 private Point ptPrevious = null;//上一个点 private ArrayList<Point> points = null;//记录全部点 private Polygon tempPolygon = null;//记录绘制过程中的多边形 public MapTouchListener(Context context, MapView view) { super(context, view); points = new ArrayList<Point>(); } // 根据用户选择设置当前绘制的几何图形类型 public void setType(String geometryType) { if(geometryType.equalsIgnoreCase("Point")) this.geoType = Geometry.Type.Point; else if(geometryType.equalsIgnoreCase("Polyline")) this.geoType = Geometry.Type.Polyline; else if(geometryType.equalsIgnoreCase("Polygon")) this.geoType = Geometry.Type.Polygon; } public Geometry.Type getType() { return this.geoType; } @Override public boolean onSingleTap(MotionEvent point) { Point ptCurrent = map.toMapPoint(new Point(point.getX(), point.getY())); if(ptStart == null) drawLayer.removeAll();//第一次开始前,清空全部graphic if (geoType == Geometry.Type.Point) {//直接画点 drawLayer.removeAll(); ptStart = ptCurrent; Graphic graphic = new Graphic(ptStart,markerSymbol); drawLayer.addGraphic(graphic); btnClear.setEnabled(true); return true; } else//绘制线或多边形 { points.add(ptCurrent);//将当前点加入点集合中 if(ptStart == null){//画线或多边形的第一个点 ptStart = ptCurrent; //绘制第一个点 Graphic graphic = new Graphic(ptStart,markerSymbol); drawLayer.addGraphic(graphic); } else{//画线或多边形的其他点 //绘制其他点 Graphic graphic = new Graphic(ptCurrent,markerSymbol); drawLayer.addGraphic(graphic); //生成当前线段(由当前点和上一个点构成) Line line = new Line(); line.setStart(ptPrevious); line.setEnd(ptCurrent); if(geoType == Geometry.Type.Polyline){ //绘制当前线段 Polyline polyline = new Polyline(); polyline.addSegment(line, true); Graphic g = new Graphic(polyline, lineSymbol); drawLayer.addGraphic(g); // 计算当前线段的长度 String length = Double.toString(Math.round(line.calculateLength2D())) + " 米"; Toast.makeText(map.getContext(), length, Toast.LENGTH_SHORT).show(); } else{ //绘制临时多边形 if(tempPolygon == null) tempPolygon = new Polygon(); tempPolygon.addSegment(line, false); drawLayer.removeAll(); Graphic g = new Graphic(tempPolygon, fillSymbol); drawLayer.addGraphic(g); //计算当前面积 String sArea = getAreaString(tempPolygon.calculateArea2D()); Toast.makeText(map.getContext(), sArea, Toast.LENGTH_SHORT).show(); } } ptPrevious = ptCurrent; return true; } } @Override public boolean onDoubleTap(MotionEvent point) { drawLayer.removeAll(); if(bIsMeasureLength == true){ Polyline polyline = new Polyline(); Point startPoint = null; Point endPoint = null; // 绘制完整的线段 for(int i=1;i<points.size();i++){ startPoint = points.get(i-1); endPoint = points.get(i); Line line = new Line(); line.setStart(startPoint); line.setEnd(endPoint); polyline.addSegment(line, false); } Graphic g = new Graphic(polyline, lineSymbol); drawLayer.addGraphic(g); // 计算总长度 String length = Double.toString(Math.round(polyline.calculateLength2D())) + " 米"; Toast.makeText(map.getContext(), length, Toast.LENGTH_SHORT).show(); } else{ Polygon polygon = new Polygon(); Point startPoint = null; Point endPoint = null; // 绘制完整的多边形 for(int i=1;i<points.size();i++){ startPoint = points.get(i-1); endPoint = points.get(i); Line line = new Line(); line.setStart(startPoint); line.setEnd(endPoint); polygon.addSegment(line, false); } Graphic g = new Graphic(polygon, fillSymbol); drawLayer.addGraphic(g); // 计算总面积 String sArea = getAreaString(polygon.calculateArea2D()); Toast.makeText(map.getContext(), sArea, Toast.LENGTH_SHORT).show(); } // 其他清理工作 btnClear.setEnabled(true); ptStart = null; ptPrevious = null; points.clear(); tempPolygon = null; return false; } private String getAreaString(double dValue){ long area = Math.abs(Math.round(dValue)); String sArea = ""; // 顺时针绘制多边形,面积为正,逆时针绘制,则面积为负 if(area >= 1000000){ double dArea = area / 1000000.0; sArea = Double.toString(dArea) + " 平方公里"; } else sArea = Double.toString(area) + " 平方米"; return sArea; } }如需要完整代码,请在评论中留下邮箱。