diff --git a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt index 09203d9..efa6785 100644 --- a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt +++ b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt @@ -19,7 +19,7 @@ * |/ * A * */ -fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { +fun AMapLocation.calculateDirection(target: LatLng): CalculateResult { //构造直角辅助点 val auxiliaryPoint = LatLng(target.latitude, this.longitude) @@ -56,4 +56,29 @@ "东偏南" } return CalculateResult(angle.toInt(), direction, distance.toInt()) +} + +fun AMapLocation.calculateAngle(target: LatLng): Int { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + return angle.toInt() } \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt index 09203d9..efa6785 100644 --- a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt +++ b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt @@ -19,7 +19,7 @@ * |/ * A * */ -fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { +fun AMapLocation.calculateDirection(target: LatLng): CalculateResult { //构造直角辅助点 val auxiliaryPoint = LatLng(target.latitude, this.longitude) @@ -56,4 +56,29 @@ "东偏南" } return CalculateResult(angle.toInt(), direction, distance.toInt()) +} + +fun AMapLocation.calculateAngle(target: LatLng): Int { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + return angle.toInt() } \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index 8d772fc..04fc7c6 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -30,6 +30,7 @@ import com.amap.api.location.AMapLocation import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions +import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.BitmapDescriptorFactory @@ -52,6 +53,7 @@ import com.casic.detector.databinding.DialogSearchMarkerBinding import com.casic.detector.databinding.DialogSearchMarkerNewBinding import com.casic.detector.extensions.appendDownloadUrl +import com.casic.detector.extensions.calculateAngle import com.casic.detector.extensions.compressImage import com.casic.detector.extensions.drawCircle import com.casic.detector.extensions.getDefaultValue @@ -73,6 +75,7 @@ import com.casic.detector.utils.RouteOnMap import com.casic.detector.vm.TaskViewModel import com.casic.detector.widgets.QueryMarkerDialog +import com.casic.detector.widgets.RadarScanView import com.casic.detector.widgets.SamplePopupWindow import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -425,9 +428,9 @@ } }).build().show() } else { -// searchDialog.show() + searchDialog.show() //TODO 新探测界面 - searchNewDialog.show() +// searchNewDialog.show() } } @@ -1746,6 +1749,66 @@ context.navigatePageTo(markerId) } } + + //开始定位,先定位一次 + val tempPoints = ArrayList() + locationHub.getCurrentLocation(true, object : OnGetLocationListener { + override fun onAMapLocationGet(location: AMapLocation?) { + if (location != null) { + DataBaseManager.get.loadTaskLabels().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(location.latitude, location.longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + //筛选出距离小于3米的点进行渲染 + if (distance < 3) { + tempPoints.add(it) + } + } + } else { + "当前位置信号差,无法精确计算标识器位置".show(context) + } + } + }) + + binding.distancePgBar.progress = 125 + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationHub.getCurrentLocation(false, object : OnGetLocationListener { + override fun onAMapLocationGet(location: AMapLocation?) { + location?.apply { + val dataPoints = ArrayList() + tempPoints.forEach { + val angle = calculateAngle( + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + val distance = AMapUtils.calculateLineDistance( + LatLng(latitude, longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + dataPoints.add(RadarScanView.DataPoint(angle, distance.toInt())) + } + binding.radarScanView.renderPointData(dataPoints) + + //获取MarkerId对应的标识器 + DataBaseManager.get.queryLabelById(markerId).forEach { + //设置距离进度条,距离最大3米,表盘最大125dp,需要转换 + val distance = AMapUtils.calculateLineDistance( + LatLng(latitude, longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + //TODO 距离转换有问题 + val d = (distance / 3) * 125 + Log.d(kTag, "onAMapLocationGet => $d") + binding.distancePgBar.progress = 125 - d.toInt() + } + } + } + }) } override fun onStart() { @@ -1872,7 +1935,6 @@ //更新罗盘角度 fun updateDegreeValue(degree: Int) { - binding.degreeView.text = degree.toString() binding.radarScanView.setDegreeValue(degree) } @@ -1906,6 +1968,7 @@ gpioManager.setGpioLow("18") isDetectMarker = false soundPool.autoPause() + locationHub.stopLocation() super.dismiss() } } diff --git a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt index 09203d9..efa6785 100644 --- a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt +++ b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt @@ -19,7 +19,7 @@ * |/ * A * */ -fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { +fun AMapLocation.calculateDirection(target: LatLng): CalculateResult { //构造直角辅助点 val auxiliaryPoint = LatLng(target.latitude, this.longitude) @@ -56,4 +56,29 @@ "东偏南" } return CalculateResult(angle.toInt(), direction, distance.toInt()) +} + +fun AMapLocation.calculateAngle(target: LatLng): Int { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + return angle.toInt() } \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index 8d772fc..04fc7c6 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -30,6 +30,7 @@ import com.amap.api.location.AMapLocation import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions +import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.BitmapDescriptorFactory @@ -52,6 +53,7 @@ import com.casic.detector.databinding.DialogSearchMarkerBinding import com.casic.detector.databinding.DialogSearchMarkerNewBinding import com.casic.detector.extensions.appendDownloadUrl +import com.casic.detector.extensions.calculateAngle import com.casic.detector.extensions.compressImage import com.casic.detector.extensions.drawCircle import com.casic.detector.extensions.getDefaultValue @@ -73,6 +75,7 @@ import com.casic.detector.utils.RouteOnMap import com.casic.detector.vm.TaskViewModel import com.casic.detector.widgets.QueryMarkerDialog +import com.casic.detector.widgets.RadarScanView import com.casic.detector.widgets.SamplePopupWindow import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -425,9 +428,9 @@ } }).build().show() } else { -// searchDialog.show() + searchDialog.show() //TODO 新探测界面 - searchNewDialog.show() +// searchNewDialog.show() } } @@ -1746,6 +1749,66 @@ context.navigatePageTo(markerId) } } + + //开始定位,先定位一次 + val tempPoints = ArrayList() + locationHub.getCurrentLocation(true, object : OnGetLocationListener { + override fun onAMapLocationGet(location: AMapLocation?) { + if (location != null) { + DataBaseManager.get.loadTaskLabels().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(location.latitude, location.longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + //筛选出距离小于3米的点进行渲染 + if (distance < 3) { + tempPoints.add(it) + } + } + } else { + "当前位置信号差,无法精确计算标识器位置".show(context) + } + } + }) + + binding.distancePgBar.progress = 125 + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationHub.getCurrentLocation(false, object : OnGetLocationListener { + override fun onAMapLocationGet(location: AMapLocation?) { + location?.apply { + val dataPoints = ArrayList() + tempPoints.forEach { + val angle = calculateAngle( + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + val distance = AMapUtils.calculateLineDistance( + LatLng(latitude, longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + dataPoints.add(RadarScanView.DataPoint(angle, distance.toInt())) + } + binding.radarScanView.renderPointData(dataPoints) + + //获取MarkerId对应的标识器 + DataBaseManager.get.queryLabelById(markerId).forEach { + //设置距离进度条,距离最大3米,表盘最大125dp,需要转换 + val distance = AMapUtils.calculateLineDistance( + LatLng(latitude, longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + //TODO 距离转换有问题 + val d = (distance / 3) * 125 + Log.d(kTag, "onAMapLocationGet => $d") + binding.distancePgBar.progress = 125 - d.toInt() + } + } + } + }) } override fun onStart() { @@ -1872,7 +1935,6 @@ //更新罗盘角度 fun updateDegreeValue(degree: Int) { - binding.degreeView.text = degree.toString() binding.radarScanView.setDegreeValue(degree) } @@ -1906,6 +1968,7 @@ gpioManager.setGpioLow("18") isDetectMarker = false soundPool.autoPause() + locationHub.stopLocation() super.dismiss() } } diff --git a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt index 4f4f2e3..ff268ad 100644 --- a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt +++ b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt @@ -15,6 +15,7 @@ import android.graphics.Typeface import android.text.TextPaint import android.util.AttributeSet +import android.util.Log import android.view.View import com.casic.detector.R import com.pengxh.kt.lite.extensions.dp2px @@ -39,15 +40,15 @@ //最外层圆半径 private var radius: Int - //内圆文字路径半径 - private var innerRadius: Int + //外圆文字路径半径 + private var outerRadius: Int //控件边长 private val viewSideLength: Int private val rect: Rect //需要渲染的数据点集合 - private val points = ArrayList() + private var points: ArrayList? = null //View中心X坐标 private var centerX = 0f @@ -66,10 +67,8 @@ private lateinit var borderPaint: Paint private lateinit var shaderPaint: Paint private lateinit var dataPaint: Paint - private lateinit var trianglePaint: Paint - private lateinit var innerPaint: TextPaint - private lateinit var innerTextPath: Path - private lateinit var trianglePath: Path + private lateinit var outerPaint: TextPaint + private lateinit var outerTextPath: Path //雷达扫描线后面的渐变梯度 private lateinit var sweepGradient: SweepGradient @@ -77,27 +76,26 @@ //背景栅格图 private lateinit var bitmap: Bitmap - //指示针 - private lateinit var needleBitmap: Bitmap - //雷达旋转矩阵 private lateinit var matrix: Matrix - //方位三角形边长 - private val tickLength = 20f.dp2px(context) - //背景区域范围 private var bgRect: Rect + //刻度长度 + private val tickLength = 15f.dp2px(context) + init { val type = context.obtainStyledAttributes(attrs, R.styleable.RadarScanView) - borderColor = type.getColor(R.styleable.RadarScanView_radar_borderColor, Color.GRAY) + borderColor = type.getColor( + R.styleable.RadarScanView_radar_borderColor, Color.parseColor("#8000FFF0") + ) border = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_border, 1) circleCount = type.getInt(R.styleable.RadarScanView_radar_circleCount, 4) radius = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_radius, 300) type.recycle() - innerRadius = radius - 10.dp2px(context) + outerRadius = radius + 8.dp2px(context) //需要给外围刻度留位置 viewSideLength = radius + 30.dp2px(context) @@ -145,29 +143,18 @@ borderPaint.strokeCap = Paint.Cap.ROUND //圆头 borderPaint.isAntiAlias = true - innerPaint = TextPaint() - innerPaint.isAntiAlias = true - innerPaint.textAlign = Paint.Align.CENTER - innerPaint.textSize = 14f.sp2px(context) - innerTextPath = Path() + outerPaint = TextPaint() + outerPaint.isAntiAlias = true + outerPaint.textAlign = Paint.Align.CENTER + outerPaint.textSize = 14f.sp2px(context) + outerTextPath = Path() val innerRectF = RectF( - -innerRadius.toFloat(), - -innerRadius.toFloat(), - innerRadius.toFloat(), - innerRadius.toFloat() + -outerRadius.toFloat(), + -outerRadius.toFloat(), + outerRadius.toFloat(), + outerRadius.toFloat() ) - innerTextPath.addArc(innerRectF, -90f, 360f) - - trianglePaint = Paint() - trianglePaint.color = Color.RED - trianglePaint.style = Paint.Style.FILL - trianglePaint.isAntiAlias = true - trianglePath = Path() - trianglePath.moveTo(0f, -viewSideLength.toFloat() + tickLength * 1.5f) - trianglePath.lineTo(tickLength * 0.5f, -viewSideLength.toFloat() + tickLength * 0.75f) - trianglePath.lineTo(-tickLength * 0.5f, -viewSideLength.toFloat() + tickLength * 0.75f) - trianglePath.close() - needleBitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.bg_needle) + outerTextPath.addArc(innerRectF, -90f, 360f) //扫描线画笔 shaderPaint = Paint() @@ -178,7 +165,7 @@ //数据点画笔 dataPaint = Paint() - dataPaint.color = borderColor + dataPaint.color = Color.RED dataPaint.isAntiAlias = true dataPaint.style = Paint.Style.FILL @@ -226,11 +213,12 @@ */ canvas.translate(centerX, centerY) + //画最外层圆环 + canvas.drawCircle(0f, 0f, (radius + tickLength), borderPaint) + //画背景 canvas.drawBitmap(bitmap, null, bgRect, backPaint) -// drawGuides(canvas) - //每道同心圆的半径差 var tempR = radius val deltaR = tempR / circleCount @@ -248,71 +236,96 @@ //角度需要转为弧度 val radians = (angle - 180) * (Math.PI / 180) - val hOffset = innerRadius * radians + val hOffset = outerRadius * radians var direction = "" when (angle) { 0 -> { direction = "北" - innerPaint.color = Color.RED - innerPaint.typeface = Typeface.DEFAULT_BOLD + outerPaint.color = Color.RED + outerPaint.typeface = Typeface.DEFAULT_BOLD } 90 -> { direction = "东" - innerPaint.color = Color.WHITE - innerPaint.typeface = Typeface.DEFAULT + outerPaint.color = Color.WHITE + outerPaint.typeface = Typeface.DEFAULT } 180 -> { direction = "南" - innerPaint.color = Color.WHITE - innerPaint.typeface = Typeface.DEFAULT + outerPaint.color = Color.WHITE + outerPaint.typeface = Typeface.DEFAULT } 270 -> { direction = "西" - innerPaint.color = Color.WHITE - innerPaint.typeface = Typeface.DEFAULT + outerPaint.color = Color.WHITE + outerPaint.typeface = Typeface.DEFAULT } } - val fontMetrics = innerPaint.fontMetrics + val fontMetrics = outerPaint.fontMetrics val top = fontMetrics.top //基线到字体上边框的距离,即上图中的top val bottom = fontMetrics.bottom //基线到字体下边框的距离,即上图中的bottom val fontHeight = top + bottom canvas.drawTextOnPath( direction, - innerTextPath, + outerTextPath, hOffset.toFloat(), -fontHeight / 2, - innerPaint + outerPaint ) } - //画正北方小三角 - canvas.drawPath(trianglePath, trianglePaint) - //画实时方位角 -// for (angle in 0..degreeValue step 3) { -// //角度需要转为弧度 -// val radians = (angle - 90) * (Math.PI / 180) -// -// canvas.drawBitmap( -// needleBitmap, -// -(needleBitmap.width shr 1).toFloat(), -// -(radians + needleBitmap.height).toFloat(), -// trianglePaint -// ) -// } - //角度需要转为弧度 - val radians = degreeValue * (Math.PI / 180) + if (degreeValue < 180) { + for (angle in 0..degreeValue step 3) { + //角度需要转为弧度 + val radians = (angle - 90) * (Math.PI / 180) -// canvas.drawBitmap(needleBitmap, null, bgRect, trianglePaint) + val startX = (radius + tickLength) * cos(radians) + val startY = (radius + tickLength) * sin(radians) + + val stopX = radius * cos(radians) + val stopY = radius * sin(radians) + + tickPaint.strokeWidth = 8f.dp2px(context) + tickPaint.color = borderColor + canvas.drawLine( + startX.toFloat(), + startY.toFloat(), + stopX.toFloat(), + stopY.toFloat(), + tickPaint + ) + } + } else { + for (angle in 360 downTo degreeValue step 3) { + //角度需要转为弧度 + val radians = (angle - 90) * (Math.PI / 180) + + val startX = (radius + tickLength) * cos(radians) + val startY = (radius + tickLength) * sin(radians) + + val stopX = radius * cos(radians) + val stopY = radius * sin(radians) + + tickPaint.color = borderColor + tickPaint.strokeWidth = 8f.dp2px(context) + canvas.drawLine( + startX.toFloat(), + startY.toFloat(), + stopX.toFloat(), + stopY.toFloat(), + tickPaint + ) + } + } //画数据点 - points.forEach { - canvas.drawCircle(it.x, it.y, 10f, dataPaint) + points?.forEach { + canvas.drawCircle(it.x, it.y, 8f, dataPaint) } /** @@ -326,17 +339,6 @@ } /** - * 辅助线 - * */ - private fun drawGuides(canvas: Canvas) { - //最外层方框,即自定义View的边界 - canvas.drawRect(rect, tickPaint) - - //内层表盘方向文字基准线 - canvas.drawPath(innerTextPath, tickPaint) - } - - /** * 更新罗盘方位角度 * @param value 方位角 * */ @@ -351,18 +353,25 @@ * @param dataPoints 数据点集合 * */ fun renderPointData(dataPoints: ArrayList) { + points = ArrayList() dataPoints.forEach { - val result = recursionAngle(it.angle) + Log.d(kTag, "renderPointData => [${it.angle}, ${it.distance}]") //转为弧度 - val dataAngle = (result * Math.PI / 180).toFloat() - val dataDistance = recursionDistance(it.distance.dp2px(context)) + val dataAngle = (it.angle * Math.PI / 180).toFloat() + + //距离最大3米,表盘最大125dp,需要转换 + //TODO 距离转换有问题 + val d = (it.distance / 3) * 125 + val dataDistance = recursionDistance(d.dp2px(context)) //计算实际圆心坐标 val x = dataDistance * cos(dataAngle) val y = dataDistance * sin(dataAngle) - points.add(PointF(x, y)) + points?.add(PointF(x, y)) } + //实时刷新点位数据 + invalidate() } /** @@ -370,29 +379,16 @@ * @param angle 数据点和圆心的方位角 * @param distance 数据点和圆心的相对距离 * */ - data class DataPoint(val angle: Float, val distance: Float) - - /** - * 递归计算周期性角度 - * */ - private fun recursionAngle(angle: Float): Float { - return if (angle < -360) { - recursionAngle(angle + 360) - } else if (angle > 360) { - recursionAngle(angle - 360) - } else { - angle - } - } + data class DataPoint(val angle: Int, val distance: Int) /** * 递归计算周期性距离 * */ - private fun recursionDistance(distance: Float): Float { + private fun recursionDistance(distance: Int): Int { return if (distance <= 0) { - 0f + 0 } else if (distance >= radius) { - radius.toFloat() + radius } else { distance } diff --git a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt index 09203d9..efa6785 100644 --- a/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt +++ b/app/src/main/java/com/casic/detector/extensions/AMapLocation.kt @@ -19,7 +19,7 @@ * |/ * A * */ -fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { +fun AMapLocation.calculateDirection(target: LatLng): CalculateResult { //构造直角辅助点 val auxiliaryPoint = LatLng(target.latitude, this.longitude) @@ -56,4 +56,29 @@ "东偏南" } return CalculateResult(angle.toInt(), direction, distance.toInt()) +} + +fun AMapLocation.calculateAngle(target: LatLng): Int { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + return angle.toInt() } \ No newline at end of file diff --git a/app/src/main/java/com/casic/detector/view/MainActivity.kt b/app/src/main/java/com/casic/detector/view/MainActivity.kt index 8d772fc..04fc7c6 100644 --- a/app/src/main/java/com/casic/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/detector/view/MainActivity.kt @@ -30,6 +30,7 @@ import com.amap.api.location.AMapLocation import com.amap.api.maps.AMap import com.amap.api.maps.AMapOptions +import com.amap.api.maps.AMapUtils import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.CoordinateConverter import com.amap.api.maps.model.BitmapDescriptorFactory @@ -52,6 +53,7 @@ import com.casic.detector.databinding.DialogSearchMarkerBinding import com.casic.detector.databinding.DialogSearchMarkerNewBinding import com.casic.detector.extensions.appendDownloadUrl +import com.casic.detector.extensions.calculateAngle import com.casic.detector.extensions.compressImage import com.casic.detector.extensions.drawCircle import com.casic.detector.extensions.getDefaultValue @@ -73,6 +75,7 @@ import com.casic.detector.utils.RouteOnMap import com.casic.detector.vm.TaskViewModel import com.casic.detector.widgets.QueryMarkerDialog +import com.casic.detector.widgets.RadarScanView import com.casic.detector.widgets.SamplePopupWindow import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -425,9 +428,9 @@ } }).build().show() } else { -// searchDialog.show() + searchDialog.show() //TODO 新探测界面 - searchNewDialog.show() +// searchNewDialog.show() } } @@ -1746,6 +1749,66 @@ context.navigatePageTo(markerId) } } + + //开始定位,先定位一次 + val tempPoints = ArrayList() + locationHub.getCurrentLocation(true, object : OnGetLocationListener { + override fun onAMapLocationGet(location: AMapLocation?) { + if (location != null) { + DataBaseManager.get.loadTaskLabels().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(location.latitude, location.longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + //筛选出距离小于3米的点进行渲染 + if (distance < 3) { + tempPoints.add(it) + } + } + } else { + "当前位置信号差,无法精确计算标识器位置".show(context) + } + } + }) + + binding.distancePgBar.progress = 125 + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationHub.getCurrentLocation(false, object : OnGetLocationListener { + override fun onAMapLocationGet(location: AMapLocation?) { + location?.apply { + val dataPoints = ArrayList() + tempPoints.forEach { + val angle = calculateAngle( + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + val distance = AMapUtils.calculateLineDistance( + LatLng(latitude, longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + dataPoints.add(RadarScanView.DataPoint(angle, distance.toInt())) + } + binding.radarScanView.renderPointData(dataPoints) + + //获取MarkerId对应的标识器 + DataBaseManager.get.queryLabelById(markerId).forEach { + //设置距离进度条,距离最大3米,表盘最大125dp,需要转换 + val distance = AMapUtils.calculateLineDistance( + LatLng(latitude, longitude), + LatLng(it.lat.toDouble(), it.lng.toDouble()) + ) + + //TODO 距离转换有问题 + val d = (distance / 3) * 125 + Log.d(kTag, "onAMapLocationGet => $d") + binding.distancePgBar.progress = 125 - d.toInt() + } + } + } + }) } override fun onStart() { @@ -1872,7 +1935,6 @@ //更新罗盘角度 fun updateDegreeValue(degree: Int) { - binding.degreeView.text = degree.toString() binding.radarScanView.setDegreeValue(degree) } @@ -1906,6 +1968,7 @@ gpioManager.setGpioLow("18") isDetectMarker = false soundPool.autoPause() + locationHub.stopLocation() super.dismiss() } } diff --git a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt index 4f4f2e3..ff268ad 100644 --- a/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt +++ b/app/src/main/java/com/casic/detector/widgets/RadarScanView.kt @@ -15,6 +15,7 @@ import android.graphics.Typeface import android.text.TextPaint import android.util.AttributeSet +import android.util.Log import android.view.View import com.casic.detector.R import com.pengxh.kt.lite.extensions.dp2px @@ -39,15 +40,15 @@ //最外层圆半径 private var radius: Int - //内圆文字路径半径 - private var innerRadius: Int + //外圆文字路径半径 + private var outerRadius: Int //控件边长 private val viewSideLength: Int private val rect: Rect //需要渲染的数据点集合 - private val points = ArrayList() + private var points: ArrayList? = null //View中心X坐标 private var centerX = 0f @@ -66,10 +67,8 @@ private lateinit var borderPaint: Paint private lateinit var shaderPaint: Paint private lateinit var dataPaint: Paint - private lateinit var trianglePaint: Paint - private lateinit var innerPaint: TextPaint - private lateinit var innerTextPath: Path - private lateinit var trianglePath: Path + private lateinit var outerPaint: TextPaint + private lateinit var outerTextPath: Path //雷达扫描线后面的渐变梯度 private lateinit var sweepGradient: SweepGradient @@ -77,27 +76,26 @@ //背景栅格图 private lateinit var bitmap: Bitmap - //指示针 - private lateinit var needleBitmap: Bitmap - //雷达旋转矩阵 private lateinit var matrix: Matrix - //方位三角形边长 - private val tickLength = 20f.dp2px(context) - //背景区域范围 private var bgRect: Rect + //刻度长度 + private val tickLength = 15f.dp2px(context) + init { val type = context.obtainStyledAttributes(attrs, R.styleable.RadarScanView) - borderColor = type.getColor(R.styleable.RadarScanView_radar_borderColor, Color.GRAY) + borderColor = type.getColor( + R.styleable.RadarScanView_radar_borderColor, Color.parseColor("#8000FFF0") + ) border = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_border, 1) circleCount = type.getInt(R.styleable.RadarScanView_radar_circleCount, 4) radius = type.getDimensionPixelOffset(R.styleable.RadarScanView_radar_radius, 300) type.recycle() - innerRadius = radius - 10.dp2px(context) + outerRadius = radius + 8.dp2px(context) //需要给外围刻度留位置 viewSideLength = radius + 30.dp2px(context) @@ -145,29 +143,18 @@ borderPaint.strokeCap = Paint.Cap.ROUND //圆头 borderPaint.isAntiAlias = true - innerPaint = TextPaint() - innerPaint.isAntiAlias = true - innerPaint.textAlign = Paint.Align.CENTER - innerPaint.textSize = 14f.sp2px(context) - innerTextPath = Path() + outerPaint = TextPaint() + outerPaint.isAntiAlias = true + outerPaint.textAlign = Paint.Align.CENTER + outerPaint.textSize = 14f.sp2px(context) + outerTextPath = Path() val innerRectF = RectF( - -innerRadius.toFloat(), - -innerRadius.toFloat(), - innerRadius.toFloat(), - innerRadius.toFloat() + -outerRadius.toFloat(), + -outerRadius.toFloat(), + outerRadius.toFloat(), + outerRadius.toFloat() ) - innerTextPath.addArc(innerRectF, -90f, 360f) - - trianglePaint = Paint() - trianglePaint.color = Color.RED - trianglePaint.style = Paint.Style.FILL - trianglePaint.isAntiAlias = true - trianglePath = Path() - trianglePath.moveTo(0f, -viewSideLength.toFloat() + tickLength * 1.5f) - trianglePath.lineTo(tickLength * 0.5f, -viewSideLength.toFloat() + tickLength * 0.75f) - trianglePath.lineTo(-tickLength * 0.5f, -viewSideLength.toFloat() + tickLength * 0.75f) - trianglePath.close() - needleBitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.bg_needle) + outerTextPath.addArc(innerRectF, -90f, 360f) //扫描线画笔 shaderPaint = Paint() @@ -178,7 +165,7 @@ //数据点画笔 dataPaint = Paint() - dataPaint.color = borderColor + dataPaint.color = Color.RED dataPaint.isAntiAlias = true dataPaint.style = Paint.Style.FILL @@ -226,11 +213,12 @@ */ canvas.translate(centerX, centerY) + //画最外层圆环 + canvas.drawCircle(0f, 0f, (radius + tickLength), borderPaint) + //画背景 canvas.drawBitmap(bitmap, null, bgRect, backPaint) -// drawGuides(canvas) - //每道同心圆的半径差 var tempR = radius val deltaR = tempR / circleCount @@ -248,71 +236,96 @@ //角度需要转为弧度 val radians = (angle - 180) * (Math.PI / 180) - val hOffset = innerRadius * radians + val hOffset = outerRadius * radians var direction = "" when (angle) { 0 -> { direction = "北" - innerPaint.color = Color.RED - innerPaint.typeface = Typeface.DEFAULT_BOLD + outerPaint.color = Color.RED + outerPaint.typeface = Typeface.DEFAULT_BOLD } 90 -> { direction = "东" - innerPaint.color = Color.WHITE - innerPaint.typeface = Typeface.DEFAULT + outerPaint.color = Color.WHITE + outerPaint.typeface = Typeface.DEFAULT } 180 -> { direction = "南" - innerPaint.color = Color.WHITE - innerPaint.typeface = Typeface.DEFAULT + outerPaint.color = Color.WHITE + outerPaint.typeface = Typeface.DEFAULT } 270 -> { direction = "西" - innerPaint.color = Color.WHITE - innerPaint.typeface = Typeface.DEFAULT + outerPaint.color = Color.WHITE + outerPaint.typeface = Typeface.DEFAULT } } - val fontMetrics = innerPaint.fontMetrics + val fontMetrics = outerPaint.fontMetrics val top = fontMetrics.top //基线到字体上边框的距离,即上图中的top val bottom = fontMetrics.bottom //基线到字体下边框的距离,即上图中的bottom val fontHeight = top + bottom canvas.drawTextOnPath( direction, - innerTextPath, + outerTextPath, hOffset.toFloat(), -fontHeight / 2, - innerPaint + outerPaint ) } - //画正北方小三角 - canvas.drawPath(trianglePath, trianglePaint) - //画实时方位角 -// for (angle in 0..degreeValue step 3) { -// //角度需要转为弧度 -// val radians = (angle - 90) * (Math.PI / 180) -// -// canvas.drawBitmap( -// needleBitmap, -// -(needleBitmap.width shr 1).toFloat(), -// -(radians + needleBitmap.height).toFloat(), -// trianglePaint -// ) -// } - //角度需要转为弧度 - val radians = degreeValue * (Math.PI / 180) + if (degreeValue < 180) { + for (angle in 0..degreeValue step 3) { + //角度需要转为弧度 + val radians = (angle - 90) * (Math.PI / 180) -// canvas.drawBitmap(needleBitmap, null, bgRect, trianglePaint) + val startX = (radius + tickLength) * cos(radians) + val startY = (radius + tickLength) * sin(radians) + + val stopX = radius * cos(radians) + val stopY = radius * sin(radians) + + tickPaint.strokeWidth = 8f.dp2px(context) + tickPaint.color = borderColor + canvas.drawLine( + startX.toFloat(), + startY.toFloat(), + stopX.toFloat(), + stopY.toFloat(), + tickPaint + ) + } + } else { + for (angle in 360 downTo degreeValue step 3) { + //角度需要转为弧度 + val radians = (angle - 90) * (Math.PI / 180) + + val startX = (radius + tickLength) * cos(radians) + val startY = (radius + tickLength) * sin(radians) + + val stopX = radius * cos(radians) + val stopY = radius * sin(radians) + + tickPaint.color = borderColor + tickPaint.strokeWidth = 8f.dp2px(context) + canvas.drawLine( + startX.toFloat(), + startY.toFloat(), + stopX.toFloat(), + stopY.toFloat(), + tickPaint + ) + } + } //画数据点 - points.forEach { - canvas.drawCircle(it.x, it.y, 10f, dataPaint) + points?.forEach { + canvas.drawCircle(it.x, it.y, 8f, dataPaint) } /** @@ -326,17 +339,6 @@ } /** - * 辅助线 - * */ - private fun drawGuides(canvas: Canvas) { - //最外层方框,即自定义View的边界 - canvas.drawRect(rect, tickPaint) - - //内层表盘方向文字基准线 - canvas.drawPath(innerTextPath, tickPaint) - } - - /** * 更新罗盘方位角度 * @param value 方位角 * */ @@ -351,18 +353,25 @@ * @param dataPoints 数据点集合 * */ fun renderPointData(dataPoints: ArrayList) { + points = ArrayList() dataPoints.forEach { - val result = recursionAngle(it.angle) + Log.d(kTag, "renderPointData => [${it.angle}, ${it.distance}]") //转为弧度 - val dataAngle = (result * Math.PI / 180).toFloat() - val dataDistance = recursionDistance(it.distance.dp2px(context)) + val dataAngle = (it.angle * Math.PI / 180).toFloat() + + //距离最大3米,表盘最大125dp,需要转换 + //TODO 距离转换有问题 + val d = (it.distance / 3) * 125 + val dataDistance = recursionDistance(d.dp2px(context)) //计算实际圆心坐标 val x = dataDistance * cos(dataAngle) val y = dataDistance * sin(dataAngle) - points.add(PointF(x, y)) + points?.add(PointF(x, y)) } + //实时刷新点位数据 + invalidate() } /** @@ -370,29 +379,16 @@ * @param angle 数据点和圆心的方位角 * @param distance 数据点和圆心的相对距离 * */ - data class DataPoint(val angle: Float, val distance: Float) - - /** - * 递归计算周期性角度 - * */ - private fun recursionAngle(angle: Float): Float { - return if (angle < -360) { - recursionAngle(angle + 360) - } else if (angle > 360) { - recursionAngle(angle - 360) - } else { - angle - } - } + data class DataPoint(val angle: Int, val distance: Int) /** * 递归计算周期性距离 * */ - private fun recursionDistance(distance: Float): Float { + private fun recursionDistance(distance: Int): Int { return if (distance <= 0) { - 0f + 0 } else if (distance >= radius) { - radius.toFloat() + radius } else { distance } diff --git a/app/src/main/res/layout/dialog_search_marker_new.xml b/app/src/main/res/layout/dialog_search_marker_new.xml index 65aa4dc..5068f74 100644 --- a/app/src/main/res/layout/dialog_search_marker_new.xml +++ b/app/src/main/res/layout/dialog_search_marker_new.xml @@ -8,13 +8,6 @@ android:gravity="center_horizontal" android:orientation="vertical"> - -