This commit is contained in:
qiji4215 2023-04-21 17:20:54 +08:00
commit 51bd47842a
5 changed files with 132 additions and 8 deletions

View File

@ -15,6 +15,7 @@ import org.locationtech.spatial4j.distance.DistanceUtils
import org.oscim.core.GeoPoint
import org.oscim.core.MercatorProjection
import javax.inject.Inject
import kotlin.streams.toList
class RealmOperateHelper() {
@ -25,29 +26,126 @@ class RealmOperateHelper() {
* @param point 点位经纬度信息
* @param buffer 点位的外扩距离
* @param bufferType 点位外扩距离的单位 -Meter像素-PIXEL
* @param order 是否需要排序
* @param sort 是否需要排序
* */
suspend fun queryLink(point: Point, buffer: Double = DEFAULT_BUFFER, bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE, order: Boolean = false): MutableList<RenderEntity> {
suspend fun queryLink(point: Point, buffer: Double = DEFAULT_BUFFER, bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE, sort: Boolean = false): MutableList<RenderEntity> {
val result = mutableListOf<RenderEntity>()
withContext(Dispatchers.IO) {
val polygon = getPolygonFromPoint(point, buffer, bufferType)
// 根据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)
// 查询realm中对应tile号的数据
Realm.getDefaultInstance().where(RenderEntity::class.java).equalTo("table", "HAD_LINK")
val realmList = Realm.getDefaultInstance().where(RenderEntity::class.java)
.equalTo("table", "HAD_LINK")
.and()
.rawPredicate("tileX>=$xStart and tileX<=$xEnd and tileY>=$yStart and tileY<=$yEnd")
.findAll()
// 将获取到的数据和查询的polygon做相交只返回相交的数据
val queryResult = realmList?.stream()?.filter {
polygon.intersects(it.wkt)
}?.toList()
queryResult?.let {
result.addAll(queryResult)
}
if (sort) {
result.clear()
result.addAll(sortRenderEntity(point, result))
}
}
return mutableListOf()
return result
}
/**
* 根据当前点位查询匹配的除Link外的其他要素数据
* @param point 点位经纬度信息
* @param buffer 点位的外扩距离
* @param bufferType 点位外扩距离的单位 -Meter像素-PIXEL
* @param sort 是否需要排序
* */
suspend fun queryElement(point: Point, buffer: Double = DEFAULT_BUFFER, bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE, sort: Boolean = false): MutableList<RenderEntity> {
val result = mutableListOf<RenderEntity>()
withContext(Dispatchers.IO) {
val polygon = getPolygonFromPoint(point, buffer, bufferType)
// 根据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)
// 查询realm中对应tile号的数据
val realmList = Realm.getDefaultInstance().where(RenderEntity::class.java)
.notEqualTo("table", "HAD_LINK")
.and()
.rawPredicate("tileX>=$xStart and tileX<=$xEnd and tileY>=$yStart and tileY<=$yEnd")
.findAll()
// 将获取到的数据和查询的polygon做相交只返回相交的数据
val queryResult = realmList?.stream()?.filter {
polygon.intersects(it.wkt)
}?.toList()
queryResult?.let {
result.addAll(queryResult)
}
if (sort) {
result.clear()
result.addAll(sortRenderEntity(point, result))
}
}
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>()
withContext(Dispatchers.IO) {
val realmList = Realm.getDefaultInstance().where(RenderEntity::class.java)
.notEqualTo("table", "HAD_LINK")
.and()
.equalTo("properties['LINK_PID']", linkPid)
.findAll()
result.addAll(realmList)
}
return result
}
/**
* 根据给定的点位对数据排序
* @param point 点位经纬度信息
* @param unSortList 未排序的数据
* @return 排序后的数据
* */
fun sortRenderEntity(point: Point, unSortList: MutableList<RenderEntity>): List<RenderEntity> {
val sortList = unSortList.stream().sorted { renderEntity, renderEntity2 ->
val near = point.distance(renderEntity.wkt) - point.distance(renderEntity2.wkt)
if (near<0) -1 else 1
}.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) { // 如果单位是米
// 计算米和地球角度之间的关系在Spatial4J中经度和纬度的单位是度而不是米。因此将距离从米转换为度需要使用一个转换因子这个转换因子是由地球的周长和360度之间的比例计算得出的。
// 在这个例子中使用的转换因子是111000.0这是因为地球的周长约为40075公里而每个经度的距离大约是地球周长的1/360因此每个经度的距离约为111.32公里
val distanceDegrees = DistanceUtils.dist2Degrees(buffer, DistanceUtils.EARTH_MEAN_RADIUS_KM) * 111000.0
val distanceDegrees = GeometryTools.convertDistanceToDegree(buffer, point.y)
// 计算外扩矩形
BufferOp.bufferOp(point, distanceDegrees) as Polygon
} else { // 如果单位是像素,需要根据当前屏幕像素计算出经纬度变化

View File

@ -224,7 +224,9 @@ class PersonalCenterViewModel @Inject constructor(
fun readRealmData() {
viewModelScope.launch(Dispatchers.IO) {
realmOperateHelper.queryLink(GeometryTools.createPoint(115.685817,28.62759))
// val result = realmOperateHelper.queryLink(GeometryTools.createPoint(115.685817,28.62759))
val result = realmOperateHelper.queryLinkByLinkPid("84206617008217069")
Log.d("xiaoyan", result.toString())
}
}
}

View File

@ -6,6 +6,7 @@ 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
@ -28,7 +29,15 @@ open class RenderEntity(): RealmObject() {
// 根据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
var properties: RealmDictionary<String?> = RealmDictionary()
val tileX: RealmSet<Int> = RealmSet() // x方向的tile编码
val tileY: RealmSet<Int> = RealmSet() // y方向的tile编码

View File

@ -1566,4 +1566,19 @@ public class GeometryTools {
return earthRadiusMeters * acos; // 最终结果
}
/**
* 将平面坐标系中的距离以米为单位转换为地理坐标系中的角度以度为单位
*
* @param distance 平面坐标系中的距离单位
* @param latitude 点的纬度单位
* @return 对应的地理坐标系中的距离单位
*/
private static final double EARTH_RADIUS = 6371000.0;
public static double convertDistanceToDegree(double distance, double latitude) {
double radianDistance = distance / EARTH_RADIUS;
double radianLatitude = Math.toRadians(latitude);
double radianDegree = 2 * Math.asin(Math.sin(radianDistance / 2) / Math.cos(radianLatitude));
return Math.toDegrees(radianDegree);
}
}

Binary file not shown.