重构测量工具代码,修改代码逻辑和展现形式。

增加面积,角度测量
修改地图渲染面会崩溃的问题
This commit is contained in:
squallzhjch 2023-08-10 11:18:14 +08:00
parent 8578ea0afd
commit 4baa137ad6
14 changed files with 679 additions and 284 deletions

View File

@ -9,6 +9,7 @@ import android.util.Log
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels import androidx.activity.viewModels
@ -20,7 +21,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.map.NIMapOptions import com.navinfo.collect.library.map.handler.MeasureLayerHandler
import com.navinfo.omqs.Constant import com.navinfo.omqs.Constant
import com.navinfo.omqs.R import com.navinfo.omqs.R
import com.navinfo.omqs.bean.ImportConfig import com.navinfo.omqs.bean.ImportConfig
@ -397,9 +398,124 @@ class MainActivity : BaseActivity() {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.console_fragment_layout, ConsoleFragment()).commit() .add(R.id.console_fragment_layout, ConsoleFragment()).commit()
} }
initMeasuringTool()
} }
//根据输入的经纬度跳转坐标 /**
*初始化测量工具栏的点击事件
*/
private fun initMeasuringTool() {
val root = binding.mainActivityMeasuringTool.root
root.findViewById<View>(R.id.measuring_tool_select_point)
.setOnClickListener(measuringToolClickListener)
root.findViewById<View>(R.id.measuring_tool_close)
.setOnClickListener(measuringToolClickListener)
root.findViewById<View>(R.id.measuring_tool_backspace)
.setOnClickListener(measuringToolClickListener)
root.findViewById<View>(R.id.measuring_tool_reset)
.setOnClickListener(measuringToolClickListener)
root.findViewById<View>(R.id.measuring_tool_distance)
.setOnClickListener(measuringToolClickListener)
root.findViewById<View>(R.id.measuring_tool_area)
.setOnClickListener(measuringToolClickListener)
root.findViewById<View>(R.id.measuring_tool_angle)
.setOnClickListener(measuringToolClickListener)
}
/**
* 测量工具点击事件
*/
private val measuringToolClickListener = View.OnClickListener {
when (it.id) {
//选点
R.id.measuring_tool_select_point -> {
viewModel.addPointForMeasuringTool()
}
//关闭
R.id.measuring_tool_close -> {
measuringToolOff()
}
//上一步
R.id.measuring_tool_backspace -> {
viewModel.backPointForMeasuringTool()
}
//重绘
R.id.measuring_tool_reset -> {
viewModel.resetMeasuringTool()
}
//测距
R.id.measuring_tool_distance -> {
it.isSelected = true
viewModel.setMeasuringToolType(MeasureLayerHandler.MEASURE_TYPE.DISTANCE)
val root = binding.mainActivityMeasuringTool.root
root.findViewById<View>(R.id.measuring_tool_area).isSelected = false
root.findViewById<View>(R.id.measuring_tool_angle).isSelected = false
}
//测面积
R.id.measuring_tool_area -> {
it.isSelected = true
viewModel.setMeasuringToolType(MeasureLayerHandler.MEASURE_TYPE.AREA)
val root = binding.mainActivityMeasuringTool.root
root.findViewById<View>(R.id.measuring_tool_distance).isSelected = false
root.findViewById<View>(R.id.measuring_tool_angle).isSelected = false
}
//测角度
R.id.measuring_tool_angle -> {
it.isSelected = true
viewModel.setMeasuringToolType(MeasureLayerHandler.MEASURE_TYPE.ANGLE)
val root = binding.mainActivityMeasuringTool.root
root.findViewById<View>(R.id.measuring_tool_distance).isSelected = false
root.findViewById<View>(R.id.measuring_tool_area).isSelected = false
}
}
}
/**
* 开始测量
*/
private fun measuringToolOn() {
val root = binding.mainActivityMeasuringTool.root
val valueView = root.findViewById<TextView>(R.id.measuring_tool_value)
val unitView = root.findViewById<TextView>(R.id.measuring_tool_value_unit)
val centerTextView = binding.mainActivityHomeCenterText
//监听测距值
mapController.measureLayerHandler.measureValueLiveData.observe(this) {
valueView.text = it.valueString
unitView.text = it.unit
}
mapController.measureLayerHandler.tempMeasureValueLiveData.observe(this)
{
centerTextView.text = "${it.valueString}${it.unit}"
}
viewModel.setMeasuringToolEnable(true)
binding.mainActivityHomeCenter.visibility = View.VISIBLE
binding.mainActivityHomeCenterText.visibility = View.VISIBLE
viewModel.setMeasuringToolType(MeasureLayerHandler.MEASURE_TYPE.DISTANCE)
root.visibility = View.VISIBLE
root.findViewById<View>(R.id.measuring_tool_distance).isSelected = true
root.findViewById<View>(R.id.measuring_tool_area).isSelected = false
root.findViewById<View>(R.id.measuring_tool_angle).isSelected = false
}
/**
* 结束测量
*/
private fun measuringToolOff() {
//监听测距值
mapController.measureLayerHandler.measureValueLiveData.removeObservers(this)
mapController.measureLayerHandler.tempMeasureValueLiveData.removeObservers(this)
viewModel.setMeasuringToolEnable(false)
binding.mainActivityHomeCenter.visibility = View.GONE
binding.mainActivityHomeCenterText.visibility = View.GONE
binding.mainActivityMeasuringTool.root.visibility = View.GONE
}
/**
* 根据输入的经纬度跳转坐标
*/
fun jumpPosition() { fun jumpPosition() {
val view = this.layoutInflater.inflate(R.layout.dialog_view_edittext, null) val view = this.layoutInflater.inflate(R.layout.dialog_view_edittext, null)
val inputDialog = MaterialAlertDialogBuilder( val inputDialog = MaterialAlertDialogBuilder(
@ -488,10 +604,10 @@ class MainActivity : BaseActivity() {
} }
/** /**
* 点击计算 * 点击测速
*/ */
fun onClickCalcDisance() { fun onClickCalcDistance() {
measuringToolOn()
} }
/** /**

View File

@ -22,16 +22,12 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.navigation.findNavController import androidx.navigation.findNavController
import com.blankj.utilcode.util.ToastUtils import com.blankj.utilcode.util.ToastUtils
import com.blankj.utilcode.util.ViewUtils.runOnUiThread
import com.navinfo.collect.library.data.dao.impl.TraceDataBase import com.navinfo.collect.library.data.dao.impl.TraceDataBase
import com.navinfo.collect.library.data.entity.* import com.navinfo.collect.library.data.entity.*
import com.navinfo.collect.library.garminvirbxe.HostBean import com.navinfo.collect.library.garminvirbxe.HostBean
import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.map.OnGeoPointClickListener import com.navinfo.collect.library.map.OnGeoPointClickListener
import com.navinfo.collect.library.map.handler.ONNoteItemClickListener import com.navinfo.collect.library.map.handler.*
import com.navinfo.collect.library.map.handler.OnNiLocationItemListener
import com.navinfo.collect.library.map.handler.OnQsRecordItemClickListener
import com.navinfo.collect.library.map.handler.OnTaskLinkItemClickListener
import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.GeometryToolsKt import com.navinfo.collect.library.utils.GeometryToolsKt
import com.navinfo.omqs.Constant import com.navinfo.omqs.Constant
@ -59,10 +55,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.locationtech.jts.geom.Point
import org.oscim.core.GeoPoint import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition import org.oscim.core.MapPosition
import org.oscim.layers.marker.MarkerItem
import org.oscim.map.Map import org.oscim.map.Map
import org.videolan.libvlc.LibVlcUtil import org.videolan.libvlc.LibVlcUtil
import java.io.File import java.io.File
@ -174,6 +168,17 @@ class MainViewModel @Inject constructor(
*/ */
private var bSelectPauseTrace = false private var bSelectPauseTrace = false
/**
* 是不是开启测距
*/
private var bMeasuringTool = false
/**
* 测量类型
*/
var measuringType: MeasureLayerHandler.MEASURE_TYPE =
MeasureLayerHandler.MEASURE_TYPE.DISTANCE
var linkIdCache = "" var linkIdCache = ""
private var lastNiLocaion: NiLocation? = null private var lastNiLocaion: NiLocation? = null
@ -219,6 +224,9 @@ class MainViewModel @Inject constructor(
object : OnGeoPointClickListener { object : OnGeoPointClickListener {
override fun onMapClick(tag: String, point: GeoPoint) { override fun onMapClick(tag: String, point: GeoPoint) {
if (tag == TAG) { if (tag == TAG) {
if (bMeasuringTool) {
mapController.measureLayerHandler.addPoint(measuringType, point)
} else {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
//线选择状态 //线选择状态
if (bSelectRoad) { if (bSelectRoad) {
@ -229,6 +237,7 @@ class MainViewModel @Inject constructor(
} }
} }
} }
}
}, },
/** /**
* 处理之间数据的点击 * 处理之间数据的点击
@ -1028,12 +1037,12 @@ class MainViewModel @Inject constructor(
val nextNiLocation = val nextNiLocation =
mapController.markerHandle.getNILocation(currentIndexNiLocation + 1) mapController.markerHandle.getNILocation(currentIndexNiLocation + 1)
if (nextNiLocation != null && niLocation != null) { if (nextNiLocation != null && niLocation != null) {
var nilocationDisTime = var niLocationDisTime =
nextNiLocation.timeStamp.toLong() - niLocation.timeStamp.toLong() nextNiLocation.timeStamp.toLong() - niLocation.timeStamp.toLong()
disTime = if (nilocationDisTime < 1000) { disTime = if (niLocationDisTime < 1000) {
1000 1000
} else { } else {
nilocationDisTime niLocationDisTime
} }
showMarker(mapController.mMapView.context, nextNiLocation) showMarker(mapController.mMapView.context, nextNiLocation)
currentIndexNiLocation += 1 currentIndexNiLocation += 1
@ -1053,5 +1062,45 @@ class MainViewModel @Inject constructor(
fun cancelTrace() { fun cancelTrace() {
timer?.cancel() timer?.cancel()
} }
/**
* 开启测量工具
*/
fun setMeasuringToolEnable(b: Boolean) {
bMeasuringTool = b
mapController.measureLayerHandler.clear()
}
/**
* 测量打点
*/
fun addPointForMeasuringTool() {
mapController.measureLayerHandler.addPoint(measuringType)
}
/**
* 测距回退点
*/
fun backPointForMeasuringTool() {
mapController.measureLayerHandler.backspacePoint()
}
/**
* 重绘
*/
fun resetMeasuringTool() {
mapController.measureLayerHandler.clear()
}
/**
* 设置测量类型 0距离 2面积 3角度
*/
fun setMeasuringToolType(type: MeasureLayerHandler.MEASURE_TYPE) {
if(measuringType != type) {
measuringType = type
mapController.measureLayerHandler.clear()
}
}
} }

View File

@ -1,6 +1,5 @@
package com.navinfo.omqs.ui.fragment.tasklink package com.navinfo.omqs.ui.fragment.tasklink
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -97,11 +96,11 @@ class TaskLinkFragment : BaseFragment(), View.OnClickListener {
/** /**
* 线长度 * 线长度
*/ */
mapController.measureLayerHandler.lineLengthLiveData.observe(viewLifecycleOwner) { mapController.measureLayerHandler.measureValueLiveData.observe(viewLifecycleOwner) {
binding.taskLinkLength.text = "${it}" binding.taskLinkLength.text = "${it}"
} }
mapController.measureLayerHandler.tempLineDistanceLiveData.observe(viewLifecycleOwner) { mapController.measureLayerHandler.tempMeasureValueLiveData.observe(viewLifecycleOwner) {
(activity as MainActivity).setHomeCenterText(it) (activity as MainActivity).setHomeCenterText("${it.valueString}${it.unit}")
} }
} }

View File

@ -1,10 +1,7 @@
package com.navinfo.omqs.ui.fragment.tasklink package com.navinfo.omqs.ui.fragment.tasklink
import android.app.Dialog
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@ -13,18 +10,15 @@ import com.navinfo.collect.library.data.entity.LinkInfoBean
import com.navinfo.collect.library.data.entity.QsRecordBean import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.collect.library.data.entity.TaskBean import com.navinfo.collect.library.data.entity.TaskBean
import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.map.handler.MeasureLayerHandler
import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.omqs.Constant import com.navinfo.omqs.Constant
import com.navinfo.omqs.ui.dialog.FirstDialog import com.navinfo.omqs.ui.dialog.FirstDialog
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import io.realm.Realm import io.realm.Realm
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.bson.codecs.UuidCodec
import org.bson.internal.UuidHelper
import org.oscim.core.GeoPoint
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
@ -136,7 +130,7 @@ class TaskLinkViewModel @Inject constructor(
* 编辑点 * 编辑点
*/ */
fun addPoint() { fun addPoint() {
mapController.measureLayerHandler.drawLineOrPolygon(false) mapController.measureLayerHandler.addPoint(MeasureLayerHandler.MEASURE_TYPE.DISTANCE)
} }
/** /**
@ -198,7 +192,7 @@ class TaskLinkViewModel @Inject constructor(
if (hadLinkDvoBean != null) { if (hadLinkDvoBean != null) {
hadLinkDvoBean!!.taskId = liveDataTaskBean.value!!.id hadLinkDvoBean!!.taskId = liveDataTaskBean.value!!.id
hadLinkDvoBean!!.length = hadLinkDvoBean!!.length =
mapController.measureLayerHandler.lineLengthLiveData.value!! mapController.measureLayerHandler.measureValueLiveData.value!!.value
hadLinkDvoBean!!.geometry = hadLinkDvoBean!!.geometry =
GeometryTools.getLineString(mapController.measureLayerHandler.mPathLayer.points) GeometryTools.getLineString(mapController.measureLayerHandler.mPathLayer.points)
hadLinkDvoBean!!.linkInfo = LinkInfoBean( hadLinkDvoBean!!.linkInfo = LinkInfoBean(
@ -218,7 +212,7 @@ class TaskLinkViewModel @Inject constructor(
taskId = liveDataTaskBean.value!!.id, taskId = liveDataTaskBean.value!!.id,
linkPid = UUID.randomUUID().toString(), linkPid = UUID.randomUUID().toString(),
linkStatus = 3, linkStatus = 3,
length = mapController.measureLayerHandler.lineLengthLiveData.value!!, length = mapController.measureLayerHandler.measureValueLiveData.value!!.value,
geometry = GeometryTools.getLineString(mapController.measureLayerHandler.mPathLayer.points), geometry = GeometryTools.getLineString(mapController.measureLayerHandler.mPathLayer.points),
linkInfo = LinkInfoBean( linkInfo = LinkInfoBean(
kind = liveDataSelectKind.value!!.type, kind = liveDataSelectKind.value!!.type,
@ -256,7 +250,7 @@ class TaskLinkViewModel @Inject constructor(
* 绘制线的时候回退点 * 绘制线的时候回退点
*/ */
fun removeLinkLastPoint() { fun removeLinkLastPoint() {
mapController.measureLayerHandler.drawLineBackspace() mapController.measureLayerHandler.backspacePoint()
} }
/** /**

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_rect_white_press_6dp_bg" android:state_selected="true"></item>
<item android:drawable="@drawable/shape_rect_white_press_6dp_bg" android:state_pressed="true"></item> <item android:drawable="@drawable/shape_rect_white_press_6dp_bg" android:state_pressed="true"></item>
<item android:drawable="@drawable/shape_rect_white_6dp_bg" /> <item android:drawable="@drawable/shape_rect_white_6dp_bg" />
</selector> </selector>

View File

@ -7,7 +7,7 @@
android:bottomRightRadius="6dp" android:bottomRightRadius="6dp"
android:topLeftRadius="6dp" android:topLeftRadius="6dp"
android:topRightRadius="6dp" /> android:topRightRadius="6dp" />
<stroke android:width="1dp" android:color="@color/blue"/>
<solid android:color="#2632335e" /> <solid android:color="#2632335e" />
</shape> </shape>

View File

@ -101,7 +101,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="@dimen/top_right_drawer_btns_mr" android:layout_marginRight="@dimen/top_right_drawer_btns_mr"
app:constraint_referenced_ids="main_activity_note,main_activity_task_line,main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_disance,main_activity_menu" app:constraint_referenced_ids="main_activity_note,main_activity_task_line,main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_calc_distance,main_activity_menu"
app:flow_horizontalGap="6dp" app:flow_horizontalGap="6dp"
app:flow_wrapMode="aligned" app:flow_wrapMode="aligned"
app:layout_constraintRight_toLeftOf="@id/main_activity_right_fragment" app:layout_constraintRight_toLeftOf="@id/main_activity_right_fragment"
@ -112,7 +112,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="invisible" android:visibility="invisible"
app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_note,main_activity_task_line,main_activity_calc_disance" /> app:constraint_referenced_ids="main_activity_serach,main_activity_2d_3d,main_activity_camera,main_activity_trace,main_activity_note,main_activity_task_line,main_activity_calc_distance" />
<ImageButton <ImageButton
android:id="@+id/main_activity_serach" android:id="@+id/main_activity_serach"
@ -139,9 +139,9 @@
android:src="@drawable/icon_trace" /> android:src="@drawable/icon_trace" />
<ImageButton <ImageButton
android:id="@+id/main_activity_calc_disance" android:id="@+id/main_activity_calc_distance"
style="@style/top_right_drawer_btns_style" style="@style/top_right_drawer_btns_style"
android:onClick="@{()->mainActivity.onClickCalcDisance()}" android:onClick="@{()->mainActivity.onClickCalcDistance()}"
android:src="@drawable/icon_calc_disance" /> android:src="@drawable/icon_calc_disance" />
<ImageButton <ImageButton
@ -164,6 +164,15 @@
android:elevation="2dp" android:elevation="2dp"
android:onClick="@{()->mainActivity.onClickMenu()}" /> android:onClick="@{()->mainActivity.onClickMenu()}" />
<include
android:id="@+id/main_activity_measuring_tool"
layout="@layout/main_measuring_tool"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:visibility="gone"
app:layout_constraintRight_toRightOf="@id/main_activity_calc_distance"
app:layout_constraintTop_toBottomOf="@id/main_activity_flow" />
<androidx.constraintlayout.widget.Barrier <androidx.constraintlayout.widget.Barrier
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -333,12 +342,12 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/five" android:layout_marginBottom="@dimen/five"
app:constraint_referenced_ids="main_activity_snapshot_finish,main_activity_trace_snapshot_points,main_activity_snapshot_media_flag,main_activity_snapshot_rewind,main_activity_snapshot_pause,main_activity_snapshot_next,main_activity_menu_indoor_group" app:constraint_referenced_ids="main_activity_snapshot_finish,main_activity_trace_snapshot_points,main_activity_snapshot_rewind,main_activity_snapshot_pause,main_activity_snapshot_next,main_activity_menu_indoor_group"
app:flow_horizontalGap="6dp" app:flow_horizontalGap="6dp"
app:flow_wrapMode="aligned" app:flow_wrapMode="aligned"
app:layout_constraintBottom_toTopOf="@id/main_activity_bottom_sheet"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintBottom_toTopOf="@id/main_activity_bottom_sheet" />
<androidx.constraintlayout.widget.Group <androidx.constraintlayout.widget.Group
android:id="@+id/main_activity_menu_indoor_group" android:id="@+id/main_activity_menu_indoor_group"

View File

@ -3,31 +3,48 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/shape_rect_white_6dp_bg" android:background="@drawable/shape_rect_white_6dp_bg"
android:clickable="true"
android:gravity="center" android:gravity="center"
android:orientation="horizontal"> android:orientation="horizontal"
android:padding="5dp">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/measuring_tool_value"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="24dp"
android:background="@drawable/shape_bg_blue_bg_4_radius" android:background="@drawable/shape_bg_blue_bg_4_radius"
android:textColor="@color/white" /> android:gravity="center"
android:minWidth="65dp"
android:text="0"
android:textColor="@color/white"
android:textSize="14sp" />
<TextView <TextView
android:id="@+id/measuring_tool_value_unit"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/blue" /> android:text="米"
android:textColor="@color/blue"
android:textSize="12sp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/measuring_tool_select_point"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical"
android:paddingLeft="6dp"
android:paddingRight="6dp">
<ImageView <ImageView
android:layout_width="24dp" android:layout_width="24dp"
@ -43,10 +60,16 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/measuring_tool_distance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/selector_default_button_white_bg"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical"
android:paddingLeft="6dp"
android:paddingRight="6dp">
<ImageView <ImageView
android:layout_width="24dp" android:layout_width="24dp"
@ -62,8 +85,12 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/measuring_tool_area"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/selector_default_button_white_bg"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
@ -81,8 +108,12 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/measuring_tool_angle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/selector_default_button_white_bg"
android:gravity="center" android:gravity="center"
android:orientation="vertical"> android:orientation="vertical">
@ -100,20 +131,36 @@
</LinearLayout> </LinearLayout>
<TextView <TextView
android:layout_width="wrap_content" android:id="@+id/measuring_tool_backspace"
android:layout_height="wrap_content" android:layout_width="80dp"
android:layout_height="32dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/shape_rect_transparent_blue_6dp_bg"
android:drawableLeft="@drawable/baseline_arrow_left_24" android:drawableLeft="@drawable/baseline_arrow_left_24"
android:drawablePadding="-15dp"
android:gravity="center" android:gravity="center"
android:text="上一步" android:text="上一步"
android:textColor="@color/blue" android:textColor="@color/blue"
android:textSize="12sp" /> android:textSize="12sp" />
<TextView <TextView
android:layout_width="wrap_content" android:id="@+id/measuring_tool_reset"
android:layout_height="wrap_content" android:layout_width="80dp"
android:drawableLeft="@drawable/baseline_arrow_left_24" android:layout_height="32dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/shape_rect_transparent_blue_6dp_bg"
android:gravity="center" android:gravity="center"
android:text="重复" android:text="重"
android:textColor="@color/blue" android:textColor="@color/blue"
android:textSize="12sp" /> android:textSize="12sp" />
<ImageView
android:id="@+id/measuring_tool_close"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/measuring_tool_close" />
</LinearLayout> </LinearLayout>

View File

@ -10,7 +10,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.navinfo.collect.library.R import com.navinfo.collect.library.R
import com.navinfo.collect.library.map.NIMapView import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.layers.NIPolygonLayer
import com.navinfo.collect.library.utils.DistanceUtil import com.navinfo.collect.library.utils.DistanceUtil
import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.StringUtil.Companion.createUUID import com.navinfo.collect.library.utils.StringUtil.Companion.createUUID
@ -26,29 +25,48 @@ import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem import org.oscim.layers.marker.MarkerItem
import org.oscim.layers.marker.MarkerSymbol import org.oscim.layers.marker.MarkerSymbol
import org.oscim.layers.vector.PathLayer import org.oscim.layers.vector.PathLayer
import org.oscim.layers.vector.geometries.PolygonDrawable
import org.oscim.layers.vector.geometries.Style import org.oscim.layers.vector.geometries.Style
import org.oscim.map.Map import org.oscim.map.Map
import java.math.BigDecimal import java.math.BigDecimal
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.ceil import kotlin.math.ceil
open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) : open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
BaseHandler(context, mapView), Map.UpdateListener { BaseHandler(context, mapView), Map.UpdateListener {
private var editIndex: Int = -1;//线修型的时候,用来表示是不是正在修型,修的第几个点 private var editIndex: Int = -1;//线修型的时候,用来表示是不是正在修型,修的第几个点
private val mPathMakers: MutableList<MarkerItem> = mutableListOf() private val mPathMakers: MutableList<MarkerItem> = mutableListOf()
private var bDrawLine = false private var bDrawLine = false
private val bDrawPoint = false private var measureType = MEASURE_TYPE.DISTANCE
/**
* 测量类型
*/
enum class MEASURE_TYPE {
DISTANCE,//距离
AREA,//面积
ANGLE,//角度
}
data class MeasureValueBean(
var value: Double = 0.00,
var valueString: String = "0.00",
var unit: String = ""
)
/** /**
* 加上虚线的总长度 * 加上虚线的总长度
*/ */
val tempLineDistanceLiveData = MutableLiveData("") val tempMeasureValueLiveData = MutableLiveData<MeasureValueBean>()
/** /**
* 实际绘制的总长度 * 实际绘制的总长度
*/ */
val lineLengthLiveData = MutableLiveData(0.000) val measureValueLiveData = MutableLiveData<MeasureValueBean>()
private val markerLayer: ItemizedLayer by lazy { private val markerLayer: ItemizedLayer by lazy {
@ -64,35 +82,46 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
layer layer
} }
private val mAreaLayer: ItemizedLayer by lazy { /**
val markerSymbol = MarkerSymbol(mPathMarkerBitmap, MarkerSymbol.HotspotPlace.CENTER) * 显示面积文字
ItemizedLayer(mMapView.vtmMap, ArrayList(), markerSymbol, null) */
private var mAreaTextLayer: ItemizedLayer? = null
/**
* 面积的渲染面
*/
private var areaPolygon: PolygonDrawable? = null
/**
* 面积的渲染样式
*/
private val areaStyle: Style by lazy {
Style.builder().scaleZoomLevel(20).buffer(1.0)
.fillColor(context.resources.getColor(R.color.draw_area_color)).fillAlpha(0.5f)
.fixed(true).build()
} }
//绘制线 样式 //绘制线 样式
private val lineStyle: Style by lazy { private val lineStyle: Style by lazy {
//新增线数据图层和线样式 //新增线数据图层和线样式
Style.builder().scaleZoomLevel(20).buffer(1.0) Style.builder().scaleZoomLevel(20).buffer(1.0)
.stippleColor(context.resources.getColor(R.color.draw_line_blue1_color)) .stippleColor(context.resources.getColor(R.color.draw_line_blue1_color)).strokeWidth(4f)
.strokeWidth(4f) .fillColor(context.resources.getColor(R.color.draw_line_blue2_color)).fillAlpha(0.5f)
.fillColor(context.resources.getColor(R.color.draw_line_blue2_color)) .strokeColor(context.resources.getColor(R.color.draw_line_blue2_color)).stippleWidth(4f)
.fillAlpha(0.5f) .fixed(true).build()
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color))
.fillColor(context.resources.getColor(R.color.draw_line_red_color))
.stippleWidth(4f).fixed(true).build()
} }
private val newTempStyle: Style by lazy { private val newTempStyle: Style by lazy {
Style.builder().stippleColor(context.resources.getColor(R.color.transparent)) Style.builder().stippleColor(context.resources.getColor(R.color.transparent)).stipple(30)
.stipple(30).stippleWidth(30f).strokeWidth(4f) .stippleWidth(30f).strokeWidth(4f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color)) .strokeColor(context.resources.getColor(R.color.draw_line_blue2_color)).fixed(true)
.fixed(true).randomOffset(false).build() .randomOffset(false).build()
} }
//线型编辑时的样式 //线型编辑时的样式
private val editTempStyle: Style by lazy { private val editTempStyle: Style by lazy {
Style.builder().stippleColor(context.resources.getColor(R.color.transparent)) Style.builder().stippleColor(context.resources.getColor(R.color.transparent)).stipple(30)
.stipple(30).stippleWidth(30f).strokeWidth(8f) .stippleWidth(30f).strokeWidth(8f)
.strokeColor(context.resources.getColor(R.color.draw_line_red_color)).fixed(true) .strokeColor(context.resources.getColor(R.color.draw_line_red_color)).fixed(true)
.randomOffset(false).build() .randomOffset(false).build()
@ -121,125 +150,115 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
) )
} }
private var bDrawPolygon = false
val mPolygonLayer: NIPolygonLayer by lazy {
val layer = NIPolygonLayer(mMapView.vtmMap, lineStyle)
addLayer(layer, NIMapView.LAYER_GROUPS.OPERATE_LINE)
layer
}
init { init {
mMapView.vtmMap.events.bind(this) mMapView.vtmMap.events.bind(this)
} }
open fun drawLineOrPolygon(isPolygon: Boolean) { open fun addPoint(type: MEASURE_TYPE, selectPoint: GeoPoint? = null) {
bDrawLine = true
//画面 bDrawLine = true
if (isPolygon && !mPolygonLayer.isEnabled) { measureType = type
mPolygonLayer.isEnabled = true if (!mPathLayer.isEnabled) {
} else if (!mPathLayer.isEnabled) {
mPathLayer.isEnabled = true mPathLayer.isEnabled = true
} }
if (!markerLayer.isEnabled) {
markerLayer.isEnabled = true
}
//上一个点的引线 //上一个点的引线
if (!mPathLayerTemp.isEnabled) { if (!mPathLayerTemp.isEnabled) {
mPathLayerTemp.isEnabled = true mPathLayerTemp.isEnabled = true
} }
val geoPoint = GeoPoint(
val geoPoint = selectPoint ?: GeoPoint(
mMapView.vtmMap.mapPosition.latitude, mMapView.vtmMap.mapPosition.longitude mMapView.vtmMap.mapPosition.latitude, mMapView.vtmMap.mapPosition.longitude
) )
//编辑点 //编辑点
if (editIndex > -1) { if (editIndex > -1) {
if (mPathMakers.size > editIndex) { Log.e("jingo", "移除marker $editIndex")
markerLayer.removeItem(editIndex) val marker = mPathMakers[editIndex]
markerLayer.removeItem(marker)
mPathMakers.removeAt(editIndex) mPathMakers.removeAt(editIndex)
val markerItem = MarkerItem(createUUID(), "", "", geoPoint) val markerItem = MarkerItem(createUUID(), "", "", geoPoint)
markerLayer.addItem(markerItem) markerLayer.addItem(markerItem)
mPathMakers.add(editIndex, markerItem) mPathMakers.add(editIndex, markerItem)
if (mPathLayer.points.size > 0) { if (mPathLayer.points.size > 0) {
val list: MutableList<GeoPoint> = mPathLayer.points val list: MutableList<GeoPoint> = mPathLayer.points
if (editIndex < list.size) {
list.removeAt(editIndex) list.removeAt(editIndex)
val list2: MutableList<GeoPoint> = java.util.ArrayList(list) val list2: MutableList<GeoPoint> = ArrayList(list)
list2.add(editIndex, geoPoint) list2.add(editIndex, geoPoint)
mPathLayer.setPoints(list2) mPathLayer.setPoints(list2)
} }
} else if (mPolygonLayer.points.size > 0) {
val list = mPolygonLayer.points
if (editIndex < list.size) {
list.removeAt(editIndex)
val list2: MutableList<GeoPoint> = java.util.ArrayList(list)
list2.add(editIndex, geoPoint)
mPolygonLayer.setPoints(list2)
}
}
mPathLayerTemp.setStyle(newTempStyle) mPathLayerTemp.setStyle(newTempStyle)
val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>() mMapView.vtmMap.animator().animateTo(mPathLayer.points[mPathLayer.points.size - 1])
if (isPolygon && mPathMakers.size > 1) {
list.add(mPathMakers[0].geoPoint)
list.add(geoPoint)
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
} else {
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
list.add(geoPoint)
}
mPathLayerTemp.setPoints(list)
}
editIndex = -1 editIndex = -1
} else { //新增点 } else { //新增点
if (isPolygon) { if (type == MEASURE_TYPE.ANGLE && mPathLayer.points.size == 3) {
val points: MutableList<GeoPoint> = java.util.ArrayList(mPolygonLayer.points)
if (points.size > 2) {
val list: MutableList<GeoPoint> = java.util.ArrayList()
points.add(points[0])
list.add(points[0])
list.add(geoPoint)
list.add(mPolygonLayer.points[mPolygonLayer.points.size - 1])
val bCross = GeometryTools.isPolygonCrosses(points, list)
if (bCross) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return return
} }
}
mPolygonLayer.addPoint(geoPoint)
} else {
val points: List<GeoPoint> = mPathLayer.points val points: List<GeoPoint> = mPathLayer.points
if (points.size > 2) { if (points.size > 2) {
val list: MutableList<GeoPoint> = java.util.ArrayList() val list = mutableListOf<GeoPoint>()
list.add(geoPoint) list.add(geoPoint)
list.add(points[points.size - 1]) list.add(points[points.size - 1])
val bCross = GeometryTools.isLineStringCrosses(points, list) var bCross = GeometryTools.isLineStringCrosses(points, list)
if (bCross) { if (bCross) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show() Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return return
} }
if (measureType == MEASURE_TYPE.AREA) {
list.clear()
list.add(geoPoint)
list.add(points[0])
bCross = GeometryTools.isLineStringCrosses(points, list)
if (bCross) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return
}
}
} }
mPathLayer.addPoint(geoPoint) mPathLayer.addPoint(geoPoint)
if (mPathLayer.points.size > 1) { // }
val distance: Double = GeometryTools.getDistance(mPathLayer.points)
val bg = BigDecimal(distance)
val f1 = bg.setScale(3, BigDecimal.ROUND_HALF_UP).toDouble()
lineLengthLiveData.value = f1
} else {
lineLengthLiveData.value = 0.000
}
}
val markerItem = MarkerItem(createUUID(), "", "", geoPoint) val markerItem = MarkerItem(createUUID(), "", "", geoPoint)
markerLayer.addItem(markerItem) markerLayer.addItem(markerItem)
mPathMakers.add(markerItem) mPathMakers.add(markerItem)
markerLayer.update()
} }
//
when (type) {
MEASURE_TYPE.AREA -> {
showAreaLayer() showAreaLayer()
} }
MEASURE_TYPE.DISTANCE -> {
if (mPathLayer.points.size > 1) {
measureValueLiveData.value = calculatedDistance(mPathLayer.points)
} else {
measureValueLiveData.value = MeasureValueBean(unit = "")
}
}
MEASURE_TYPE.ANGLE -> {
if (mPathLayer.points.size == 3) {
val bean = calculatedAngle(mPathLayer.points)
measureValueLiveData.value = bean
} else {
measureValueLiveData.value = MeasureValueBean(unit = "")
}
}
}
//点击选点让地图动一下好出发mapEvent
if (selectPoint != null) {
mMapView.vtmMap.animator().animateTo(selectPoint)
}
mPathLayer.update()
}
/** /**
* 绘制线回退点 * 绘制线回退点
*/ */
open fun drawLineBackspace() { open fun backspacePoint() {
if (mPathLayer.points.size > 0) { if (mPathLayer.points.size > 0) {
val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>(mPathLayer.getPoints()) val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>(mPathLayer.points)
val point = list[mPathLayer.points.size - 1] val point = list[mPathLayer.points.size - 1]
list.remove(point) list.remove(point)
mPathLayer.setPoints(list) mPathLayer.setPoints(list)
@ -250,115 +269,196 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
) )
} }
if (mPathMakers.size > 0) { if (mPathMakers.size > 0) {
var item: MarkerItem? = mPathMakers[mPathMakers.size - 1] val item: MarkerItem = mPathMakers[mPathMakers.size - 1]
markerLayer.removeItem(item) markerLayer.removeItem(item)
mPathMakers.remove(item) mPathMakers.remove(item)
} }
if (mPathMakers.size == 0 && mPathLayerTemp != null) { if (mPathMakers.size == 0) {
mPathLayerTemp.clearPath() mPathLayerTemp.clearPath()
} }
editIndex = -1 editIndex = -1
if (mPathLayerTemp != null) {
mPathLayerTemp.setStyle(newTempStyle) mPathLayerTemp.setStyle(newTempStyle)
when (measureType) {
MEASURE_TYPE.AREA -> {
showAreaLayer()
} }
MEASURE_TYPE.DISTANCE -> {
if (mPathLayer.points.size > 1) { if (mPathLayer.points.size > 1) {
val distance: Double = GeometryTools.getDistance(mPathLayer.points) measureValueLiveData.value = calculatedDistance(mPathLayer.points)
val bg = BigDecimal(distance)
val f1 = bg.setScale(3, BigDecimal.ROUND_HALF_UP).toDouble()
lineLengthLiveData.value = f1
} else { } else {
lineLengthLiveData.value = 0.000 val bean = MeasureValueBean(unit = "")
tempLineDistanceLiveData.value = "0米" measureValueLiveData.value = bean
tempMeasureValueLiveData.value = bean
}
}
MEASURE_TYPE.ANGLE -> {
val bean = MeasureValueBean(unit = "")
measureValueLiveData.value = bean
tempMeasureValueLiveData.value = bean
} }
} }
/**
* 绘制面回退点
*/
open fun drawPolygonBackspace() {
// if (mPathLayer.points.size > 0) {
// val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>(mPathLayer.getPoints())
// val point = list[mPathLayer.getPoints().size - 1]
// list.remove(point)
// mPathLayer.setPoints(list)
// mMapView.layerManager.jumpToPosition(point.longitude, point.latitude, 0)
// } else if (mPolygonLayer.points.size > 0) {
// val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>(mPolygonLayer.points)
// val point = list[mPolygonLayer.points.size - 1]
// list.remove(point)
// mPolygonLayer.setPoints(list)
// mMapView.layerManager.jumpToPosition(point!!.longitude, point.latitude, 0)
// }
// if (mPathMakers.size > 0) {
// var item: MarkerItem? = mPathMakers[mPathMakers.size - 1]
// mMapView.layerManager.removeMarker(item, NILayerManager.MARQUEE_MARKER_LAYER)
// mPathMakers.remove(item)
// item = null
// }
// if (mPathMakers.size == 0 && mPathLayerTemp != null) {
// mPathLayerTemp.clearPath()
// }
// editIndex = -1
// if (mPathLayerTemp != null) {
// mPathLayerTemp.setStyle(newTempStyle)
// }
} }
/** /**
* 隐藏面积计算 * 隐藏面积计算
*/ */
open fun hideAreaLayer() { open fun hideAreaLayer() {
mAreaLayer.removeAllItems() mAreaTextLayer?.let {
mMapView.vtmMap.layers().remove(mAreaLayer) it.removeAllItems()
removeLayer(it)
} }
}
/** /**
* 显示面积计算 * 显示面积计算
*/ */
open fun showAreaLayer() { open fun showAreaLayer() {
mAreaLayer.removeAllItems() if (mAreaTextLayer != null) {
mMapView.vtmMap.layers().remove(mAreaLayer) mAreaTextLayer!!.removeAllItems()
if (mPolygonLayer.points.size > 2) { removeLayer(mAreaTextLayer!!)
val list: MutableList<GeoPoint> = ArrayList(mPolygonLayer.points)
val area = DistanceUtil.planarPolygonAreaMeters2(list)
val areaString = if (area < 1000000) {
area.toString() + "平方米"
} else if (area < 10000000000.0) {
val d = area / 1000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
f1.toString() + "平方公里"
} else {
val d = area / 10000000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
f1.toString() + "万平方公里"
} }
if (areaPolygon != null) mPathLayer.remove(areaPolygon)
if (mPathLayer.points.size > 2) {
val list: MutableList<GeoPoint> = mPathLayer.points.toMutableList()
val valueBean = calculatedArea(list)
val textPaint = TextPaint() val textPaint = TextPaint()
textPaint.textSize = 13 * CanvasAdapter.getScale() textPaint.textSize = 13 * CanvasAdapter.getScale()
textPaint.color = Color.BLUE textPaint.color = Color.BLUE
val width = ceil(textPaint.measureText(areaString).toDouble()).toInt() val width = ceil(
textPaint.measureText("${valueBean.valueString}${valueBean.unit}").toDouble()
).toInt()
val fontMetrics = textPaint.fontMetrics val fontMetrics = textPaint.fontMetrics
val height = ceil((abs(fontMetrics.bottom) + abs(fontMetrics.top)).toDouble()).toInt() val height = ceil((abs(fontMetrics.bottom) + abs(fontMetrics.top)).toDouble()).toInt()
val bitmap = android.graphics.Bitmap.createBitmap( val bitmap = android.graphics.Bitmap.createBitmap(
width, height, android.graphics.Bitmap.Config.ARGB_8888 width, height, android.graphics.Bitmap.Config.ARGB_8888
) )
val canvas = Canvas(bitmap) val canvas = Canvas(bitmap)
canvas.drawText(areaString, 0f, abs(fontMetrics.ascent), textPaint) canvas.drawText(
// val bitmap2: Bitmap = AndroidBitmap(bitmap) "${valueBean.valueString}${valueBean.unit}",
// val markerSymbol = MarkerSymbol(bitmap2, MarkerSymbol.HotspotPlace.CENTER) 0f,
// mAreaLayer = ItemizedLayer(mMapView.vtmMap, ArrayList(), markerSymbol, null) abs(fontMetrics.ascent),
// mMapView.vtmMap.layers().add(mAreaLayer) textPaint
)
val bitmap2: Bitmap = AndroidBitmap(bitmap)
val markerSymbol = MarkerSymbol(bitmap2, MarkerSymbol.HotspotPlace.CENTER)
mAreaTextLayer = ItemizedLayer(
mMapView.vtmMap, java.util.ArrayList(), markerSymbol, null
)
addLayer(mAreaTextLayer!!, NIMapView.LAYER_GROUPS.OPERATE_MARKER)
list.add(list[0]) list.add(list[0])
val polygon = GeometryTools.createPolygon(list) val polygon = GeometryTools.createPolygon(list)
val point = polygon.centroid val point = polygon.centroid
val item = MarkerItem(areaString, "", GeoPoint(point.coordinate.y, point.coordinate.x)) val item = MarkerItem(
mAreaLayer.removeAllItems() "${valueBean.valueString}${valueBean.unit}",
mAreaLayer.addItem(item) "",
mAreaLayer.update() GeoPoint(point.coordinate.y, point.coordinate.x)
)
mAreaTextLayer!!.removeAllItems()
mAreaTextLayer!!.addItem(item)
mAreaTextLayer!!.update()
areaPolygon = PolygonDrawable(polygon, areaStyle)
mPathLayer.add(areaPolygon)
measureValueLiveData.postValue(valueBean)
} }
}
/**
* 计算角度
*/
private fun calculatedAngle(list: MutableList<GeoPoint>): MeasureValueBean {
val bean = MeasureValueBean(unit = "")
if (list.size == 3) {
var angle = DistanceUtil.angle(
list[0],
list[1],
list[2]
)
if (angle > 180)
angle = 360 - angle
val bg = BigDecimal(angle)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.value = angle
bean.valueString = f1.toString()
}
return bean
}
/**
* 计算距离
*/
private fun calculatedDistance(list: MutableList<GeoPoint>): MeasureValueBean {
val bean = MeasureValueBean(unit = "")
if (list.size < 2) {
return bean
}
val distance: Double = GeometryTools.getDistance(list)
bean.value = distance
try {
if (distance < 1000) {
val bg = BigDecimal(distance)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = ""
} else if (distance < 10000000) {
val d = distance / 1000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = "公里"
} else {
val d = distance / 10000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = "万公里"
}
} catch (e: Exception) {
Log.e("jingo", e.toString() + "$distance")
}
return bean
}
/**
* 计算面积
*/
private fun calculatedArea(list: MutableList<GeoPoint>): MeasureValueBean {
val bean = MeasureValueBean(unit = "平方米")
val area = DistanceUtil.planarPolygonAreaMeters2(list)
bean.value = area
if (area == 0.0) {
"0"
} else if (area < 10000) {
val bg = BigDecimal(area)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = "平方米"
} else if (area < 1000000) {
val d = area / 10000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = "万平方米"
} else if (area < 10000000000.0) {
val d = area / 1000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = "平方公里"
} else {
val d = area / 10000000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP)
bean.valueString = f1.toString()
bean.unit = "万平方公里"
}
return bean
} }
/** /**
@ -368,17 +468,20 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
bDrawLine = false bDrawLine = false
editIndex = -1 editIndex = -1
markerLayer.removeAllItems() markerLayer.removeAllItems()
markerLayer.isEnabled = false
mPathMakers.clear() mPathMakers.clear()
mPathLayer.clearPath() mPathLayer.clearPath()
if (areaPolygon != null) {
mPathLayer.remove(areaPolygon)
areaPolygon = null
}
mPathLayer.isEnabled = false mPathLayer.isEnabled = false
mPolygonLayer.clearPath()
mPolygonLayer.isEnabled = false
mPathLayerTemp.clearPath() mPathLayerTemp.clearPath()
mPathLayerTemp.isEnabled = false mPathLayerTemp.isEnabled = false
mPathLayerTemp.setStyle(newTempStyle) mPathLayerTemp.setStyle(newTempStyle)
hideAreaLayer() hideAreaLayer()
lineLengthLiveData.value = 0.000 measureValueLiveData.value = MeasureValueBean()
tempLineDistanceLiveData.value = "0米" tempMeasureValueLiveData.value = MeasureValueBean()
mMapView.vtmMap.updateMap(true) mMapView.vtmMap.updateMap(true)
} }
@ -394,27 +497,94 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
// mapPosition.setPosition(geoPoint) // mapPosition.setPosition(geoPoint)
// } // }
if (e === Map.POSITION_EVENT) { if (e === Map.POSITION_EVENT) {
mPathLayerTemp.clearPath()
//测角度3个点后不渲染引导线
if (mPathLayer.points.size > 0) { if (mPathLayer.points.size > 0) {
if (editIndex > -1) { if (editIndex > -1) {
val list: MutableList<GeoPoint> = mutableListOf() val list = mutableListOf<GeoPoint>()
if (editIndex == 0 || editIndex == mPathMakers.size - 1) { val tempList = mutableListOf<GeoPoint>()
list.add(mPathMakers[editIndex].geoPoint) //编辑起点
if (editIndex == 0) {
//如果现在只有一个点,显示当前点要移动到的位置
if (mPathLayer.points.size == 1) {
list.add(mPathLayer.points[0])
list.add( list.add(
GeoPoint( GeoPoint(
mapPosition.latitude, mapPosition.longitude mapPosition.latitude, mapPosition.longitude
) )
) )
} else { } else {
list.add(mPathMakers[editIndex - 1].geoPoint) //当前有多个点,红线链接第二个点
list.add(mPathLayer.points[1])
list.add( list.add(
GeoPoint( GeoPoint(
mapPosition.latitude, mapPosition.longitude mapPosition.latitude, mapPosition.longitude
) )
) )
list.add(mPathMakers[editIndex + 1].geoPoint) if (measureType == MEASURE_TYPE.AREA) {
list.add(mPathLayer.points[mPathLayer.points.size - 1])
}
tempList.add(
GeoPoint(
mapPosition.latitude, mapPosition.longitude
)
)
for (i in 1 until mPathLayer.points.size) {
tempList.add(mPathLayer.points[i])
}
}
} else if (editIndex == mPathLayer.points.size - 1) {
//如果当前编辑的是最后一个点
list.add(mPathLayer.points[editIndex - 1])
list.add(
GeoPoint(
mapPosition.latitude, mapPosition.longitude
)
)
for (i in 0 until mPathLayer.points.size - 1) {
tempList.add(mPathLayer.points[i])
}
tempList.add(
GeoPoint(
mapPosition.latitude, mapPosition.longitude
)
)
if (measureType == MEASURE_TYPE.AREA) {
list.add(mPathLayer.points[0])
}
} else {
list.add(mPathLayer.points[editIndex - 1])
list.add(
GeoPoint(
mapPosition.latitude, mapPosition.longitude
)
)
list.add(mPathLayer.points[editIndex + 1])
for (i in 0 until editIndex) {
tempList.add(mPathLayer.points[i])
}
tempList.add(
GeoPoint(
mapPosition.latitude, mapPosition.longitude
)
)
for (i in editIndex + 1 until mPathLayer.points.size) {
tempList.add(mPathLayer.points[i])
}
} }
mPathLayerTemp.setPoints(list) mPathLayerTemp.setPoints(list)
// crossText.setText("") when (measureType) {
MEASURE_TYPE.DISTANCE -> {
tempMeasureValueLiveData.value = calculatedDistance(tempList)
}
MEASURE_TYPE.AREA -> {
tempMeasureValueLiveData.value = calculatedArea(tempList)
}
MEASURE_TYPE.ANGLE -> {
tempMeasureValueLiveData.value = calculatedAngle(tempList)
}
}
} else { } else {
val list: MutableList<GeoPoint> = mutableListOf() val list: MutableList<GeoPoint> = mutableListOf()
list.add(mPathLayer.points[mPathLayer.points.size - 1]) list.add(mPathLayer.points[mPathLayer.points.size - 1])
@ -424,29 +594,40 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
list.add( list.add(
nowPoint nowPoint
) )
when (measureType) {
MEASURE_TYPE.DISTANCE -> {
mPathLayerTemp.setPoints(list) mPathLayerTemp.setPoints(list)
if (mPathLayer.points.size > 0) {
val dList = mPathLayer.points.toMutableList() val dList = mPathLayer.points.toMutableList()
dList.add(nowPoint) dList.add(nowPoint)
val distance: Double = tempMeasureValueLiveData.value = calculatedDistance(dList)
GeometryTools.getDistance(dList) }
if (distance < 1000) { MEASURE_TYPE.AREA -> {
tempLineDistanceLiveData.value = "${distance.toInt()}" if (mPathLayer.points.size == 1) {
mPathLayerTemp.setPoints(list)
} else if (mPathLayer.points.size > 1) {
list.add(mPathLayer.points[0])
mPathLayerTemp.setPoints(list)
val dList = mPathLayer.points.toMutableList()
dList.add(nowPoint)
dList.add(mPathLayer.points[0])
tempMeasureValueLiveData.value = calculatedArea(dList)
} else { } else {
try { tempMeasureValueLiveData.value = MeasureValueBean(unit = "平方米")
val d = distance / 1000.0 }
val bg = BigDecimal(d)
val f1 = }
bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble() MEASURE_TYPE.ANGLE -> {
tempLineDistanceLiveData.value = "${f1}公里" mPathLayerTemp.setPoints(list)
} catch (e: Exception) { val dList = mPathLayer.points.toMutableList()
Log.e("jingo", e.toString() + "$distance") if(dList.size < 3) {
dList.add(nowPoint)
}
tempMeasureValueLiveData.value = calculatedAngle(dList)
}
} }
} }
} else { } else {
tempLineDistanceLiveData.value = "0米" tempMeasureValueLiveData.value = MeasureValueBean(unit = "平方米")
}
}
} }
} }
} }
@ -466,13 +647,11 @@ open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
mPathMakers.add(markerItem) mPathMakers.add(markerItem)
} }
if (mPathLayer.points.size > 1) { if (mPathLayer.points.size > 1) {
val distance: Double = GeometryTools.getDistance(mPathLayer.points) val bean = calculatedDistance(mPathLayer.points)
val bg = BigDecimal(distance) measureValueLiveData.value = bean
val f1 = bg.setScale(3, BigDecimal.ROUND_HALF_UP).toDouble() tempMeasureValueLiveData.value = bean
lineLengthLiveData.value = f1
tempLineDistanceLiveData.value = "${f1}"
} else { } else {
lineLengthLiveData.value = 0.000 measureValueLiveData.value = MeasureValueBean(unit = "")
} }
mMapView.updateMap(true) mMapView.updateMap(true)
} }

View File

@ -258,7 +258,7 @@ public class GeometryTools {
* @return Polygon * @return Polygon
*/ */
public static Polygon createPolygon(List<GeoPoint> geoPointList) { public static Polygon createPolygon(List<GeoPoint> geoPointList) {
if (geoPointList != null && geoPointList.size() >= 3) { if (geoPointList != null && geoPointList.size() > 2) {
Coordinate[] coordinates = new Coordinate[geoPointList.size()]; Coordinate[] coordinates = new Coordinate[geoPointList.size()];
for (int i = 0; i < geoPointList.size(); i++) { for (int i = 0; i < geoPointList.size(); i++) {
coordinates[i] = new Coordinate(geoPointList.get(i).getLongitude(), geoPointList.get(i).getLatitude()); coordinates[i] = new Coordinate(geoPointList.get(i).getLongitude(), geoPointList.get(i).getLatitude());

View File

@ -9,5 +9,6 @@
<color name="draw_line_blue2_color" comment="线数据样式">#4E55AF</color> <color name="draw_line_blue2_color" comment="线数据样式">#4E55AF</color>
<color name="draw_line_red_color" comment="线数据样式">#FFF6565D</color> <color name="draw_line_red_color" comment="线数据样式">#FFF6565D</color>
<color name="default_red" comment="应用主要色调">#F03736</color> <color name="default_red" comment="应用主要色调">#F03736</color>
<color name="draw_area_color" comment="测量面积渲染颜色">#8DEF08EB</color>
</resources> </resources>

2
vtm

@ -1 +1 @@
Subproject commit 4c9926d105877fce305025e8f85651ccea947c4f Subproject commit a8b86629c698e0fe24bac6ee1dc296f3b65b0f79