Commit 42135beb authored by p x's avatar p x
Browse files

迁移基础功能

parent 6b587c56
......@@ -19,7 +19,7 @@ import java.io.File
import java.io.IOException
/***在线地图上绘制小车**/
object MShowMainCarModel {
object MShowMainCarModel {
//四维主车obj模型
private var objPath = ""
......
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic
import android.location.Location
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.model.LatLng
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.bean.MSLatLng
import com.amap.api.maps.model.LatLng as ALatLng
/**
* 地图计算工具
......@@ -40,8 +39,8 @@ object MSCalcuMapUtil {
MAP_TYPE.AMAP -> {
// 使用高德地图工具类计算两点间距离
val latlngA = ALatLng(latLng1.lat, latLng1.lng)
val latlngB = ALatLng(latLng2.lat, latLng2.lng)
val latlngA = LatLng(latLng1.lat, latLng1.lng)
val latlngB = LatLng(latLng2.lat, latLng2.lng)
val distance = AMapUtils.calculateLineDistance(latlngA, latlngB)
return distance
}
......@@ -66,8 +65,8 @@ object MSCalcuMapUtil {
}
MAP_TYPE.AMAP -> {
val leftTopLatlng = ALatLng(latLng1.lat, latLng1.lng)
val rightBottomLatlng = ALatLng(latLng2.lat, latLng2.lng)
val leftTopLatlng = LatLng(latLng1.lat, latLng1.lng)
val rightBottomLatlng = LatLng(latLng2.lat, latLng2.lng)
val area = AMapUtils.calculateArea(leftTopLatlng, rightBottomLatlng)
return area
}
......
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic
import android.graphics.BitmapFactory
import androidx.core.graphics.toColorInt
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.Circle
import com.amap.api.maps.model.Polygon
import com.amap.api.maps.model.Polyline
import com.minedata.minenavi.map.CircleOptions
import com.minedata.minenavi.map.Marker
import com.minedata.minenavi.map.MarkerOptions
import com.minedata.minenavi.map.Overlay
import com.minedata.minenavi.map.PolygonOptions
import com.minedata.minenavi.map.PolylineOptions
import com.minedata.minenavi.mapdal.LatLng
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.R
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.MSLatLng
import com.sd.maplibrary.core.MapReadyView
import com.amap.api.maps.model.CircleOptions as ACircleOptions
import com.amap.api.maps.model.LatLng as ALatLng
import com.amap.api.maps.model.Marker as AMarker
import com.amap.api.maps.model.MarkerOptions as AMarkerOptions
import com.amap.api.maps.model.PolygonOptions as APolygonOptions
import com.amap.api.maps.model.PolylineOptions as APolylineOptions
/**返回的mark*/
object MSMarker {
//四维mark
var maker: Marker? = null
//高德mark
var amaker: AMarker? = null
}
/**返回的图层*/
object MSOverlay {
//四维线图层
var polyline: Overlay? = null
//四维面图层
var polygon: Overlay? = null
//四维圆形图层
var circle: Overlay? = null
//高德圆形
var aCircle: Circle? = null
//高德线
var aPolyline: Polyline? = null
//高德面
var aPolygon: Polygon? = null
}
/**
* 在地图上绘制
*/
object MSCanvesInMap {
object MSDrawInMap {
/**
......@@ -70,7 +28,7 @@ object MSCanvesInMap {
* @param lng 经度坐标
* @return MSMarker 标记点对象
*/
fun drawMarket(
/*fun drawMarket(
mapReadView: MapReadyView?,
lat: Double,
lng: Double
......@@ -110,7 +68,7 @@ object MSCanvesInMap {
return MSMarker
}
}
}
}*/
/**
......@@ -122,7 +80,7 @@ object MSCanvesInMap {
* @param isDotted 是否为虚线,默认为false
* @return MSOverlay 覆盖物对象
*/
fun drawPolyline(
/* fun drawPolyline(
mapReadView: MapReadyView?,
msLatLng: List<MSLatLng>,
width: Float = 10f,
......@@ -161,7 +119,7 @@ object MSCanvesInMap {
return MSOverlay
}
}
}
}*/
/**绘制圆形
......@@ -174,7 +132,7 @@ object MSCanvesInMap {
* @param strokeWidth 边框宽度,默认为15f
* @return MSOverlay 返回覆盖物对象
*/
fun drawCircle(
/* fun drawCircle(
mapReadView: MapReadyView?,
lat: Double,
lng: Double,
......@@ -211,7 +169,7 @@ object MSCanvesInMap {
return MSOverlay
}
}
}
}*/
/***
......@@ -222,7 +180,7 @@ object MSCanvesInMap {
* @param strokeWidth 边框宽度
* @param strokeColor 边框颜色
* ****/
fun drawPolygon(
/* fun drawPolygon(
mapReadView: MapReadyView?,
msLatLng: List<MSLatLng>,
dLine: Boolean = false,
......@@ -263,7 +221,7 @@ object MSCanvesInMap {
return MSOverlay
}
}
}
}*/
/**
......
package com.sd.maplibrary.core.basic
/**
* 定位蓝点常量
*/
object MSLocStyle {
/**定位一次,且将视角移动到地图中心点**/
const val LOCATION_TYPE_LOCATE: Int = 2
/**连续定位、且将视角移动到地图中心点,定位蓝点跟随设备移动**/
const val LOCATION_TYPE_FOLLOW: Int = 3
/**连续定位、且将视角移动到地图中心点,地图依照设备方向旋转,定位点会跟随设备移动**/
const val LOCATION_TYPE_MAP_ROTATE: Int = 4
/**连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动**/
const val LOCATION_TYPE_LOCATION_ROTATE: Int = 5
/**连续定位、蓝点不会移动到地图中心点,定位点依照设备方向旋转,并且蓝点会跟随设备移动**/
const val LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER: Int = 6
/**连续定位、蓝点不会移动到地图中心点,并且蓝点会跟随设备移动**/
const val LOCATION_TYPE_FOLLOW_NO_CENTER: Int = 7
/**连续定位、蓝点不会移动到地图中心点,地图依照设备方向旋转,并且蓝点会跟随设备移动**/
const val LOCATION_TYPE_MAP_ROTATE_NO_CENTER: Int = 8
}
\ No newline at end of file
package com.sd.maplibrary.core.basic
import com.amap.api.maps.model.Marker as AMarker
import com.minedata.minenavi.map.Marker
/**返回的mark*/
object MSMarker {
/**四维mark*/
var maker: Marker? = null
/**高德mark*/
var amaker: AMarker? = null
}
\ No newline at end of file
package com.sd.maplibrary.core.basic
import com.amap.api.maps.model.Circle
import com.amap.api.maps.model.Polygon
import com.amap.api.maps.model.Polyline
import com.minedata.minenavi.map.Overlay
/**返回的图层*/
object MSOverlay {
//四维线图层
var polyline: Overlay? = null
//四维面图层
var polygon: Overlay? = null
//四维圆形图层
var circle: Overlay? = null
//高德圆形
var aCircle: Circle? = null
//高德线
var aPolyline: Polyline? = null
//高德面
var aPolygon: Polygon? = null
}
\ No newline at end of file
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic
import com.amap.api.services.core.AMapException
import com.minedata.minenavi.poiquery.GeocodeResult
......@@ -10,13 +10,9 @@ import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.RegeocodeRes
import com.amap.api.services.core.LatLonPoint as ALatLonPoint
import com.amap.api.services.geocoder.GeocodeSearch as AGeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery as ARegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult as ARegeocodeResult
/**逆地理编码*/
object MSRegeoCode : GeocodeSearch.OnGeocodeSearchListener, AGeocodeSearch.OnGeocodeSearchListener {
object MSRegeoCode : GeocodeSearch.OnGeocodeSearchListener, com.amap.api.services.geocoder.GeocodeSearch.OnGeocodeSearchListener {
private var mSOnRegeo: MSOnRegeo? = null
......@@ -38,7 +34,7 @@ object MSRegeoCode : GeocodeSearch.OnGeocodeSearchListener, AGeocodeSearch.OnGeo
if (lat == 0.0 || lng == 0.0)
return
this.mSOnRegeo = msOnRegeo
var context= UserCtx.instance.mContext
var context= UserCtx.Companion.instance.mContext
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
val geocoderSearch = GeocodeSearch(context)
......@@ -50,11 +46,11 @@ object MSRegeoCode : GeocodeSearch.OnGeocodeSearchListener, AGeocodeSearch.OnGeo
MAP_TYPE.AMAP -> {
// 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系
val query = ARegeocodeQuery(
ALatLonPoint(lat, lng), 200f,
AGeocodeSearch.AMAP
val query = com.amap.api.services.geocoder.RegeocodeQuery(
com.amap.api.services.core.LatLonPoint(lat, lng), 200f,
com.amap.api.services.geocoder.GeocodeSearch.AMAP
)
var geocoderSearch = AGeocodeSearch(context)
var geocoderSearch = com.amap.api.services.geocoder.GeocodeSearch(context)
geocoderSearch.setOnGeocodeSearchListener(this)
geocoderSearch.getFromLocationAsyn(query) // 设置异步逆地理编码请求
}
......@@ -97,7 +93,7 @@ object MSRegeoCode : GeocodeSearch.OnGeocodeSearchListener, AGeocodeSearch.OnGeo
* 逆地理编码回调
*/
override fun onRegeocodeSearched(
result: ARegeocodeResult?,
result: com.amap.api.services.geocoder.RegeocodeResult?,
rCode: Int
) {
if (rCode == AMapException.CODE_AMAP_SUCCESS) {
......
package com.sd.maplibrary.core.basic
import com.sd.maplibrary.bean.PoiSearchRes
/**
* POI搜素回调
*/
interface OnMSPoiSearchLis {
/**
* 搜索返回
* @param poiList 返回列表
*/
fun onPoiLis(poiList: List<PoiSearchRes>)
}
\ No newline at end of file
package com.sd.maplibrary.core.basic
import com.sd.maplibrary.bean.MSLocBean
/**业务层Gps定位回调接口**/
interface OnMsGpsLoc {
fun onMsGpsLoc(mSLocBean: MSLocBean)
}
\ No newline at end of file
package com.sd.maplibrary.core.basic.amap
import android.graphics.BitmapFactory
import androidx.core.graphics.toColorInt
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.Circle
import com.amap.api.maps.model.Polygon
import com.amap.api.maps.model.Polyline
import com.minedata.minenavi.map.CircleOptions
import com.minedata.minenavi.map.Marker
import com.minedata.minenavi.map.MarkerOptions
import com.minedata.minenavi.map.Overlay
import com.minedata.minenavi.map.PolygonOptions
import com.minedata.minenavi.map.PolylineOptions
import com.minedata.minenavi.mapdal.LatLng
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.R
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.MSLatLng
import com.sd.maplibrary.core.MapReadyView
import com.sd.maplibrary.core.basic.MSMarker
import com.sd.maplibrary.core.basic.MSOverlay
import com.amap.api.maps.model.CircleOptions as ACircleOptions
import com.amap.api.maps.model.LatLng as ALatLng
import com.amap.api.maps.model.Marker as AMarker
import com.amap.api.maps.model.MarkerOptions as AMarkerOptions
import com.amap.api.maps.model.PolygonOptions as APolygonOptions
import com.amap.api.maps.model.PolylineOptions as APolylineOptions
/**
* 在地图上绘制
*/
object AmapDrawInMap {
/**
* 绘制 marker 点
* @param mapReadView 地图准备就绪的视图对象
* @param lat 纬度坐标
* @param lng 经度坐标
* @return MSMarker 标记点对象
*/
fun drawMarket(
mapReadView: MapReadyView?,
lat: Double,
lng: Double
): MSMarker {
var context = UserCtx.instance.mContext
// 处理高德地图类型的标记点绘制
val aLatLng = ALatLng(lat, lng)
val aMarkerOption = AMarkerOptions().apply {
position(aLatLng)
icon(
BitmapDescriptorFactory.fromBitmap(
BitmapFactory
.decodeResource(context?.resources, R.drawable.market_loc)
)
)
}
var aMaker = mapReadView?.aMap?.addMarker(aMarkerOption)
MSMarker.amaker = aMaker
return MSMarker
}
/**
* 绘制线
* @param mapReadView 地图加载返回
* @param msLatLng 坐标点集合
* @param width 线宽度,默认为10f
* @param fcolor 线颜色,默认为"#FF00FF"对应的int值
* @param isDotted 是否为虚线,默认为false
* @return MSOverlay 覆盖物对象
*/
fun drawPolyline(
mapReadView: MapReadyView?,
msLatLng: List<MSLatLng>,
width: Float = 10f,
fcolor: Int = "#FF00FF".toColorInt(),
isDotted: Boolean = false
): MSOverlay {
// 绘制高德地图的线
var latLngs = msLatLng.map {
ALatLng(it.lat, it.lng)
}
val aOption = APolylineOptions().addAll(latLngs)
.width(width)
.color(fcolor)
.setDottedLine(isDotted)
var polyline = mapReadView?.aMap?.addPolyline(aOption)
MSOverlay.aPolyline = polyline
return MSOverlay
}
/**绘制圆形
* @param mapReadView 地图准备就绪视图对象
* @param lat 维度
* @param lng 经度
* @param radius 半径(米)
* @param fillColor 填充颜色,默认为半透明红色
* @param strokeColor 边框颜色,默认为半透明蓝色
* @param strokeWidth 边框宽度,默认为15f
* @return MSOverlay 返回覆盖物对象
*/
fun drawCircle(
mapReadView: MapReadyView?,
lat: Double,
lng: Double,
radius: Float,
fillColor: Int = "#50FF0000".toColorInt(),
strokeColor: Int = "#500000FF".toColorInt(),
strokeWidth: Float = 15f
): MSOverlay {
var latLng = ALatLng(lat, lng)
val options = ACircleOptions()
.center(latLng)
.radius(radius.toDouble())
.fillColor(fillColor)
.strokeColor(strokeColor)
.strokeWidth(strokeWidth)
var circle = mapReadView?.aMap?.addCircle(options)
MSOverlay.aCircle = circle
return MSOverlay
}
/***
* 绘制多边形
* @param msLatLng 添加多边形顶点坐标集合
* @param dLine 是否虚线
* @param fillColor 填充颜色
* @param strokeWidth 边框宽度
* @param strokeColor 边框颜色
* ****/
fun drawPolygon(
mapReadView: MapReadyView?,
msLatLng: List<MSLatLng>,
dLine: Boolean = false,
fillColor: Int = "#10FF00FF".toColorInt(),
strokeWidth: Float = 5f,
strokeColor: Int = "#50FF00FF".toColorInt()
): MSOverlay {
var latLngs = msLatLng.map {
ALatLng(it.lat, it.lng)
}
val aPolygonOptions = APolygonOptions().apply {
addAll(latLngs)
fillColor(fillColor)
strokeWidth(strokeWidth)
strokeColor(strokeColor)
}
var polygon = mapReadView?.aMap?.addPolygon(aPolygonOptions)
MSOverlay.aPolygon = polygon
return MSOverlay
}
}
\ No newline at end of file
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic.amap
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.core.MapReadyView
/**
* 手势交互
* 高德手势交互
*/
object MSGestures {
object AmapGestures {
//
// /***缩放**/
......@@ -31,15 +30,7 @@ object MSGestures {
*/
fun setRotateGesturesEnabled(mapReadView: MapReadyView?, enable: Boolean) {
// 根据不同的地图类型设置对应的旋转手势可用状态
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
mapReadView?.fMapView?.uiSettings?.isRotateGesturesEnabled = enable
}
MAP_TYPE.AMAP -> {
mapReadView?.aMap?.uiSettings?.isRotateGesturesEnabled = enable
}
}
mapReadView?.aMap?.uiSettings?.isRotateGesturesEnabled = enable
}
......@@ -48,17 +39,9 @@ object MSGestures {
* @param mapReadView 地图准备就绪视图对象
* @param enable 是否启用倾斜手势功能,true为启用,false为禁用
* */
fun setTiltGesturesEnabled(mapReadView: MapReadyView, enable: Boolean) {
fun setTiltGesturesEnabled(mapReadView: MapReadyView?, enable: Boolean) {
// 根据不同的地图类型设置对应的倾斜手势功能
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
mapReadView.fMapView?.uiSettings?.isTiltGesturesEnabled = enable
}
MAP_TYPE.AMAP -> {
mapReadView.aMap?.uiSettings?.isTiltGesturesEnabled = enable
}
}
mapReadView?.aMap?.uiSettings?.isTiltGesturesEnabled = enable
}
......
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic.amap
import android.annotation.SuppressLint
import android.os.Bundle
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode
import com.amap.api.location.AMapLocationClientOption.AMapLocationProtocol
import com.amap.api.location.AMapLocationListener
import com.minedata.minenavi.location.MineLocation
import com.minedata.minenavi.location.MineLocationListener
import com.minedata.minenavi.location.MineLocationManager
import com.minedata.minenavi.location.MineLocationOptions
import com.minedata.minenavi.mapdal.CoordType
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.MSLocBean
import com.sd.maplibrary.core.basic.OnMsGpsLoc
/**GPS定位类*/
object MSGpsLocation {
class AmapGpsLocation {
// 设置四维定位参数,并开始定位。
private val options: MineLocationOptions by lazy {
MineLocationOptions().apply {
setCoordType(CoordType.GCJ02)
setGpsInterval(1000)//GPS定位更新时间,最小1000
setNetWorkInterval(3000)//WiFi定位更新时间,最小3000
setStationInterval(5000)//基站定位更新时间,最小500
}
companion object {
val instance: AmapGpsLocation by lazy { AmapGpsLocation() }
}
// 设置高德定位参数
private val locationOption: AMapLocationClientOption by lazy {
val mOption = AMapLocationClientOption()
......@@ -51,134 +37,50 @@ object MSGpsLocation {
}
// 高德定位实例
@SuppressLint("StaticFieldLeak")
private var alocationClient: AMapLocationClient? = null
/**业务层Gps定位回调**/
private var onMsGpsLoc: OnMsGpsLoc? = null
/**初始化定位*/
fun initLoc() {
private fun initLoc() {
var context = UserCtx.instance.mContext
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
MineLocationManager.getInstance()
.init(context, MineLocationManager.LocationSource.gpsAndNetwork)
// MineLocationManager.getInstance().removeListener(mineLocationListener)
MineLocationManager.getInstance().addListener(mineLocationListener)
}
MAP_TYPE.AMAP -> {
alocationClient = AMapLocationClient(context)
//设置定位参数
alocationClient!!.setLocationOption(locationOption)
// 设置定位监听
alocationClient!!.setLocationListener(locationListener)
}
}
}
/**
* 设置GPS定位回调监听器
* @param onMsGpsLoc GPS定位回调监听器实例
*/
fun setOnMsGpsLoc(onMsGpsLoc: OnMsGpsLoc) {
this.onMsGpsLoc = onMsGpsLoc
alocationClient = AMapLocationClient(context)
//设置定位参数
alocationClient!!.setLocationOption(locationOption)
// 设置定位监听
alocationClient!!.setLocationListener(locationListener)
}
/**开启定位*/
fun starLoc() {
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
MineLocationManager.getInstance().start(options)
}
MAP_TYPE.AMAP -> {
fun starLoc(onMsGpsLoc: OnMsGpsLoc) {
initLoc()
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
// 注意设置合适的定位时间的间隔(最小间隔支持为1000ms),并且在合适时间调用stopLocation()方法来取消定位请求
// 在定位结束后,在合适的生命周期调用onDestroy()方法
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
//启动定位
alocationClient?.startLocation()
}
}
alocationClient?.startLocation()
}
/**停止定位*/
fun stopLoc() {
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
MineLocationManager.getInstance().removeAllListener()
MineLocationManager.getInstance().stop()
}
MAP_TYPE.AMAP -> {
alocationClient?.stopLocation()
}
}
// alocationClient?.unRegisterLocationListener(locationListener)
alocationClient?.stopLocation()
}
/**清理定位资源**/
fun cleansLoc() {
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
MineLocationManager.getInstance().cleanup()
}
MAP_TYPE.AMAP -> {
alocationClient?.onDestroy()
alocationClient = null
}
}
}
//----------------自定义回调---------
/**业务层Gps定位回调接口**/
interface OnMsGpsLoc {
fun onMsGpsLoc(mSLocBean: MSLocBean)
}
//---------------四维回调---------------
private var mineLocationListener = object : MineLocationListener {
override fun onSimLocationChanged(location: MineLocation?) {
}
override fun onLocationChanged(location: MineLocation?) {
// println("-------四维定位改变 = ${location?.latitude} curLng=${location?.longitude} speed=${location?.speed}")
var loc = MSLocBean.instance.apply {
lat = location?.latitude ?: 0.0
lng = location?.longitude ?: 0.0
speed = location?.speed ?: 0f
bearing = location?.bearing ?: 0f
accuracy = location?.accuracy ?: 0f
altitude = location?.altitude ?: 0.0
}
onMsGpsLoc?.onMsGpsLoc(loc)
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
}
override fun onProviderEnabled(provider: String?) {
}
override fun onProviderDisabled(provider: String?) {
}
alocationClient?.onDestroy()
}
//-------高德回调------
var locationListener: AMapLocationListener = object : AMapLocationListener {
override fun onLocationChanged(location: AMapLocation?) {
if (null != location) {
val sb = StringBuffer()
// val sb = StringBuffer()
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if (location.getErrorCode() == 0) {
// println("-------高德定位改变 = ${location?.latitude} curLng=${location?.longitude} speed=${location?.speed}")
......
package com.sd.maplibrary.core.basic.amap
import com.sd.maplibrary.core.MapReadyView
import com.sd.maplibrary.core.basic.MSLocStyle
import com.amap.api.maps.model.MyLocationStyle as aMapMyLocationStyle
/**
* 显示定位小圆点
*/
object AmapLocationStyle {
// 高德定位类型
private var styleAMap = mapOf(
MSLocStyle.LOCATION_TYPE_LOCATE to aMapMyLocationStyle.LOCATION_TYPE_LOCATE,
MSLocStyle.LOCATION_TYPE_FOLLOW to aMapMyLocationStyle.LOCATION_TYPE_FOLLOW,
MSLocStyle.LOCATION_TYPE_MAP_ROTATE to aMapMyLocationStyle.LOCATION_TYPE_MAP_ROTATE,
MSLocStyle.LOCATION_TYPE_LOCATION_ROTATE to aMapMyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE,
MSLocStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER to aMapMyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER,
MSLocStyle.LOCATION_TYPE_FOLLOW_NO_CENTER to aMapMyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER,
MSLocStyle.LOCATION_TYPE_MAP_ROTATE_NO_CENTER to aMapMyLocationStyle.LOCATION_TYPE_MAP_ROTATE_NO_CENTER
)
//高德初始化定位蓝点样式类
private val aMyLocationStyle by lazy { aMapMyLocationStyle() }
/**
* 设置定位蓝点样式
* @param mapReadView 地图准备就绪视图对象
* @param type 定位类型,默认为LOCATION_TYPE_LOCATION_ROTATE,表示连续定位并旋转视角
*/
fun setLocationStyle(mapReadView: MapReadyView?, type: Int = MSLocStyle.LOCATION_TYPE_LOCATION_ROTATE) {
var aMap = mapReadView?.aMap
aMyLocationStyle.myLocationType(styleAMap.get(type)!!)
aMyLocationStyle.interval(2000) //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
//aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示,非必需设置。
aMap?.setMyLocationEnabled(true) // 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
aMap?.setMyLocationStyle(aMyLocationStyle)//设置定位蓝点的Style
}
}
\ No newline at end of file
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic.amap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.CameraPosition
import com.minedata.minenavi.mapdal.LatLng
import com.minedata.minenavi.util.Tools
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.sd.maplibrary.core.MapReadyView
import com.amap.api.maps.model.LatLng as ALatLng
/**
* 地图方法交互
* 高德地图方法交互
*/
object MSMethodAdv {
object AmapMethodAdv {
/****
* 改变地图中心点
......@@ -25,22 +22,11 @@ object MSMethodAdv {
lat: Double = 39.977290,
lng: Double = 116.337000
) {
when (MSDKInitializer.getMapType()) {
// 处理自定义地图类型
MAP_TYPE.MINE -> {
val point = Tools.latLngToPoint(LatLng(lat, lng))
mapReadView?.mMineMap?.setPointToCenter(point.x, point.y)
}
// 处理高德地图类型
MAP_TYPE.AMAP -> {
//参数依次是:视角调整区域的中心点坐标、希望调整到的缩放级别、俯仰角0°~45°(垂直与地图时为0)、偏航角 0~360° (正北方为0)
val mCameraUpdate = CameraUpdateFactory.newCameraPosition(
CameraPosition(ALatLng(lat, lng), 18f, 30f, 0f)
)
mapReadView?.aMap?.moveCamera(mCameraUpdate)
}
}
//参数依次是:视角调整区域的中心点坐标、希望调整到的缩放级别、俯仰角0°~45°(垂直与地图时为0)、偏航角 0~360° (正北方为0)
val mCameraUpdate = CameraUpdateFactory.newCameraPosition(
CameraPosition(ALatLng(lat, lng), 18f, 30f, 0f)
)
mapReadView?.aMap?.moveCamera(mCameraUpdate)
}
......@@ -50,17 +36,8 @@ object MSMethodAdv {
* @param zoom 缩放级别,值越小站得越高,默认值为13f
* */
fun setMapZoom(mapReadView: MapReadyView?, zoom: Float = 13f) {
// 根据不同的地图类型设置对应的缩放级别
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
mapReadView?.mMineMap?.setZoomLevel(zoom)
}
MAP_TYPE.AMAP -> {
var mCameraUpdate = CameraUpdateFactory.zoomTo(zoom)
mapReadView?.aMap?.moveCamera(mCameraUpdate)
}
}
var mCameraUpdate = CameraUpdateFactory.zoomTo(zoom)
mapReadView?.aMap?.moveCamera(mCameraUpdate)
}
......@@ -71,20 +48,10 @@ object MSMethodAdv {
*/
fun getMapZoom(mapReadView: MapReadyView?): Float {
// 根据不同的地图类型获取对应的缩放级别
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
return mapReadView?.mMineMap?.zoomLevel?:0f
}
MAP_TYPE.AMAP -> {
return mapReadView?.aMap?.cameraPosition?.zoom?:0f
}
}
return mapReadView?.aMap?.cameraPosition?.zoom ?: 0f
}
/***设置地图显示区域**/
// fun setMapBoundArea(mapReadView: MapReadyView?) {
// when (MSDKInitializer.getMapType()) {
......
package com.sd.maplibrary.core
package com.sd.maplibrary.core.basic.amap
import android.content.Context
import com.amap.api.services.core.AMapException
import com.minedata.minenavi.mapdal.PoiItem
import com.minedata.minenavi.poiquery.LatLonPoint
import com.minedata.minenavi.poiquery.PoiResult
import com.minedata.minenavi.poiquery.PoiSearch
import com.minedata.minenavi.poiquery.SearchErrorCode
import com.minedata.minenavi.poiquery.SortType
import com.sd.maplibrary.MAP_TYPE
import com.sd.maplibrary.MSDKInitializer
import com.amap.api.services.poisearch.PoiSearch.SearchBound
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.PoiSearchRes
import com.sd.maplibrary.core.basic.OnMSPoiSearchLis
import com.amap.api.services.core.LatLonPoint as ALatLonPoint
import com.amap.api.services.poisearch.PoiResult as APoiResult
import com.amap.api.services.poisearch.PoiSearch as APoiSearch
import com.amap.api.services.poisearch.PoiSearch.SearchBound
import com.sd.maplibrary.UserCtx
/****Poi 搜索相关**/
object MSPoiSearch : PoiSearch.OnPoiSearchListener, APoiSearch.OnPoiSearchListener {
/**
* 高配的Poi 搜索相关
*/
object AmapPoiSearch : APoiSearch.OnPoiSearchListener {
private var onMSPoiSearchLis: OnMSPoiSearchLis? = null
//四维搜索对象
// private var poiSearch: PoiSearch? = null
//搜索接口回调
interface OnMSPoiSearchLis {
/**
* 搜索返回
* @param poiList 返回列表
*/
fun onPoiLis(poiList: List<PoiSearchRes>)
}
/**关键字搜索
* @param keyWord 关键字
......@@ -50,40 +32,19 @@ object MSPoiSearch : PoiSearch.OnPoiSearchListener, APoiSearch.OnPoiSearchListen
) {
this.onMSPoiSearchLis = onMSPoiSearchLis
var context = UserCtx.instance.mContext
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
val poiSearch = PoiSearch(context)
poiSearch.setOnPoiSearchListener(this)
val query = PoiSearch.Query(keyWord, "", "").apply {
// 设置查询位置点
location = LatLonPoint(lat, lng)
// 限制严格按照设置城市搜索
setCityLimit(false)
// 设置排序方式为热度排序
setSortType(SortType.SORT_TYPE_HIT)
// 返回父子关系
requireSubPois(true)
pageNum = 0
setPageSize(20)// 设置每页最多返回多少条poiitem
}
poiSearch.query = query
poiSearch.searchPOIAsyn()
}
MAP_TYPE.AMAP -> {
var query = APoiSearch.Query(keyWord, "", "").apply {
location = ALatLonPoint(lat, lng)
cityLimit = false
// 返回父子关系
requireSubPois(true)
pageNum = 1
pageSize = 20
}
var poiSearch = APoiSearch(context, query)
poiSearch.setOnPoiSearchListener(this)
poiSearch.searchPOIAsyn()
}
var query = APoiSearch.Query(keyWord, "", "").apply {
location = ALatLonPoint(lat, lng)
cityLimit = false
// 返回父子关系
requireSubPois(true)
pageNum = 1
pageSize = 20
}
var poiSearch = APoiSearch(context, query)
poiSearch.setOnPoiSearchListener(this)
poiSearch.searchPOIAsyn()
}
/**周边搜索
......@@ -102,77 +63,22 @@ object MSPoiSearch : PoiSearch.OnPoiSearchListener, APoiSearch.OnPoiSearchListen
) {
this.onMSPoiSearchLis = onMSPoiSearchLis
var context = UserCtx.instance.mContext
when (MSDKInitializer.getMapType()) {
MAP_TYPE.MINE -> {
val poiSearch = PoiSearch(context)
poiSearch.setOnPoiSearchListener(this)
// 第一个参数表示搜索中心点, 第二个参数表示搜索半径
val bound = PoiSearch.SearchBound(LatLonPoint(lat, lng), radios)
poiSearch.setBound(bound)
// 第一个参数表示搜索关键字(可传空字符串),
// 第二个参数表示 POI 搜索类型,不同类型用|分割,
// 第三个参数表示 POI 搜索城市编码
val query = PoiSearch.Query(keyWord, "", "").apply {
// 设置查询位置点
location = LatLonPoint(lat, lng)
// 限制严格按照设置城市搜索
setCityLimit(true)
// 设置排序方式为热度排序
setSortType(SortType.SORT_TYPE_HIT)
// 返回父子关系
requireSubPois(true)
pageNum = 0
setPageSize(20)// 设置每页最多返回多少条poiitem
}
poiSearch.query = query
poiSearch.searchPOIAsyn()
}
MAP_TYPE.AMAP -> {
var query = APoiSearch.Query(keyWord, "", "").apply {
location = ALatLonPoint(lat, lng)
cityLimit = true
// 返回父子关系
requireSubPois(true)
pageNum = 1
pageSize = 20
}
var poiSearch = APoiSearch(context, query)
poiSearch.setOnPoiSearchListener(this)
poiSearch.setBound(SearchBound(ALatLonPoint(lat, lng), radios, true))
poiSearch.searchPOIAsyn()
}
var query = APoiSearch.Query(keyWord, "", "").apply {
location = ALatLonPoint(lat, lng)
cityLimit = true
// 返回父子关系
requireSubPois(true)
pageNum = 1
pageSize = 20
}
}
var poiSearch = APoiSearch(context, query)
poiSearch.setOnPoiSearchListener(this)
poiSearch.setBound(SearchBound(ALatLonPoint(lat, lng), radios, true))
//---------------------------------四维POI 返回 -------------------------------
override fun onPoiItemSearched(p0: PoiItem?, p1: Int) {
var b = 0
}
poiSearch.searchPOIAsyn()
override fun onPoiSearched(result: PoiResult?, rCode: Int) {
if (rCode == SearchErrorCode.none) {
var temps = result?.getPois()
var poiList = temps!!.map { pos ->
PoiSearchRes().apply {
lat = pos.location.latitude
lng = pos.location.longitude
title = pos.title
snippet = pos.snippet
cityName = pos.cityName
//这里为0 因为不是范围搜索
distance = pos.distance
adCode = pos.adCode
}
}
onMSPoiSearchLis?.onPoiLis(poiList)
} else {
onMSPoiSearchLis?.onPoiLis(listOf())
}
}
......
package com.sd.maplibrary.core.basic.mine
import com.sd.maplibrary.core.MapReadyView
/**
* 四维手势交互
*/
object MimeGestures {
//
// /***缩放**/
// fun setZoomGesturesEnabled(mapReadView: MapReadyView,enable: Boolean) {
// when (MSDKInitializer.getMapType()) {
// MAP_TYPE.MINE -> {
// mapReadView.fMapView?.zoomView.is
// }
//
// MAP_TYPE.AMAP -> {
// mapReadView.amap?.uiSettings?.setZoomGesturesEnabled(enable)
// }
// }
// }
/**
* 设置地图旋转手势是否可用
* @param mapReadView 地图准备就绪视图对象
* @param enable 是否启用旋转手势功能
*/
fun setRotateGesturesEnabled(mapReadView: MapReadyView?, enable: Boolean) {
// 根据不同的地图类型设置对应的旋转手势可用状态
mapReadView?.fMapView?.uiSettings?.isRotateGesturesEnabled = enable
}
/**
* 设置地图倾斜手势功能的启用状态
* @param mapReadView 地图准备就绪视图对象
* @param enable 是否启用倾斜手势功能,true为启用,false为禁用
* */
fun setTiltGesturesEnabled(mapReadView: MapReadyView?, enable: Boolean) {
// 根据不同的地图类型设置对应的倾斜手势功能
mapReadView?.fMapView?.uiSettings?.isTiltGesturesEnabled = enable
}
}
\ No newline at end of file
package com.sd.maplibrary.core.basic.mine
import android.graphics.BitmapFactory
import androidx.core.graphics.toColorInt
import com.minedata.minenavi.map.CircleOptions
import com.minedata.minenavi.map.MarkerOptions
import com.minedata.minenavi.map.PolygonOptions
import com.minedata.minenavi.map.PolylineOptions
import com.minedata.minenavi.mapdal.LatLng
import com.sd.maplibrary.R
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.MSLatLng
import com.sd.maplibrary.core.MapReadyView
import com.sd.maplibrary.core.basic.MSMarker
import com.sd.maplibrary.core.basic.MSOverlay
/**
* 四维在地图上绘制
*/
object MineDrawInMap {
/**
* 绘制 marker 点
* @param mapReadView 地图准备就绪的视图对象
* @param lat 纬度坐标
* @param lng 经度坐标
* @return MSMarker 标记点对象
*/
fun drawMarket(
mapReadView: MapReadyView?,
lat: Double,
lng: Double
): MSMarker {
var context = UserCtx.instance.mContext
// 根据不同的地图类型绘制标记点
val icon = BitmapFactory.decodeResource(context?.resources, R.drawable.market_loc)
val latLng = LatLng(lat, lng)
var options = MarkerOptions()
.zLevel(7)
.bitmap(icon)
// 位置坐标
.position(latLng)
var maker = mapReadView?.mMineMap?.addMarker(options)
MSMarker.maker = maker
return MSMarker
}
/**
* 绘制线
* @param mapReadView 地图加载返回
* @param msLatLng 坐标点集合
* @param width 线宽度,默认为10f
* @param fcolor 线颜色,默认为"#FF00FF"对应的int值
* @param isDotted 是否为虚线,默认为false
* @return MSOverlay 覆盖物对象
*/
fun drawPolyline(
mapReadView: MapReadyView?,
msLatLng: List<MSLatLng>,
width: Float = 10f,
fcolor: Int = "#FF00FF".toColorInt(),
isDotted: Boolean = false
): MSOverlay {
// 绘制自定义地图的线
var latLngs = msLatLng.map {
LatLng(it.lat, it.lng)
}
var options = PolylineOptions()
// 添加顶点坐标
.addAll(latLngs)
.width(width)
.color(fcolor)
.setDottedLine(isDotted)
var polyline = mapReadView?.mMineMap?.addPolyline(options)
MSOverlay.polyline = polyline
return MSOverlay
}
/**绘制圆形
* @param mapReadView 地图准备就绪视图对象
* @param lat 维度
* @param lng 经度
* @param radius 半径(米)
* @param fillColor 填充颜色,默认为半透明红色
* @param strokeColor 边框颜色,默认为半透明蓝色
* @param strokeWidth 边框宽度,默认为15f
* @return MSOverlay 返回覆盖物对象
*/
fun drawCircle(
mapReadView: MapReadyView?,
lat: Double,
lng: Double,
radius: Float,
fillColor: Int = "#50FF0000".toColorInt(),
strokeColor: Int = "#500000FF".toColorInt(),
strokeWidth: Float = 15f
): MSOverlay {
// 根据地图类型绘制不同类型的圆形
var latLng = LatLng(lat, lng)
val options = CircleOptions()
.center(latLng)
.radius(radius)
.fillColor(fillColor)
.strokeColor(strokeColor)
.strokeWidth(strokeWidth)
var circle = mapReadView?.mMineMap?.addCircle(options)
MSOverlay.circle = circle
return MSOverlay
}
/***
* 绘制多边形
* @param msLatLng 添加多边形顶点坐标集合
* @param dLine 是否虚线
* @param fillColor 填充颜色
* @param strokeWidth 边框宽度
* @param strokeColor 边框颜色
* ****/
fun drawPolygon(
mapReadView: MapReadyView?,
msLatLng: List<MSLatLng>,
dLine: Boolean = false,
fillColor: Int = "#10FF00FF".toColorInt(),
strokeWidth: Float = 5f,
strokeColor: Int = "#50FF00FF".toColorInt()
): MSOverlay {
var latLngs = msLatLng.map {
LatLng(it.lat, it.lng)
}
// 声明 多边形参数对象
val polygonOptions = PolygonOptions().apply {
addAll(latLngs)
fillColor(fillColor)
strokeWidth(strokeWidth)
strokeColor(strokeColor)
dottedLine(dLine)
}
var polygon = mapReadView?.mMineMap?.addPolygon(polygonOptions)
MSOverlay.polygon = polygon
return MSOverlay
}
}
\ No newline at end of file
package com.sd.maplibrary.core.basic.mine
import android.os.Bundle
import com.minedata.minenavi.location.MineLocation
import com.minedata.minenavi.location.MineLocationListener
import com.minedata.minenavi.location.MineLocationManager
import com.minedata.minenavi.location.MineLocationOptions
import com.minedata.minenavi.mapdal.CoordType
import com.sd.maplibrary.UserCtx
import com.sd.maplibrary.bean.MSLocBean
import com.sd.maplibrary.core.basic.OnMsGpsLoc
/**GPS定位类*/
object MineGpsLocation {
// 设置四维定位参数,并开始定位。
private val options: MineLocationOptions by lazy {
MineLocationOptions().apply {
setCoordType(CoordType.GCJ02)
setGpsInterval(1000)//GPS定位更新时间,最小1000
setNetWorkInterval(3000)//WiFi定位更新时间,最小3000
setStationInterval(5000)//基站定位更新时间,最小500
}
}
/**业务层Gps定位回调**/
private var onMsGpsLoc: OnMsGpsLoc? = null
/**初始化定位*/
private fun initLoc() {
var context = UserCtx.instance.mContext
MineLocationManager.getInstance()
.init(context, MineLocationManager.LocationSource.gpsAndNetwork)
// MineLocationManager.getInstance().removeListener(mineLocationListener)
MineLocationManager.getInstance().addListener(mineLocationListener)
}
/**开启定位*/
fun starLoc(onMsGpsLoc: OnMsGpsLoc) {
initLoc()
this.onMsGpsLoc = onMsGpsLoc
MineLocationManager.getInstance().start(options)
}
/**停止定位*/
fun stopLoc() {
MineLocationManager.getInstance().removeAllListener()
MineLocationManager.getInstance().stop()
}
/**清理定位资源**/
fun cleansLoc() {
MineLocationManager.getInstance().cleanup()
}
//---------------四维回调---------------
private var mineLocationListener = object : MineLocationListener {
override fun onSimLocationChanged(location: MineLocation?) {
}
override fun onLocationChanged(location: MineLocation?) {
// println("-------四维定位改变 = ${location?.latitude} curLng=${location?.longitude} speed=${location?.speed}")
var loc = MSLocBean.instance.apply {
lat = location?.latitude ?: 0.0
lng = location?.longitude ?: 0.0
speed = location?.speed ?: 0f
bearing = location?.bearing ?: 0f
accuracy = location?.accuracy ?: 0f
altitude = location?.altitude ?: 0.0
}
onMsGpsLoc?.onMsGpsLoc(loc)
}
override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
}
override fun onProviderEnabled(provider: String?) {
}
override fun onProviderDisabled(provider: String?) {
}
}
}
\ No newline at end of file
package com.sd.maplibrary.core.basic.mine
import com.minedata.minenavi.map.MyLocationStyle
import com.sd.maplibrary.core.MapReadyView
import com.sd.maplibrary.core.basic.MSLocStyle
/**
* 显示定位小圆点
*/
object MineLocationStyle {
// 四维初始化定位蓝点样式类
private val myLocationStyle: MyLocationStyle by lazy { MyLocationStyle() }
/**
* 设置定位蓝点样式
* @param mapReadView 地图准备就绪视图对象
* @param type 定位类型,默认为LOCATION_TYPE_LOCATION_ROTATE,表示连续定位并旋转视角
*/
fun setLocationStyle(
mapReadView: MapReadyView?,
type: Int = MSLocStyle.LOCATION_TYPE_LOCATION_ROTATE
) {
var mMineMap = mapReadView?.mMineMap
// 连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
myLocationStyle.myLocationType(type)
// 设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
myLocationStyle.interval(2000)
// 设置为true表示显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是true。
myLocationStyle.showMyLocation(true)
mMineMap?.setMyLocationStyle(myLocationStyle)
}
}
\ No newline at end of file
package com.sd.maplibrary.core.basic.mine
import com.minedata.minenavi.mapdal.LatLng
import com.minedata.minenavi.util.Tools
import com.sd.maplibrary.core.MapReadyView
/**
* 四维地图方法交互
*/
object MineMethodAdv {
/****
* 改变地图中心点
* @param mapReadView 地图准备就绪的视图对象,可能为null
* @param lat 纬度,默认值为39.977290
* @param lng 经度,默认值为116.337000
* **/
fun setMapCenter(
mapReadView: MapReadyView?,
lat: Double,
lng: Double
) {
val point = Tools.latLngToPoint(LatLng(lat, lng))
mapReadView?.mMineMap?.setPointToCenter(point.x, point.y)
}
/**
* 改变地图缩放级别
* @param mapReadView 地图准备就绪的视图对象
* @param zoom 缩放级别,值越小站得越高,默认值为13f
* */
fun setMapZoom(mapReadView: MapReadyView?, zoom: Float = 13f) {
mapReadView?.mMineMap?.setZoomLevel(zoom)
}
/**
* 获取地图缩放级别
* @param mapReadView 地图准备就绪视图对象
* @return 返回当前地图的缩放级别,如果地图未初始化则返回0f
*/
fun getMapZoom(mapReadView: MapReadyView?): Float {
// 根据不同的地图类型获取对应的缩放级别
return mapReadView?.mMineMap?.zoomLevel ?: 0f
}
/***设置地图显示区域**/
// fun setMapBoundArea(mapReadView: MapReadyView?) {
// when (MSDKInitializer.getMapType()) {
// MAP_TYPE.MINE -> {
// val rect = mapReadView?.mMineMap?.getBoundArea()
// if (rect==null)
// return
// val rect1 = Rect(rect.left / 2, rect.top / 2, rect.right / 2, rect.bottom / 2)
// mapReadView.mMineMap?.setBoundArea(rect1)
// }
//
// MAP_TYPE.AMAP -> {
//
// }
// }
// }
// /****改变地图显示区域**/
// fun setMapZoom(mapReadView: MapReadyView?, zoom: Float=16f) {
// when (MSDKInitializer.getMapType()) {
// MAP_TYPE.MINE -> {
// mapReadView?.mMineMap?.setZoomLevel(zoom)
// }
//
// MAP_TYPE.AMAP -> {
// var mCameraUpdate = CameraUpdateFactory.zoomTo(zoom)
// mapReadView?.aMap?.moveCamera(mCameraUpdate)
// }
// }
// }
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment