From 0a9376d398365999a8bc2ed1f4872b03f67209d1 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Wed, 19 Apr 2023 17:32:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E7=94=9F=E6=88=90json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/navinfo/omqs/bean/ImportConfig.kt | 9 ++- .../personalcenter/PersonalCenterViewModel.kt | 38 ++++++++++--- .../collect/library/data/entity/OMDBEntity.kt | 57 ++++++++++++++++++- 3 files changed, 94 insertions(+), 10 deletions(-) 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 4dc8304f..9d26031d 100644 --- a/app/src/main/java/com/navinfo/omqs/bean/ImportConfig.kt +++ b/app/src/main/java/com/navinfo/omqs/bean/ImportConfig.kt @@ -1,5 +1,12 @@ package com.navinfo.omqs.bean + class ImportConfig { - var tables: MutableList = mutableListOf() + var tables: MutableList = mutableListOf() +} + +class TableInfo { + val table: String = "" + val code: Int = 0 + val name: String = "" } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt index d96f9b67..e8e26f40 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt @@ -5,7 +5,10 @@ import android.net.Uri import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.blankj.utilcode.util.FileIOUtils import com.blankj.utilcode.util.UriUtils +import com.google.gson.Gson +import com.navinfo.collect.library.data.entity.HAD_LINK import com.navinfo.collect.library.data.entity.OMDBEntity import com.navinfo.omqs.bean.ScProblemTypeBean import com.navinfo.omqs.bean.ScRootCauseAnalysisBean @@ -35,24 +38,43 @@ class PersonalCenterViewModel @Inject constructor( suspend fun importOMDBData(importOMDBHelper: ImportOMDBHelper) { Log.d("OMQSApplication", "开始导入数据") // Realm.getDefaultInstance().beginTransaction() - for (table in importOMDBHelper.openConfigFile().tables/*listOf("HAD_LINK")*/) { - importOMDBHelper.getOMDBTableData(table).collect { + val gson = Gson() + for (tableName in listOf("HAD_LINK", "HAD_LINK_SPEEDLIMIT", "HAD_LINK_SPEEDLIMIT_COND", "HAD_LINK_SPEEDLIMIT_VAR")/*listOf("HAD_LINK")*/) { + importOMDBHelper.getOMDBTableData(tableName).collect { + val hadLinkFile = File(importOMDBHelper.omdbFile, "HAD_LINK.txt") for (map in it) { + if ("HAD_LINK" == tableName) { + // 根据HAD_Link生成json文件 + val hadLink = HAD_LINK() + hadLink.LINK_PID = map["LINK_PID"].toString() + hadLink.MESH = map["MESH"].toString() + hadLink.S_NODE_PID = map["S_NODE_PID"].toString() + hadLink.E_NODE_PID = map["E_NODE_PID"].toString() + hadLink.GEOMETRY = map["GEOMETRY"].toString() + // 将该数据写入到对应的txt文件 + FileIOUtils.writeFileFromString(hadLinkFile, gson.toJson(hadLink)+"\r", true) + } val properties = RealmDictionary() for (entry in map.entries) { properties.putIfAbsent(entry.key, entry.value.toString()) } - // 将读取到的sqlite数据插入到Realm中 - Realm.getDefaultInstance().insert(OMDBEntity(table, properties)) - // 将读取到的数据写入到json中 - +// // 将读取到的sqlite数据插入到Realm中 +// Realm.getDefaultInstance().insert(OMDBEntity(tableName, properties)) } } } // Realm.getDefaultInstance().commitTransaction() - // 数据导入结束后,开始生成渲染表所需的json文件,并生成压缩包 - +// val gson = Gson() +// // 数据导入结束后,开始生成渲染表所需的json文件,并生成压缩包 +// for (table in importOMDBHelper.openConfigFile().tables/*listOf("HAD_LINK")*/) { +// val omdbList = Realm.getDefaultInstance().where(OMDBEntity::class.java).equalTo("table", table.table).findAll() +// val outputFile = File(importOMDBHelper.omdbFile, "${table.table}.txt") +// // 将读取到的数据转换为json数据文件 +// for (omdb in omdbList) { +// FileIOUtils.writeFileFromString(outputFile, gson.toJson(omdb)) +// } +// } Log.d("OMQSApplication", "导入数据完成") } diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OMDBEntity.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OMDBEntity.kt index 8cfadb83..923c7bf7 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OMDBEntity.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/OMDBEntity.kt @@ -14,4 +14,59 @@ open class OMDBEntity(): RealmObject() { this.table = table this.properties = properties } -} \ No newline at end of file +} + +class HAD_LINK() { + var LINK_PID: String = "" + var MESH: String = "" + var S_NODE_PID: String = "" + var E_NODE_PID: String = "" + var GEOMETRY: String = "" +} + +class HAD_LINK_KIND() { + var LINK_PID: String = "" + var MESH: String = "" + var KIND: Int = 0 + var GEOMETRY: String = "" +} + +class HAD_LINK_DIRECT() { + var LINK_PID: String = "" + var MESH: String = "" + var DIRECT: Int = 0 + var GEOMETRY: String = "" +} + +class HAD_SPEEDLIMIT() { + var SPEED_ID: String = "" + var MESH: String = "" + var LINK_PID: String = "" + var GEOMETRY: String = "" + var DIRECT: Int = 0 + var SPEED_FLAG: Int = 0 + var MAX_SPEED: Int = 0 + var MIN_SPEED: Int = 0 +} + +class HAD_SPEEDLIMIT_COND() { + var SPEED_COND_ID: String = "" + var MESH: String = "" + var LINK_PID: String = "" + var GEOMETRY: String = "" + var DIRECT: Int = 0 + var SPEED_FLAG: Int = 0 + var MAX_SPEED: Int = 0 + var SPEED_DEPENDENT: Int = 0 + var VEHICLE_TYPE: Int = 0 + var VALID_PERIOD: String = "" +} + +class HAD_SPEEDLIMIT_VAR() { + var SPEED_VAR_ID: String = "" + var MESH: String = "" + var LINK_PID: String = "" + var GEOMETRY: String = "" + var DIRECT: Int = 0 + var LOCATION: String = "" +} From 7649777bb8edf152ba024dc208be61310cdb4ea5 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Fri, 21 Apr 2023 14:20:58 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20Realm=E5=A2=9E=E5=8A=A0=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2Link=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/navinfo/omqs/OMQSApplication.kt | 2 +- .../com/navinfo/omqs/db/ImportOMDBHelper.kt | 50 +++++++- .../com/navinfo/omqs/db/RealmOperateHelper.kt | 94 ++++++++++++++ .../com/navinfo/omqs/hilt/GlobalModule.kt | 7 ++ .../navinfo/omqs/hilt/MainActivityModule.kt | 6 + .../personalcenter/PersonalCenterFragment.kt | 23 +++- .../personalcenter/PersonalCenterViewModel.kt | 119 ++++++++++++++++-- .../main/res/menu/personal_center_menu.xml | 8 ++ collect-library/build.gradle | 4 +- .../library/data/entity/RenderEntity.kt | 6 +- .../collect/library/utils/GeometryTools.java | 20 +++ .../collect/library/utils/GeometryToolsKt.kt | 8 +- navinfo.jks | Bin 0 -> 2066 bytes 13 files changed, 323 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt create mode 100644 navinfo.jks diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt index 556829bb..fd8928cd 100644 --- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt +++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt @@ -18,7 +18,7 @@ class OMQSApplication : Application() { FileManager.initRootDir(this) Realm.init(this) val password = "encryp".encodeToByteArray().copyInto(ByteArray(64)) - // 70617373776f72640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Log.d("OMQSApplication", "密码是: ${byteArrayToHexString(password)}") val config = RealmConfiguration.Builder() .directory(File(Constant.DATA_PATH)) diff --git a/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt b/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt index f29fd87b..adef0eaa 100644 --- a/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt +++ b/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt @@ -6,7 +6,11 @@ import androidx.core.database.getBlobOrNull import androidx.core.database.getFloatOrNull import androidx.core.database.getIntOrNull import androidx.core.database.getStringOrNull +import com.blankj.utilcode.util.FileIOUtils +import com.blankj.utilcode.util.ZipUtils import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.navinfo.collect.library.data.entity.RenderEntity import com.navinfo.omqs.bean.ImportConfig import com.navinfo.omqs.hilt.ImportOMDBHiltFactory import com.navinfo.omqs.hilt.OMDBDataBaseHiltFactory @@ -90,6 +94,46 @@ class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val cont } } + /** + * 从zip文件中导入数据到Realm中 + * @param omdbZipFile omdb数据抽取生成的Zip文件 + * @param configFile 对应的配置文件 + * */ + suspend fun importOmdbZipFile(omdbZipFile: File): Flow>> = withContext(Dispatchers.IO) { + val importConfig = openConfigFile() + val unZipFolder = File(omdbZipFile.parentFile, "result") + flow>> { + if (unZipFolder.exists()) { + unZipFolder.deleteRecursively() + } + unZipFolder.mkdirs() + // 开始解压zip文件 + val unZipFiles = ZipUtils.unzipFile(omdbZipFile, unZipFolder) + // 遍历解压后的文件,读取该数据返回 + for (txtFile in unZipFiles) { + val listResult: MutableList> = mutableListOf() + // 根据文件名称获取对应的配置 + val currentConfig=importConfig.tables.find { + txtFile.name.substring(0, txtFile.name.lastIndexOf("."))==it.table + } + val list = FileIOUtils.readFile2List(txtFile, "UTF-8") + // 将list数据转换为map + for (line in list) { + val map = gson.fromJson>(line, object : TypeToken>() {}.type) + .toMutableMap() + currentConfig?.let { + map["QItable"] = currentConfig.table + map["QIname"] = currentConfig.name + map["QIcode"] = currentConfig.code + listResult.add(map) + } + } + // 1个文件发送一次flow流 + emit(listResult) + } + } + } + // 获取指定数据表的列名 fun getColumns(db: SQLiteDatabase, tableName: String): List { val columns = mutableListOf() @@ -110,9 +154,13 @@ class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val cont } } } - cursor.close() return columns } + /** + * 预处理渲染要素,某些要素需要对数据做二次处理 + * */ + fun performRenderEntity(renderEntity: RenderEntity) { + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt b/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt new file mode 100644 index 00000000..e4b1d608 --- /dev/null +++ b/app/src/main/java/com/navinfo/omqs/db/RealmOperateHelper.kt @@ -0,0 +1,94 @@ +package com.navinfo.omqs.db + +import android.util.Log +import com.navinfo.collect.library.data.entity.RenderEntity +import com.navinfo.collect.library.map.NIMapController +import com.navinfo.collect.library.utils.GeometryTools +import com.navinfo.collect.library.utils.GeometryToolsKt +import io.realm.Realm +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.locationtech.jts.geom.* +import org.locationtech.jts.operation.buffer.BufferOp +import org.locationtech.spatial4j.context.SpatialContext +import org.locationtech.spatial4j.distance.DistanceUtils +import org.oscim.core.GeoPoint +import org.oscim.core.MercatorProjection +import javax.inject.Inject + + +class RealmOperateHelper() { + @Inject + lateinit var niMapController: NIMapController + /** + * 根据当前点位查询匹配的Link数据 + * @param point 点位经纬度信息 + * @param buffer 点位的外扩距离 + * @param bufferType 点位外扩距离的单位: 米-Meter,像素-PIXEL + * @param order 是否需要排序 + * */ + suspend fun queryLink(point: Point, buffer: Double = DEFAULT_BUFFER, bufferType: BUFFER_TYPE = DEFAULT_BUFFER_TYPE, order: Boolean = false): MutableList { + withContext(Dispatchers.IO) { + val polygon = getPolygonFromPoint(point, buffer, bufferType) + // 根据polygon查询相交的tile号 + val tileXSet = mutableSetOf() + GeometryToolsKt.getTileXByGeometry(polygon.toString(), tileXSet) + val tileYSet = mutableSetOf() + GeometryToolsKt.getTileYByGeometry(polygon.toString(), tileYSet) + + // 查询realm中对应tile号的数据 + Realm.getDefaultInstance().where(RenderEntity::class.java).equalTo("table", "HAD_LINK") + } + return mutableListOf() + } + + 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 + // 计算外扩矩形 + 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(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 + } +} + +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 val DEFAULT_BUFFER: Double = 15.0 +private val DEFAULT_BUFFER_TYPE = BUFFER_TYPE.METER diff --git a/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt b/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt index c3478149..907043db 100644 --- a/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt +++ b/app/src/main/java/com/navinfo/omqs/hilt/GlobalModule.kt @@ -16,6 +16,7 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import io.realm.Realm import kotlinx.coroutines.* import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor @@ -136,4 +137,10 @@ class GlobalModule { // fun provideRealmService(context: Application): RealmCoroutineScope { // return RealmCoroutineScope(context) // } + + @Singleton + @Provides + fun provideRealmDefaultInstance(): Realm { + return Realm.getDefaultInstance() + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt b/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt index f5ba69a6..cffe1f47 100644 --- a/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt +++ b/app/src/main/java/com/navinfo/omqs/hilt/MainActivityModule.kt @@ -1,6 +1,7 @@ package com.navinfo.omqs.hilt import com.navinfo.collect.library.map.NIMapController +import com.navinfo.omqs.db.RealmOperateHelper import com.navinfo.omqs.db.RoomAppDatabase import com.navinfo.omqs.http.RetrofitNetworkServiceAPI import com.navinfo.omqs.http.offlinemapdownload.OfflineMapDownloadManager @@ -43,4 +44,9 @@ class MainActivityModule { // return MainViewModel(mapController) // } + @ActivityRetainedScoped + @Provides + fun providesRealmOperateHelper(): RealmOperateHelper { + return RealmOperateHelper() + } } \ No newline at end of file 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 9ceee4ad..b4d7f882 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 @@ -62,8 +62,7 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { when (it.itemId) { R.id.personal_center_menu_offline_map -> findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) - R.id.personal_center_menu_import_data -> { - // 用户选中导入数据,打开文件选择器,用户选择导入的数据文件目录 + R.id.personal_center_menu_obtain_data -> { // 生成数据,根据sqlite文件生成对应的zip文件 fileChooser.openChooseFileDialog(object: FileChooserCallback() { override fun onCancel(reason: String) { } @@ -72,7 +71,22 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { val file = UriUtils.uri2File(uri) // 开始导入数据 // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - val job = CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "导入数据...") { + val job = CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "生成数据...") { + val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper(requireContext(), file, File(file.parentFile, "config.json")) + viewModel.obtainOMDBZipData(importOMDBHelper) + } + } + }) + } + R.id.personal_center_menu_import_data -> { // 导入zip数据 + fileChooser.openChooseFileDialog(object: FileChooserCallback() { + override fun onCancel(reason: String) { + } + + override fun onResult(uri: Uri) { + val file = UriUtils.uri2File(uri) + // 开始导入数据 + CoroutineUtils.launchWithLoading(requireContext(), loadingMessage = "导入数据...") { val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper(requireContext(), file, File(file.parentFile, "config.json")) viewModel.importOMDBData(importOMDBHelper) } @@ -91,6 +105,9 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { } }) } + R.id.personal_center_menu_test -> { + viewModel.readRealmData() + } } true } diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt index e8e26f40..1318e3fe 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt @@ -7,20 +7,24 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.blankj.utilcode.util.FileIOUtils import com.blankj.utilcode.util.UriUtils +import com.blankj.utilcode.util.ZipUtils import com.google.gson.Gson -import com.navinfo.collect.library.data.entity.HAD_LINK -import com.navinfo.collect.library.data.entity.OMDBEntity +import com.navinfo.collect.library.data.entity.* +import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.omqs.bean.ScProblemTypeBean import com.navinfo.omqs.bean.ScRootCauseAnalysisBean import com.navinfo.omqs.db.ImportOMDBHelper +import com.navinfo.omqs.db.RealmOperateHelper import com.navinfo.omqs.db.RoomAppDatabase import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.scopes.ViewModelScoped import io.realm.Realm import io.realm.RealmDictionary import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.apache.poi.ss.usermodel.Row import org.apache.poi.ss.usermodel.WorkbookFactory +import org.locationtech.jts.geom.Point import java.io.File import java.io.FileInputStream import java.io.IOException @@ -32,17 +36,25 @@ import javax.inject.Inject class PersonalCenterViewModel @Inject constructor( private val roomAppDatabase: RoomAppDatabase ) : ViewModel() { + @Inject + lateinit var realmOperateHelper: RealmOperateHelper /** * 导入OMDB数据 * */ - suspend fun importOMDBData(importOMDBHelper: ImportOMDBHelper) { - Log.d("OMQSApplication", "开始导入数据") + suspend fun obtainOMDBZipData(importOMDBHelper: ImportOMDBHelper) { + Log.d("OMQSApplication", "开始生成数据") // Realm.getDefaultInstance().beginTransaction() val gson = Gson() - for (tableName in listOf("HAD_LINK", "HAD_LINK_SPEEDLIMIT", "HAD_LINK_SPEEDLIMIT_COND", "HAD_LINK_SPEEDLIMIT_VAR")/*listOf("HAD_LINK")*/) { + val hadLinkFile = File(importOMDBHelper.omdbFile.parentFile, "HAD_LINK.txt") + val hadLinkKindFile = File(importOMDBHelper.omdbFile.parentFile, "HAD_LINK_KIND.txt") + val hadLinkDirectFile = File(importOMDBHelper.omdbFile.parentFile, "HAD_LINK_DIRECT.txt") + val hadSpeedLimitFile = File(importOMDBHelper.omdbFile.parentFile, "HAD_SPEEDLIMIT.txt") + val hadSpeedLimitCondFile = File(importOMDBHelper.omdbFile.parentFile, "HAD_SPEEDLIMIT_COND.txt") + val hadSpeedLimitVarFile = File(importOMDBHelper.omdbFile.parentFile, "HAD_SPEEDLIMIT_VAR.txt") + + for (tableName in listOf("HAD_LINK", "HAD_SPEEDLIMIT", "HAD_SPEEDLIMIT_COND", "HAD_SPEEDLIMIT_VAR")/*listOf("HAD_LINK")*/) { importOMDBHelper.getOMDBTableData(tableName).collect { - val hadLinkFile = File(importOMDBHelper.omdbFile, "HAD_LINK.txt") - for (map in it) { + for (map in it) { if ("HAD_LINK" == tableName) { // 根据HAD_Link生成json文件 val hadLink = HAD_LINK() @@ -53,16 +65,95 @@ class PersonalCenterViewModel @Inject constructor( hadLink.GEOMETRY = map["GEOMETRY"].toString() // 将该数据写入到对应的txt文件 FileIOUtils.writeFileFromString(hadLinkFile, gson.toJson(hadLink)+"\r", true) + + val hadLinkDirect = HAD_LINK_DIRECT() + hadLinkDirect.LINK_PID = map["LINK_PID"].toString() + hadLinkDirect.MESH = map["MESH"].toString() + hadLinkDirect.DIRECT = map["DIRECT"].toString().toInt() + hadLinkDirect.GEOMETRY = map["GEOMETRY"].toString() + // 将该数据写入到对应的txt文件 + FileIOUtils.writeFileFromString(hadLinkDirectFile, gson.toJson(hadLinkDirect)+"\r", true) + + val hadLinkKind = HAD_LINK_KIND() + hadLinkKind.LINK_PID = map["LINK_PID"].toString() + hadLinkKind.MESH = map["MESH"].toString() + hadLinkKind.KIND = map["KIND"].toString().toInt() + hadLinkKind.GEOMETRY = map["GEOMETRY"].toString() + // 将该数据写入到对应的txt文件 + FileIOUtils.writeFileFromString(hadLinkKindFile, gson.toJson(hadLinkKind)+"\r", true) + } else if ("HAD_SPEEDLIMIT" == tableName) { + val hadSpeedlimit = HAD_SPEEDLIMIT() + hadSpeedlimit.SPEED_ID = map["SPEED_ID"].toString() + hadSpeedlimit.MESH = map["MESH"].toString() + hadSpeedlimit.LINK_PID = map["LINK_PID"].toString() + hadSpeedlimit.GEOMETRY = map["GEOMETRY"].toString() + hadSpeedlimit.DIRECT = map["DIRECT"].toString().toInt() + hadSpeedlimit.SPEED_FLAG = map["SPEED_FLAG"].toString().toInt() + hadSpeedlimit.MAX_SPEED = map["MAX_SPEED"].toString().toInt() + hadSpeedlimit.MIN_SPEED = map["MIN_SPEED"].toString().toInt() + // 将该数据写入到对应的txt文件 + FileIOUtils.writeFileFromString(hadSpeedLimitFile, gson.toJson(hadSpeedlimit)+"\r", true) + } else if ("HAD_SPEEDLIMIT_COND" == tableName) { + val hadSpeedlimitCond = HAD_SPEEDLIMIT_COND() + hadSpeedlimitCond.SPEED_COND_ID = map["SPEED_COND_ID"].toString() + hadSpeedlimitCond.MESH = map["MESH"].toString() + hadSpeedlimitCond.LINK_PID = map["LINK_PID"].toString() + hadSpeedlimitCond.GEOMETRY = map["GEOMETRY"].toString() + hadSpeedlimitCond.DIRECT = map["DIRECT"].toString().toInt() + hadSpeedlimitCond.SPEED_FLAG = map["SPEED_FLAG"].toString().toInt() + hadSpeedlimitCond.MAX_SPEED = map["MAX_SPEED"].toString().toInt() + hadSpeedlimitCond.SPEED_DEPENDENT = map["SPEED_DEPENDENT"].toString().toInt() + hadSpeedlimitCond.VEHICLE_TYPE = map["VEHICLE_TYPE"].toString().toInt() + hadSpeedlimitCond.VALID_PERIOD = map["VALID_PERIOD"].toString() + // 将该数据写入到对应的txt文件 + FileIOUtils.writeFileFromString(hadSpeedLimitCondFile, gson.toJson(hadSpeedlimitCond)+"\r", true) + } else if ("HAD_SPEEDLIMIT_VAR" == tableName) { + val hadSpeedlimitVar = HAD_SPEEDLIMIT_VAR() + hadSpeedlimitVar.SPEED_VAR_ID = map["SPEED_ID"].toString() + hadSpeedlimitVar.MESH = map["MESH"].toString() + hadSpeedlimitVar.LINK_PID = map["LINK_PID"].toString() + hadSpeedlimitVar.GEOMETRY = map["GEOMETRY"].toString() + hadSpeedlimitVar.DIRECT = map["DIRECT"].toString().toInt() + hadSpeedlimitVar.LOCATION = map["LOCATION"].toString() + // 将该数据写入到对应的txt文件 + FileIOUtils.writeFileFromString(hadSpeedLimitVarFile, gson.toJson(hadSpeedlimitVar)+"\r", true) } - val properties = RealmDictionary() - for (entry in map.entries) { - properties.putIfAbsent(entry.key, entry.value.toString()) - } +// val properties = RealmDictionary() +// for (entry in map.entries) { +// properties.putIfAbsent(entry.key, entry.value.toString()) +// } + // // 将读取到的sqlite数据插入到Realm中 // Realm.getDefaultInstance().insert(OMDBEntity(tableName, properties)) } } } + ZipUtils.zipFiles(mutableListOf(hadLinkFile, hadLinkKindFile, hadLinkDirectFile, hadSpeedLimitFile, hadSpeedLimitCondFile, hadSpeedLimitVarFile), File(importOMDBHelper.omdbFile.parentFile, "output.zip")) + + Log.d("OMQSApplication", "生成数据完成") + } + /** + * 导入OMDB数据 + * */ + suspend fun importOMDBData(importOMDBHelper: ImportOMDBHelper) { + Log.d("OMQSApplication", "开始导入数据") +// Realm.getDefaultInstance().beginTransaction() + importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile).collect { + Realm.getDefaultInstance().beginTransaction() + for (map in it) { // 每一个map就是Realm的一条数据 + val renderEntity = RenderEntity() + renderEntity.code = map["QIcode"].toString().toInt() + renderEntity.name = map["QIname"].toString() + renderEntity.table = map["QItable"].toString() + // 其他数据插入到Properties中 + renderEntity.geometry = map["GEOMETRY"].toString() + for (entry in map) { + renderEntity.properties[entry.key] = entry.value.toString() + } + Realm.getDefaultInstance().insert(renderEntity) + } + Realm.getDefaultInstance().commitTransaction() + } // Realm.getDefaultInstance().commitTransaction() // val gson = Gson() @@ -130,4 +221,10 @@ class PersonalCenterViewModel @Inject constructor( } } + + fun readRealmData() { + viewModelScope.launch(Dispatchers.IO) { + realmOperateHelper.queryLink(GeometryTools.createPoint(115.685817,28.62759)) + } + } } \ No newline at end of file diff --git a/app/src/main/res/menu/personal_center_menu.xml b/app/src/main/res/menu/personal_center_menu.xml index 1a7be959..3dd10a72 100644 --- a/app/src/main/res/menu/personal_center_menu.xml +++ b/app/src/main/res/menu/personal_center_menu.xml @@ -10,6 +10,10 @@ android:id="@+id/personal_center_menu_offline_map" android:icon="@drawable/baseline_map_24" android:title="离线地图" /> + + diff --git a/collect-library/build.gradle b/collect-library/build.gradle index 3cca075f..cfe6c51b 100644 --- a/collect-library/build.gradle +++ b/collect-library/build.gradle @@ -80,7 +80,7 @@ dependencies { // VTM依赖 implementation "net.sf.kxml:kxml2:2.3.0" implementation 'org.slf4j:slf4j-api:2.0.7' - implementation "org.mapsforge:vtm:$vtmVersion" + api "org.mapsforge:vtm:$vtmVersion" implementation "org.mapsforge:vtm-themes:$vtmVersion" implementation "org.mapsforge:vtm-android:$vtmVersion" runtimeOnly "org.mapsforge:vtm-android:$vtmVersion:natives-armeabi-v7a" @@ -107,7 +107,7 @@ dependencies { implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0" implementation "com.caverock:androidsvg:1.4" implementation "org.mapsforge:vtm-jts:$vtmVersion" - implementation 'org.locationtech.jts:jts-core:1.19.0' + api 'org.locationtech.jts:jts-core:1.19.0' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11' implementation 'com.squareup.okio:okio:3.3.0' diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt index 9a49b7b0..2627658d 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt @@ -10,14 +10,16 @@ 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 RenderEntity(): RealmObject() { @PrimaryKey - var id: Long = 0 // id + var id: String = UUID.randomUUID().toString() // id lateinit var name: String //要素名 + lateinit var table: String //要素表名 var code: Int = 0 // 要素编码 var geometry: String = "" get() = field @@ -27,7 +29,7 @@ open class RenderEntity(): RealmObject() { GeometryToolsKt.getTileXByGeometry(value, tileX) GeometryToolsKt.getTileYByGeometry(value, tileY) } - lateinit var properties: RealmDictionary + var properties: RealmDictionary = RealmDictionary() val tileX: RealmSet = RealmSet() // x方向的tile编码 val tileY: RealmSet = RealmSet() // y方向的tile编码 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 b1080d37..9e78c304 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 @@ -327,6 +327,26 @@ public class GeometryTools { return point; } + /** + * 根据经纬度构建一个Point类型的数据 + * + * @param lon 经度 + * @param lat 纬度 + * @return Point类型的数据 + */ + public static org.locationtech.jts.geom.Point createPoint(double lon, double lat) { + // 创建Coordinate对象 + Coordinate coordinate = new Coordinate(lon, lat); + + // 创建GeometryFactory对象 + GeometryFactory geometryFactory = new GeometryFactory(); + + // 创建Point对象 + + + return geometryFactory.createPoint(coordinate); + } + /** * 点几何转换为GeoPoint diff --git a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryToolsKt.kt b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryToolsKt.kt index 11e9c6db..3d5fd4a5 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryToolsKt.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/utils/GeometryToolsKt.kt @@ -11,12 +11,12 @@ class GeometryToolsKt { /** * 根据给定的geometry计算其横跨的20级瓦片Y值 */ - fun getTileYByGeometry(wkt: String, tileYSet: MutableSet) { + fun getTileYByGeometry(wkt: String, tileYSet: MutableSet) { val reader = WKTReader() val geometry = reader.read(wkt); - var tileYSet: MutableSet? = tileYSet + var tileYSet: MutableSet? = tileYSet val startTime = System.currentTimeMillis() if (tileYSet == null) { tileYSet = RealmSet() @@ -55,11 +55,11 @@ class GeometryToolsKt { /** * 根据给定的geometry计算其横跨的20级瓦片X值 */ - fun getTileXByGeometry(wkt: String, tileXSet: MutableSet) { + fun getTileXByGeometry(wkt: String, tileXSet: MutableSet) { val reader = WKTReader() val geometry = reader.read(wkt); - var tileXSet: MutableSet? = tileXSet + var tileXSet: MutableSet? = tileXSet val startTime = System.currentTimeMillis() if (tileXSet == null) { tileXSet = RealmSet() diff --git a/navinfo.jks b/navinfo.jks new file mode 100644 index 0000000000000000000000000000000000000000..28de488bb1bb1cef36b6d6d3dd05025caf34a629 GIT binary patch literal 2066 zcmV+t2<`X&?f&fm0006200031000312XA$BWN&YB0004bvZ?e*000F8FoFdCFb)O^ zD+U1s0V)C!0RaU71cC(XroI(-CWcETgp*TO&3a2ceL%S0D>)-qh!E;23Gt?JJ>g!+ zA}-1idd5mnCE7(5tp7=-I9Qf%j58R&poc^qu+WOeS_|jvB%RT64hl=zkE12|5or8;yf4LIa|)J=WV2ZuWp<2o{YQ`$%?(F{4RI z0j3WSNj`fRJtL~_pTHgm$zEEW1g&hdd_bTo*RGI&K1-*5aboM!g+&A8+hzpmq{!jN zMhmpsD;?AXLQc6pHttl6yK_;#*GY0a;n+Q?q+kcjc|y!3xj;*&K}ByKBiK< zddhxj?cTF8NuwY|6Rb#OouC&?RH8&K(Bni~Pw;L;Vm-2gxuh7aMkC~lh$eB`NqNJ< zsu}!~qFOfb4#8xdKWH#-`WFAn<`wL8$mOiET!f)A?`*(*NeErTM+r>~>iG9JF{j&5 zFHVklk_BIvvT^j#%}^Jg?2Py00GM70JL~tMIm%Z+AyymO{#XyxAIe|4WH_W8o4)nV zoRIQmG6c(bA;~w1J>P=2askco7Ojp*80)oDIAF7-2iJa4y;LU_+|@^!w)QWrt|d>Y zpLlKf1a*IwOQ`7N)wD25Ai~l%d|&;z3?=_?IR;D$j}bd}>}nskY*)v*D72U~1S4)B z=A)p|L;`j>ArWdE>@lJ;GO|!Ev#QOCh--SF3$c3=g z+Xd6%d_9BuHl|z$nD)B?r6EcZ$7Bt1d+RT>$T?e#lYcSUtU~68*K?3#$#p5O@my)b zVIGt*zS1qlgYX}{40&C86$Vweh9^cFK$GV2{m(ihl_%4oeA&Tyk{7&sBbLUj=O*|+ zW1{(~c}}+7b-cOHwGcxLvSH_F^_u>6%-<)br;@HM8?JD>!dZ#IiUbtd`~-Z9&iiG& zq8cK3u`1#!@lC#=$L#mzqMI|Og;%^E`vh_mh2>LYR>Ny@GVZcdgU==&2xT&+U3>Cjz1OK!UWy-Cfu9>Hx zYqsw_O*mrVFf#}?6G{;6?7x%QTS0Hdaai|D%)e9EmJ-}rD=eVY);hsdEEu`{j}ez; ziEge%aW6FU#hk;`g39S-CmA7*R|d?~SC1x&Anzj@FiWACO;xHh@Q|v1BP^F~=T1IB z58ZOing-Gg?r%1|)a(jSfm60EkZ=c}G;DdAf}lc(tknZdW;2adwaXhY{lO@~1u@{S z_p8a1(9`nik_~DKu%gcWyuU?3?~QF0^c)@l000311z0XMFgXAK0>?0d0>dzZ0jr<` z0s#U71Og&S|1b>(2`Yw2hW8Bt0Sg5HFcL8kFb)O-RRjtX2X0|@X>Mk3Fdi2TGBGeU zGB`0YFgYMk3FoFRhFbxI? zDuzgg_YDC70R;d9f&mWzFoFRJ0)hbn0GVs8*N0$Q;!R(;a`bZPb62DFq~pza!di&& zEV~kNG$07Qf#QTCH({ms->c0YsJU}DJ7HDqG~L?SuEB`6N>jRBd;qpo8+=*kbT;`k zMoxEcTdmx@9vd^ZY8xiVVOR?&kz zAn%hS8dVjE5AAeCq8k3QdY3nylGl3h@6J_Ukt`Z8i{a8uUK-M^EXLZm?(X~d)Pt&S z1dTsP>EM}Y<pGf^Vh zlmJJo=k}GO$uJED2`Yw2hW8Bt0Sg5H1A+ko01IJ(Q~WK6L$;{k){EmV16L2ff9Dk3 z5vqTcAFk4jP}hzU>MKC?`9B`Q3`8W>ot0Fc30i^GV_(hSz^xhqPMWNi*TIGERhyN- zBZW~6cPHH*pff@t^LM$_8}W9r7^T&4>FoHPLmRZ!g>w(Sr`JO zJk^ni?<^1+ra?bCjtj~v7d;$V$imS~@~ literal 0 HcmV?d00001