FragmentMap.kt 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067
  1. package com.cr.pages
  2. import android.graphics.Bitmap
  3. import android.graphics.Color
  4. import android.graphics.drawable.BitmapDrawable
  5. import android.os.Bundle
  6. import android.view.LayoutInflater
  7. import android.view.View
  8. import android.view.ViewGroup
  9. import androidx.fragment.app.activityViewModels
  10. import com.cr.common.*
  11. import com.cr.cruav.CrApplication
  12. import com.cr.cruav.R
  13. import com.cr.data.CrUtil
  14. import com.cr.dialog.DialogInput
  15. import com.cr.dialog.DialogNormal
  16. import com.cr.event.EventMapCapture
  17. import com.cr.map.*
  18. import com.cr.models.CompletionModel
  19. import com.cr.models.ICompletion
  20. import com.cr.viewmodel.CrFlightControlVM
  21. import com.esri.arcgisruntime.arcgisservices.LabelDefinition
  22. import com.esri.arcgisruntime.data.*
  23. import com.esri.arcgisruntime.geometry.*
  24. import com.esri.arcgisruntime.layers.ArcGISMapImageLayer
  25. import com.esri.arcgisruntime.layers.ArcGISTiledLayer
  26. import com.esri.arcgisruntime.layers.FeatureLayer
  27. import com.esri.arcgisruntime.layers.Layer
  28. import com.esri.arcgisruntime.mapping.ArcGISMap
  29. import com.esri.arcgisruntime.mapping.view.*
  30. import com.esri.arcgisruntime.symbology.*
  31. import com.google.gson.JsonObject
  32. import com.google.gson.JsonParser
  33. import com.google.gson.JsonPrimitive
  34. import com.squareup.otto.Subscribe
  35. import kotlinx.android.synthetic.main.frag_map.*
  36. import kotlinx.coroutines.*
  37. import java.io.File
  38. import java.io.FileOutputStream
  39. import java.lang.Runnable
  40. import java.util.*
  41. import java.util.concurrent.ExecutionException
  42. import kotlin.math.abs
  43. /**
  44. * 操作系统:MAC系统
  45. * 创建者:王成
  46. * 创建日期:2023/3/14 09:51
  47. * 描述:地图界面
  48. */
  49. class FragmentMap : CrAnimationFragment() {
  50. // todo: 2023/8/17 飞行器模型
  51. private val flightControlVm:CrFlightControlVM by activityViewModels()
  52. /**
  53. * 事件监听接口
  54. */
  55. interface EventListener {
  56. // todo: 2023/6/15 案件上传监听
  57. fun onCaseUpdate(selCase: CaseModel)
  58. }
  59. // define: 2023/3/14 地图容器
  60. private var mapView: MapView? = null
  61. // define: 2023/3/14 地图
  62. private var mMap: ArcGISMap? = null
  63. // todo: 2023/4/13 常量定义
  64. val ONLINE_LAYER_NAME = "底图"
  65. val ONLINE_LABEL_LAYER_NAME = "标签"
  66. // todo: 2023/4/13 图层名称定义
  67. val LAYER_NAME_ICO = "永久标志"
  68. val LAYER_NAME_DOODLE = "永久涂鸦"
  69. val LAYER_NAME_MEDIA = "案件点"
  70. val LAYER_NAME_CASE = "绘制案件图斑"
  71. val LAYER_NAME_YX = "影像图"
  72. val LAYER_NAME_GH = "规划图"
  73. val LAYER_NAME_XZ = "现状图"
  74. val LAYER_NAME_NET_CASE = "在线案件图斑"
  75. val LAYER_NAME_TEMP_ICO = "临时标志"
  76. val LAYER_NAME_TEMP_DOODLE = "临时涂鸦"
  77. val LAYER_NAME_CONFIG_VILLAGE = "行政区(村界)"
  78. val LAYER_NAME_CONFIG_TOWNS = "行政区(镇界)"
  79. val LAYER_NAME_AIR_LINE = "飞行航线"
  80. val LAYER_NAME_AIR_HISTORY_LINE = "历史航线"
  81. val LAYER_NAME_AIR_LOCATION = "飞行器"
  82. val LAYER_NAME_AIR_HOME = "返航点"
  83. // todo: 2023/4/14 符号相关常量
  84. val SYMBOL_WIDTH = 25.0f // define: 2023/4/13 图片符号的宽度
  85. val SYMBOL_HEIGHT = 25.0f // define: 2023/4/13 图片符号的高度
  86. val R_LABEL_WJ_NO = "wj_no" // define: 2023/4/13 未上传违建标识
  87. val R_LABEL_WJ_YES = "wj_yes" // define: 2023/4/13 已上传违建标识
  88. val R_LABEL_REPEAT_NO = "repeat_no" // define: 2023/4/13 为上传复飞点标识
  89. val R_LABEL_REPEAT_YES = "repeat_yes" // define: 2023/4/13 已上传复飞点标识
  90. // todo: 2023/4/14 媒体点相关常量
  91. val MEDIA_TYPE_WJ_NO = "0" // define: 2023/4/13 未上传的违建点
  92. val MEDIA_TYPE_WJ_YES = "1" // define: 2023/4/13 已上传的违建点
  93. val MEDIA_TYPE_REPEAT_NO = "4" // define: 2023/4/13 未上传的复飞案件
  94. val MEDIA_TYPE_REPEAT_YES = "5" // define: 2023/4/13 已上传的复飞案件
  95. // todo: 2023/4/14 字段相关常量
  96. companion object {
  97. val FIELD_NET_CASE_POLYGON_AJH = "AJH" // define: 2023/4/13 网络案件的案件编号
  98. val FIELD_CASE_POLYGON_ANJID = "ANJID" // define: 2023/4/13 案件ID
  99. val FIELD_CASE_POLYGON_MJ = "MJ" // define: 2023/4/13 面积
  100. val FIELD_CASE_POLYGON_BZ = "BZ" // define: 2023/4/13 违建面的类型 0--代表未匹配 1--代表已匹配
  101. val FIELD_CASE_POLYGON_BZ_VALUE_NO = "0" // define: 2023/4/13 未匹配
  102. val FIELD_CASE_POLYGON_BZ_VALUE_YES = "1" // define: 2023/4/13 已匹配
  103. val FIELD_CASE_NAME = "NAME" // define: 2023/4/13 名称字段
  104. val FIELD_CASE_IMAGES = "IMAGES" // define: 2023/4/13 图片集合字段
  105. val FIELD_CASE_RQ = "RQ" // define: 2023/4/13 日期字段
  106. val FIELD_CASE_LAT = "LAT" // define: 2023/4/13 纬度字段
  107. val FIELD_CASE_LNG = "LNG" // define: 2023/4/13 经度字段
  108. val FIELD_CASE_ISUP = "ISUP" // define: 2023/4/13 是否上传
  109. val FIELD_CASE_ALT = "ALT" // define: 2023/4/13 高度字段
  110. val FIELD_CASE_ANG = "ANG" // define: 2023/4/13 角度字段
  111. val FIELD_CASE_TYPE = "TYPE" // define: 2023/4/13 类型字段
  112. val FIELD_CASE_ISDOWN = "ISDOWN" // define: 2023/4/13 是否下载
  113. val MEDIA_TYPE_WJ_NO = "0" // define: 2023/6/12 未上传的案件点
  114. val MEDIA_TYPE_WJ_YES = "1" // define: 2023/6/12 已上传的案件点
  115. val MEDIA_TYPE_REPEAT_NO = "4" // define: 2023/6/12 未上传的复飞点
  116. val MEDIA_TYPE_REPEAT_YES = "5" // define: 2023/6/12 已上传的复飞点
  117. }
  118. // todo: 2023/4/13 标志相关
  119. private var markChange: EventMarkChange? = null
  120. // todo: 2023/4/14 绘制图层
  121. private var gLayerIco: GraphicsOverlay? = null // define: 2023/4/13 标志图层
  122. private var gLayerAirplaneLocation: GraphicsOverlay? = null // define: 2023/4/13 飞行器位置图层
  123. private var gLayerAirplaneHomeLocation: GraphicsOverlay? = null // define: 2023/4/13 飞行器返航点位置图层
  124. private var gLayerAirplaneLine: GraphicsOverlay? = null // define: 2023/4/13 飞行航线图层
  125. private var gLayerHistoryAirplaneLine: GraphicsOverlay? = null // define: 2023/4/13 历史航线图层
  126. private var gLayerTemp: GraphicsOverlay? = null // define: 2023/6/5 临时展示内容图层
  127. // todo: 2023/4/13 样式相关
  128. private var symbolAirplaneLine: SimpleLineSymbol? = null // define: 2023/4/13 飞行航线样式
  129. private var symbolAirplaneLink: SimpleLineSymbol? = null // define: 2023/4/13 飞行器与返航点连接线样式
  130. private var symbolAirplaneLocation: PictureMarkerSymbol? = null // define: 2023/4/13 飞行器符号样式
  131. // todo: 2023/4/13 要素相关
  132. private var builderAirplaneLine: PolylineBuilder? = null // define: 2023/4/13 航线点集
  133. private var builderAirplaneLink: PolylineBuilder? = null // define: 2023/4/13 飞行器与返航点连接线点集
  134. private var builderAirplaneLocation: PointBuilder? = null // define: 2023/4/13 飞行器位置点
  135. private var builderAirplaneHomeLocation: PointBuilder? = null // define: 2023/4/13 返航点位置
  136. private var graAirplaneLine: Graphic? = null // define: 2023/4/13 航线图形
  137. private var graAirplaneLink: Graphic? = null // define: 2023/4/13 飞行器与返航点连接线图形
  138. private var graAirplaneLocation: Graphic? = null // define: 2023/4/13 飞行器位置图形
  139. private var graAirplaneHomeLocation: Graphic? = null // define: 2023/4/13 返航点位置图形
  140. // todo: 2023/4/17 草图编辑
  141. private var sketchEditor: SketchEditor? = null // define: 2023/4/13 草图编辑器
  142. private var feaSelectCase: Feature? = null // define: 2023/4/13 选中的案件点
  143. // todo: 2023/4/14 编辑图层
  144. private var fTableMark: FeatureTable? = null // define: 2023/4/14 永久标志表
  145. private var fLayerMark: FeatureLayer? = null // define: 2023/4/14 永久标志图层
  146. private var fTableMedia: FeatureTable? = null // define: 2023/4/14 媒体表
  147. private var fLayerMedia: FeatureLayer? = null // define: 2023/4/14 媒体图层
  148. private var fTableDoodle: FeatureTable? = null // define: 2023/4/14 永久涂鸦表
  149. private var fLayerDoodle: FeatureLayer? = null // define: 2023/4/14 永久涂鸦图层
  150. private var fTableCasePolygon: FeatureTable? = null // define: 2023/4/14 永久案件表
  151. private var fLayerCasePolygon: FeatureLayer? = null // define: 2023/4/14 永久案件图层
  152. private var fTableNetCasePolygon: ServiceFeatureTable? = null // define: 2023/4/14 网路案件表
  153. private var fLayerNetCasePolygon: ArcGISMapImageLayer? = null // define: 2023/4/14 网络案件图层
  154. // todo: 2023/4/18 地图Touch事件
  155. private var mapTouch: MapTouch? = null
  156. // todo: 2023/6/15 内部监听 自行设置
  157. private var eventListener: EventListener? = null
  158. // todo: 2023/8/8 截屏相关
  159. private var mapStateList = mutableListOf<MapStateModel>() // define: 2023/8/14 地图状态
  160. private var captureNames = mutableListOf<String>() // define: 2023/8/14 截屏图片名称
  161. // todo: 2023/8/17 投影
  162. private val spatialReferenceWGS84 = SpatialReference.create(4326)
  163. private val spatialReferenceWebMTK = SpatialReference.create(3857)
  164. /**
  165. * 重写创建View方法
  166. * @param inflater LayoutInflater
  167. * @param container ViewGroup?
  168. * @param savedInstanceState Bundle?
  169. * @return View?
  170. */
  171. override fun onCreateView(
  172. inflater: LayoutInflater,
  173. container: ViewGroup?,
  174. savedInstanceState: Bundle?
  175. ): View? {
  176. mainView = inflater.inflate(R.layout.frag_map, container, false)
  177. // todo: 2023/4/17 注册订阅
  178. CrApplication.getEventBus().register(this)
  179. return mainView
  180. }
  181. /**
  182. * 重写创建视图
  183. * @param view View
  184. * @param savedInstanceState Bundle?
  185. */
  186. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  187. super.onViewCreated(view, savedInstanceState)
  188. initUI()
  189. }
  190. /**
  191. * 初始化UI
  192. */
  193. private fun initUI() {
  194. //ArcGISRuntimeEnvironment.setLicense("runtimelite,1000,rud4449636536,none,NKMFA0PL4S0DRJE15166");
  195. // todo: 2023/3/14 初始化控件
  196. mapView = mainView?.findViewById(R.id.map_mapView)
  197. mapView?.let { itView ->
  198. // todo: 2023/4/13 设置底部标识是否显示
  199. itView.isAttributionTextVisible = false
  200. mMap = ArcGISMap()
  201. itView.map = mMap
  202. // todo: 2023/4/13 地图控件初始化
  203. itView.backgroundGrid.color = Color.argb(255, 216, 216, 216)
  204. itView.backgroundGrid.gridLineColor = Color.argb(0, 255, 255, 255)
  205. // todo: 2023/4/17 设置草图编辑
  206. sketchEditor = SketchEditor()
  207. setSketchEditor()
  208. itView.sketchEditor = sketchEditor
  209. // todo: 2023/4/18 Touch事件初始化
  210. mapTouch = MapTouch(CrApplication.getContext(), itView)
  211. mapTouch?.setListener(touchListener)
  212. itView.onTouchListener = mapTouch
  213. }
  214. // todo: 2023/4/13 地图初始化
  215. mapInit()
  216. }
  217. /**
  218. * 草图编辑工具监听
  219. */
  220. private var sketchGeometryChangeListener =
  221. SketchGeometryChangedListener { p0 ->
  222. if (p0!!.geometry.geometryType == GeometryType.POLYLINE) {
  223. // todo: 2023/6/5 清除已展示内容
  224. gLayerTemp?.graphics?.clear()
  225. var polyline = p0.geometry as Polyline
  226. var pointCollection = PointCollection(SpatialReference.create(3857))
  227. if (polyline.parts.size > 0) {
  228. for (point in polyline.parts[0].points) {
  229. pointCollection.add(point)
  230. if (pointCollection.size >= 2) {
  231. var polyline = Polyline(pointCollection)
  232. // todo: 2023/6/5 计算长度
  233. var lineLength = GeometryEngine.length(polyline)
  234. // todo: 2023/6/5 添加标签
  235. appendMeasureLabel(point, CrUnitManager.formatLength(lineLength))
  236. }
  237. }
  238. }
  239. } else if (p0!!.geometry.geometryType == GeometryType.POLYGON) {
  240. // todo: 2023/6/6 清除临时标签
  241. gLayerTemp?.graphics?.clear()
  242. var polygon = p0.geometry as Polygon
  243. if (polygon.parts.size > 0) {
  244. if (CrUnitManager.querySizeByIterable(polygon.parts[0].points) >= 3) {
  245. // todo: 2023/6/6 计算面积
  246. var area = GeometryEngine.area(polygon)
  247. area = abs(area)
  248. // todo: 2023/6/6 添加标签
  249. appendMeasureLabel(
  250. polygon.parts[0].startPoint,
  251. CrUnitManager.formatArea(area)
  252. )
  253. }
  254. }
  255. } else if (p0!!.geometry.geometryType == GeometryType.POINT && mapTouch!!.getAction() == MapAction.MapTapStopMoveWaypoint) {
  256. caseMoveWaypointToEnd(p0!!.geometry as Point)
  257. }
  258. }
  259. /**
  260. * 添加一个测量标签
  261. * @param location Point 位置
  262. * @param label String 标签内容
  263. */
  264. private fun appendMeasureLabel(location: Point, label: String) {
  265. var tSymbol = TextSymbol();
  266. tSymbol.color = Color.rgb(17, 46, 114)
  267. tSymbol.text = label
  268. tSymbol.size = 10f
  269. tSymbol.haloColor = Color.WHITE
  270. tSymbol.haloWidth = 2f
  271. tSymbol.fontWeight = TextSymbol.FontWeight.BOLD
  272. tSymbol.offsetY = 20f
  273. tSymbol.backgroundColor = Color.argb(200, 13, 49, 130)
  274. var graphic = Graphic(location, tSymbol)
  275. gLayerTemp?.graphics?.add(graphic)
  276. }
  277. /**
  278. * 设置草图编辑器
  279. */
  280. private fun setSketchEditor() {
  281. // todo: 2023/4/21 获取样式
  282. var sketchStyle: SketchStyle = sketchEditor!!.sketchStyle
  283. // todo: 2023/4/21 设置点符号样式
  284. var markerSymbol = SimpleMarkerSymbol()
  285. markerSymbol.size = 10f
  286. markerSymbol.color = Color.RED
  287. markerSymbol.style = SimpleMarkerSymbol.Style.CIRCLE
  288. // todo: 2023/4/21 设置样式
  289. sketchStyle.vertexSymbol = markerSymbol
  290. // todo: 2023/4/21 启用
  291. sketchEditor?.sketchStyle = sketchStyle
  292. }
  293. /**
  294. * Touch监听
  295. */
  296. private var touchListener = object : MapTouch.TouchListener {
  297. // todo: 2023/4/21 选择
  298. override fun onSelect(feature: Feature?, layer: Layer) {
  299. if (layer is FeatureLayer) {
  300. if (feature != null) {
  301. // todo: 2023/4/18 高亮显示
  302. focusFeature(layer!!, feature)
  303. } else {
  304. unfocusFeature(layer!!)
  305. }
  306. }
  307. }
  308. // todo: 2023/4/19 标志添加回调
  309. override fun onMarkAppend(mapPoint: Point) {
  310. markAppend(mapPoint)
  311. }
  312. // todo: 2023/6/7 查询地理位置回调
  313. override fun onQueryLocation(location: Point, longitude: String, latitude: String) {
  314. appendLocation(location, longitude, latitude)
  315. }
  316. // todo: 2023/6/12 添加案件点
  317. override fun onAppendWaypoint(location: Point, longitude: String, latitude: String) {
  318. caseAppendWaypointToMap(location, longitude, latitude)
  319. }
  320. // todo: 2023/6/14 删除案件点
  321. override fun onRemoveWaypoint(screenPoint: android.graphics.Point) {
  322. caseRemoveCaseWaypoing(screenPoint)
  323. }
  324. // todo: 2023/6/14 选择移动的案件点
  325. override fun onMoveWaypointBySelect(location: Point) {
  326. caseMoveWaypointBySelect(location)
  327. }
  328. // todo: 2023/6/15 案件分享及上传选择回调
  329. override fun onCaseUploadBySelect(screenPoint: android.graphics.Point) {
  330. caseUpload(screenPoint)
  331. }
  332. }
  333. /**
  334. * 地图初始化
  335. */
  336. private fun mapInit() {
  337. // todo: 2023/4/13 加载在线底图
  338. addOnlineRasterLayer()
  339. // todo: 2023/4/13 添加切片图层
  340. addTiledToMap()
  341. // todo: 2023/4/13 添加基础矢量地图
  342. addBaseGeoDatabaseToMap()
  343. // todo: 2023/4/14 添加可编辑矢量数据
  344. addEditGeoDatabaseToMap()
  345. // todo: 2023/4/19 添加动态图层
  346. addGraphicOverlayToMap()
  347. // todo: 2023/8/17 添加飞行相关图层
  348. addAirplaneLayerToMap()
  349. // todo: 2023/4/13 定位地图中心点
  350. setMapCenter(118.709, 35.219, 5000.0);
  351. }
  352. /**
  353. * 添加在线地图
  354. */
  355. private fun addOnlineRasterLayer() {
  356. var url: String =
  357. "https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer";
  358. var layer = ArcGISTiledLayer(url)
  359. layer.name = ONLINE_LAYER_NAME
  360. mMap?.operationalLayers?.add(layer)
  361. }
  362. /**
  363. * 添加切片图层
  364. */
  365. private fun addTiledToMap() {
  366. var tileLayers = DataManager.getTileLayerConfig()
  367. for (model in tileLayers) {
  368. var layer = ArcGISTiledLayer(model.url)
  369. layer.name = model.name
  370. layer.isVisible = model.isVisible
  371. mMap?.operationalLayers?.add(layer)
  372. // todo: 2023/4/13 添加到配置
  373. LayerManager.getInstance().addLayer(
  374. LayerModel(
  375. model.name!!,
  376. model.isVisible,
  377. LayerType.LAYER_TYPE_TILED,
  378. layer
  379. ), LayerManager.LayerGroup.LAYER_NAME_DAILY
  380. )
  381. }
  382. }
  383. /**
  384. * 添加基础矢量地图集合
  385. */
  386. private fun addBaseGeoDatabaseToMap() {
  387. if (!CrFileManager.isExists(CrUtil.MAP_PATH_BASE)) return
  388. var geoDatabase = Geodatabase(CrUtil.MAP_PATH_BASE)
  389. // todo: 2023/4/13 加载完成监听
  390. geoDatabase.addDoneLoadingListener(Runnable {
  391. var vLayers = DataManager.getVectorLayerConfig()
  392. var tables = geoDatabase.geodatabaseFeatureTables
  393. for (vLayer in vLayers) {
  394. var table = tables[vLayer.lyrIdx]
  395. var layer = FeatureLayer(table)
  396. layer.name = vLayer.lyrName
  397. layer.isVisible = vLayer.isVisible
  398. mMap?.operationalLayers?.add(layer)
  399. // todo: 2023/4/13 添加到配置信息
  400. LayerManager.getInstance().addLayer(
  401. LayerModel(
  402. vLayer.lyrName,
  403. vLayer.isVisible,
  404. LayerType.LAYER_TYPE_FEATURE,
  405. layer
  406. ), LayerManager.LayerGroup.LAYER_NAME_BASE
  407. )
  408. }
  409. })
  410. // todo: 2023/4/13 加载数据集
  411. geoDatabase.loadAsync()
  412. }
  413. /**
  414. * 加载可编辑数据
  415. */
  416. private fun addEditGeoDatabaseToMap() {
  417. if (!CrFileManager.isExists(CrUtil.MAP_PATH_EDIT)) return
  418. var geoDatabase = Geodatabase(CrUtil.MAP_PATH_EDIT)
  419. // todo: 2023/4/14 数据加载完监听
  420. geoDatabase.addDoneLoadingListener(Runnable {
  421. // todo: 2023/4/14 初始化标志图层
  422. fTableMark = geoDatabase.getGeodatabaseFeatureTable("ico84")
  423. fLayerMark = FeatureLayer(fTableMark)
  424. fLayerMark!!.name = LAYER_NAME_ICO
  425. fLayerMark!!.isVisible = true
  426. mMap!!.operationalLayers.add(fLayerMark)
  427. LayerManager.getInstance().addLayer(
  428. LayerModel(
  429. fLayerMark!!.name,
  430. fLayerMark!!.isVisible, LayerType.LAYER_TYPE_FEATURE_EDIT, fLayerMark!!
  431. ), LayerManager.LayerGroup.LAYER_NAME_DAILY
  432. )
  433. // todo: 2023/4/14 初始化涂鸦图层
  434. fTableDoodle = geoDatabase.getGeodatabaseFeatureTable("ty84")
  435. fLayerDoodle = FeatureLayer(fTableDoodle)
  436. fLayerDoodle!!.name = LAYER_NAME_DOODLE
  437. fLayerDoodle!!.isVisible = true
  438. mMap!!.operationalLayers.add(fLayerDoodle)
  439. LayerManager.getInstance().addLayer(
  440. LayerModel(
  441. fLayerDoodle!!.name,
  442. fLayerDoodle!!.isVisible, LayerType.LAYER_TYPE_FEATURE_EDIT, fLayerDoodle!!
  443. ), LayerManager.LayerGroup.LAYER_NAME_DAILY
  444. )
  445. // todo: 2023/4/14 初始化媒体点图层
  446. fTableMedia = geoDatabase.getGeodatabaseFeatureTable("media84")
  447. fLayerMedia = FeatureLayer(fTableMedia)
  448. fLayerMedia!!.name = LAYER_NAME_MEDIA
  449. fLayerMedia!!.isVisible = true
  450. mMap!!.operationalLayers.add(fLayerMedia)
  451. LayerManager.getInstance().addLayer(
  452. LayerModel(
  453. fLayerMedia!!.name,
  454. fLayerMedia!!.isVisible, LayerType.LAYER_TYPE_FEATURE_EDIT, fLayerMedia!!
  455. ), LayerManager.LayerGroup.LAYER_NAME_DAILY
  456. )
  457. // todo: 2023/4/14 初始化违建面图层
  458. fTableCasePolygon = geoDatabase.getGeodatabaseFeatureTable("sbwj84")
  459. fLayerCasePolygon = FeatureLayer(fTableCasePolygon)
  460. fLayerCasePolygon!!.name = LAYER_NAME_CASE
  461. fLayerCasePolygon!!.isVisible = true
  462. // todo: 2023/4/14 给图层添加标注
  463. val labelDefinition: LabelDefinition =
  464. createLabelDefinition(Color.BLUE, 12.0f, "round(\$feature.MJ,2) + '亩';")
  465. fLayerCasePolygon!!.labelDefinitions.add(labelDefinition)
  466. fLayerCasePolygon!!.isLabelsEnabled = true
  467. mMap!!.operationalLayers.add(fLayerCasePolygon)
  468. LayerManager.getInstance().addLayer(
  469. LayerModel(
  470. fLayerCasePolygon!!.name,
  471. fLayerCasePolygon!!.isVisible,
  472. LayerType.LAYER_TYPE_FEATURE_EDIT,
  473. fLayerCasePolygon!!
  474. ), LayerManager.LayerGroup.LAYER_NAME_DAILY
  475. )
  476. // todo: 2023/4/14 可编辑数据符号化
  477. editLayerRenderer()
  478. })
  479. // todo: 2023/4/14 异步加载
  480. geoDatabase.loadAsync()
  481. }
  482. /**
  483. * 添加动态图层到地图
  484. */
  485. private fun addGraphicOverlayToMap() {
  486. // todo: 2023/4/19 初始化动态标志图层
  487. gLayerIco = GraphicsOverlay()
  488. appendGraphicOverlay(gLayerIco!!, LAYER_NAME_TEMP_ICO)
  489. // todo: 2023/6/5 初始化临时展示内容图层
  490. gLayerTemp = GraphicsOverlay();
  491. mapView?.graphicsOverlays?.add(gLayerTemp)
  492. }
  493. /**
  494. * 添加飞行相关图层到地图
  495. */
  496. private fun addAirplaneLayerToMap() {
  497. // todo: 2023/8/16 初始化航线图层
  498. gLayerAirplaneLine = GraphicsOverlay()
  499. gLayerAirplaneLine?.let {
  500. overlaysAddToMap(it,LAYER_NAME_AIR_LINE,LayerManager.LayerGroup.LAYER_NAME_AIR)
  501. }
  502. // todo: 2023/8/16 初始化历史航线图层
  503. gLayerHistoryAirplaneLine = GraphicsOverlay()
  504. gLayerHistoryAirplaneLine?.let {
  505. overlaysAddToMap(it,LAYER_NAME_AIR_HISTORY_LINE,LayerManager.LayerGroup.LAYER_NAME_AIR)
  506. }
  507. // todo: 2023/8/17 初始化返航点图层
  508. gLayerAirplaneHomeLocation = GraphicsOverlay()
  509. gLayerAirplaneHomeLocation?.let {
  510. overlaysAddToMap(it,LAYER_NAME_AIR_HOME,LayerManager.LayerGroup.LAYER_NAME_AIR)
  511. }
  512. // todo: 2023/8/17 初始化飞行器图层
  513. gLayerAirplaneLocation = GraphicsOverlay()
  514. gLayerAirplaneLocation?.let {
  515. overlaysAddToMap(it,LAYER_NAME_AIR_LOCATION,LayerManager.LayerGroup.LAYER_NAME_AIR)
  516. }
  517. // todo: 2023/8/17 符号化
  518. initAirplaneSymbolInfo()
  519. }
  520. /**
  521. * 飞行相关符号化
  522. */
  523. private fun initAirplaneSymbolInfo(){
  524. // todo: 2023/8/17 符号化航线
  525. symbolAirplaneLine = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID,Color.WHITE,2.0f)
  526. symbolAirplaneLink = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID,Color.GREEN,2.0f)
  527. builderAirplaneLine = PolylineBuilder(spatialReferenceWGS84)
  528. builderAirplaneLink = PolylineBuilder(spatialReferenceWGS84)
  529. graAirplaneLine = Graphic(builderAirplaneLine!!.toGeometry(),symbolAirplaneLine)
  530. graAirplaneLink = Graphic(builderAirplaneLink!!.toGeometry(),symbolAirplaneLink)
  531. gLayerAirplaneLine?.graphics?.add(graAirplaneLine)
  532. gLayerAirplaneLine?.graphics?.add(graAirplaneLink)
  533. // todo: 2023/8/17 飞行器符号化
  534. builderAirplaneLocation = PointBuilder(spatialReferenceWGS84)
  535. symbolAirplaneLocation = createPictureMarkerSymbol(R.drawable.ico_air,25f,40f)
  536. graAirplaneLocation = Graphic(builderAirplaneLocation!!.toGeometry(),symbolAirplaneLocation)
  537. gLayerAirplaneLocation?.graphics?.add(graAirplaneLocation)
  538. // todo: 2023/8/17 返航位置初始化
  539. builderAirplaneHomeLocation = PointBuilder(spatialReferenceWGS84)
  540. var symbolAirplaneHomeLocation = createPictureMarkerSymbol(R.drawable.ico_home,30f,30f)
  541. graAirplaneHomeLocation = Graphic(builderAirplaneHomeLocation!!.toGeometry(),symbolAirplaneHomeLocation)
  542. gLayerAirplaneHomeLocation?.graphics?.add(graAirplaneHomeLocation)
  543. }
  544. /**
  545. * 添加绘制图层到地图中
  546. * @param layer GraphicsOverlay 绘制图层
  547. * @param layerName String 图层名称
  548. * @param group LayerGroup 分组
  549. */
  550. private fun overlaysAddToMap(layer:GraphicsOverlay,layerName:String,group:LayerManager.LayerGroup){
  551. // todo: 2023/8/17 设置可见
  552. layer.isVisible = true
  553. // todo: 2023/8/17 加入到地图中
  554. mapView?.graphicsOverlays!!.add(layer)
  555. // todo: 2023/8/17 加入到图层控制中
  556. LayerManager.getInstance().addLayer(
  557. LayerModel(
  558. layerName,
  559. layer.isVisible,
  560. LayerType.LAYER_TYPE_GRAPHIC,
  561. layer
  562. ), group
  563. )
  564. }
  565. /**
  566. * 编辑图层符号化
  567. */
  568. private fun editLayerRenderer() {
  569. // todo: 2023/4/14 永久涂鸦图层符号化
  570. val doodleSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLUE, 2.5f)
  571. val doodleRenderer = SimpleRenderer(doodleSymbol)
  572. fLayerDoodle?.renderer = doodleRenderer
  573. // todo: 2023/4/14 永久标志图层符号化
  574. val icoSymbol: PictureMarkerSymbol =
  575. createPictureMarkerSymbol(R.drawable.ico_ty1, 30f, 30f)
  576. val icoRenderer = SimpleRenderer(icoSymbol)
  577. fLayerMark?.renderer = icoRenderer
  578. // todo: 2023/4/14 违建符号化
  579. val mediaRenderer = UniqueValueRenderer()
  580. val mediaSymbolYes: PictureMarkerSymbol = createPictureMarkerSymbol(
  581. R.drawable.ico_wj_upload_yes,
  582. SYMBOL_WIDTH,
  583. SYMBOL_HEIGHT
  584. )
  585. val mediaSymbolNo: PictureMarkerSymbol = createPictureMarkerSymbol(
  586. R.drawable.ico_wj_no,
  587. SYMBOL_WIDTH,
  588. SYMBOL_HEIGHT
  589. )
  590. val mediaSymbolRepeatYes: PictureMarkerSymbol = createPictureMarkerSymbol(
  591. R.drawable.ico_repeatflight_yes,
  592. SYMBOL_WIDTH,
  593. SYMBOL_HEIGHT
  594. )
  595. val mediaSymbolRepeatNo: PictureMarkerSymbol = createPictureMarkerSymbol(
  596. R.drawable.ico_repeatflight_no,
  597. SYMBOL_WIDTH,
  598. SYMBOL_HEIGHT
  599. )
  600. mediaRenderer.defaultSymbol = mediaSymbolNo
  601. mediaRenderer.defaultLabel = R_LABEL_WJ_NO
  602. mediaRenderer.fieldNames.add(FIELD_CASE_ISUP)
  603. val cValueNo: MutableList<Any> = ArrayList()
  604. cValueNo.add(MEDIA_TYPE_WJ_NO)
  605. mediaRenderer.uniqueValues.add(
  606. UniqueValueRenderer.UniqueValue(
  607. R_LABEL_WJ_NO,
  608. R_LABEL_WJ_NO,
  609. mediaSymbolNo,
  610. cValueNo
  611. )
  612. )
  613. val cValueYes: MutableList<Any> = ArrayList()
  614. cValueYes.add(MEDIA_TYPE_WJ_YES)
  615. mediaRenderer.uniqueValues.add(
  616. UniqueValueRenderer.UniqueValue(
  617. R_LABEL_WJ_YES,
  618. R_LABEL_WJ_YES,
  619. mediaSymbolYes,
  620. cValueYes
  621. )
  622. )
  623. val cValueRepeatNo: MutableList<Any> = ArrayList()
  624. cValueRepeatNo.add(MEDIA_TYPE_REPEAT_NO)
  625. mediaRenderer.uniqueValues.add(
  626. UniqueValueRenderer.UniqueValue(
  627. R_LABEL_REPEAT_NO,
  628. R_LABEL_REPEAT_NO,
  629. mediaSymbolRepeatNo,
  630. cValueRepeatNo
  631. )
  632. )
  633. val cValueRepeatYes: List<Any> = ArrayList()
  634. cValueNo.add(MEDIA_TYPE_REPEAT_YES)
  635. mediaRenderer.uniqueValues.add(
  636. UniqueValueRenderer.UniqueValue(
  637. R_LABEL_REPEAT_YES,
  638. R_LABEL_REPEAT_YES,
  639. mediaSymbolRepeatYes,
  640. cValueRepeatYes
  641. )
  642. )
  643. fLayerMedia?.renderer = mediaRenderer
  644. // todo: 2023/4/14 绘制违建面符号化
  645. val colorClear = Color.argb(0, 255, 255, 255)
  646. val caseNoLineSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.DASH_DOT, Color.BLUE, 2.5f)
  647. val caseYesLineSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.DASH_DOT, Color.RED, 2.5f)
  648. val caseNoFillSymbol =
  649. SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, colorClear, caseNoLineSymbol)
  650. val caseYesFillSymbol =
  651. SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, colorClear, caseYesLineSymbol)
  652. val casePolygonRenderer = UniqueValueRenderer()
  653. casePolygonRenderer.fieldNames.add(FIELD_CASE_POLYGON_BZ)
  654. casePolygonRenderer.defaultSymbol = caseNoFillSymbol
  655. casePolygonRenderer.defaultLabel = FIELD_CASE_POLYGON_BZ_VALUE_NO
  656. val cValueCaseNo: MutableList<Any> = ArrayList()
  657. cValueCaseNo.add(FIELD_CASE_POLYGON_BZ_VALUE_NO)
  658. casePolygonRenderer.uniqueValues.add(
  659. UniqueValueRenderer.UniqueValue(
  660. FIELD_CASE_POLYGON_BZ_VALUE_NO,
  661. FIELD_CASE_POLYGON_BZ_VALUE_NO,
  662. caseNoFillSymbol,
  663. cValueCaseNo
  664. )
  665. )
  666. val cValueCaseYes: MutableList<Any> = ArrayList()
  667. cValueCaseYes.add(FIELD_CASE_POLYGON_BZ_VALUE_YES)
  668. casePolygonRenderer.uniqueValues.add(
  669. UniqueValueRenderer.UniqueValue(
  670. FIELD_CASE_POLYGON_BZ_VALUE_YES,
  671. FIELD_CASE_POLYGON_BZ_VALUE_YES,
  672. caseYesFillSymbol,
  673. cValueCaseYes
  674. )
  675. )
  676. fLayerCasePolygon?.renderer = casePolygonRenderer
  677. }
  678. /**
  679. * 向地图中添加动态绘制图层
  680. * @param layer GraphicsOverlay 动态绘制图层
  681. * @param layerName String 图层名称
  682. */
  683. private fun appendGraphicOverlay(layer: GraphicsOverlay, layerName: String) {
  684. // todo: 2023/4/19 设置该图层显示
  685. layer.isVisible = true
  686. mapView?.graphicsOverlays?.let {
  687. it.add(layer)
  688. LayerManager.getInstance().addLayer(
  689. LayerModel(
  690. layerName,
  691. layer.isVisible,
  692. LayerType.LAYER_TYPE_GRAPHIC,
  693. layer
  694. ), LayerManager.LayerGroup.LAYER_NAME_DRAW
  695. )
  696. }
  697. }
  698. /**
  699. * 创建图片符号
  700. * @param drawable Int 图片资源Id
  701. * @param width Float 宽度
  702. * @param height Float 高度
  703. * @return PictureMarkerSymbol?
  704. */
  705. private fun createPictureMarkerSymbol(
  706. drawable: Int,
  707. width: Float,
  708. height: Float
  709. ): PictureMarkerSymbol {
  710. val tDrawable = CrApplication.getContext().resources.getDrawable(drawable) as BitmapDrawable
  711. val symbol = PictureMarkerSymbol(tDrawable)
  712. if (width > 0) symbol.width = width else symbol.width =
  713. CrUnitManager.px2dp(tDrawable.bitmap.width).toFloat()
  714. if (height > 0) symbol.height = height else symbol.height =
  715. CrUnitManager.px2dp(tDrawable.bitmap.height).toFloat()
  716. return symbol
  717. }
  718. /**
  719. * 创建标注
  720. * @param txtColor Int 文字颜色
  721. * @param txtSize Float 文字大小
  722. * @param expression String 表达式
  723. * @return LabelDefinition? 标注
  724. */
  725. private fun createLabelDefinition(
  726. txtColor: Int,
  727. txtSize: Float,
  728. expression: String
  729. ): LabelDefinition {
  730. val textSymbol = TextSymbol()
  731. textSymbol.color = txtColor
  732. textSymbol.fontWeight = TextSymbol.FontWeight.BOLD
  733. textSymbol.haloColor = Color.WHITE
  734. textSymbol.haloWidth = 2.0f
  735. textSymbol.fontFamily = "Arial"
  736. textSymbol.size = txtSize
  737. val label = JsonObject()
  738. val labelExpression = JsonObject()
  739. labelExpression.add("expression", JsonPrimitive(expression))
  740. label.add("labelExpressionInfo", labelExpression)
  741. label.add("labelPlacement", JsonPrimitive("esriServerPolygonPlacementAlwaysHorizontal"))
  742. label.add("symbol", JsonParser().parse(textSymbol.toJson()))
  743. return LabelDefinition.fromJson(label.toString())
  744. }
  745. /**
  746. * 定位地图中心
  747. * @param longitude Double 中心经度
  748. * @param latitude Double 中心纬度
  749. * @param scale Double 缩放比例
  750. */
  751. private fun setMapCenter(longitude: Double, latitude: Double, scale: Double) {
  752. // todo: 2023/4/13 创建中心点
  753. var centerPoint: Point =
  754. Point(longitude, latitude, MapTouch.wgs84SpatialReference)
  755. if (scale > 0) {
  756. mapView?.setViewpointCenterAsync(centerPoint, scale)
  757. } else {
  758. mapView?.setViewpointCenterAsync(centerPoint)
  759. }
  760. }
  761. /**
  762. * 高亮显示要素
  763. * @param layer FeatureLayer 要素所在图层
  764. * @param feature Feature 要素
  765. */
  766. private fun focusFeature(layer: FeatureLayer, feature: Feature) {
  767. layer.selectFeature(feature)
  768. }
  769. /**
  770. * 清除高亮显示
  771. * @param layer FeatureLayer 图层
  772. */
  773. private fun unfocusFeature(layer: FeatureLayer) {
  774. layer.clearSelection()
  775. }
  776. /**
  777. * 清除全部选择
  778. */
  779. private fun unfocusAllFeature() {
  780. for (layer in mMap!!.operationalLayers) {
  781. if (layer is FeatureLayer) {
  782. layer.clearSelection()
  783. }
  784. }
  785. for (overLayer in mapView!!.graphicsOverlays) {
  786. overLayer.clearSelection()
  787. }
  788. }
  789. /**
  790. * 开始绘制涂鸦
  791. */
  792. private fun doodleStartDraw() {
  793. sketchEditor?.start(SketchCreationMode.FREEHAND_LINE)
  794. }
  795. /**
  796. * 清除草图
  797. */
  798. private fun clearSketch() {
  799. sketchEditor?.clearGeometry()
  800. }
  801. /**
  802. * 保存绘制的涂鸦
  803. */
  804. private fun doodleSave() {
  805. var geometry: Geometry? = sketchEditor?.geometry
  806. geometry?.let {
  807. var feature: Feature = fTableDoodle!!.createFeature()
  808. feature.geometry = it
  809. var addAsync = fTableDoodle!!.addFeatureAsync(feature)
  810. addAsync.addDoneListener(Runnable {
  811. try {
  812. addAsync.get()
  813. if (addAsync.isDone) {
  814. showInformation("涂鸦保存成功!")
  815. sketchEditor?.stop()
  816. CrApplication.getEventBus()
  817. .post(FragmentDoodle.EventDoodleAction(FragmentDoodle.EventDoodleAction.CLOSE_DRAW))
  818. }
  819. } catch (e: InterruptedException) {
  820. showWarning(e.message!!)
  821. } catch (e: ExecutionException) {
  822. showWarning(e.message!!)
  823. }
  824. })
  825. }
  826. }
  827. /**
  828. * 删除数据表中的全部数据
  829. * @param delTable FeatureTable 数据表
  830. */
  831. private fun removeAllFeatureByTable(delTable: FeatureTable) {
  832. var dialog = DialogNormal(CrApplication.getContext(), "警告", "删除后无法恢复,是否删除?")
  833. dialog.setButtonsText("是", "否")
  834. dialog.setListener(object : DialogNormal.DialogNormalListener {
  835. // todo: 2023/4/17 删除
  836. override fun completion() {
  837. var params = QueryParameters()
  838. params.whereClause = "1=1"
  839. var queryAsync = delTable?.queryFeaturesAsync(params)
  840. queryAsync?.addDoneListener(Runnable {
  841. try {
  842. if (queryAsync.isDone) {
  843. var deleteAsync = delTable?.deleteFeaturesAsync(queryAsync.get())
  844. deleteAsync?.addDoneListener(Runnable {
  845. try {
  846. if (deleteAsync.isDone) {
  847. showInformation("删除成功!")
  848. }
  849. } catch (e: java.lang.IllegalArgumentException) {
  850. showError("删除错误!")
  851. }
  852. })
  853. }
  854. } catch (e: java.lang.IllegalArgumentException) {
  855. showError("删除错误!")
  856. }
  857. })
  858. }
  859. // todo: 2023/4/17 否
  860. override fun close() {
  861. }
  862. })
  863. dialog.show()
  864. }
  865. /**
  866. * 删除图层中选中的要素
  867. * @param layer FeatureLayer 图层
  868. */
  869. private fun doodleSelectFeature(layer: FeatureLayer) {
  870. var dialog = DialogNormal(requireContext(), "警告", "删除后无法恢复,是否删除?")
  871. dialog.setButtonsText("是", "否")
  872. dialog.setListener(object : DialogNormal.DialogNormalListener {
  873. override fun completion() {
  874. var sAsync = layer!!.selectedFeaturesAsync
  875. sAsync.addDoneListener(Runnable {
  876. if (sAsync.isDone) {
  877. var result = sAsync.get()
  878. var dAsync = layer.featureTable.deleteFeaturesAsync(result)
  879. dAsync.addDoneListener(Runnable {
  880. try {
  881. if (dAsync.isDone) {
  882. showInformation("删除成功!")
  883. }
  884. } catch (e: java.lang.IllegalArgumentException) {
  885. showError("删除错误!")
  886. }
  887. })
  888. }
  889. })
  890. }
  891. override fun close() {
  892. }
  893. })
  894. dialog.show()
  895. }
  896. /**
  897. * 添加标志
  898. * @param mapPoint Point 地图点
  899. */
  900. private fun markAppend(mapPoint: Point) {
  901. if (markChange == null) return
  902. var markSymbol = createPictureMarkerSymbol(markChange!!.markDrawable, 0f, 0f)
  903. // todo: 2023/4/19 设置偏移
  904. markSymbol.offsetX = -1 * markSymbol.width / 2
  905. markSymbol.angle = markChange!!.markAngle.toFloat()
  906. // todo: 2023/4/19 创建要素
  907. var markGraphic = Graphic(mapPoint, markSymbol)
  908. gLayerIco?.graphics?.add(markGraphic)
  909. CrUtil.showToast("标志添加成功!")
  910. }
  911. /**
  912. * 保存标志
  913. */
  914. private fun markSave() {
  915. gLayerIco?.let {
  916. var features: MutableList<Feature> = mutableListOf()
  917. for (graphic in it.graphics) {
  918. var feature = fTableMark?.createFeature()
  919. feature?.geometry = graphic.geometry
  920. features.add(feature!!)
  921. }
  922. var addAsync = fTableMark?.addFeaturesAsync(features)
  923. addAsync?.addDoneListener(Runnable {
  924. try {
  925. if (addAsync.isDone) {
  926. showInformation("保存成功!")
  927. gLayerIco?.graphics?.clear()
  928. }
  929. } catch (e: java.lang.IllegalArgumentException) {
  930. showError("保存错误!")
  931. }
  932. })
  933. }
  934. }
  935. /**
  936. * 添加展示获取经纬度位置
  937. * @param location Point 地理位置
  938. * @param longitude String 经度
  939. * @param latitude String 纬度
  940. */
  941. private fun appendLocation(location: Point, longitude: String, latitude: String) {
  942. // todo: 2023/6/7 点符号样式
  943. var markSymbol: SimpleMarkerSymbol = SimpleMarkerSymbol()
  944. markSymbol.color = Color.argb(255, 0, 0, 255)
  945. markSymbol.size = 14.0f
  946. markSymbol.style = SimpleMarkerSymbol.Style.CIRCLE
  947. markSymbol.outline =
  948. SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.argb(255, 255, 255, 255), 1.0f)
  949. // todo: 2023/6/7 创建点符号
  950. var graphic = Graphic(location, markSymbol)
  951. gLayerTemp?.graphics?.add(graphic)
  952. // todo: 2023/6/7 添加标注
  953. appendMeasureLabel(location, String.format("经度:%s 纬度:%s", longitude, latitude))
  954. }
  955. /**
  956. * 添加经纬度点到地图中
  957. * @param longitude String 经度值
  958. * @param latitude String 纬度值
  959. */
  960. private fun appendWGS84PointToMap(longitude: String, latitude: String) {
  961. var lng = longitude.toDouble()
  962. var lat = latitude.toDouble()
  963. var wgs84Point = Point(lng, lat, SpatialReference.create(4326))
  964. var location = GeometryEngine.project(wgs84Point, mMap?.spatialReference) as Point
  965. appendLocation(location, longitude, latitude)
  966. }
  967. /**
  968. * 测量长度
  969. */
  970. private fun measureLength() {
  971. CrUtil.showToast("地图上点击开始测量!")
  972. sketchEditor?.let {
  973. it.stop()
  974. it.removeGeometryChangedListener(sketchGeometryChangeListener)
  975. // todo: 2023/4/21 设置编辑模式
  976. var model = SketchEditConfiguration()
  977. model.isAllowPartSelection = false
  978. model.isContextMenuEnabled = false
  979. model.isRequireSelectionBeforeDrag = true
  980. it.start(SketchCreationMode.POLYLINE, model)
  981. it.opacity = 1.0f
  982. // todo: 2023/4/21 设置监听
  983. it.addGeometryChangedListener(sketchGeometryChangeListener)
  984. }
  985. }
  986. /**
  987. * 面积测量
  988. */
  989. private fun measureArea() {
  990. CrUtil.showToast("地图上点击开始测量!")
  991. sketchEditor?.let {
  992. it.stop()
  993. it.removeGeometryChangedListener(sketchGeometryChangeListener)
  994. // todo: 2023/6/6 设置编辑模式
  995. var model = SketchEditConfiguration()
  996. model.isAllowPartSelection = false
  997. model.isContextMenuEnabled = false
  998. model.isRequireSelectionBeforeDrag = true
  999. it.start(SketchCreationMode.POLYGON, model)
  1000. it.opacity = 1.0f
  1001. // todo: 2023/6/6 设置监听
  1002. it.addGeometryChangedListener(sketchGeometryChangeListener)
  1003. }
  1004. }
  1005. /**
  1006. * 输入坐标定位监听
  1007. */
  1008. private var inputLocationToMapListener: DialogInput.DialogInputListener =
  1009. object : DialogInput.DialogInputListener {
  1010. // todo: 2023/6/7 点击完成按钮回调
  1011. override fun completion(valueOne: String, valueTwo: String, self: DialogInput) {
  1012. if (!CrUnitManager.checkLongitude(valueOne)) {
  1013. CrUtil.showToast("输入的经度值不符合要求!")
  1014. } else if (!CrUnitManager.checkLatitude(valueTwo)) {
  1015. CrUtil.showToast("输入的纬度值不符合要求!")
  1016. } else {
  1017. self.dismiss()
  1018. // todo: 2023/6/8 添加到地图中
  1019. appendWGS84PointToMap(valueOne, valueTwo)
  1020. }
  1021. }
  1022. // todo: 2023/6/7 点击取消按钮回调
  1023. override fun close() {
  1024. }
  1025. }
  1026. /**
  1027. * 开始绘制案件图斑
  1028. */
  1029. private fun caseStartDraw() {
  1030. CrUtil.showToast("地图上点击开始绘制!")
  1031. sketchEditor?.let {
  1032. it.stop()
  1033. it.removeGeometryChangedListener(sketchGeometryChangeListener)
  1034. // todo: 2023/6/6 设置编辑模式
  1035. var model = SketchEditConfiguration()
  1036. model.isAllowPartSelection = true
  1037. model.isContextMenuEnabled = false
  1038. model.isRequireSelectionBeforeDrag = true
  1039. it.start(SketchCreationMode.POLYGON, model)
  1040. it.opacity = 1.0f
  1041. }
  1042. }
  1043. /**
  1044. * 保存编辑的案件图斑
  1045. */
  1046. private fun caseSave() {
  1047. var geo = sketchEditor?.geometry
  1048. if (geo != null && geo.geometryType == GeometryType.POLYGON) {
  1049. var polygon = geo as Polygon
  1050. if (CrUnitManager.querySizeByIterable(polygon.parts[0].points) < 4) {
  1051. showWarning("提交保存的要素少于4个点,无法提交!")
  1052. } else {
  1053. // todo: 2023/6/12 查询关联的案件点
  1054. var queryParams = QueryParameters()
  1055. queryParams.geometry = polygon
  1056. queryParams.spatialRelationship = QueryParameters.SpatialRelationship.CONTAINS
  1057. queryParams.whereClause = String.format(
  1058. "%s='%s' or %s='%s'",
  1059. FIELD_CASE_ISUP,
  1060. MEDIA_TYPE_WJ_NO,
  1061. FIELD_CASE_ISUP,
  1062. MEDIA_TYPE_WJ_YES
  1063. )
  1064. var queryAsync = fTableMedia?.queryFeaturesAsync(queryParams)
  1065. queryAsync?.addDoneListener(Runnable {
  1066. if (queryAsync.isDone) {
  1067. // todo: 2023/6/12 获取查询结果
  1068. var featureResult = queryAsync.get().iterator()
  1069. var features = ArrayList<Feature>()
  1070. while (featureResult.hasNext()) {
  1071. features.add(featureResult.next())
  1072. }
  1073. // todo: 2023/6/12 如果存在违建点 则赋值 否则为 空
  1074. var caseId = ""
  1075. if (features.size > 0) {
  1076. caseId = features[0].attributes[FIELD_CASE_NAME].toString()
  1077. }
  1078. // todo: 2023/6/12 计算面积 并添加要素到图层
  1079. var area = abs(GeometryEngine.area(polygon)) * 0.0015
  1080. var wjFeature = fTableCasePolygon?.createFeature()
  1081. wjFeature!!.let {
  1082. it.attributes[FIELD_CASE_POLYGON_ANJID] = caseId
  1083. it.attributes[FIELD_CASE_POLYGON_MJ] = area
  1084. if (caseId == "") {
  1085. it.attributes[FIELD_CASE_POLYGON_BZ] =
  1086. FIELD_CASE_POLYGON_BZ_VALUE_NO
  1087. } else {
  1088. it.attributes[FIELD_CASE_POLYGON_BZ] =
  1089. FIELD_CASE_POLYGON_BZ_VALUE_YES
  1090. }
  1091. it.geometry = polygon
  1092. var appendAsync = fTableCasePolygon?.addFeatureAsync(it)
  1093. appendAsync?.addDoneListener(Runnable {
  1094. try {
  1095. if (appendAsync.isDone) {
  1096. showInformation("案件保存成功!")
  1097. sketchEditor?.stop()
  1098. }
  1099. } catch (ex: java.lang.IllegalArgumentException) {
  1100. showError("案件保存失败!")
  1101. }
  1102. })
  1103. }
  1104. }
  1105. })
  1106. }
  1107. } else {
  1108. showWarning("提交保存的要素不符合要求!")
  1109. }
  1110. }
  1111. /**
  1112. * 删除保存的案件图斑
  1113. */
  1114. private fun caseDelete() {
  1115. var queryParameters = QueryParameters()
  1116. queryParameters.whereClause = "1=1"
  1117. var queryAsync = fTableCasePolygon?.queryFeaturesAsync(queryParameters)
  1118. queryAsync?.addDoneListener(Runnable {
  1119. try {
  1120. if (queryAsync.isDone) {
  1121. var deleteAsync = fTableCasePolygon?.deleteFeaturesAsync(queryAsync.get())
  1122. deleteAsync?.addDoneListener(Runnable {
  1123. try {
  1124. if (deleteAsync.isDone) {
  1125. showInformation("删除成功!")
  1126. }
  1127. } catch (ex: java.lang.IllegalArgumentException) {
  1128. showError("删除失败!")
  1129. }
  1130. })
  1131. }
  1132. } catch (ex: java.lang.IllegalArgumentException) {
  1133. showError("删除失败!")
  1134. }
  1135. })
  1136. }
  1137. /**
  1138. * 添加案件点到地图
  1139. * @param location Point 点位置
  1140. * @param longitude String 经度
  1141. * @param latitude String 纬度
  1142. */
  1143. private fun caseAppendWaypointToMap(location: Point, longitude: String, latitude: String) {
  1144. // todo: 2023/6/13 创建案件点模型
  1145. var caseModel =
  1146. CaseModel(longitude.toDouble(), latitude.toDouble(), 0.0, 0.0, CaseType.MediaTypeWjNo)
  1147. // todo: 2023/6/13 创建案件点图元
  1148. var caseFeature = fTableMedia?.createFeature()
  1149. // todo: 2023/6/13 添加属性
  1150. caseModel.setAttributes(caseFeature!!.attributes)
  1151. // todo: 2023/6/13 设置要素空间图元
  1152. caseFeature.geometry = location
  1153. // todo: 2023/6/13 添加到地图中
  1154. var appendAsync = fTableMedia?.addFeatureAsync(caseFeature)
  1155. appendAsync?.addDoneListener(Runnable {
  1156. try {
  1157. if (appendAsync.isDone) {
  1158. fLayerMedia?.clearSelection()
  1159. fLayerMedia?.selectFeature(caseFeature)
  1160. caseUpdatePolygonByFeature(caseFeature, object : ICompletion<String> {
  1161. override fun onCompletion(completion: CompletionModel<String>) {
  1162. if (completion.isSuccess == true) {
  1163. CrUtil.showToast(
  1164. String.format(
  1165. "案件点追加成功 %s",
  1166. caseFeature.attributes[FIELD_CASE_NAME]
  1167. )
  1168. )
  1169. } else {
  1170. showError(completion.result!!)
  1171. }
  1172. }
  1173. })
  1174. }
  1175. } catch (ex: java.lang.IllegalArgumentException) {
  1176. showError("案件点添加错误!")
  1177. }
  1178. })
  1179. }
  1180. /**
  1181. * 根据案件点要素图元的案件编号查询到与之关联的案件面,并进行初始化
  1182. * @param geom Feature 案件点要素
  1183. * @param callback iCompletion 完成回调
  1184. */
  1185. private fun caseClearPolygonByFeature(geom: Feature, callback: ICompletion<String>) {
  1186. // todo: 2023/6/13 获取案件ID
  1187. val caseId = geom.attributes[FIELD_CASE_NAME]
  1188. // todo: 2023/6/15 先判断是否存在与该案件点名称相同的案件图斑 将其标志清除
  1189. var queryParameters = QueryParameters()
  1190. queryParameters.whereClause = String.format("%s = '%s'", FIELD_CASE_POLYGON_ANJID, caseId)
  1191. var asyncQuery = fTableCasePolygon?.queryFeaturesAsync(queryParameters)
  1192. asyncQuery?.addDoneListener(Runnable {
  1193. try {
  1194. if (asyncQuery.isDone) {
  1195. var features = mutableListOf<Feature>()
  1196. for (fea in asyncQuery.get()) {
  1197. fea.attributes[FIELD_CASE_POLYGON_ANJID] = ""
  1198. fea.attributes[FIELD_CASE_POLYGON_BZ] = FIELD_CASE_POLYGON_BZ_VALUE_NO
  1199. features.add(fea)
  1200. }
  1201. var asyncUpdate = fTableCasePolygon?.updateFeaturesAsync(features)
  1202. asyncUpdate?.addDoneListener(Runnable {
  1203. try {
  1204. if (asyncUpdate.isDone) {
  1205. if (callback != null) callback.onCompletion(
  1206. CompletionModel(
  1207. true,
  1208. ""
  1209. )
  1210. )
  1211. }
  1212. } catch (ex: java.lang.IllegalArgumentException) {
  1213. if (callback != null) callback.onCompletion(
  1214. CompletionModel(
  1215. false,
  1216. "案件面初始化错误!"
  1217. )
  1218. )
  1219. }
  1220. })
  1221. }
  1222. } catch (ex: java.lang.IllegalArgumentException) {
  1223. if (callback != null) callback.onCompletion(CompletionModel(false, "案件面初始化错误!"))
  1224. }
  1225. })
  1226. }
  1227. /**
  1228. * 更新案件点对应的案件对象
  1229. * @param geom Feature 案件点
  1230. * @param callback iCompletion 回调
  1231. */
  1232. private fun caseUpdatePolygonByFeature(geom: Feature, callback: ICompletion<String>) {
  1233. // todo: 2023/6/15 先进行初始化
  1234. caseClearPolygonByFeature(geom, object : ICompletion<String> {
  1235. override fun onCompletion(completion: CompletionModel<String>) {
  1236. if (completion.isSuccess == false) {
  1237. if (callback != null) callback.onCompletion(completion)
  1238. } else {
  1239. // todo: 2023/6/13 获取案件ID
  1240. val caseId = geom.attributes[FIELD_CASE_NAME]
  1241. // todo: 2023/6/15 先判断是否存在与该案件点名称相同的案件图斑 将其标志清除
  1242. var queryParameters = QueryParameters()
  1243. // todo: 2023/6/13 先进行空间查询 查询案件点对应的案件面
  1244. queryParameters.geometry = geom.geometry
  1245. queryParameters.spatialRelationship =
  1246. QueryParameters.SpatialRelationship.INTERSECTS
  1247. queryParameters.whereClause = "1=1"
  1248. var queryAsync = fTableCasePolygon!!.queryFeaturesAsync(queryParameters)
  1249. queryAsync?.addDoneListener(Runnable {
  1250. try {
  1251. if (queryAsync.isDone) {
  1252. var features = mutableListOf<Feature>()
  1253. for (fea in queryAsync.get()) {
  1254. fea.attributes[FIELD_CASE_POLYGON_ANJID] = caseId
  1255. fea.attributes[FIELD_CASE_POLYGON_BZ] =
  1256. FIELD_CASE_POLYGON_BZ_VALUE_YES
  1257. features.add(fea)
  1258. }
  1259. // todo: 2023/6/13 更新
  1260. var updateAsync = fTableCasePolygon!!.updateFeaturesAsync(features)
  1261. updateAsync?.addDoneListener(Runnable {
  1262. try {
  1263. if (updateAsync.isDone) {
  1264. // todo: 2023/6/13 更新完成
  1265. if (callback != null) callback.onCompletion(
  1266. CompletionModel(
  1267. true,
  1268. "成功!"
  1269. )
  1270. )
  1271. }
  1272. } catch (ex: java.lang.IllegalArgumentException) {
  1273. if (callback != null) callback.onCompletion(
  1274. CompletionModel(
  1275. false,
  1276. "案件对象更新失败!"
  1277. )
  1278. )
  1279. }
  1280. })
  1281. }
  1282. } catch (ex: java.lang.IllegalArgumentException) {
  1283. if (callback != null) callback.onCompletion(
  1284. CompletionModel(
  1285. false,
  1286. "案件对象查询失败!"
  1287. )
  1288. )
  1289. }
  1290. })
  1291. }
  1292. }
  1293. })
  1294. }
  1295. /**
  1296. * 删除案件点
  1297. * @param screenPoint android.graphics.Point 查询产靠位置
  1298. */
  1299. private fun caseRemoveCaseWaypoing(screenPoint: android.graphics.Point) {
  1300. // todo: 2023/6/14 开始查询
  1301. var identifyAsync = map_mapView?.identifyLayerAsync(fLayerMedia, screenPoint, 6.0, false)
  1302. identifyAsync?.addDoneListener(Runnable {
  1303. try {
  1304. if (identifyAsync.isDone) {
  1305. var features = mutableListOf<Feature>()
  1306. for (element in identifyAsync.get().elements) {
  1307. features.add(element as Feature)
  1308. }
  1309. if (features.size > 0) {
  1310. var dig = DialogNormal(CrApplication.getContext())
  1311. dig.setTitle("提示")
  1312. dig.setMessage("删除后将无法恢复,确定删除吗?")
  1313. dig.setButtonsText("删除", "取消")
  1314. dig.setListener(object : DialogNormal.DialogNormalListener {
  1315. // todo: 2023/6/14 确认删除
  1316. override fun completion() {
  1317. caseRemoveWaypointAndUpdateCasePolygon(features,
  1318. object : ICompletion<String> {
  1319. override fun onCompletion(completion: CompletionModel<String>) {
  1320. if (completion.isSuccess == true) {
  1321. CrUtil.showToast("删除成功!")
  1322. } else {
  1323. showError(completion.result!!)
  1324. }
  1325. }
  1326. })
  1327. }
  1328. // todo: 2023/6/14 关闭
  1329. override fun close() {
  1330. }
  1331. })
  1332. dig.show()
  1333. } else {
  1334. showWarning("未查询到任何案件点!")
  1335. }
  1336. }
  1337. } catch (ex: java.lang.IllegalArgumentException) {
  1338. showError("查询错误,无法删除!")
  1339. }
  1340. })
  1341. }
  1342. /**
  1343. * 删除案件点并更新与之相对应的案件面
  1344. * @param features List<Feature> 案件点集合
  1345. * @param callback iCompletion 完成回调
  1346. */
  1347. private fun caseRemoveWaypointAndUpdateCasePolygon(
  1348. features: List<Feature>,
  1349. callback: ICompletion<String>
  1350. ) {
  1351. var deleteAsync = fTableMedia?.deleteFeaturesAsync(features)
  1352. deleteAsync?.addDoneListener(Runnable {
  1353. try {
  1354. if (deleteAsync.isDone) {
  1355. // todo: 2023/6/16 更新
  1356. var wheres = mutableListOf<String>()
  1357. for (fea in features) {
  1358. wheres.add(fea.attributes[FIELD_CASE_NAME].toString())
  1359. }
  1360. caseUpdateCasePolygonByWhere(wheres, callback)
  1361. }
  1362. } catch (ex: java.lang.IllegalArgumentException) {
  1363. if (callback != null) callback.onCompletion(CompletionModel(false, "案件点删除失败!"))
  1364. }
  1365. })
  1366. }
  1367. /**
  1368. * 根据更新条件更新案件点关联的案件面为 未关联案件点状态
  1369. * @param wheres List<String> 案件Id的集合
  1370. * @param callback iCompletion 完成回调
  1371. */
  1372. private fun caseUpdateCasePolygonByWhere(wheres: List<String>, callback: ICompletion<String>) {
  1373. var updateWhere = ""
  1374. // todo: 2023/6/16 组合条件
  1375. for (where in wheres) {
  1376. updateWhere += if (updateWhere == "") {
  1377. String.format("'%s'", where)
  1378. } else {
  1379. String.format(",'%s'", where)
  1380. }
  1381. }
  1382. // todo: 2023/6/16 开始查询
  1383. var queryParameters = QueryParameters()
  1384. queryParameters.whereClause = updateWhere
  1385. var asyncQuery = fTableCasePolygon?.queryFeaturesAsync(queryParameters)
  1386. asyncQuery?.addDoneListener(Runnable {
  1387. try {
  1388. if (asyncQuery.isDone) {
  1389. var features = mutableListOf<Feature>()
  1390. for (fea in asyncQuery.get()) {
  1391. fea.attributes[FIELD_CASE_POLYGON_ANJID] = ""
  1392. fea.attributes[FIELD_CASE_POLYGON_BZ] = FIELD_CASE_POLYGON_BZ_VALUE_NO
  1393. features.add(fea)
  1394. }
  1395. // todo: 2023/6/16 开始更新
  1396. var asyncUpdate = fTableCasePolygon?.updateFeaturesAsync(features)
  1397. asyncUpdate?.addDoneListener(Runnable {
  1398. try {
  1399. if (asyncUpdate.isDone) {
  1400. if (callback != null) callback.onCompletion(
  1401. CompletionModel(
  1402. true,
  1403. ""
  1404. )
  1405. )
  1406. }
  1407. } catch (ex: java.lang.IllegalArgumentException) {
  1408. if (callback != null) callback.onCompletion(
  1409. CompletionModel(
  1410. false,
  1411. "关联案件更新失败!"
  1412. )
  1413. )
  1414. }
  1415. })
  1416. }
  1417. } catch (ex: java.lang.IllegalArgumentException) {
  1418. if (callback != null) callback.onCompletion(CompletionModel(false, "关联案件查询失败!"))
  1419. }
  1420. })
  1421. }
  1422. /**
  1423. * 移动案件点
  1424. */
  1425. private fun caseMoveWaypoint() {
  1426. CrUtil.showToast("选择需要移动的案件点!")
  1427. mapTouch?.setAction(MapAction.MapTapStartMoveWaypoing)
  1428. }
  1429. /**
  1430. * 选择移动的案件点
  1431. * @param location Point 点击位置
  1432. */
  1433. private fun caseMoveWaypointBySelect(location: Point) {
  1434. // todo: 2023/6/14 设置查询区域
  1435. var queryGeometry = GeometryEngine.buffer(location, 10.0)
  1436. // todo: 2023/6/14 设置查询条件
  1437. var queryParameters = QueryParameters()
  1438. queryParameters.geometry = queryGeometry
  1439. queryParameters.spatialRelationship = QueryParameters.SpatialRelationship.CONTAINS
  1440. queryParameters.whereClause = "1=1"
  1441. // todo: 2023/6/14 开始查询
  1442. var queryAsync = fTableMedia?.queryFeaturesAsync(queryParameters)
  1443. queryAsync?.addDoneListener(Runnable {
  1444. try {
  1445. if (queryAsync.isDone) {
  1446. var features = mutableListOf<Feature>()
  1447. for (fea in queryAsync.get()) {
  1448. features.add(fea)
  1449. }
  1450. if (features.size == 0) {
  1451. CrUtil.showToast("未查询到任何违建点!")
  1452. } else {
  1453. fLayerMedia?.clearSelection()
  1454. fLayerMedia?.selectFeature(features[0])
  1455. CrUtil.showToast("地图点击确定移动位置!")
  1456. mapTouch?.setAction(MapAction.MapTapStopMoveWaypoint)
  1457. // todo: 2023/6/15 利用编辑工具
  1458. sketchEditor?.start(location)
  1459. sketchEditor?.addGeometryChangedListener(sketchGeometryChangeListener)
  1460. }
  1461. }
  1462. } catch (ex: java.lang.IllegalArgumentException) {
  1463. showError("案件点查询错误!")
  1464. }
  1465. })
  1466. }
  1467. /**
  1468. * 案件点移动结束
  1469. * @param location Point 移动后位置
  1470. */
  1471. private fun caseMoveWaypointToEnd(location: Point) {
  1472. var asyncSelected = fLayerMedia?.selectedFeaturesAsync
  1473. asyncSelected?.addDoneListener(Runnable {
  1474. try {
  1475. if (asyncSelected.isDone) {
  1476. var features = mutableListOf<Feature>()
  1477. for (fea in asyncSelected.get()) {
  1478. features.add(fea)
  1479. }
  1480. if (features.size == 0) {
  1481. showError("未获取到可移动违建点,无法完成移动操作!")
  1482. } else {
  1483. features[0].geometry = location
  1484. var asyncUpdate = fTableMedia?.updateFeatureAsync(features[0])
  1485. asyncUpdate?.addDoneListener(Runnable {
  1486. try {
  1487. if (asyncUpdate.isDone) {
  1488. caseUpdatePolygonByFeature(
  1489. features[0],
  1490. object : ICompletion<String> {
  1491. override fun onCompletion(completion: CompletionModel<String>) {
  1492. if (completion.isSuccess == true) {
  1493. CrUtil.showToast("移动完成!")
  1494. sketchEditor?.removeGeometryChangedListener(
  1495. sketchGeometryChangeListener
  1496. )
  1497. sketchEditor?.stop()
  1498. fLayerMedia?.clearSelection()
  1499. } else {
  1500. showError(completion.result!!)
  1501. }
  1502. }
  1503. })
  1504. }
  1505. } catch (ex: java.lang.IllegalArgumentException) {
  1506. showError("移动错误,无法完成移动操作!")
  1507. }
  1508. })
  1509. }
  1510. }
  1511. } catch (ex: java.lang.IllegalArgumentException) {
  1512. showError("获取可移动违建点错误,无法完成移动操作!")
  1513. }
  1514. })
  1515. }
  1516. /**
  1517. * 案件分享及上传选择执行
  1518. * @param screenPoint Point 屏幕点
  1519. */
  1520. private fun caseUpload(screenPoint: android.graphics.Point) {
  1521. // todo: 2023/6/15 查询
  1522. var asyncQuery = map_mapView?.identifyLayerAsync(fLayerMedia, screenPoint, 6.0, false)
  1523. asyncQuery?.addDoneListener(Runnable {
  1524. try {
  1525. if (asyncQuery.isDone) {
  1526. var elements = asyncQuery.get().elements
  1527. if (elements.size <= 0) {
  1528. CrUtil.showToast("未选择上传案件!")
  1529. } else {
  1530. fLayerMedia?.selectFeature(elements.last() as Feature)
  1531. if (eventListener != null) eventListener?.onCaseUpdate(CaseModel(elements.last().attributes))
  1532. }
  1533. }
  1534. } catch (ex: java.lang.IllegalArgumentException) {
  1535. showError("案件查询错误!")
  1536. }
  1537. })
  1538. }
  1539. /**
  1540. * 保存截图
  1541. * @param joinCaseName String 关联的案件名称
  1542. */
  1543. private fun captures(joinCaseName: String) {
  1544. // todo: 2023/8/14 显示等待框
  1545. showLoading("初始化...")
  1546. // todo: 2023/8/14 初始化图片信息
  1547. captureNames.clear()
  1548. captureNames.add("${joinCaseName}_yx.jpg")
  1549. captureNames.add("${joinCaseName}_xz.jpg")
  1550. captureNames.add("${joinCaseName}_gh.jpg")
  1551. // todo: 2023/8/14 初始化信息
  1552. var opNameList = mutableListOf<MutableList<String>>()
  1553. var ovLayerList = mutableListOf<MutableList<GraphicsOverlay>>()
  1554. // todo: 2023/8/14 截图-影像图
  1555. val opNamesYX = mutableListOf<String>(
  1556. LAYER_NAME_YX,
  1557. LAYER_NAME_CONFIG_VILLAGE,
  1558. LAYER_NAME_CONFIG_TOWNS,
  1559. LAYER_NAME_CASE
  1560. )
  1561. val ovLayersYX = mutableListOf<GraphicsOverlay>(gLayerIco!!)
  1562. opNameList.add(opNamesYX)
  1563. ovLayerList.add(ovLayersYX)
  1564. // todo: 2023/8/14 截图-现状图
  1565. var opNamesXZ = mutableListOf<String>(
  1566. LAYER_NAME_XZ, LAYER_NAME_CONFIG_VILLAGE, LAYER_NAME_CONFIG_TOWNS, LAYER_NAME_CASE
  1567. )
  1568. var ovLayersXZ = mutableListOf<GraphicsOverlay>(gLayerIco!!)
  1569. opNameList.add(opNamesXZ)
  1570. ovLayerList.add(ovLayersXZ)
  1571. // todo: 2023/8/14 截图-规划图
  1572. var opNamesGH = mutableListOf<String>(
  1573. LAYER_NAME_GH, LAYER_NAME_CONFIG_VILLAGE, LAYER_NAME_CONFIG_TOWNS, LAYER_NAME_CASE
  1574. )
  1575. var ovLayersGH = mutableListOf<GraphicsOverlay>(gLayerIco!!)
  1576. opNameList.add(opNamesGH)
  1577. ovLayerList.add(ovLayersGH)
  1578. // todo: 2023/8/14 执行协程
  1579. GlobalScope.launch {
  1580. withContext(Dispatchers.IO) {
  1581. updateLoading("保存地图状态...")
  1582. saveMapLayerState()
  1583. updateLoading("截取影像图...")
  1584. capturesByName(opNameList[0], ovLayerList[0], captureNames[0])
  1585. updateLoading("截取现状图...")
  1586. capturesByName(opNameList[1], ovLayerList[1], captureNames[1])
  1587. updateLoading("截取规划图...")
  1588. capturesByName(opNameList[2], ovLayerList[2], captureNames[2])
  1589. updateLoading("恢复地图状态...")
  1590. restoreMapLayerState()
  1591. // todo: 2023/8/14 发送截图完成事件
  1592. CrApplication.getEventBus().post(
  1593. EventMapCapture(
  1594. EventMapCapture.CaptureAction.CAPTURE_ACTION_COMPLETE,
  1595. null,
  1596. captureNames
  1597. )
  1598. )
  1599. // todo: 2023/8/14 关闭等待框
  1600. closeLoading()
  1601. }
  1602. }
  1603. }
  1604. /**
  1605. * 协程函数 可挂起
  1606. * 保存地图图层当前可视状态
  1607. */
  1608. private suspend fun saveMapLayerState() {
  1609. // todo: 2023/8/8 清除数据
  1610. mapStateList.clear()
  1611. // todo: 2023/8/8 循环操作类型图层
  1612. for (i in 0 until mMap?.operationalLayers!!.size) {
  1613. var visible = mMap?.operationalLayers!![i].isVisible
  1614. mapStateList.add(MapStateModel(i, visible, MapType.MAP_TYPE_O_LAYER))
  1615. }
  1616. // todo: 2023/8/8 循环绘制类型图层
  1617. for (i in 0 until map_mapView.graphicsOverlays.size) {
  1618. var visible = map_mapView.graphicsOverlays[i].isVisible
  1619. mapStateList.add(MapStateModel(i, visible, MapType.MAP_TYPE_D_LAYER))
  1620. }
  1621. delay(1000)
  1622. }
  1623. /**
  1624. * 协程函数 可挂起
  1625. * 恢复地图图层状态
  1626. */
  1627. private suspend fun restoreMapLayerState() {
  1628. for (model in mapStateList) {
  1629. if (model.mapType == MapType.MAP_TYPE_O_LAYER) {
  1630. mMap?.operationalLayers!![model.index].isVisible = model.visible
  1631. } else if (model.mapType == MapType.MAP_TYPE_D_LAYER) {
  1632. map_mapView.graphicsOverlays[model.index].isVisible = model.visible
  1633. }
  1634. }
  1635. delay(1000)
  1636. }
  1637. /**
  1638. * 地图截图
  1639. * @param opLayerNames List<String> 显示的操作图层名称
  1640. * @param ovLayerNames List<GraphicsOverlay> 显示的绘制图层名称
  1641. * @param saveName String 保存截图名称
  1642. */
  1643. private suspend fun capturesByName(
  1644. opLayerNames: List<String>,
  1645. ovLayerNames: List<GraphicsOverlay>,
  1646. saveName: String
  1647. ) {
  1648. // todo: 2023/8/14 控制操作图层
  1649. for (layer in mMap?.operationalLayers!!) {
  1650. layer.isVisible = opLayerNames.indexOf(layer.name) != -1
  1651. }
  1652. // todo: 2023/8/14 操作绘制图层
  1653. for (overlay in map_mapView.graphicsOverlays) {
  1654. overlay.isVisible = ovLayerNames.indexOf(overlay) != -1
  1655. }
  1656. // todo: 2023/8/14 延迟1.5秒 为了图层能正确加载
  1657. delay(1500)
  1658. toBitmapAndSave("${CrUtil.IMAGE_PATH}${saveName}")
  1659. }
  1660. /**
  1661. * 保存地图截图到指定路径文件
  1662. * @param filePath String 文件全路径
  1663. */
  1664. private suspend fun toBitmapAndSave(filePath: String) {
  1665. map_mapView.clearFocus()
  1666. map_mapView.isPressed = false
  1667. // todo: 2023/8/14 能绘制缓存就返回false
  1668. var willNotCache = map_mapView.willNotCacheDrawing()
  1669. map_mapView.setWillNotCacheDrawing(false)
  1670. var color: Int = map_mapView.drawingCacheBackgroundColor
  1671. map_mapView.drawingCacheBackgroundColor = 0
  1672. if (color != 0) {
  1673. map_mapView.destroyDrawingCache()
  1674. }
  1675. map_mapView.buildDrawingCache()
  1676. var cacheBitmap: Bitmap? = null
  1677. while (cacheBitmap == null) {
  1678. var export = map_mapView.exportImageAsync()
  1679. try {
  1680. cacheBitmap = export.get()
  1681. } catch (e: InterruptedException) {
  1682. e.message?.let { CrUtil.showToast(it) }
  1683. } catch (e: ExecutionException) {
  1684. e.message?.let { CrUtil.showToast(it) }
  1685. }
  1686. }
  1687. // todo: 2023/8/14 创建位图
  1688. var bitmap = Bitmap.createBitmap(cacheBitmap)
  1689. // todo: 2023/8/14 重置地图
  1690. map_mapView.destroyDrawingCache()
  1691. map_mapView.setWillNotCacheDrawing(willNotCache)
  1692. map_mapView.drawingCacheBackgroundColor = color
  1693. // todo: 2023/8/14 保存截图
  1694. var saveFile = File(filePath)
  1695. var stream = FileOutputStream(saveFile)
  1696. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
  1697. }
  1698. /**
  1699. * 飞行器位置超边界剧中
  1700. * @param longitude Double 经度
  1701. * @param latitude Double 纬度
  1702. */
  1703. private fun aircraftCenter(longitude:Double,latitude:Double){
  1704. var visiblePolygon = mapView?.visibleArea
  1705. var airPoint = Point(longitude,latitude,spatialReferenceWGS84)
  1706. var targetPoint = GeometryEngine.project(airPoint,mapView?.spatialReference) as Point
  1707. if(!GeometryEngine.within(targetPoint,visiblePolygon)){
  1708. setMapCenter(longitude,latitude,0.0)
  1709. }
  1710. }
  1711. /**
  1712. * 初始化订阅
  1713. */
  1714. private fun initObserver(){
  1715. flightControlVm.flightControlInfo.observe(requireActivity()){
  1716. it?.let {
  1717. if(it.longitude > 10 && it.latitude > 10){
  1718. // todo: 2023/8/17 更新位置
  1719. updateAirplaneLocation(it)
  1720. // todo: 2023/8/17 更新返航点
  1721. updateAirplaneHomeLocation(it)
  1722. // todo: 2023/8/17 更新连接线
  1723. updateAirplaneLinkLine(it)
  1724. }
  1725. }
  1726. }
  1727. }
  1728. /**
  1729. * 更新飞行器位置
  1730. * @param obj CrFlightControlInfo 飞行器信息
  1731. */
  1732. private fun updateAirplaneLocation(obj:CrFlightControlInfo){
  1733. // todo: 2023/8/17 更新飞行器位置
  1734. builderAirplaneLocation?.setXY(obj.longitude,obj.latitude)
  1735. graAirplaneLocation?.geometry = builderAirplaneLocation!!.toGeometry()
  1736. // todo: 2023/8/17 更新角度
  1737. symbolAirplaneLocation?.angle = obj.yaw.toFloat()
  1738. // todo: 2023/8/17 超边界更新
  1739. aircraftCenter(obj.longitude,obj.latitude)
  1740. // todo: 2023/8/17 更新航线
  1741. builderAirplaneLine?.addPoint(Point(obj.longitude,obj.latitude))
  1742. graAirplaneLine?.geometry = builderAirplaneLine!!.toGeometry()
  1743. }
  1744. /**
  1745. * 更新返航位置
  1746. * @param obj CrFlightControlInfo 飞行器信息
  1747. */
  1748. private fun updateAirplaneHomeLocation(obj:CrFlightControlInfo){
  1749. if(obj.isUpdateHomeLocation){
  1750. CrUtil.print("返航点已刷新,请留意返航位置!")
  1751. CrAudioUtil.getInstance().play("返航点已刷新,请留意返航位置!")
  1752. builderAirplaneHomeLocation?.setXY(obj.homeLongitude,obj.homeLatitude)
  1753. graAirplaneHomeLocation?.geometry = builderAirplaneHomeLocation!!.toGeometry()
  1754. // todo: 2023/8/17 如果返航点已刷新 则认为是更换了起飞位置 则重新初始化航线
  1755. builderAirplaneLine = PolylineBuilder(spatialReferenceWGS84)
  1756. builderAirplaneLine?.addPoint(Point(obj.homeLongitude,obj.homeLatitude))
  1757. graAirplaneLine?.geometry = builderAirplaneLine!!.toGeometry()
  1758. // todo: 2023/8/17 设置更新标志 否则一直更新
  1759. obj.isUpdateHomeLocation = false
  1760. }
  1761. }
  1762. /**
  1763. * 更新连接线
  1764. * @param obj CrFlightControlInfo 飞行器信息
  1765. */
  1766. private fun updateAirplaneLinkLine(obj:CrFlightControlInfo){
  1767. if(obj.isHomeLocationValid && obj.isLocationValid){
  1768. builderAirplaneLink = PolylineBuilder(spatialReferenceWGS84)
  1769. builderAirplaneLink?.addPoint(Point(obj.longitude,obj.latitude))
  1770. builderAirplaneLink?.addPoint(Point(obj.homeLongitude,obj.homeLatitude))
  1771. graAirplaneLink?.geometry = builderAirplaneLink!!.toGeometry()
  1772. }
  1773. }
  1774. /**
  1775. * 订阅地图事件执行动作
  1776. * @param event EventMap 事件
  1777. */
  1778. @Subscribe
  1779. fun onAction(event: EventMap) {
  1780. when (event.action) {
  1781. // todo: 2023/4/17 绘制涂鸦
  1782. MapAction.MapTapDrawDoodle -> {
  1783. CrUtil.showToast("地图接收绘制命令")
  1784. doodleStartDraw()
  1785. }
  1786. // todo: 2023/4/17 清除涂鸦
  1787. MapAction.EventDoodleClear -> {
  1788. clearSketch()
  1789. }
  1790. // todo: 2023/4/17 保存涂鸦
  1791. MapAction.EventDoodleSave -> {
  1792. doodleSave()
  1793. }
  1794. // todo: 2023/4/17 停止草图编辑
  1795. MapAction.EventStopSketch -> {
  1796. sketchEditor?.stop()
  1797. }
  1798. // todo: 2023/4/17 全部删除保存的涂鸦
  1799. MapAction.EventDoodleRemove -> {
  1800. removeAllFeatureByTable(fTableDoodle!!)
  1801. }
  1802. // todo: 2023/4/18 删除选择涂鸦
  1803. MapAction.EventDoodleDelete -> {
  1804. doodleSelectFeature(fLayerDoodle!!)
  1805. }
  1806. // todo: 2023/4/18 选择涂鸦
  1807. MapAction.MapTapSelectDoodle -> {
  1808. CrUtil.showToast("地图上点击需要选择的涂鸦")
  1809. mapTouch?.setQueryLayer(fLayerDoodle!!, MapAction.MapTapSelectDoodle)
  1810. }
  1811. // todo: 2023/4/18 停止Touch
  1812. MapAction.EventStopTouch -> {
  1813. mapTouch?.setQueryLayer(null, null)
  1814. unfocusAllFeature()
  1815. }
  1816. // todo: 2023/4/19 绘制标志
  1817. MapAction.MapTapAppendMark -> {
  1818. CrUtil.showToast("地图上单击创建标志!")
  1819. if (event.owner is FragmentMark) {
  1820. markChange = (event.owner as FragmentMark).getMark()
  1821. mapTouch?.setAction(MapAction.MapTapAppendMark)
  1822. }
  1823. }
  1824. // todo: 2023/4/19 清除标志
  1825. MapAction.EventMarkClear -> {
  1826. gLayerIco?.let {
  1827. it.graphics?.clear()
  1828. CrUtil.showToast("标志清除完成!")
  1829. }
  1830. }
  1831. // todo: 2023/4/19 标志保存
  1832. MapAction.EventMarkSave -> {
  1833. markSave()
  1834. }
  1835. // todo: 2023/4/19 删除保存的全部标志
  1836. MapAction.EventMarkRemove -> {
  1837. removeAllFeatureByTable(fTableMark!!)
  1838. }
  1839. // todo: 2023/4/21 选择标志
  1840. MapAction.MapTapSelectMark -> {
  1841. CrUtil.showToast("地图上点击需要选择的标志")
  1842. mapTouch?.setQueryLayer(fLayerMark!!, MapAction.MapTapSelectMark)
  1843. }
  1844. // todo: 2023/4/21 删除选择的标志
  1845. MapAction.EventMarkDelete -> {
  1846. doodleSelectFeature(fLayerMark!!)
  1847. }
  1848. // todo: 2023/4/21 长度测量
  1849. MapAction.EventSurveyLength -> {
  1850. measureLength()
  1851. }
  1852. // todo: 2023/6/6 面积测量
  1853. MapAction.EventSurveyArea -> {
  1854. measureArea()
  1855. }
  1856. // todo: 2023/6/7 初始化测量
  1857. MapAction.EventSurveyClear -> {
  1858. // todo: 2023/6/7 清理临时标注
  1859. gLayerTemp?.graphics?.clear()
  1860. // todo: 2023/6/7 结束编辑
  1861. sketchEditor?.let {
  1862. it.stop()
  1863. it.removeGeometryChangedListener(sketchGeometryChangeListener)
  1864. }
  1865. }
  1866. // todo: 2023/6/7 获取地图位置
  1867. MapAction.MapTapGetLocation -> {
  1868. CrUtil.showToast("地图上点击查询地理位置")
  1869. mapTouch?.setAction(MapAction.MapTapGetLocation)
  1870. }
  1871. // todo: 2023/6/7 输入坐标定位
  1872. MapAction.EventInputLocationToMap -> {
  1873. var dialogInput: DialogInput = DialogInput(requireContext(), "输入位置信息")
  1874. dialogInput.setButtonsText("确定", "关闭")
  1875. dialogInput.setHints("输入经度,例118.70687", "输入纬度,例35.218991")
  1876. dialogInput.setFonts(
  1877. getString(R.string.ico_location),
  1878. getString(R.string.ico_location)
  1879. )
  1880. dialogInput.setListener(inputLocationToMapListener)
  1881. dialogInput.show()
  1882. }
  1883. // todo: 2023/6/9 开始绘制案件图斑
  1884. MapAction.EventCaseDrawPolygon -> {
  1885. caseStartDraw()
  1886. }
  1887. // todo: 2023/6/9 重置绘制
  1888. MapAction.EventCaseDrawReset -> {
  1889. caseStartDraw()
  1890. }
  1891. // todo: 2023/6/9 回退
  1892. MapAction.EventCaseDrawUndo -> {
  1893. sketchEditor?.undo()
  1894. }
  1895. // todo: 2023/6/12 保存绘制的图斑
  1896. MapAction.EventCaseSavePolygon -> {
  1897. caseSave()
  1898. }
  1899. // todo: 2023/6/12 删除保存的图斑
  1900. MapAction.EventCaseRemovePolygon -> {
  1901. caseDelete()
  1902. }
  1903. // todo: 2023/6/12 地图点击添加违建点
  1904. MapAction.MapTapAddWaypoint -> {
  1905. CrUtil.showToast("地图上点击添加案件点!")
  1906. mapTouch?.setAction(MapAction.MapTapAddWaypoint)
  1907. }
  1908. // todo: 2023/6/13 删除案件点
  1909. MapAction.MapTapDeleteWaypoint -> {
  1910. CrUtil.showToast("地图上选择需要删除的违建点后删除!")
  1911. mapTouch?.setAction(MapAction.MapTapDeleteWaypoint)
  1912. }
  1913. // todo: 2023/6/14 移动案件点
  1914. MapAction.MapTapStartMoveWaypoing -> {
  1915. caseMoveWaypoint()
  1916. }
  1917. // todo: 2023/6/15 案件分享及上传
  1918. MapAction.MapTapCaseWxAndUpload -> {
  1919. CrUtil.showToast("地图上选择需要上传或分享的案件!")
  1920. mapTouch?.setAction(MapAction.MapTapCaseWxAndUpload)
  1921. }
  1922. }
  1923. }
  1924. /**
  1925. * 订阅截屏事件
  1926. */
  1927. @Subscribe
  1928. fun onCapture(event: EventMapCapture) {
  1929. event?.let {
  1930. if (it.action == EventMapCapture.CaptureAction.CAPTURE_ACTION_START) {
  1931. captures(it.joinCaseName!!)
  1932. }
  1933. }
  1934. }
  1935. /**
  1936. * 设置事件监听
  1937. * @param listener EventListener 事件监听
  1938. */
  1939. fun crSetEventListener(listener: EventListener) {
  1940. this.eventListener = listener
  1941. }
  1942. // todo: 2023/4/17 生命周期
  1943. override fun onDestroy() {
  1944. // todo: 2023/4/17 移除订阅监听
  1945. CrApplication.getEventBus().unregister(this)
  1946. super.onDestroy()
  1947. }
  1948. /**
  1949. * 生命周期
  1950. * 后台转前台
  1951. */
  1952. override fun onResume() {
  1953. super.onResume()
  1954. // todo: 2023/8/17 初始化订阅
  1955. initObserver()
  1956. }
  1957. }