本文通过一个简单的小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;
}
}
如需要完整代码,请在评论中留下邮箱。