开始最前提到对地图覆盖物的使用,到目前为止只剩 Polygon(多边形) Circle(圆形)这两个还没有进一步说明,那么今天我们所要讲解的电子围栏功能会用到这两个覆盖物,当然也会用到Marker覆盖物 Polyline(折线)一起来实现:
看到这里可能有点懵,怎么一会儿是Polygon对象一会儿又是PolygonOptions对象,其实给地图添加覆盖物时需要的参数都是xxOptions对象,但是添加到地图时,返回的可操作对象就是xx了。之前添加Marker覆盖物添加时必须使用MarkerOptions,而返回的对象就是Marker对象。
用户点击地图选择电子围栏范围:
//地图上点击监听
aMap.setOnMapClickListener {
/**
* 根据用户在地图上的点击,绘制多边形的定点
*/
if (iseDitMode) { //iseditMode是一个控制当用户点击添加电子围栏时该变量修改为true
//将位置加入集合
latLngs.add(it)
//判断是否为第一个顶点
if (latLngs.size > 1) {
/*
* 如果非首个顶点添加到轨迹中
*/
//这里逻辑在运动轨迹文章中已经介绍
var polyline = aMap.addPolyline(PolylineOptions()
//集合数据
.addAll(latLngs).width(4f).setDottedLine(false).geodesic(true)
//颜色
.color(Color.argb(255, 255, 68, 0)))
polylines.add(polyline)
//移除首个锚点
this.marker!!.remove()
} else {
如果是首个顶点那么先标记成锚点
markerOptions.position(it)
marker = aMap.addMarker(markerOptions);
trajectory(it)
}
}
}
选择好电子围栏顶点点击保存:
//使用本次添加的顶点生成多边形对象并存储起来
mPolygonOptions.add(PolygonOptions().addAll(latLngs))
/**
* 移除绘制过程的定点覆盖物
*/
for (polyline in polylines) {
polyline.remove()
}
显示电子围栏
/**
* 根据用户存储的多边形对象显示电子围栏
* 通过aMap.addPolygon(polygonOptions)可以得到多边形对象
* 通过polygon.contains(LatLng)可以判断出该Latlng对象是否在电子围栏中
*
*/
private fun showPolygonOptions() {
//将存储的多边形对象取出添加到地图上
for (polygonOptions in mPolygonOptions) {
polygonOptions.fillColor(Color.argb(150, 239, 113, 113))
.strokeColor(Color.argb(150, 239, 113, 113)).strokeWidth(1f)
var polygon = aMap.addPolygon(polygonOptions);
mPolygons.add(aMap.addPolygon(polygonOptions))
}
}
关闭电子围栏显示:
/**
* 关闭显示的电子围覆盖层
*/
private fun closAllPolygonOptions() {
//循化将多个电子围栏覆盖物移除
for (polygon in mPolygons) {
polygon.remove()
}
aMap.invalidate()
}
到目前高德地图的设置不规则电子围栏设置步骤完成,但是代码还有待优化尤其显示和关闭,其实可以用显示和隐藏,不用每次添加和移除。百度地图的实现将使用不同的方式,这里就不给贴代码了 。
用户点击地图选择电子围栏范围:
//用户点击地图回调
mBaiduMap.setOnMapClickListener(object : BaiduMap.OnMapClickListener {
override fun onMapClick(latLng: LatLng) {
/**
* 根据用户的点击绘制多边形的定点
*/
if (iseDitMode) {
latLngs.add(latLng)
if (latLngs.size > 1) {
if (bdPolyline != null) {
bdPolyline!!.remove()
}
mPolylineOptions.points(latLngs).dottedLine(false).color(Color.argb(255, 255, 20, 147)).width(5)
bdPolyline = mBaiduMap.addOverlay(mPolylineOptions);
bdStartMarker1!!.remove()
} else if (latLngs.size > 0) {
var markerOption = MarkerOptions()
markerOption.position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.express_icon_location_centre_point))
bdStartMarker1 = mBaiduMap.addOverlay(markerOption)
}
}
}
override fun onMapPoiClick(mapPoi: MapPoi): Boolean {
return false
}
})
用户点击保存电子围栏:
/**
* 根据定点生产多边形对象,及可以作为围栏对象
* 通过com.baidu.mapapi.utils
* SpatialRelationUtil
* 可以判断经纬度是否在电子围栏中
* isPolygonContainsPoint()可以判断对象点位是否在电子围栏中
*/
private fun savPolygonOptions() {
if (latLngs.size > 2) {
//latLngs.add(latLngs.get(0))
var latLng = arrayListOf()
latLng = latLngs.clone() as ArrayList;
//生成多边形对象
var polygonOptions = PolygonOptions().points(latLngs).fillColor(Color.argb(150, 239, 113, 113))
//设置为不可见
polygonOptions.visible(false)
//将多边形对象存储
bdPolygonOptions.add(polygonOptions)
//添加多边形到地图,并将返回的可操作对象(电子围栏)存储
bdDrawPolylineOptionsOverlayList.add(mBaiduMap.addOverlay(polygonOptions))
//移除添加电子围栏时的选点过程
if (bdPolyline != null) {
bdPolyline!!.remove()
}
trajectory.setText("显示围栏")
} else {
Toast.makeText(this, "至少添加三个点才能建立围栏", Toast.LENGTH_LONG).show()
}
}
显示电子围栏
/**
* 显示围栏对象(高德地图也可以使用该方式显示,)
*/
private fun showPolygonOptions() {
//将电子存储的电子围栏对象取出通过setVisible(true)方法显示出来
for (overlay in bdDrawPolylineOptionsOverlayList) {
overlay.setVisible(true)
}
}
关闭电子围栏:
/**
* 隐藏围栏对象
*/
private fun closAllPolygonOptions() {
for (overlay in bdDrawPolylineOptionsOverlayList) {
overlay.setVisible(false)
}
}
百度地图添加电子围栏过程到这里完成了
通过以上分别介绍了高德地图和百度地图的电子围栏实现方法,但是怎么确定某一个位置是否位于电子围栏中呢:
高德地图通过:Polygon的contains(LatLng latLng) 方法可以知道指定的位置是否在电子围栏中不
百度地图需要通过一个工具类:com.baidu.mapapi.utils.SpatialRelationUtil
后两个方法可以判断指定位置是否在区域中
这里是通过百度地图提供的一些覆盖为去划定,区域做电子围栏添加和管理,其实还可以自定义一个画图控件覆盖在地图上,通过手动绘制区域,通过地图的Api获取屏幕位置对应的Api可以添加电子围栏,电子围栏其实就是划定的一个区域,通过两个的对不您应该发现了,百度地图和高德地图有一些Api的使用和甚至名称都相同。如果您有更好的实现过程请您分享一下。地图的使用文章更新到这里,如果有问题欢迎提问
项目已经上传Github项目地址点击这里