OneMapQS/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt
2023-09-21 10:12:03 +08:00

484 lines
18 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.navinfo.omqs.db
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.navinfo.collect.library.data.entity.HadLinkDvoBean
import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.collect.library.data.entity.RenderEntity
import com.navinfo.collect.library.data.entity.RenderEntity.Companion.LinkTable
import com.navinfo.collect.library.enums.DataCodeEnum
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.GeometryToolsKt
import com.navinfo.collect.library.utils.MapParamUtils
import com.navinfo.omqs.Constant
import io.realm.Realm
import io.realm.RealmModel
import io.realm.RealmQuery
import org.locationtech.jts.geom.*
import org.locationtech.jts.operation.buffer.BufferOp
import org.oscim.core.GeoPoint
import org.oscim.core.MercatorProjection
import javax.inject.Inject
import kotlin.streams.toList
class RealmOperateHelper() {
@Inject
lateinit var niMapController: NIMapController
private var isUpdate: Boolean = false
/**
* 根据当前点位查询匹配的Link数据
* @param point 点位经纬度信息
* @param buffer 点位的外扩距离
* @param bufferType 点位外扩距离的单位: 米-Meter像素-PIXEL
* @param sort 是否需要排序
* */
@RequiresApi(Build.VERSION_CODES.N)
suspend fun queryLink(
point: GeoPoint,
buffer: Double = DEFAULT_BUFFER,
bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE,
sort: Boolean = true
): MutableList<RenderEntity> {
val result = mutableListOf<RenderEntity>()
val polygon = getPolygonFromPoint(
GeometryTools.createPoint(point.longitude, point.latitude),
buffer,
bufferType
)
// 根据polygon查询相交的tile号
val tileXSet = mutableSetOf<Int>()
GeometryToolsKt.getTileXByGeometry(polygon.toString(), tileXSet)
val tileYSet = mutableSetOf<Int>()
GeometryToolsKt.getTileYByGeometry(polygon.toString(), tileYSet)
// 对tileXSet和tileYSet查询最大最小值
val xStart = tileXSet.stream().min(Comparator.naturalOrder()).orElse(null)
val xEnd = tileXSet.stream().max(Comparator.naturalOrder()).orElse(null)
val yStart = tileYSet.stream().min(Comparator.naturalOrder()).orElse(null)
val yEnd = tileYSet.stream().max(Comparator.naturalOrder()).orElse(null)
// 查询realm中对应tile号的数据
val realm = getSelectTaskRealmInstance()
val realmList =
getSelectTaskRealmTools(RenderEntity::class.java, false)
.equalTo("table", DataCodeEnum.OMDB_LINK_DIRECT.name)
.greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd)
.greaterThanOrEqualTo("tileY", yStart)
.lessThanOrEqualTo("tileY", yEnd)
.findAll()
// 将获取到的数据和查询的polygon做相交只返回相交的数据
val dataList = realm.copyFromRealm(realmList)
realm.close()
val queryResult = dataList?.stream()?.filter {
polygon.intersects(it.wkt)
}?.toList()
queryResult?.let {
if (sort) {
result.addAll(
sortRenderEntity(
GeometryTools.createPoint(
point.longitude,
point.latitude
), it
)
)
} else {
result.addAll(it)
}
}
return result
}
/**
* 根据当前点位查询匹配的Link数据
* @param point 点位经纬度信息
* @param buffer 点位的外扩距离
* @param bufferType 点位外扩距离的单位: 米-Meter像素-PIXEL
* @param sort 是否需要排序
* */
@RequiresApi(Build.VERSION_CODES.N)
suspend fun queryLine(
point: GeoPoint,
buffer: Double = DEFAULT_BUFFER,
bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE,
table: String,
sort: Boolean = true
): MutableList<RenderEntity> {
val result = mutableListOf<RenderEntity>()
val polygon = getPolygonFromPoint(
GeometryTools.createPoint(point.longitude, point.latitude),
buffer,
bufferType
)
// 根据polygon查询相交的tile号
val tileXSet = mutableSetOf<Int>()
GeometryToolsKt.getTileXByGeometry(polygon.toString(), tileXSet)
val tileYSet = mutableSetOf<Int>()
GeometryToolsKt.getTileYByGeometry(polygon.toString(), tileYSet)
// 对tileXSet和tileYSet查询最大最小值
val xStart = tileXSet.stream().min(Comparator.naturalOrder()).orElse(null)
val xEnd = tileXSet.stream().max(Comparator.naturalOrder()).orElse(null)
val yStart = tileYSet.stream().min(Comparator.naturalOrder()).orElse(null)
val yEnd = tileYSet.stream().max(Comparator.naturalOrder()).orElse(null)
// 查询realm中对应tile号的数据
val realm = getSelectTaskRealmInstance()
val realmList = getSelectTaskRealmTools(RenderEntity::class.java, true)
.equalTo("table", table)
.greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd)
.greaterThanOrEqualTo("tileY", yStart)
.lessThanOrEqualTo("tileY", yEnd)
.findAll()
// 将获取到的数据和查询的polygon做相交只返回相交的数据
val dataList = realm.copyFromRealm(realmList)
val queryResult = dataList?.stream()?.filter {
polygon.intersects(it.wkt)
}?.toList()
queryResult?.let {
if (sort) {
result.addAll(
sortRenderEntity(
GeometryTools.createPoint(
point.longitude,
point.latitude
), it
)
)
} else {
result.addAll(it)
}
}
return result
}
suspend fun captureTaskLink(
point: GeoPoint,
buffer: Double = DEFAULT_BUFFER,
bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE,
): HadLinkDvoBean? {
val polygon = getPolygonFromPoint(
GeometryTools.createPoint(point.longitude, point.latitude),
buffer,
bufferType
)
val realm = getRealmDefaultInstance()
try {
val realmList = getRealmTools(HadLinkDvoBean::class.java).findAll()
var linkBean: HadLinkDvoBean? = null
var nearLast: Double = 99999.99
for (link in realmList) {
if (polygon.intersects(GeometryTools.createGeometry(link.geometry))) {
val near = point.distance(GeometryTools.createGeoPoint(link.geometry))
if (near < nearLast) {
nearLast = near
linkBean = link
}
}
}
if (linkBean != null)
return realm.copyFromRealm(linkBean)
} catch (e: Exception) {
} finally {
realm.close()
}
return null
}
suspend fun queryLink(linkPid: String): RenderEntity? {
var link: RenderEntity? = null
val realm = getSelectTaskRealmInstance()
val realmR =
realm.where(RenderEntity::class.java).equalTo("table", "OMDB_RD_LINK_KIND")
.equalTo("properties['${LinkTable.linkPid}']", linkPid).findFirst()
if (realmR != null) {
link = realm.copyFromRealm(realmR)
}
realm.close()
return link
}
/**
* 根据markid查询获取对应数据
* @param markId
* */
suspend fun queryQcRecordBean(markId: String): QsRecordBean? {
var qsRecordBean: QsRecordBean? = null
val realm = getRealmDefaultInstance()
val realmR = getRealmTools(QsRecordBean::class.java)
.equalTo("table", "QsRecordBean").equalTo("id", markId).findFirst()
if (realmR != null) {
qsRecordBean = realm.copyFromRealm(realmR)
}
realm.close()
return qsRecordBean
}
suspend fun queryLinkToMutableRenderEntityList(linkPid: String): MutableList<RenderEntity>? {
val resultList = mutableListOf<RenderEntity>()
val realm = getSelectTaskRealmInstance()
val realmR = getSelectTaskRealmTools(RenderEntity::class.java, true)
.equalTo("properties['${LinkTable.linkPid}']", linkPid).findAll()
val dataList = realm.copyFromRealm(realmR)
dataList.forEach {
resultList.add(it)
}
realm.close()
return resultList
}
/**
* 根据当前点位查询匹配的除Link外的其他要素数据
* @param point 点位经纬度信息
* @param buffer 点位的外扩距离
* @param bufferType 点位外扩距离的单位: 米-Meter像素-PIXEL
* @param sort 是否需要排序
* */
@RequiresApi(Build.VERSION_CODES.N)
suspend fun queryElement(
point: Point,
buffer: Double = DEFAULT_BUFFER,
bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE,
catchAll: Boolean = true,
sort: Boolean = true
): MutableList<RenderEntity> {
val result = mutableListOf<RenderEntity>()
val polygon = getPolygonFromPoint(point, buffer, bufferType)
niMapController.lineHandler.showLine(polygon.toText())
// 根据polygon查询相交的tile号
val tileXSet = mutableSetOf<Int>()
tileXSet.toString()
GeometryToolsKt.getTileXByGeometry(polygon.toString(), tileXSet)
val tileYSet = mutableSetOf<Int>()
GeometryToolsKt.getTileYByGeometry(polygon.toString(), tileYSet)
// 对tileXSet和tileYSet查询最大最小值
val xStart = tileXSet.stream().min(Comparator.naturalOrder()).orElse(null)
val xEnd = tileXSet.stream().max(Comparator.naturalOrder()).orElse(null)
val yStart = tileYSet.stream().min(Comparator.naturalOrder()).orElse(null)
val yEnd = tileYSet.stream().max(Comparator.naturalOrder()).orElse(null)
val realm = getSelectTaskRealmInstance()
var realmList = mutableListOf<RenderEntity>()
if (catchAll) {
// 查询realm中对应tile号的数据
realmList = getSelectTaskRealmTools(RenderEntity::class.java, false)
.greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd)
.greaterThanOrEqualTo("tileY", yStart)
.lessThanOrEqualTo("tileY", yEnd)
.findAll()
} else {
// 查询realm中对应tile号的数据
if (Constant.CATCH_ALL) {
realmList = getSelectTaskRealmTools(RenderEntity::class.java, false)
.greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd)
.greaterThanOrEqualTo("tileY", yStart)
.lessThanOrEqualTo("tileY", yEnd)
.findAll()
} else {
realmList = getSelectTaskRealmTools(RenderEntity::class.java, false)
.greaterThanOrEqualTo("tileX", xStart)
.lessThanOrEqualTo("tileX", xEnd)
.greaterThanOrEqualTo("tileY", yStart)
.lessThanOrEqualTo("tileY", yEnd)
.greaterThan("catchEnable", 0)
.findAll()
}
}
// 将获取到的数据和查询的polygon做相交只返回相交的数据
val queryResult = realmList?.stream()?.filter {
polygon.intersects(it.wkt)
}?.toList()
queryResult?.let {
if (sort) {
result.addAll(sortRenderEntity(point, realm.copyFromRealm(it)))
} else {
result.addAll(realm.copyFromRealm(it))
}
}
realm.close()
return result
}
/**
* 根据linkPid查询关联的要素除去Link数据
* @param point 点位经纬度信息
* @param buffer 点位的外扩距离
* @param bufferType 点位外扩距离的单位: 米-Meter像素-PIXEL
* @param sort 是否需要排序
* */
suspend fun queryLinkByLinkPid(linkPid: String): MutableList<RenderEntity> {
val result = mutableListOf<RenderEntity>()
val realm = getSelectTaskRealmInstance()
val realmList = getSelectTaskRealmTools(RenderEntity::class.java, false)
.notEqualTo("table", DataCodeEnum.OMDB_RD_LINK_KIND.name)
.equalTo("properties['${LinkTable.linkPid}']", linkPid)
.findAll()
result.addAll(realm.copyFromRealm(realmList))
realm.close()
return result
}
/**
* 根据给定的点位对数据排序
* @param point 点位经纬度信息
* @param unSortList 未排序的数据
* @return 排序后的数据
* */
@RequiresApi(Build.VERSION_CODES.N)
fun sortRenderEntity(point: Point, unSortList: List<RenderEntity>): List<RenderEntity> {
val sortList = unSortList.stream().sorted { renderEntity, renderEntity2 ->
point.distance(renderEntity.wkt).compareTo(point.distance(renderEntity2.wkt))
}.toList()
return sortList
}
private fun getPolygonFromPoint(
point: Point,
buffer: Double = DEFAULT_BUFFER,
bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE
): Polygon {
// 首先计算当前点位的buffer组成的geometry
val wkt: Polygon = if (bufferType == BUFFER_TYPE.METER) { // 如果单位是米
val distanceDegrees = GeometryTools.convertDistanceToDegree(buffer, point.y)
// 计算外扩矩形
BufferOp.bufferOp(point, distanceDegrees) as Polygon
} else { // 如果单位是像素,需要根据当前屏幕像素计算出经纬度变化
val currentMapScale = niMapController.mMapView.vtmMap.mapPosition.scale
// 转换为屏幕坐标
val pixelPoint =
MercatorProjection.getPixelWithScale(
GeoPoint(point.y, point.x),
currentMapScale
)
// 将屏幕坐标外扩指定距离
// 计算外扩矩形
val envelope = Envelope(
MercatorProjection.pixelXToLongitudeWithScale(
pixelPoint.x - buffer,
currentMapScale
),
MercatorProjection.pixelXToLongitudeWithScale(
pixelPoint.x + buffer,
currentMapScale
),
MercatorProjection.pixelYToLatitudeWithScale(
pixelPoint.y - buffer,
currentMapScale
),
MercatorProjection.pixelYToLatitudeWithScale(
pixelPoint.y + buffer,
currentMapScale
),
)
// 将Envelope对象转换为Polygon对象
val geometryFactory = GeometryFactory()
val coordinates = arrayOfNulls<Coordinate>(5)
coordinates[0] = Coordinate(envelope.minX, envelope.minY)
coordinates[1] = Coordinate(envelope.minX, envelope.maxY)
coordinates[2] = Coordinate(envelope.maxX, envelope.maxY)
coordinates[3] = Coordinate(envelope.maxX, envelope.minY)
coordinates[4] = coordinates[0]
geometryFactory.createPolygon(coordinates)
}
Log.d("queryLink", wkt.toString())
return wkt
}
/**
* 默认的数据库,用于存储任务、作业数据
* @param clazz 查询表
* @param enableSql
* */
fun <E : RealmModel> getRealmTools(clazz: Class<E>): RealmQuery<E> {
return getRealmDefaultInstance().where(clazz)
}
fun getRealmDefaultInstance(): Realm {
if (isUpdate) {
Log.e("jingo", "数据库更新")
if (Realm.getDefaultInstance().isInTransaction) {
Realm.getDefaultInstance().cancelTransaction()
Log.e("jingo", "数据库正在事物,需要退出当前事物")
}
Realm.getDefaultInstance().refresh()
isUpdate = false;
}
return Realm.getDefaultInstance()
}
fun <E : RealmModel> getSelectTaskRealmTools(
clazz: Class<E>,
enableSql: Boolean
): RealmQuery<E> {
return if (MapParamUtils.getDataLayerEnum() != null) {
if (enableSql) {
var sql =
" enable${MapParamUtils.getDataLayerEnum().sql}"
getSelectTaskRealmInstance().where(clazz).rawPredicate(sql)
} else {
getSelectTaskRealmInstance().where(clazz)
}
} else {
getSelectTaskRealmInstance().where(clazz)
}
}
fun getSelectTaskRealmInstance(): Realm {
if (isUpdate) {
Log.e("jingo", "数据库更新")
if (Realm.getInstance(Constant.currentSelectTaskConfig).isInTransaction) {
Realm.getInstance(Constant.currentSelectTaskConfig).cancelTransaction()
Log.e("jingo", "数据库正在事物,需要退出当前事物")
}
Realm.getInstance(Constant.currentSelectTaskConfig).refresh()
isUpdate = false;
}
return Realm.getInstance(Constant.currentSelectTaskConfig)
}
fun updateRealmDefaultInstance() {
isUpdate = true
}
}
enum class BUFFER_TYPE(val index: Int) {
METER(0)/*米*/, PIXEL(1)/*像素*/;
fun getBufferTypeByIndex(index: Int): BUFFER_TYPE {
for (item in BUFFER_TYPE.values()) {
if (item.index == index) {
return item;
}
}
return METER
}
}
private const val DEFAULT_BUFFER: Double = 15.0
private val DEFAULT_BUFFER_TYPE = BUFFER_TYPE.METER