diff --git a/app/src/main/assets/omdb_config.json b/app/src/main/assets/omdb_config.json index 994a1511..0800ec23 100644 --- a/app/src/main/assets/omdb_config.json +++ b/app/src/main/assets/omdb_config.json @@ -101,7 +101,12 @@ "code": 4001, "name": "路口", "transformer": [ - + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateIntersectionReference()" + } ] }, "4002": { @@ -170,7 +175,25 @@ "k": "geometry", "v": "~", "klib": "geometry", - "vlib": "generateRestrictionRerference()" + "vlib": "translateBack()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "translateRight()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateS2EReferenceLine()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateDirectReferenceLine()" } ] }, @@ -179,7 +202,30 @@ "code": 4010, "name": "电子眼", "transformer": [ - + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "translateRight()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateS2EReferenceLine()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateDirectReferenceLine()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateElectronName()" + } ] }, "4022": { @@ -200,7 +246,24 @@ "code": 4601, "name": "车信", "transformer": [ - + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "translateBack()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "translateRight()" + }, + { + "k": "geometry", + "v": "~", + "klib": "geometry", + "vlib": "generateDirectReferenceLine()" + } ] }, "5001":{ diff --git a/app/src/main/java/com/navinfo/omqs/bean/ImportConfig.kt b/app/src/main/java/com/navinfo/omqs/bean/ImportConfig.kt index 1e15ce0d..5a8e099e 100644 --- a/app/src/main/java/com/navinfo/omqs/bean/ImportConfig.kt +++ b/app/src/main/java/com/navinfo/omqs/bean/ImportConfig.kt @@ -2,6 +2,8 @@ package com.navinfo.omqs.bean import com.navinfo.collect.library.data.entity.RenderEntity import com.navinfo.omqs.db.ImportPreProcess +import kotlin.reflect.KFunction +import kotlin.reflect.KParameter import kotlin.reflect.full.declaredMemberFunctions @@ -36,16 +38,46 @@ class ImportConfig { for (v in processKeyOrValue(value)) { if ("~" == v ) { // ~符可以匹配任意元素 if (valuelib.endsWith("()")) { // 以()结尾,说明该value配置是一个function,需要通过反射调用指定方法 - val method = preProcess::class.declaredMemberFunctions.first { it.name == valuelib.replace("()", "") } - method.call(preProcess, renderEntity) + // 获取方法名 + val methodName = valuelib.substringBefore("(") + // 获取参数 + val params: List = valuelib.substringAfter("(").substringBefore(")").split(",").filter{ it.isNotEmpty() }.map { it.trim() } + val method = preProcess::class.members.filter { it.name == methodName }.first() as KFunction<*> + + val methodParams = method.parameters + val callByParams = mutableMapOf( + methodParams[0] to preProcess, + methodParams[1] to renderEntity + ) + for ((index, value) in params.withIndex()) { + if (methodParams.size>index+1) { + callByParams[methodParams[index+1]] = value + } + } + method.callBy(callByParams) } else { renderEntity.properties[keylib] = valuelib } break@m } else if (renderEntity.properties[k] == v) { // 完全匹配 if (valuelib.endsWith("()")) { // 以()结尾,说明该value配置是一个function,需要通过反射调用指定方法 - val method = preProcess::class.declaredMemberFunctions.first { it.name == valuelib.replace("()", "") } - method.call(preProcess, renderEntity) + // 获取方法名 + val methodName = valuelib.substringBefore("(") + // 获取参数 + val params: List = valuelib.substringAfter("(").substringBefore(")").split(",").filter{ it.isNotEmpty() }.map { it.trim() } + val method = preProcess::class.members.filter { it.name == methodName }.first() as KFunction<*> + + val methodParams = method.parameters + val callByParams = mutableMapOf( + methodParams[0] to preProcess, + methodParams[1] to renderEntity + ) + for ((index, value) in params.withIndex()) { + if (methodParams.size>index+1) { + callByParams[methodParams[index+1]] = value + } + } + method.callBy(callByParams) } else { renderEntity.properties[keylib] = valuelib } diff --git a/app/src/main/java/com/navinfo/omqs/db/Code2NameMap.kt b/app/src/main/java/com/navinfo/omqs/db/Code2NameMap.kt new file mode 100644 index 00000000..40a09740 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/db/Code2NameMap.kt @@ -0,0 +1,43 @@ +package com.navinfo.omqs.db + +class Code2NameMap { + val electronEyeKindMap = mapOf( + 1 to "超高", + 2 to "超低", + 3 to "移动", + 4 to "可变", + 5 to "分车道", + 6 to "分车种", + 7 to "车灯", + 8 to "占车道", + 9 to "过路口", + 10 to "闯红灯", + 11 to "路况", + 12 to "单行", + 13 to "非机动", + 14 to "出入口", + 15 to "公交", + 16 to "禁转", + 17 to "掉头", + 18 to "应急", + 19 to "标线", + 20 to "区间S", + 21 to "区间E", + 22 to "停车", + 23 to "尾号", + 24 to "环保", + 25 to "安全带", + 26 to "手机", + 27 to "行人", + 28 to "禁令", + 29 to "鸣笛", + 30 to "年检", + 31 to "尾气", + 32 to "交通灯", + 33 to "专用", + 34 to "标线", + 35 to "违章", + 36 to "卡车", + 37 to "限时长", + ) +} \ No newline at end of file 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 55b5d4b7..3f2d8749 100644 --- a/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt +++ b/app/src/main/java/com/navinfo/omqs/db/ImportPreProcess.kt @@ -13,29 +13,36 @@ import org.oscim.core.GeoPoint class ImportPreProcess { - /** - * 预处理所需要的函数 - * */ - fun foo(renderEntity: RenderEntity): RenderEntity { - println("foo") - renderEntity.properties["foo"] = "bar" - return renderEntity - } - + val code2NameMap = Code2NameMap() /** * 计算指定数据指定方向的坐标 + * @param direction 判断当前数据是否为逆向,给定的应该是一个a=b的表达式,a为对应的properties的key,b为对应的值 * */ - fun translateRight(renderEntity: RenderEntity): RenderEntity { + fun translateRight(renderEntity: RenderEntity, direction: String = "") { // 获取当前renderEntity的geometry val geometry = renderEntity.wkt var radian = 0.0 // geometry的角度,如果是点,获取angle,如果是线,获取最后两个点的方向 var point = Coordinate(geometry?.coordinate) + var isReverse = false // 是否为逆向 + if (direction.isNotEmpty()) { + val paramDirections = direction.split("=") + if (paramDirections.size>=2 && renderEntity.properties[paramDirections[0].trim()] == paramDirections[1].trim()) { + isReverse = true; + } + } if (Geometry.TYPENAME_POINT == geometry?.geometryType) { - val angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!! + var angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!! + if (isReverse) { + angle += 180 + } radian = Math.toRadians(angle) } else if (Geometry.TYPENAME_LINESTRING == geometry?.geometryType) { - val p1: Coordinate = geometry.coordinates.get(geometry.coordinates.size - 2) - val p2: Coordinate = geometry.coordinates.get(geometry.coordinates.size - 1) + var coordinates = geometry.coordinates + if (isReverse) { + coordinates = coordinates.reversedArray() + } + val p1: Coordinate = coordinates.get(coordinates.size - 2) + val p2: Coordinate = coordinates.get(coordinates.size - 1) // 计算线段的方向 radian = Angle.angle(p1, p2) point = p2 @@ -52,46 +59,126 @@ class ImportPreProcess { // 将这个点记录在数据中 val geometryTranslate: Geometry = GeometryTools.createGeometry(doubleArrayOf(coord.x, coord.y)) renderEntity.geometry = geometryTranslate.toString() - return renderEntity } /** - * 将要素按照点位角度的垂直方向右移5米,并生成一个按照垂直角度指向方向的线段,用以显示有方向的图标 + * 向方向对应的反方向偏移 * */ - fun translateRightWithAngle(renderEntity: RenderEntity): RenderEntity { + fun translateBack(renderEntity: RenderEntity, direction: String = "") { // 获取当前renderEntity的geometry val geometry = renderEntity.wkt + var isReverse = false // 是否为逆向 + if (direction.isNotEmpty()) { + val paramDirections = direction.split("=") + if (paramDirections.size>=2 && renderEntity.properties[paramDirections[0].trim()] == paramDirections[1].trim()) { + isReverse = true; + } + } var radian = 0.0 // geometry的角度,如果是点,获取angle,如果是线,获取最后两个点的方向 var point = Coordinate(geometry?.coordinate) if (Geometry.TYPENAME_POINT == geometry?.geometryType) { - // angle为正北方向夹角,需要将其转换为与正东方向夹角 var angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!! - angle-=90 + if (isReverse) { + angle += 180 + } radian = Math.toRadians(angle) } else if (Geometry.TYPENAME_LINESTRING == geometry?.geometryType) { - val p1: Coordinate = geometry.coordinates.get(geometry.coordinates.size - 2) - val p2: Coordinate = geometry.coordinates.get(geometry.coordinates.size - 1) + var coordinates = geometry.coordinates + if (isReverse) { + coordinates = coordinates.reversedArray() + } + val p1: Coordinate = coordinates.get(coordinates.size - 2) + val p2: Coordinate = coordinates.get(coordinates.size - 1) // 计算线段的方向 radian = Angle.angle(p1, p2) point = p2 } - // 根据角度计算偏移距离 + // 计算偏移距离 val dx: Double = GeometryTools.convertDistanceToDegree(3.0, geometry?.coordinate?.y!!) * Math.cos(radian) val dy: Double = GeometryTools.convertDistanceToDegree(3.0, geometry?.coordinate?.y!!) * Math.sin(radian) // 计算偏移后的点 -// 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) + val coord = + Coordinate(point.getX() - dx, point.getY() - dy) - // 将这个线记录在数据中 - val geometryTranslate: Geometry = GeometryTools.createLineString(listOf(pointStart, pointEnd)) + // 将这个点记录在数据中 + val geometryTranslate: Geometry = GeometryTools.createGeometry(doubleArrayOf(coord.x, coord.y)) renderEntity.geometry = geometryTranslate.toString() - return renderEntity + } + + /** + * 生成偏移后数据的起终点参考线 + * */ + fun generateS2EReferenceLine(renderEntity: RenderEntity) { + // 获取当前renderEntity的geometry,该坐标为偏移后坐标,即为终点 + val translateGeometry = renderEntity.wkt + val startGeometry = GeometryTools.createGeometry(renderEntity.properties["geometry"]) + + val pointEnd = translateGeometry!!.coordinates[translateGeometry.numPoints-1] // 获取这个geometry对应的结束点坐标 + val pointStart = startGeometry!!.coordinates[startGeometry.numPoints-1] // 获取这个geometry对应的结束点坐标 + + // 将这个起终点的线记录在数据中 + val startEndReference = ReferenceEntity() + startEndReference.renderEntityId = renderEntity.id + startEndReference.name = "${renderEntity.name}参考线" + startEndReference.table = renderEntity.table + // 起终点坐标组成的线 + startEndReference.geometry = GeometryTools.createLineString(arrayOf(pointStart, pointEnd)).toString() + startEndReference.properties["qi_table"] = renderEntity.table + startEndReference.properties["type"] = "s_2_e" + Realm.getDefaultInstance().insert(startEndReference) + } + + /** + * 生成与对应方向相同的方向线,用以绘制方向箭头 + * */ + fun generateDirectReferenceLine(renderEntity: RenderEntity, direction: String = "") { + // 根据数据或angle计算方向对应的角度和偏移量 + val geometry = renderEntity.wkt + var isReverse = false // 是否为逆向 + if (direction.isNotEmpty()) { + val paramDirections = direction.split("=") + if (paramDirections.size>=2 && renderEntity.properties[paramDirections[0].trim()] == paramDirections[1].trim()) { + isReverse = true; + } + } + var radian = 0.0 // geometry的角度,如果是点,获取angle,如果是线,获取最后两个点的方向 + var point = Coordinate(geometry?.coordinate) + if (Geometry.TYPENAME_POINT == geometry?.geometryType) { + point = Coordinate(geometry?.coordinate) + var angle = if(renderEntity?.properties?.get("angle") == null) 0.0 else renderEntity?.properties?.get("angle")?.toDouble()!! + if (isReverse) { + angle += 180 + } + radian = Math.toRadians(angle) + } else if (Geometry.TYPENAME_LINESTRING == geometry?.geometryType) { + var coordinates = geometry.coordinates + if (isReverse) { + coordinates = coordinates.reversedArray() + } + val p1: Coordinate = coordinates.get(coordinates.size - 2) + val p2: Coordinate = coordinates.get(coordinates.size - 1) + // 计算线段的方向 + radian = Angle.angle(p1, p2) + point = p2 + } + + // 计算偏移距离 + val dx: Double = GeometryTools.convertDistanceToDegree(3.0, geometry?.coordinate?.y!!) * Math.cos(radian) + val dy: Double = GeometryTools.convertDistanceToDegree(3.0, geometry?.coordinate?.y!!) * Math.sin(radian) + + val coorEnd = Coordinate(point.getX() + dy, point.getY() - dx) + + val angleReference = ReferenceEntity() + angleReference.renderEntityId = renderEntity.id + angleReference.name = "${renderEntity.name}参考方向" + angleReference.table = renderEntity.table + // 与原有方向指向平行的线 + angleReference.geometry = GeometryTools.createLineString(arrayOf(point, coorEnd)).toString() + angleReference.properties["qi_table"] = renderEntity.table + angleReference.properties["type"] = "angle" + Realm.getDefaultInstance().insert(angleReference) } fun addAngleFromGeometry(renderEntity: RenderEntity): String { @@ -143,6 +230,7 @@ class ImportPreProcess { } } + /** * 自动生成普通交限的参考数据 * */ @@ -191,6 +279,58 @@ class ImportPreProcess { Realm.getDefaultInstance().insert(angleReference) } + /** + * 自动生成电子眼的参考数据 + * */ + fun generateElectronicEyeRerference(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) + } + + + /** + * 生成默认道路名数据 + * */ fun generateRoadName(renderEntity: RenderEntity) { // LinkName的真正名称数据,是保存在properties的shapeList中的,因此需要解析shapeList数据 var shape :JSONObject? = null @@ -217,4 +357,39 @@ class ImportPreProcess { renderEntity.properties["name"] = "" } } + + /** + * 生成电子眼对应的渲染名称 + * */ + fun generateElectronName(renderEntity: RenderEntity) { + // 解析电子眼的kind,将其转换为渲染的简要名称 + var shape :JSONObject? = null + if (renderEntity.properties.containsKey("kind")) { + renderEntity.properties["name"] = code2NameMap.electronEyeKindMap[renderEntity.properties["kind"].toString().toInt()] + } else { + renderEntity.properties["name"] = "" + } + } + + /** + * 生成默认路口数据的参考数据 + * */ + fun generateIntersectionReference(renderEntity: RenderEntity) { + // 路口数据的其他点位,是保存在nodeList对应的数组下 + if (renderEntity.properties.containsKey("nodeList")) { + val nodeListJsonArray: JSONArray = JSONArray(renderEntity.properties["nodeList"]) + for (i in 0 until nodeListJsonArray.length()) { + val nodeJSONObject = nodeListJsonArray.getJSONObject(i) + val intersectionReference = ReferenceEntity() + intersectionReference.renderEntityId = renderEntity.id + intersectionReference.name = "${renderEntity.name}参考点" + intersectionReference.table = renderEntity.table + // 与原有方向指向平行的线 + intersectionReference.geometry = GeometryTools.createGeometry(nodeJSONObject["geometry"].toString()).toString() + intersectionReference.properties["qi_table"] = renderEntity.table + intersectionReference.properties["type"] = "node" + Realm.getDefaultInstance().insert(intersectionReference) + } + } + } } \ No newline at end of file diff --git a/collect-library/src/main/assets/editormarker.xml b/collect-library/src/main/assets/editormarker.xml index fadfe6ab..e4be6b84 100644 --- a/collect-library/src/main/assets/editormarker.xml +++ b/collect-library/src/main/assets/editormarker.xml @@ -174,7 +174,8 @@ - + @@ -1799,13 +1800,41 @@ symbol-width="76"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java index e0855bb1..44271835 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java +++ b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryTools.java @@ -293,7 +293,7 @@ public class GeometryTools { * @param coords [] * @return Geometry */ - public LineString createLineString(Coordinate[] coords) { + public static LineString createLineString(Coordinate[] coords) { LineString lineString = null; GeometryFactory factory = new GeometryFactory(); lineString = factory.createLineString(coords); diff --git a/vtm b/vtm index 1ee201a4..c6ba77aa 160000 --- a/vtm +++ b/vtm @@ -1 +1 @@ -Subproject commit 1ee201a41f78f169873848209a3f3bdac36f185a +Subproject commit c6ba77aa0eb90a84fb19377706eb6792ec4a42b6