From 6a77e69ed7c0bbcacea421a3d7054552b0b14d60 Mon Sep 17 00:00:00 2001
From: xiaoyan <xiaoyan159@163.com>
Date: Fri, 2 Jun 2023 10:05:53 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E8=BD=A6=E9=81=93?=
 =?UTF-8?q?=E8=BE=B9=E7=BA=BF=E6=B8=B2=E6=9F=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/src/main/assets/omdb_config.json          |  20 +-
 .../com/navinfo/omqs/db/ImportPreProcess.kt   |  71 +++++-
 .../omqs/ui/activity/login/LoginViewModel.kt  |   2 +-
 .../personalcenter/PersonalCenterFragment.kt  |   2 +-
 .../src/main/assets/editormarker.xml          | 231 ++++++------------
 .../src/main/assets/omdb/icon_arrow_right.png | Bin 0 -> 1032 bytes
 .../src/main/assets/omdb/icon_close.png       | Bin 0 -> 279 bytes
 .../src/main/assets/omdb/icon_right.png       | Bin 0 -> 305 bytes
 .../library/data/entity/ReferenceEntity.kt    |  64 +++++
 .../map/handler/LayerManagerHandler.kt        |  15 ++
 .../map/source/OMDBReferenceDataSource.java   |  71 ++++++
 .../map/source/OMDBReferenceDecoder.java      | 186 ++++++++++++++
 .../map/source/OMDBReferenceTileSource.java   |  25 ++
 vtm                                           |   1 +
 14 files changed, 529 insertions(+), 159 deletions(-)
 create mode 100644 collect-library/src/main/assets/omdb/icon_arrow_right.png
 create mode 100644 collect-library/src/main/assets/omdb/icon_close.png
 create mode 100644 collect-library/src/main/assets/omdb/icon_right.png
 create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/data/entity/ReferenceEntity.kt
 create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDataSource.java
 create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDecoder.java
 create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceTileSource.java
 create mode 160000 vtm

diff --git a/app/src/main/assets/omdb_config.json b/app/src/main/assets/omdb_config.json
index d7ac2a91..c09fe454 100644
--- a/app/src/main/assets/omdb_config.json
+++ b/app/src/main/assets/omdb_config.json
@@ -20,6 +20,19 @@
 			"code": 2010,
 			"name": "道路方向"
 		},
+		"2013": {
+			"table": "OMDB_LANE_MARK_BOUNDARYTYPE",
+			"code": 2013,
+			"name": "车道边界类型",
+			"transformer": [
+				{
+					"k": "geometry",
+					"v": "~",
+					"klib": "geometry",
+					"vlib": "unpackingLaneBoundary()"
+				}
+			]
+		},
 		"2019": {
 			"table": "OMDB_LINK_SPEEDLIMIT",
 			"code": 2019,
@@ -55,6 +68,11 @@
 			"code": 2041,
 			"name": "车道数"
 		},
+		"2083":{
+			"table": "OMDB_RDBOUND_BOUNDARYTYPE",
+			"code": 2083,
+			"name": "道路边界类型"
+		},
 		"2201":{
 			"table": "OMDB_BRIDGE",
 			"code": 2201,
@@ -131,7 +149,7 @@
 					"k": "geometry",
 					"v": "~",
 					"klib": "geometry",
-					"vlib": "translateRightWithAngle()"
+					"vlib": "generateRestrictionRerference()"
 				}
 			]
 		},
diff --git a/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt b/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt
index 51bebc84..99abeeb1 100644
--- a/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt
+++ b/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt
@@ -1,7 +1,11 @@
 package com.navinfo.omqs.db
 
+import com.navinfo.collect.library.data.entity.ReferenceEntity
 import com.navinfo.collect.library.data.entity.RenderEntity
 import com.navinfo.collect.library.utils.GeometryTools
+import io.realm.Realm
+import org.json.JSONArray
+import org.json.JSONObject
 import org.locationtech.jts.algorithm.Angle
 import org.locationtech.jts.geom.Coordinate
 import org.locationtech.jts.geom.Geometry
@@ -60,7 +64,9 @@ class ImportPreProcess {
         var radian = 0.0 // geometry的角度,如果是点,获取angle,如果是线,获取最后两个点的方向
         var point = Coordinate(geometry?.coordinate)
         if (Geometry.TYPENAME_POINT == geometry?.geometryType) {
-            val angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!!
+            // angle为正北方向夹角,需要将其转换为与正东方向夹角
+            var angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!!
+            angle-=90
             radian = Math.toRadians(angle)
         } else if (Geometry.TYPENAME_LINESTRING == geometry?.geometryType) {
             val p1: Coordinate = geometry.coordinates.get(geometry.coordinates.size - 2)
@@ -77,6 +83,7 @@ class ImportPreProcess {
         // 计算偏移后的点
 //        val coordMid =
 //            Coordinate(point.getX() + dy, point.getY() - dx)
+        // 计算指定距离外与当前位置成90度夹角的点位
         val pointStart = GeoPoint(point.getY() - dx, point.getX() + dy)
 //        val pointStart = GeoPoint(pointMid.latitude-dy, pointMid.longitude-dx)
         val pointEnd = GeoPoint(pointStart.latitude- dx, pointStart.longitude+ dy)
@@ -107,4 +114,66 @@ class ImportPreProcess {
         }
         return "0"
     }
+
+    /**
+     * 解析车道边线数据二级属性
+     * */
+    fun unpackingLaneBoundary(renderEntity: RenderEntity) {
+        if (renderEntity.code == 2013&&!renderEntity.properties["shapeList"].isNullOrEmpty()&&renderEntity.properties["shapeList"]!="null") {
+            // 解析shapeList,将数组中的属性放会properties
+            val shapeList = JSONArray(renderEntity.properties["shapeList"])
+            val shape = shapeList.getJSONObject(0)
+            for (key in shape.keys()) {
+                renderEntity.properties[key] = shape[key].toString()
+            }
+        }
+    }
+
+    /**
+     * 自动生成普通交限的参考数据
+     * */
+    fun generateRestrictionRerference(renderEntity: RenderEntity) {
+        // 获取当前renderEntity的geometry
+        val geometry = renderEntity.wkt
+        var radian = 0.0 // geometry的角度,如果是点,获取angle,如果是线,获取最后两个点的方向
+        var point = Coordinate(geometry?.coordinate)
+        if (Geometry.TYPENAME_POINT == geometry?.geometryType) {
+            var angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!!
+            radian = Math.toRadians(angle)
+        }
+
+        // 计算偏移距离
+        val dx: Double = GeometryTools.convertDistanceToDegree(3.0, geometry?.coordinate?.y!!) * Math.sin(radian)
+        val dy: Double = GeometryTools.convertDistanceToDegree(3.0, geometry?.coordinate?.y!!) * Math.cos(radian)
+
+        // 计算偏移后的点
+        val pointTranS =
+            GeoPoint(point.getY() - dx, point.getX() + dy) // 向右偏移的点
+
+        // 计算与原有方向平行的终点坐标
+        val pointTranE = GeoPoint(pointTranS.latitude + dy, pointTranS.longitude + dx)
+
+        renderEntity.geometry = GeometryTools.createGeometry(pointTranS).toString()
+
+        // 将这个点记录在数据中
+        val startEndReference = ReferenceEntity()
+        startEndReference.renderEntityId = renderEntity.id
+        startEndReference.name = "普通交限参考线"
+        startEndReference.table = renderEntity.table
+        // 起终点坐标组成的线
+        startEndReference.geometry = GeometryTools.createLineString(listOf(GeoPoint(point.y, point.x), pointTranS)).toString()
+        startEndReference.properties["qi_table"] = renderEntity.table
+        startEndReference.properties["type"] = "s_2_e"
+        Realm.getDefaultInstance().insert(startEndReference)
+
+        val angleReference = ReferenceEntity()
+        angleReference.renderEntityId = renderEntity.id
+        angleReference.name = "普通交限参考方向"
+        angleReference.table = renderEntity.table
+        // 与原有方向指向平行的线
+        angleReference.geometry = GeometryTools.createLineString(listOf(pointTranS, pointTranE)).toString()
+        angleReference.properties["qi_table"] = renderEntity.table
+        angleReference.properties["type"] = "angle"
+        Realm.getDefaultInstance().insert(angleReference)
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt
index cd36992d..6177e508 100644
--- a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt
+++ b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt
@@ -228,7 +228,7 @@ class LoginViewModel @Inject constructor(
             .name("OMQS.realm")
             .encryptionKey(password)
 //            .modules(Realm.getDefaultModule(), MyRealmModule())
-            .schemaVersion(1)
+            .schemaVersion(2)
             .build()
         Realm.setDefaultConfiguration(config)
         // 拷贝配置文件到用户目录下
diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt
index 1e5e5a81..6930ef2c 100644
--- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt
+++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt
@@ -111,7 +111,7 @@ class PersonalCenterFragment : BaseFragment(), FSAFActivityCallbacks {
                     viewModel.readRealmData()
                     // 定位到指定位置
                     niMapController.mMapView.vtmMap.animator()
-                        .animateTo(GeoPoint(28.724637921467508 ,115.83412668023867  ))
+                        .animateTo(GeoPoint(40.03342017243118, 116.3211538409127 ))
                 }
                 R.id.personal_center_menu_task_list -> {
                     findNavController().navigate(R.id.TaskManagerFragment)
diff --git a/collect-library/src/main/assets/editormarker.xml b/collect-library/src/main/assets/editormarker.xml
index 7815f74b..430e94cd 100644
--- a/collect-library/src/main/assets/editormarker.xml
+++ b/collect-library/src/main/assets/editormarker.xml
@@ -173,6 +173,9 @@
     <!-- oneway -->
     <style-symbol id="oneway" repeat="true" src="assets:symbols/oneway.svg" />
 
+    <!-- omdb -->
+    <style-line id="boundaryType" width="0.1" stipple-width="0.1"  />
+
     <!--###### ASSIGNMENT ######-->
 
     <m e="way" k="natural" v="issea|sea">
@@ -1651,81 +1654,6 @@
                     <caption k="maxSpeed" fill="#000000" priority="0" size="16" stroke="#ffffff"
                         stroke-width="1.0"></caption>
                     <symbol src="assets:omdb/icon_4002_0.png" symbol-width="46" symbol-height="46"></symbol>
-<!--                    <circle fill="#ffffff" radius="28" scale-radius="true" stroke="#ff0000" stroke-width="6"/>-->
-<!--                    <m k="maxSpeed">-->
-<!--                        <m v="5">-->
-<!--                            <symbol src="assets:omdb/1101/1101_5_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="10">-->
-<!--                            <symbol src="assets:omdb/1101/1101_10_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="15">-->
-<!--                            <symbol src="assets:omdb/1101/1101_15_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="20">-->
-<!--                            <symbol src="assets:omdb/1101/1101_20_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="25">-->
-<!--                            <symbol src="assets:omdb/1101/1101_25_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="30">-->
-<!--                            <symbol src="assets:omdb/1101/1101_30_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="35">-->
-<!--                            <symbol src="assets:omdb/1101/1101_35_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="40">-->
-<!--                            <symbol src="assets:omdb/1101/1101_40_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="45">-->
-<!--                            <symbol src="assets:omdb/1101/1101_45_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="50">-->
-<!--                            <symbol src="assets:omdb/1101/1101_50_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="55">-->
-<!--                            <symbol src="assets:omdb/1101/1101_55_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="60">-->
-<!--                            <symbol src="assets:omdb/1101/1101_60_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="65">-->
-<!--                            <symbol src="assets:omdb/1101/1101_65_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="70">-->
-<!--                            <symbol src="assets:omdb/1101/1101_70_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="75">-->
-<!--                            <symbol src="assets:omdb/1101/1101_75_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="80">-->
-<!--                            <symbol src="assets:omdb/1101/1101_80_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="85">-->
-<!--                            <symbol src="assets:omdb/1101/1101_85_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="90">-->
-<!--                            <symbol src="assets:omdb/1101/1101_90_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="95">-->
-<!--                            <symbol src="assets:omdb/1101/1101_95_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="100">-->
-<!--                            <symbol src="assets:omdb/1101/1101_100_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="105">-->
-<!--                            <symbol src="assets:omdb/1101/1101_105_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="110">-->
-<!--                            <symbol src="assets:omdb/1101/1101_110_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="115">-->
-<!--                            <symbol src="assets:omdb/1101/1101_115_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="120">-->
-<!--                            <symbol src="assets:omdb/1101/1101_120_0.png"></symbol>-->
-<!--                        </m>-->
-<!--                    </m>-->
                     <caption k="minSpeed" dy="-28" fill="#000000" priority="0" size="14" stroke="#ffffff"
                         stroke-width="1.0"></caption>
                 </m>
@@ -1733,81 +1661,6 @@
                     <caption k="maxSpeed" fill="#000000" priority="0" size="14" stroke="#ffffff"
                         stroke-width="1.0"></caption>
                     <symbol src="assets:omdb/icon_4002_1.png" symbol-width="46" symbol-height="46"></symbol>
-<!--                    <circle fill="#ffffff" radius="28" scale-radius="true" stroke="#00ff00" stroke-width="6"/>-->
-<!--                    <m k="maxSpeed">-->
-<!--                        <m v="5">-->
-<!--                            <symbol src="assets:omdb/1101/1101_5_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="10">-->
-<!--                            <symbol src="assets:omdb/1101/1101_10_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="15">-->
-<!--                            <symbol src="assets:omdb/1101/1101_15_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="20">-->
-<!--                            <symbol src="assets:omdb/1101/1101_20_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="25">-->
-<!--                            <symbol src="assets:omdb/1101/1101_25_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="30">-->
-<!--                            <symbol src="assets:omdb/1101/1101_30_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="35">-->
-<!--                            <symbol src="assets:omdb/1101/1101_35_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="40">-->
-<!--                            <symbol src="assets:omdb/1101/1101_40_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="45">-->
-<!--                            <symbol src="assets:omdb/1101/1101_45_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="50">-->
-<!--                            <symbol src="assets:omdb/1101/1101_50_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="55">-->
-<!--                            <symbol src="assets:omdb/1101/1101_55_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="60">-->
-<!--                            <symbol src="assets:omdb/1101/1101_60_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="65">-->
-<!--                            <symbol src="assets:omdb/1101/1101_65_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="70">-->
-<!--                            <symbol src="assets:omdb/1101/1101_70_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="75">-->
-<!--                            <symbol src="assets:omdb/1101/1101_75_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="80">-->
-<!--                            <symbol src="assets:omdb/1101/1101_80_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="85">-->
-<!--                            <symbol src="assets:omdb/1101/1101_85_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="90">-->
-<!--                            <symbol src="assets:omdb/1101/1101_90_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="95">-->
-<!--                            <symbol src="assets:omdb/1101/1101_95_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="100">-->
-<!--                            <symbol src="assets:omdb/1101/1101_100_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="105">-->
-<!--                            <symbol src="assets:omdb/1101/1101_105_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="110">-->
-<!--                            <symbol src="assets:omdb/1101/1101_110_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="115">-->
-<!--                            <symbol src="assets:omdb/1101/1101_115_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                        <m v="120">-->
-<!--                            <symbol src="assets:omdb/1101/1101_120_1.png"></symbol>-->
-<!--                        </m>-->
-<!--                    </m>-->
                     <caption k="minSpeed" dy="-28" fill="#000000" priority="0" size="14" stroke="#ffffff"
                         stroke-width="1.0"></caption>
                 </m>
@@ -1855,6 +1708,70 @@
         <m v="OMDB_LANE_LINK_LG">
             <line stroke="#ecf0f1" width="0.1" dasharray="35,35"/>
         </m>
+        <!-- 道路边界类型 -->
+        <m v="OMDB_RDBOUND_BOUNDARYTYPE">
+            <line stroke="#ffffff" width="0.1"/>
+        </m>
+        <!-- 车道边界类型 -->
+        <m v="OMDB_LANE_MARK_BOUNDARYTYPE">
+            <outline-layer id="boundary" stroke="#ffffff" width="0.2" />
+            <m k="boundaryType">
+                <!--标线-->
+                <m v="2">
+                    <m k="markType">
+                        <!--其他|实线-->
+                        <m v="0|1">
+                            <m k="markColor">
+                                <m v="0|1">
+                                    <line stroke="#ffffff" use="boundaryType"/>
+                                </m>
+                                <m v="2">
+                                    <line stroke="#eccc68" use="boundaryType"/>
+                                </m>
+                                <m v="6">
+                                    <line stroke="#0000ff" use="boundaryType"/>
+                                </m>
+                                <m v="7">
+                                    <line stroke="#00ff00" use="boundaryType"/>
+                                </m>
+                                <m v="9">
+                                    <line stroke="#8e44ad" use="boundaryType"/>
+                                </m>
+                            </m>
+                        </m>
+                        <!--虚线-->
+                        <m v="2">
+                            <m k="markColor">
+                                <m v="0|1">
+                                    <line stroke="#ffffff" use="boundaryType" dasharray="3,3"/>
+                                </m>
+                                <m v="2">
+                                    <line stroke="#eccc68" use="boundaryType" dasharray="3,3"/>
+                                </m>
+                                <m v="6">
+                                    <line stroke="#0000ff" use="boundaryType" dasharray="3,3"/>
+                                </m>
+                                <m v="7">
+                                    <line stroke="#00ff00" use="boundaryType" dasharray="3,3"/>
+                                </m>
+                                <m v="9">
+                                    <line stroke="#8e44ad" use="boundaryType" dasharray="3,3"/>
+                                </m>
+                            </m>
+                        </m>
+                        <!--导流区边线-->
+                        <m v="4">
+                            <line outline="boundary" stroke="#545D6C"></line>
+                            <lineSymbol src="assets:omdb/icon_right.png" repeat-start="0" repeat-gap="0.5"/>
+                        </m>
+<!--                        &lt;!&ndash;铺设路面边缘&ndash;&gt;-->
+<!--                        <m v="5">-->
+<!--                            <line outline="#ffffff" fix="true" src="assets:omdb/icon_close.png" stroke="#ffffffff" use="boundaryType"/>-->
+<!--                        </m>-->
+                    </m>
+                </m>
+            </m>
+        </m>
         <!--道路方向-->
         <m v="OMDB_LINK_DIRECT">
             <m k="direct">
@@ -1874,11 +1791,15 @@
         </m>
         <!--普通交限-->
         <m v="OMDB_RESTRICTION">
-            <symbol src="assets:omdb/icon_4006_0.png" repeat="false" symbol-width="35" symbol-height="35" rotate="true" repeat-start="0" ></symbol>
-<!--            <line stroke="#14582c" width="0.1"/>-->
-<!--            <caption k="angle" fill="#000000" priority="0" size="14" stroke="#ffffff"-->
-<!--                stroke-width="1.0"></caption>-->
-
+            <m k="angle">
+                <symbol src="assets:omdb/icon_4006_0.png" repeat="false" symbol-width="35" symbol-height="35" rotate="false" repeat-start="0" ></symbol>
+            </m>
+            <m k="type" v="angle">
+                <symbol src="assets:omdb/icon_arrow_right.png" repeat-start="0" repeat-gap="2000" symbol-percent="45" repeat="false" rotate="true"></symbol>
+            </m>
+            <m k="type" v="s_2_e">
+                <line stroke="#14582c" width="0.1" dasharray="1,1" repeat-gap="3" repeat-start="0"/>
+            </m>
         </m>
     </m>
 </rendertheme>
\ No newline at end of file
diff --git a/collect-library/src/main/assets/omdb/icon_arrow_right.png b/collect-library/src/main/assets/omdb/icon_arrow_right.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0246785a209f0298a7435042062a26414f0ca3a
GIT binary patch
literal 1032
zcmV+j1o!)iP)<h;3K|Lk000e1NJLTq002e+002e^1^@s6aW3M700001b5ch_0Itp)
z=>Px&!bwCyRCr$P*iB3nXB@}z-}CJIu4}p?i`q1Z<;4WFr&3Bx6c4>LCPoiEaA@KI
zjfa8?c+p5qdMMOZ5=}~)G$tB7*d`{v#9pk4FQIBLCeTn;ieOk51Xgg_-PxJvX=Y&s
z4cpAqV4BJP_r&3uVfM4%=RZ5kK(A#57`ZGjKrngAAQ*yC8yZv$6+^|S2~aU=UNmE<
z7%E0hfQnJ`q8UTQP%&x(RE(Mz%@`_%icu4wV${57#!xX-jG6!ylNB&WhqNMBNHb<V
z00#gLU<`o%Z$O0t6WF;L)wMo%*+^PMFUIxg0!|_yPC>vND)DaG9$=B6lQAYG1~qZ&
z>uCC?5e+8L^l~@_0dqd=Zv3de=)!yN`;boP`18&Lk`fP2#*$5a2}}Z6AY&<z-C#B?
z%n2*=Gq)!5OT*fI4RuAwbz^?+3L)_L*BG>vfghgF)nA*<!kBYM%N=AV81LCqZ<~wB
z5CgY--MS%+ty@E%RMxECCJg~sRULRRghcNRJbfI;)bJc4hCJ5%G<6BU6o7c{_NAi#
zzpcGo?my@><QWIc-f}I!qyUP`0;s5610F8Js=e)Cz92FKy?AxK2l25P^xv5f8fW*v
z7)tI2-~td+`X`pJ<{d1&QXcqj%l5U0LhF2x($ZIv*H>XK7ls6Lx)IpZ2ImKxvwx?0
zuONB*0%l(5h&-G`GHJZ(8P9xnb5@Vo2Ig6F`S%_#Z&5UP^CL13W(>X^jqud&Lh85k
zNd0~l+~q)GTEl4HOT<R!riX<5(l#*9TPwObXJ4&Uj67Hbk%*fq&7YD1LYElpe~Hn7
z*?abZIb6}roht{E57_1Ai2N}XwGYe+7n2Xhyx*l$V$41;M=DNp2Wwubt(5OP0XIiN
zGfvwEX5wg7mz1*gUBToYyCv{r*#Fl7+rY%yD^GFYu-c8<8l%g>pcztQQtl6T4W6^r
z7d-P~$J;As{4O4}_I4LnWrRd#;c?*YV;KXa#DJ9I^OCN}6FWW<sCv9!KipJ$WL3!X
ztyq$qxm8RQA#u0ZzoCJ3+<xQt8QW~7|Eyv@9kzVf<ncIqa?vczlQh6iggXbmS?=5g
z0TXSnYVdO0GPl&?R?$B$?i_lQ54<2?vh%5}>Sr)n!ypsm{=rYHI~IRpDA;0hZ~X6$
zjoz}3;gpqaSun*|!C1P6VDg9&48f>vCMt%Cp<>hos2DXbnlV%i6{99V#i)7FjG<zv
z7&QSZM$L<63>8Dgs0mOpYF;#Bs2D0nO@N9~^ZExES0W1-p<h`50000<MNUMnLSTY@
C4cSNl

literal 0
HcmV?d00001

diff --git a/collect-library/src/main/assets/omdb/icon_close.png b/collect-library/src/main/assets/omdb/icon_close.png
new file mode 100644
index 0000000000000000000000000000000000000000..33cb188465c6e33ae0bde2c1dbd01ba1d340ed7b
GIT binary patch
literal 279
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}7d>4ZLn7SY
zPWjJy$bqLd-n>v`cc-6{Uy}LCyhj?J4zfCFd|Nb4>B&FMJ5%@Q>)W%vt!bP4HI(70
zgJl5UpSjHHp5mU1m!#iV)c)<*->v0`(`09;%Ff==?(pZ@JvGngYZ(NXn)GKf9W*R_
zC$K-C)!`0D<BFY=gw!Lpu}quM{y=Z;PS#&+2Xf3CmL7{)dqkaK-@_cC8vi3NE4U}J
zc09TwbMVHDy8@96IqBj@X8oR*z?5TE7soVBfWiB2UiS;d&e#j3oA^pt&;AL4xM&Kq
Z{z5e!#TEOV7=fN+@O1TaS?83{1OVlrZl(YL

literal 0
HcmV?d00001

diff --git a/collect-library/src/main/assets/omdb/icon_right.png b/collect-library/src/main/assets/omdb/icon_right.png
new file mode 100644
index 0000000000000000000000000000000000000000..949982b5ace64c834908a5dfff9ca09eff231e7f
GIT binary patch
literal 305
zcmV-10nYx3P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800001b5ch_0Itp)
z=>Px#>q$gGR9HvtmC+5tFc3rSP3R_c6PScD32XwJP$n^Q)k+aR=q?fcN&YG|@~iLc
z5<4I6td9=R9q0~(9guW#bV=S@L^uQR0&oB@keq8FG5{8Tw1Nl&_=_cN5PlqMoJawz
z5Jv#Fbp&aMG{6dR0kAA()`=>B0%8L21aOXyqZ;4~Vj_8sB%>98_rb|{k{tgEAZZhy
zNe&V5rO=`m%J<hex|m!@sU)NU3h^xgUc&H60Te~#Lh_fV#M2{?<c0I>tHe_PlH7hS
zA7{S$j~E_-B)8wYg?P$=@Rt3!5O$ygbO*WvtsVFP(>_rle{GHp00000NkvXXu0mjf
D>F#z*

literal 0
HcmV?d00001

diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/ReferenceEntity.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/ReferenceEntity.kt
new file mode 100644
index 00000000..5697cd25
--- /dev/null
+++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/ReferenceEntity.kt
@@ -0,0 +1,64 @@
+package com.navinfo.collect.library.data.entity
+
+import com.navinfo.collect.library.system.Constant
+import com.navinfo.collect.library.utils.GeometryTools
+import com.navinfo.collect.library.utils.GeometryToolsKt
+import io.realm.RealmDictionary
+import io.realm.RealmObject
+import io.realm.RealmSet
+import io.realm.annotations.Ignore
+import io.realm.annotations.PrimaryKey
+import org.locationtech.jts.geom.Coordinate
+import org.locationtech.jts.geom.Geometry
+import org.oscim.core.MercatorProjection
+import java.util.*
+
+/**
+ * 渲染要素对应的实体
+ * */
+open class ReferenceEntity() : RealmObject() {
+    @PrimaryKey
+    var id: String = UUID.randomUUID().toString() // id
+    var renderEntityId: String = "" // 参考的renderEntity的Id
+    lateinit var name: String //要素名
+    lateinit var table: String //要素表名
+    var code: Int = 0 // 要素编码
+    var geometry: String = "" // 要素渲染参考的geometry,该数据可能会在导入预处理环节被修改,原始geometry会保存在properties的geometry字段下
+        get() {
+            wkt = GeometryTools.createGeometry(field)
+            return field
+        }
+        set(value) {
+            field = value
+            // 根据geometry自动计算当前要素的x-tile和y-tile
+            GeometryToolsKt.getTileXByGeometry(value, tileX)
+            GeometryToolsKt.getTileYByGeometry(value, tileY)
+            // 根据传入的geometry文本,自动转换为Geometry对象
+            try {
+                wkt = GeometryTools.createGeometry(value)
+            } catch (e: Exception) {
+
+            }
+        }
+
+    @Ignore
+    var wkt: Geometry? = null
+        get() {
+            if (field == null || field!!.isEmpty) {
+                try {
+                    field = GeometryTools.createGeometry(geometry)
+                } catch (e: Exception) {
+
+                }
+            }
+            return field
+        }
+    var properties: RealmDictionary<String> = RealmDictionary()
+    var tileX: RealmSet<Int> = RealmSet() // x方向的tile编码
+    var tileY: RealmSet<Int> = RealmSet()  // y方向的tile编码
+
+    constructor(name: String): this() {
+        this.name = name
+    }
+
+}
\ No newline at end of file
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt
index ba22bce1..75aafa44 100644
--- a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt
+++ b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt
@@ -4,6 +4,7 @@ import androidx.appcompat.app.AppCompatActivity
 import com.navinfo.collect.library.map.NIMapView
 import com.navinfo.collect.library.map.source.MapLifeNiLocationTileSource
 import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource
+import com.navinfo.collect.library.map.source.OMDBReferenceTileSource
 import com.navinfo.collect.library.map.source.OMDBTileSource
 import com.navinfo.collect.library.system.Constant
 import okhttp3.Cache
@@ -45,9 +46,12 @@ class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tracePa
      * 显示待测评OMDB数据的图层
      * */
     private lateinit var omdbVectorTileLayer: VectorTileLayer
+    private lateinit var omdbReferenceTileLayer: VectorTileLayer
     private lateinit var omdbLabelLayer: LabelLayer
+    private lateinit var omdbReferenceLabelLayer: LabelLayer
 
     private val omdbTileSource by lazy { OMDBTileSource() }
+    private val omdbReferenceTileSource by lazy { OMDBReferenceTileSource() }
 
     init {
         initMap()
@@ -99,6 +103,7 @@ class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tracePa
     }
 
     private fun initOMDBVectorTileLayer() {
+        // 初始化OMDB相关图层
         omdbVectorTileLayer = VectorTileLayer(mMapView.vtmMap, omdbTileSource)
         omdbLabelLayer = LabelLayer(mMapView.vtmMap, omdbVectorTileLayer, LabelTileLoaderHook(), Constant.OMDB_MIN_ZOOM)
         if(omdbVectorTileLayer!=null){
@@ -107,6 +112,16 @@ class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tracePa
         if(omdbLabelLayer!=null){
             addLayer(omdbLabelLayer, NIMapView.LAYER_GROUPS.VECTOR_TILE)
         }
+
+        // 初始化OMDB参考相关图层
+        omdbReferenceTileLayer = VectorTileLayer(mMapView.vtmMap, omdbReferenceTileSource)
+        omdbReferenceLabelLayer = LabelLayer(mMapView.vtmMap, omdbReferenceTileLayer, LabelTileLoaderHook(), Constant.OMDB_MIN_ZOOM)
+        if(omdbReferenceTileLayer!=null){
+            addLayer(omdbReferenceTileLayer,NIMapView.LAYER_GROUPS.VECTOR_TILE)
+        }
+        if(omdbReferenceLabelLayer!=null){
+            addLayer(omdbReferenceLabelLayer, NIMapView.LAYER_GROUPS.VECTOR_TILE)
+        }
     }
 
     /**
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDataSource.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDataSource.java
new file mode 100644
index 00000000..917f632e
--- /dev/null
+++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDataSource.java
@@ -0,0 +1,71 @@
+package com.navinfo.collect.library.map.source;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.navinfo.collect.library.data.entity.ReferenceEntity;
+import com.navinfo.collect.library.system.Constant;
+
+import org.oscim.layers.tile.MapTile;
+import org.oscim.tiling.ITileDataSink;
+import org.oscim.tiling.ITileDataSource;
+import org.oscim.tiling.QueryResult;
+
+import java.util.List;
+
+import io.realm.Realm;
+import io.realm.RealmQuery;
+
+public class OMDBReferenceDataSource implements ITileDataSource {
+    private final ThreadLocal<OMDBReferenceDecoder> mThreadLocalDecoders = new ThreadLocal<OMDBReferenceDecoder>() {
+        @Override
+        protected OMDBReferenceDecoder initialValue() {
+            return new OMDBReferenceDecoder();
+        }
+    };
+
+    @RequiresApi(api = Build.VERSION_CODES.N)
+    @Override
+    public void query(MapTile tile, ITileDataSink mapDataSink) {
+        // 获取tile对应的坐标范围
+        if (tile.zoomLevel>=Constant.OMDB_MIN_ZOOM&&tile.zoomLevel<=Constant.OVER_ZOOM) {
+            int m = Constant.OVER_ZOOM-tile.zoomLevel;
+            int xStart = (int)tile.tileX<<m;
+            int xEnd = (int)((tile.tileX+1)<<m);
+            int yStart = (int)tile.tileY<<m;
+            int yEnd = (int)((tile.tileY+1)<<m);
+
+            RealmQuery<ReferenceEntity> realmQuery = Realm.getDefaultInstance().where(ReferenceEntity.class)
+                    .rawPredicate("tileX>="+xStart+" and tileX<="+xEnd+" and tileY>="+yStart+" and tileY<="+yEnd);
+            // 筛选不显示的数据
+            if (Constant.HAD_LAYER_INVISIABLE_ARRAY!=null&&Constant.HAD_LAYER_INVISIABLE_ARRAY.length>0) {
+                realmQuery.beginGroup();
+                for (String type: Constant.HAD_LAYER_INVISIABLE_ARRAY) {
+                    realmQuery.notEqualTo("table", type);
+                }
+                realmQuery.endGroup();
+            }
+            List<ReferenceEntity> listResult = realmQuery/*.distinct("id")*/.findAll();
+            if (!listResult.isEmpty()) {
+                mThreadLocalDecoders.get().decode(tile, mapDataSink, listResult);
+            }
+            mapDataSink.completed(QueryResult.SUCCESS);
+//            Log.d("RealmDBTileDataSource", "tile:"+tile.getBoundingBox().toString());
+        } else {
+            mapDataSink.completed(QueryResult.SUCCESS);
+        }
+    }
+
+    @Override
+    public void dispose() {
+
+    }
+
+    @Override
+    public void cancel() {
+        if (Realm.getDefaultInstance().isInTransaction()) {
+            Realm.getDefaultInstance().cancelTransaction();
+        }
+    }
+}
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDecoder.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDecoder.java
new file mode 100644
index 00000000..d859fde9
--- /dev/null
+++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceDecoder.java
@@ -0,0 +1,186 @@
+package com.navinfo.collect.library.map.source;
+
+import static org.oscim.core.MercatorProjection.latitudeToY;
+import static org.oscim.core.MercatorProjection.longitudeToX;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.navinfo.collect.library.data.entity.ReferenceEntity;
+
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.MultiLineString;
+import org.locationtech.jts.geom.MultiPoint;
+import org.locationtech.jts.geom.MultiPolygon;
+import org.locationtech.jts.geom.Point;
+import org.locationtech.jts.geom.Polygon;
+import org.oscim.core.MapElement;
+import org.oscim.core.Tag;
+import org.oscim.core.Tile;
+import org.oscim.tiling.ITileDataSink;
+import org.oscim.tiling.source.mvt.TileDecoder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+public class OMDBReferenceDecoder extends TileDecoder {
+    private final String mLocale;
+
+    private static final float REF_TILE_SIZE = 4096.0f;
+
+    private final GeometryFactory mGeomFactory;
+    private final MapElement mMapElement;
+    private ITileDataSink mTileDataSink;
+    private double mTileY, mTileX, mTileScale;
+
+    public OMDBReferenceDecoder() {
+        super();
+        mLocale = "";
+        mGeomFactory = new GeometryFactory();
+        mMapElement = new MapElement();
+        mMapElement.layer = 5;
+    }
+
+    @Override
+    public boolean decode(Tile tile, ITileDataSink sink, InputStream is) throws IOException {
+        mTileDataSink = sink;
+        mTileScale = 1 << tile.zoomLevel;
+        mTileX = tile.tileX / mTileScale;
+        mTileY = tile.tileY / mTileScale;
+        mTileScale *= Tile.SIZE;
+        return true;
+    }
+
+    @RequiresApi(api = Build.VERSION_CODES.N)
+    public boolean decode(Tile tile, ITileDataSink sink, List<ReferenceEntity> listResult) {
+        mTileDataSink = sink;
+        mTileScale = 1 << tile.zoomLevel;
+        mTileX = tile.tileX / mTileScale;
+        mTileY = tile.tileY / mTileScale;
+        mTileScale *= Tile.SIZE;
+
+        listResult.stream().iterator().forEachRemaining(new Consumer<ReferenceEntity>() {
+            @Override
+            public void accept(ReferenceEntity renderEntity) {
+//                Log.d("RealmDBTileDataSource", renderEntity.getGeometry());
+                Map<String, Object> properties= new HashMap<>(renderEntity.getProperties().size());
+                properties.putAll(renderEntity.getProperties());
+                parseGeometry(renderEntity.getTable(), renderEntity.getWkt(), properties);
+            }
+        });
+        return true;
+    }
+
+    public void parseGeometry(String layerName, Geometry geometry, Map<String, Object> tags) {
+        mMapElement.clear();
+        mMapElement.tags.clear();
+
+        parseTags(tags, layerName);
+        if (mMapElement.tags.size() == 0) {
+            return;
+        }
+
+        boolean err = false;
+        if (geometry instanceof Point) {
+            mMapElement.startPoints();
+            processCoordinateArray(geometry.getCoordinates(), false);
+        } else if (geometry instanceof MultiPoint) {
+            MultiPoint multiPoint = (MultiPoint) geometry;
+            for (int i = 0; i < multiPoint.getNumGeometries(); i++) {
+                mMapElement.startPoints();
+                processCoordinateArray(multiPoint.getGeometryN(i).getCoordinates(), false);
+            }
+        } else if (geometry instanceof LineString) {
+            processLineString((LineString) geometry);
+        } else if (geometry instanceof MultiLineString) {
+            MultiLineString multiLineString = (MultiLineString) geometry;
+            for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
+                processLineString((LineString) multiLineString.getGeometryN(i));
+            }
+        } else if (geometry instanceof Polygon) {
+            Polygon polygon = (Polygon) geometry;
+            processPolygon(polygon);
+        } else if (geometry instanceof MultiPolygon) {
+            MultiPolygon multiPolygon = (MultiPolygon) geometry;
+            for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
+                processPolygon((Polygon) multiPolygon.getGeometryN(i));
+            }
+        } else {
+            err = true;
+        }
+
+        if (!err) {
+            mTileDataSink.process(mMapElement);
+        }
+    }
+
+    private void processLineString(LineString lineString) {
+        mMapElement.startLine();
+        processCoordinateArray(lineString.getCoordinates(), false);
+    }
+
+    private void processPolygon(Polygon polygon) {
+        mMapElement.startPolygon();
+        processCoordinateArray(polygon.getExteriorRing().getCoordinates(), true);
+        for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
+            mMapElement.startHole();
+            processCoordinateArray(polygon.getInteriorRingN(i).getCoordinates(), true);
+        }
+    }
+
+    private void processCoordinateArray(Coordinate[] coordinates, boolean removeLast) {
+        int length = removeLast ? coordinates.length - 1 : coordinates.length;
+        for (int i = 0; i < length; i++) {
+            mMapElement.addPoint((float) ((longitudeToX(coordinates[i].x) - mTileX) * mTileScale),
+                    (float) ((latitudeToY(coordinates[i].y) - mTileY) * mTileScale));
+        }
+
+//        int length = removeLast ? coordinates.length - 1 : coordinates.length;
+//        // 初始化3D数据类型
+//        float[] point3D = new float[coordinates.length*3];
+//        for (int i = 0; i < length; i++) {
+//            point3D[i*3] = (float) coordinates[i].x;
+//            point3D[(i*3)+1] = (float) coordinates[i].y;
+//            point3D[(i*3)+2] = (float) coordinates[i].z;
+//        }
+//        mMapElement.points = point3D;
+//        mMapElement.pointNextPos = mMapElement.points.length;
+//        mMapElement.type = GeometryBuffer.GeometryType.TRIS;
+    }
+
+    private void parseTags(Map<String, Object> map, String layerName) {
+        mMapElement.tags.add(new Tag("layer", layerName));
+        boolean hasName = false;
+        String fallbackName = null;
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            String val = (value instanceof String) ? (String) value : String.valueOf(value);
+            if (key.startsWith(Tag.KEY_NAME)) {
+                int len = key.length();
+                if (len == 4) {
+                    fallbackName = val;
+                    continue;
+                }
+                if (len < 7)
+                    continue;
+                if (mLocale.equals(key.substring(5))) {
+                    hasName = true;
+                    mMapElement.tags.add(new Tag(Tag.KEY_NAME, val, false));
+                }
+            } else {
+                mMapElement.tags.add(new Tag(key, val));
+            }
+        }
+        if (!hasName && fallbackName != null)
+            mMapElement.tags.add(new Tag(Tag.KEY_NAME, fallbackName, false));
+    }
+}
diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceTileSource.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceTileSource.java
new file mode 100644
index 00000000..aa661822
--- /dev/null
+++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBReferenceTileSource.java
@@ -0,0 +1,25 @@
+package com.navinfo.collect.library.map.source;
+
+import com.navinfo.collect.library.system.Constant;
+
+import org.oscim.tiling.ITileDataSource;
+import org.oscim.tiling.OverzoomTileDataSource;
+import org.oscim.tiling.TileSource;
+
+public class OMDBReferenceTileSource extends TileSource {
+
+    @Override
+    public ITileDataSource getDataSource() {
+        return new OverzoomTileDataSource(new OMDBReferenceDataSource(), Constant.OVER_ZOOM);
+    }
+
+    @Override
+    public OpenResult open() {
+        return OpenResult.SUCCESS;
+    }
+
+    @Override
+    public void close() {
+
+    }
+}
diff --git a/vtm b/vtm
new file mode 160000
index 00000000..fb0b88e9
--- /dev/null
+++ b/vtm
@@ -0,0 +1 @@
+Subproject commit fb0b88e916c51754baedfb7c5b42aa86b9dc337d