创建工程

This commit is contained in:
squallzhjch
2023-03-21 17:06:56 +08:00
parent f76c8b050c
commit 1b94b361ca
387 changed files with 46661 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
package com.navinfo.collect;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.PermissionChecker;
import com.baidu.ai.edge.core.base.Consts;
/**
* Created by linyiran on 6/16/22.
*/
public abstract class BaseActivity extends AppCompatActivity {
private static final int REQUEST_PERMISSION = 1;
protected boolean allPermissionsGranted;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setLayout();
requestPermission();
onActivityCreated(savedInstanceState);
}
protected abstract void setLayout();
protected abstract void onActivityCreated(Bundle savedInstanceState);
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String[] permissions = new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CAMERA
};
allPermissionsGranted = true;
for (String perm : permissions) {
if ((PermissionChecker.checkSelfPermission(this, perm) != PermissionChecker.PERMISSION_GRANTED)) {
allPermissionsGranted = false;
break;
}
}
if (!allPermissionsGranted) {
ActivityCompat.requestPermissions(BaseActivity.this, permissions, REQUEST_PERMISSION);
} else {
requestAllFilesAccess();
}
} else {
allPermissionsGranted = true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_PERMISSION) {
allPermissionsGranted = true;
for (int grantRes : grantResults) {
if (grantRes != PackageManager.PERMISSION_GRANTED) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted) {
requestAllFilesAccess();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
/**
* Android 11 跳转到设置获取SD卡根目录写入权限
*/
private void requestAllFilesAccess() {
if (!Consts.AUTH_REQUIRE_SDCARD) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
allPermissionsGranted = false;
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(BaseActivity.this,
androidx.appcompat.R.style.Theme_AppCompat_Light_Dialog_Alert);
alertBuilder.setMessage("需授权访问SD卡文件");
alertBuilder.setCancelable(false);
alertBuilder.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
alertBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertBuilder.show();
}
}
}

View File

@@ -0,0 +1,43 @@
package com.navinfo.collect
import android.content.Intent
import android.util.Log
import com.baidu.ai.edge.ui.view.model.BasePolygonResultModel
import com.navinfo.collect.library.map.flutter.plugin.FlutterMapViewFactory
import com.navinfo.collect.library.map.flutter.plugin.FlutterMapViewFlutterPlugin
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
abstract class FlutterBaseActivity : FlutterActivity(), CoroutineScope by MainScope() {
lateinit var factory: FlutterMapViewFactory
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
factory = FlutterMapViewFlutterPlugin.registerWith(flutterEngine, this);
// FlutterNiMapCopyViewFlutterPlugin.registerWith(flutterEngine, this);
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == 0x10 && data != null) {
val path = data.getStringExtra("photo_path")
val list = data.getParcelableArrayListExtra<BasePolygonResultModel>("result_list")
Log.e("jingo","OCR java 返回的数据:"+ path + list.toString());
if (path != null && list != null) {
factory.dataController.flutterDataCameraHandler.sendOcrResults(
path,
list as List<BasePolygonResultModel>
)
}
}
}
override fun onDestroy() {
super.onDestroy()
//协程销毁
cancel()
}
}

View File

@@ -0,0 +1,224 @@
package com.navinfo.collect.library.data
import android.graphics.Point
import android.graphics.Rect
import android.util.Log
import android.view.WindowInsetsAnimation.Bounds
import com.baidu.ai.edge.ui.view.model.BasePolygonResultModel
import com.baidu.ai.edge.ui.view.model.OcrViewResultModel
import com.navinfo.collect.library.data.entity.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedWriter
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.io.OutputStreamWriter
/**
* 和flutter层进行数据传递时的数据格式转换
*/
class DataConversion {
companion object {
/**
* 将数据转成map形式-传给flutter使用
*/
fun toElementMapList(list: List<Element>): List<Map<*, *>> {
val newList = mutableListOf<Map<*, *>>()
for (element in list) {
newList.add(element.toMap())
}
return newList
}
/**
* json转数据图层自定义子表的所有字段对象列表
* (现在用于从数据库中提取数据图层自定义表所有字段信息时,主要用于原生层)
*/
fun jsonToLayerItemsList(json: String): List<CustomLayerItem> {
val list = mutableListOf<CustomLayerItem>()
try {
val jsonArray = JSONArray(json)
for (i in 0 until jsonArray.length()) {
val itemObject = jsonArray.getJSONObject(i)
val itemMap = jsonToCustomLayerItem(itemObject)
list.add(itemMap);
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
}
return list
}
/**
* 数据图层子表字段配置转Map
* (主要原生层使用)
*/
fun customLayerItemsToMapList(list: List<CustomLayerItem>?): List<Map<*, *>> {
var newList = mutableListOf<Map<*, *>>()
if (list == null) {
return newList
}
for (item in list) {
newList.add(item.toMap())
}
return newList
}
/**
* 数据图层子表字段配置 json形式的数据 转成对象形式
* 原生层主要用json所以主要原生层使用
*/
private fun jsonToCustomLayerItem(itemObject: JSONObject): CustomLayerItem {
return CustomLayerItem(
key = itemObject.optString("key"),
title = itemObject.optString("title"),
type = DataLayerItemType.values()[itemObject.optInt("type")],
// nullable = itemObject.optBoolean("nullable"),
// primaryKey = itemObject.optBoolean("primaryKey"),
// value = itemObject.opt("value"),
// selectOptions = itemObject.optString("selectOptions"),
// isMainName = itemObject.optBoolean("isMainName"),
describe = itemObject.optString("describe"),
// checkManagerList = mutableListOf()
itemBean = ""
)
}
/**
* 数据图层子表字段配置转Map
* flutter层喜欢用map所以主要用于flutter和原生交互使用
*/
private fun jsonToCustomLayerItem(itemMap: Map<*, *>): CustomLayerItem {
val checkMapList = itemMap["checkMangerList"] as List<Map<*, *>>
val checkManagerList = mutableListOf<CheckManager>()
for (c in checkMapList) {
checkManagerList.add(
CheckManager(
id = (c["id"] as Int).toLong(),
type = c["type"] as Int,
tag = c["tag"] as String,
regexStr = c["regexStr"] as String
)
)
}
return CustomLayerItem(
key = itemMap["key"] as String,
title = itemMap["title"] as String,
type = DataLayerItemType.values()[itemMap["type"] as Int],
// nullable = itemMap["nullable"] as Boolean,
// primaryKey = itemMap["primaryKey"] as Boolean,
// value = itemMap["value"] as Any,
// selectOptions = itemMap["selectOptions"] as String,
// isMainName = itemMap["isMainName"] as Boolean,
describe = itemMap["describe"] as String,
// checkManagerList = checkManagerList
itemBean = ""
)
}
/**
* 数据图层 map形式的字段数据集合转成对象集合
* 主要用于flutter层与原生层数据交互时
*/
fun listMapToCustomLayerItemsList(itemList: List<Map<*, *>>): List<CustomLayerItem> {
val list = mutableListOf<CustomLayerItem>()
for (itemMap in itemList) {
list.add(jsonToCustomLayerItem(itemMap));
}
return list
}
// /**
// * layerManager转化成map
// */
// fun layerManagerToMap(
// layerManager: LayerManager,
// itemsMap: List<Map<String, *>>
// ): Map<*, *> {
// return mapOf("layerManager" to layerManager.toMap(), "itemsList" to itemsMap);
// }
/**
* 检查项转map给flutter
*/
fun toCheckManagerMapList(list: List<CheckManager>): List<Map<*, *>> {
val newList = mutableListOf<Map<*, *>>()
for (check in list) {
newList.add(
check.toMap()
)
}
return newList
}
fun toOcrList(
path: String,
basePolygonResultModels: List<BasePolygonResultModel>
): Map<*, *> {
val newList = mutableMapOf<String, Any>()
newList["photo_path"] = path
val list = mutableListOf<String>();
for (model in basePolygonResultModels) {
list.add(model.name)
}
newList["result"] = list
return newList
}
/**
* 将ocr识别结果返回给flutter
*/
suspend fun toFlutterOcrList(
list: List<Map<String, Any>>,
): List<Any> {
val listR = mutableListOf<Any>()
val job = MainScope().async(Dispatchers.IO) {
Log.e("jingo", "OCR图像识别写CSV文件 ${Thread.currentThread().name}")
for (item in list) {
if (item is Map) {
val map1 = mutableMapOf<String, Any>()
map1["path"] = item["path"]!!
map1["width"] = item["width"]!!
map1["height"] = item["height"]!!
var data = item["data"]
if (data is List<*>) {
val dataList = mutableListOf<Any>()
for (v in data) {
val map = mutableMapOf<String, Any>()
map["index"] = (v as OcrViewResultModel).index
map["bounds"] = rectToMap(v.bounds)
map["text"] = v.name
map["confidence"] = v.confidence
dataList.add(map)
}
map1["data"] = dataList
}
listR.add(map1)
}
}
}
job.await()
Log.e("jingo", "ORC 识别结果 ${listR.toString()}")
return listR
}
private fun rectToMap(list: List<Point>): List<List<Int>> {
val pointList = mutableListOf<List<Int>>()
for (point in list) {
val l = mutableListOf<Int>()
l.add(point.x)
l.add(point.y)
pointList.add(l)
}
return pointList
}
}
}

View File

@@ -0,0 +1,8 @@
package com.navinfo.collect.library.data
import com.navinfo.collect.library.data.entity.GeometryFeatureEntity
import java.io.File
interface GisFileUtils {
fun parserGisFile(file: File): List<GeometryFeatureEntity>
}

View File

@@ -0,0 +1,21 @@
package com.navinfo.collect.library.data;
import org.gdal.gdal.gdal;
import org.gdal.ogr.ogr;
/**
* 使用gdal和ogr解析Gis数据的引擎
*/
public abstract class GisFileParserEngine implements IGisFileParserEngine {
public GisFileParserEngine() {
initEngine();
}
@Override
public void initEngine() {
ogr.RegisterAll();
gdal.AllRegister();
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
}
}

View File

@@ -0,0 +1,17 @@
package com.navinfo.collect.library.data;
import com.navinfo.collect.library.data.entity.LayerEntity;
import org.locationtech.jts.geom.Geometry;
import java.io.File;
import java.util.List;
/**
* 常用Gis文件的解析写入引擎
* */
public interface IGisFileParserEngine {
void initEngine();
List<LayerEntity> parserGisFile(File gisFile);
}

View File

@@ -0,0 +1,56 @@
package com.navinfo.collect.library.data;
import com.navinfo.collect.library.data.entity.GeometryFeatureEntity;
import com.navinfo.collect.library.data.entity.LayerEntity;
import org.gdal.gdal.gdal;
import org.gdal.ogr.DataSource;
import org.gdal.ogr.Feature;
import org.gdal.ogr.FeatureDefn;
import org.gdal.ogr.ogr;
import org.locationtech.jts.geom.Geometry;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MapInfoParserEngine extends GisFileParserEngine {
/**
* 读取MapInfo文件
* */
@Override
public List<LayerEntity> parserGisFile(File mifFile) {
DataSource ds = ogr.Open(mifFile.getAbsolutePath(), 0);
if (ds == null) {
System.out.println("打开文件失败");
return null;
}
System.out.println("打开文件成功");
List<LayerEntity> layerEntityList = new ArrayList<>();
if (ds.GetLayerCount()>0) {
for (int i = 0; i < ds.GetLayerCount(); i++) {
org.gdal.ogr.Layer layer = ds.GetLayer(i);
if (layer == null) {
System.out.println("获取第"+i+"个图层失败");
continue;
}
LayerEntity layerEntity = new LayerEntity();
layerEntity.setLayerName(layer.GetName());
layerEntity.setGeomType(layer.GetGeomType());
layerEntity.setFromDataName(mifFile.getName());
System.out.println("读取到Layer" + layer.GetName());
layer.ResetReading();
for (int j = 0; j < layer.GetFeatureCount(); j++) {
GeometryFeatureEntity entity = new GeometryFeatureEntity();
Feature feature = layer.GetFeature(j);
entity.setGeometry(feature.GetGeometryRef().toString());
}
}
}
return layerEntityList;
}
}

View File

@@ -0,0 +1,33 @@
package com.navinfo.collect.library.data
import android.content.Context
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.handler.DataLayerHandler
import com.navinfo.collect.library.system.Constant
/**
* 地图控制器
*/
open class NIDataController(
context: Context,
activity: FlutterBaseActivity,
) {
protected val mContext = context
protected val mActivity = activity
internal val mDateBase: MapLifeDataBase = MapLifeDataBase.getDatabase(
context, "${Constant.ROOT_PATH}/coremap.db"
)
init {
RealmUtils.getInstance().init(mContext, Constant.ROOT_PATH, "hd-data")
}
protected val dataHandler: DataLayerHandler = DataLayerHandler(mContext, mDateBase);
open fun release() {
mDateBase.close()
}
}

View File

@@ -0,0 +1,162 @@
package com.navinfo.collect.library.data;
import com.google.protobuf.Descriptors;
import com.google.protobuf.GeneratedMessageV3;
import com.navinfo.collect.library.data.entity.GeometryFeatureEntity;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Resultdata;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateXYM;
import org.locationtech.jts.geom.CoordinateXYZM;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.WKBWriter;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.context.SpatialContextFactory;
import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory;
import org.locationtech.spatial4j.io.ShapeIO;
import org.locationtech.spatial4j.io.ShapeReader;
import org.locationtech.spatial4j.io.ShapeWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class NavinfoPbfData {
private static GeometryFactory factory;
private static SpatialContext spatialContext;
private static ShapeReader shapeReader;
private static ShapeWriter shapeWriter;
private static WKBWriter wkbWriter;
private boolean isInit = false;
public NavinfoPbfData() {
if (!isInit) {
init();
}
}
public static boolean init() {
SpatialContextFactory spatialContextFactory = new SpatialContextFactory();
wkbWriter= new WKBWriter(3, true);
factory = new JtsSpatialContextFactory().getGeometryFactory();
spatialContext = new SpatialContext(spatialContextFactory);
shapeReader = spatialContext.getFormats().getWktReader();
shapeWriter = spatialContext.getFormats().getWktWriter();
return true;
}
public static Resultdata.ResultData readPbfData(InputStream inputStream) throws IOException {
return Resultdata.ResultData.parseFrom(inputStream);
}
public static Geometry createGeometry(GeneratedMessageV3 geometry) {
Geometry resultGeometry = null;
if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point2d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point2d point2d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point2d) geometry;
Coordinate coordinate = new Coordinate(point2d.getLongitudeDegrees(), point2d.getLatitudeDegrees());
resultGeometry = factory.createPoint(coordinate);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d point3d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d) geometry;
CoordinateXYZM coordinate = new CoordinateXYZM(point3d.getLatLon().getLongitudeDegrees(), point3d.getLatLon().getLatitudeDegrees(), point3d.getElevation().getZ(), 7);
resultGeometry = factory.createPoint(coordinate);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString2d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString2d lineString2d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString2d) geometry;
Coordinate[] coordinates = new Coordinate[lineString2d.getLinestringPointsCount()];
for (int i = 0; i < lineString2d.getLinestringPointsCount(); i++) {
coordinates[i] = new Coordinate(lineString2d.getLinestringPoints(i).getLongitudeDegrees(), lineString2d.getLinestringPoints(i).getLatitudeDegrees());
}
resultGeometry = factory.createLineString(coordinates);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString3d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString3d lineString3d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString3d) geometry;
CoordinateXYZM[] coordinates = new CoordinateXYZM[lineString3d.getLinestringPointsCount()];
for (int i = 0; i < lineString3d.getLinestringPointsCount(); i++) {
coordinates[i] = new CoordinateXYZM(lineString3d.getLinestringPoints(i).getLatLon().getLongitudeDegrees(), lineString3d.getLinestringPoints(i).getLatLon().getLatitudeDegrees(), lineString3d.getLinestringPoints(i).getElevation().getZ(), 7);
}
resultGeometry = factory.createLineString(coordinates);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiLineString2d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiLineString2d multiLineString2d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiLineString2d) geometry;
LineString[] lineStrings = new LineString[multiLineString2d.getLineStringsCount()];
for (int i = 0; i < multiLineString2d.getLineStringsCount(); i++) {
lineStrings[i] = (LineString) createGeometry(multiLineString2d.getLineStrings(i));
}
resultGeometry = factory.createMultiLineString(lineStrings);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiLineString3d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiLineString3d multiLineString3d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiLineString3d) geometry;
LineString[] lineStrings = new LineString[multiLineString3d.getLineStringsCount()];
for (int i = 0; i < multiLineString3d.getLineStringsCount(); i++) {
lineStrings[i] = (LineString) createGeometry(multiLineString3d.getLineStrings(i));
}
resultGeometry = factory.createMultiLineString(lineStrings);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Polygon2d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Polygon2d polygon2d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Polygon2d) geometry;
Coordinate[] coordinates = new Coordinate[polygon2d.getPolygonPointsCount()];
for (int i = 0; i < polygon2d.getPolygonPointsCount(); i++) {
coordinates[i] = new Coordinate(polygon2d.getPolygonPoints(i).getLongitudeDegrees(), polygon2d.getPolygonPoints(i).getLatitudeDegrees());
}
resultGeometry = factory.createPolygon(coordinates);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Polygon3d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Polygon3d polygon3d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Polygon3d) geometry;
CoordinateXYZM[] coordinates = new CoordinateXYZM[polygon3d.getPolygonPointsCount()];
for (int i = 0; i < polygon3d.getPolygonPointsCount(); i++) {
coordinates[i] = new CoordinateXYZM(polygon3d.getPolygonPoints(i).getLatLon().getLongitudeDegrees(), polygon3d.getPolygonPoints(i).getLatLon().getLatitudeDegrees(), polygon3d.getPolygonPoints(i).getElevation().getZ(), 7);
}
resultGeometry = factory.createPolygon(coordinates);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiPolygon2d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiPolygon2d multiPolygon2d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiPolygon2d) geometry;
Polygon[] polygons = new Polygon[multiPolygon2d.getPolygonsCount()];
for (int i = 0; i < multiPolygon2d.getPolygonsCount(); i++) {
polygons[i] = (Polygon) createGeometry(multiPolygon2d.getPolygons(i));
}
resultGeometry = factory.createMultiPolygon(polygons);
} else if (geometry instanceof com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiPolygon3d) {
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiPolygon3d multiPolygon3d = (com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.MultiPolygon3d) geometry;
Polygon[] polygons = new Polygon[multiPolygon3d.getPolygonsCount()];
for (int i = 0; i < multiPolygon3d.getPolygonsCount(); i++) {
polygons[i] = (Polygon) createGeometry(multiPolygon3d.getPolygons(i));
}
resultGeometry = factory.createMultiPolygon(polygons);
}
return resultGeometry;
}
public static GeometryFeatureEntity createGeometryEntity(Geometry geometry, Map<Descriptors.FieldDescriptor, Object> userData, Map<String, String> extendFields) {
if (geometry == null) {
return null;
}
StringBuilder prefixStr = new StringBuilder();
GeometryFeatureEntity entity = new GeometryFeatureEntity();
entity.setId(UUID.randomUUID().toString());
entity.setGeometry(geometry);
entity.setWkb(wkbWriter.write(geometry));
if (userData!=null&&!userData.isEmpty()) {
for (Map.Entry<Descriptors.FieldDescriptor, Object> e: userData.entrySet()) {
getFieldEntry(e, prefixStr, entity.getProperties());
}
}
if (extendFields!=null&&!extendFields.isEmpty()) {
entity.getOtherProperties().putAll(extendFields);
}
return entity;
}
/**
* 递归调用,如果存在子属性,则父子属性以{parent.child}格式存入map
* */
private static void getFieldEntry(Map.Entry<Descriptors.FieldDescriptor, Object> e, StringBuilder prefix, Map<String, String> properties) {
prefix.append(".").append(e.getKey().getName());
if (e.getValue() instanceof GeneratedMessageV3) {
for (Map.Entry<Descriptors.FieldDescriptor, Object> subE: ((GeneratedMessageV3)e.getValue()).getAllFields().entrySet()) {
getFieldEntry(subE, prefix, properties);
}
} else {
properties.put(e.getKey().getName(), e.getValue().toString());
}
}
}

View File

@@ -0,0 +1,384 @@
package com.navinfo.collect.library.data
import android.os.Build
import androidx.annotation.RequiresApi
import com.google.protobuf.GeneratedMessageV3
import com.navinfo.collect.library.data.entity.GeometryFeatureEntity
import com.navinfo.collect.library.data.entity.LayerEntity
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.*
import org.locationtech.jts.algorithm.Angle
import org.locationtech.jts.geom.Coordinate
import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.util.AffineTransformation
import org.locationtech.jts.geom.util.AffineTransformationFactory
import java.io.File
import java.io.FileInputStream
import java.util.*
import kotlin.math.cos
import kotlin.math.sin
import kotlin.streams.toList
@RequiresApi(Build.VERSION_CODES.N)
class NavinfoPbfFileUtils: GisFileUtils {
/*
* 解析Pbf文件
* */
override fun parserGisFile(file: File): List<GeometryFeatureEntity> {
val geometryEntityList = ArrayList<GeometryFeatureEntity>()
if (!file?.isFile || !file.exists()) {
return geometryEntityList;
}
// 解析pbf文件
val pbfData = NavinfoPbfData.readPbfData(FileInputStream(file))
// 解析roadLink道路线
geometryEntityList.addAll(parserRoadLink(pbfData.roadlinkList, file, "道路线"))
// 解析roadLink上的道路方向
geometryEntityList.addAll(parserRoadDirect(pbfData.roadlinkList, file, "道路方向"))
// 解析roadLink的桥属性
geometryEntityList.addAll(parserRoadBrunnel(pbfData.roadlinkList, file, "桥隧道"))
// 解析roadLink的移动式桥属性
geometryEntityList.addAll(parserRoadMovBrg(pbfData.roadlinkList, file, "移动式桥"))
// 解析hadLaneLink车道中心线
geometryEntityList.addAll(parserHadLaneLink(pbfData.hadlanelinkList, file, "车道中心线"))
// 解析hadLaneMarkLink车道边线
geometryEntityList.addAll(parserHadLaneMarkLink(pbfData.hadlanemarklinkList, file, "车道边线"))
// 解析hadLaneMarkLink.traversal车道边线可跨越性
geometryEntityList.addAll(parserHadLaneMarkLinkTraversal(pbfData.hadlanemarklinkList, file, "车道边线可跨越性"))
// 解析hadLaneMarkLink.marking车道边线划线类型
geometryEntityList.addAll(parserHadLaneMarkLinkBoundary(pbfData.hadlanemarklinkList, file, "车道边线非标线类型"))
// 解析speedLimitGen固定限速
geometryEntityList.addAll(parserSpeedLimitGen(pbfData.rdspeedlimitgenList, file, "固定限速"))
// 解析speedLimitDepend条件限速
geometryEntityList.addAll(parserSpeedLimitDepend(pbfData.rdspeedlimitdependList, file, "条件限速"))
// 解析speedLimitVar可变限速
geometryEntityList.addAll(parserSpeedLimitVar(pbfData.rdspeedlimitvarList, file, "可变限速"))
return geometryEntityList;
}
/**
* 处理道路线RoadLink
* */
private fun parserRoadLink(roadLinkList: List<Roadlink.RoadLink>, file: File, layerName: String= "道路线", layerTableName: String = "ROAD_LINK"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (roadLinkList?.isEmpty()) {
return featureEntityList
}
for (roadLink in roadLinkList) {
val geometry = NavinfoPbfData.createGeometry(roadLink.geometry)
val geometryFeatureEntity =
convertDefaultHDEntity(geometry, roadLink, layerName, layerTableName, file)
featureEntityList.add(geometryFeatureEntity)
}
return featureEntityList;
}
/**
* 处理车道中心线HadLaneLink
* */
private fun parserHadLaneLink(hadLaneLinkList: List<Hadlanelink.HadLaneLink>, file: File, layerName: String= "车道中心线", layerTableName: String = "HAD_LANE_LINK"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (hadLaneLinkList?.isEmpty()) {
return featureEntityList
}
for (hadLaneLink in hadLaneLinkList) {
val geometry = NavinfoPbfData.createGeometry(hadLaneLink.geometry)
val geometryFeatureEntity =
convertDefaultHDEntity(geometry, hadLaneLink, layerName, layerTableName, file)
featureEntityList.add(geometryFeatureEntity)
}
return featureEntityList;
}
/**
* 处理speedLimitGen固定限速
* */
private fun parserSpeedLimitGen(speedLimitGenList: List<Rdspeedlimitgen.RdSpeedlimitGen>, file: File, layerName: String= "固定限速", layerTableName: String = "SPEED_LIMIT_GEN"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (speedLimitGenList?.isEmpty()) {
return featureEntityList
}
for (speedLimitGen in speedLimitGenList) {
val geometry = NavinfoPbfData.createGeometry(speedLimitGen.geometry)
val geometryFeatureEntity =
convertDefaultHDEntity(geometry, speedLimitGen, layerName, layerTableName, file)
geometryFeatureEntity.otherProperties["SPEED_FLAG"] = speedLimitGen.speedFlag.toString()
featureEntityList.add(geometryFeatureEntity)
}
return featureEntityList;
}
/**
* 处理speedLimitDepend条件限速
* */
private fun parserSpeedLimitDepend(speedLimitDenpendList: List<Rdspeedlimitdepend.RdSpeedlimitDepend>, file: File, layerName: String= "条件限速", layerTableName: String = "SPEED_LIMIT_DEPEND"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (speedLimitDenpendList?.isEmpty()) {
return featureEntityList
}
for (speedLimitDepend in speedLimitDenpendList) {
val geometry = NavinfoPbfData.createGeometry(speedLimitDepend.geometry)
val geometryFeatureEntity =
convertDefaultHDEntity(geometry, speedLimitDepend, layerName, layerTableName, file)
geometryFeatureEntity.otherProperties["SPEED_FLAG"] = speedLimitDepend.speedFlag.toString()
featureEntityList.add(geometryFeatureEntity)
}
return featureEntityList;
}
/**
* 处理speedLimitDepend条件限速
* */
private fun parserSpeedLimitVar(speedLimitVarList: List<Rdspeedlimitvar.RdSpeedlimitVar>, file: File,
layerName: String= "可变限速", layerTableName: String = "SPEED_LIMIT_VAR"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (speedLimitVarList?.isEmpty()) {
return featureEntityList
}
for (speedLimitVar in speedLimitVarList) {
val geometry = NavinfoPbfData.createGeometry(speedLimitVar.geometry)
val geometryFeatureEntity =
convertDefaultHDEntity(geometry, speedLimitVar, layerName, layerTableName, file)
geometryFeatureEntity.otherProperties["SPEED_FLAG"] = speedLimitVar.speedFlag.toString()
featureEntityList.add(geometryFeatureEntity)
}
return featureEntityList;
}
/**
* 处理车道边线HadLaneMarkLink
* */
private fun parserHadLaneMarkLink(hadLaneMarkLinkList: List<Hadlanemarklink.HadLaneMarkLink>, file: File,
layerName: String= "车道边线", layerTableName: String = "HAD_LANE_MARK_LINK"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (hadLaneMarkLinkList?.isEmpty()) {
return featureEntityList
}
for (hadLaneMarkLink in hadLaneMarkLinkList) {
val geometry = NavinfoPbfData.createGeometry(hadLaneMarkLink.geometry)
val geometryFeatureEntity =
convertDefaultHDEntity(geometry, hadLaneMarkLink, layerName, layerTableName, file)
featureEntityList.add(geometryFeatureEntity)
}
return featureEntityList;
}
/**
* 处理车道边线HadLaneMarkLinkTraversal
* */
private fun parserHadLaneMarkLinkTraversal(hadLaneMarkLinkList: List<Hadlanemarklink.HadLaneMarkLink>, file: File,
layerName: String= "车道边线可跨越性", layerTableName: String = "HAD_LANE_MARK_LINK_TRAVERSAL"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (hadLaneMarkLinkList?.isEmpty()) {
return featureEntityList
}
// 解析道路边线可跨越性
for (hadLaneMarkLink in hadLaneMarkLinkList) {
// for (traversal in hadLaneMarkLink.traversalList) {
// // 根据给出的起终点计算切割点在线上的index
// val startPoint3d = traversal.paPosition.sIndex
// val endPoint3d = traversal.paPosition.eIndex
// val subIndex:List<Map<String, Any>> = List()
// val sortedIndex =subIndex.sortedBy { item->item["startIndex"].toString().toInt() }
// for ((index, map) in sortedIndex.withIndex()) {
//
// }
// }
for (traversal in hadLaneMarkLink.traversalList) {
val startPoint3d = traversal.paPosition.sIndex
val endPoint3d = traversal.paPosition.eIndex
val traversalLineString = subLine(hadLaneMarkLink.geometry, startPoint3d, endPoint3d)
val geometryFeatureEntity =
convertDefaultHDEntity(traversalLineString, traversal, layerName, layerTableName, file)
geometryFeatureEntity.otherProperties["TYPE"] = traversal.type.toString()
featureEntityList.add(geometryFeatureEntity)
}
}
return featureEntityList;
}
/**
* 处理车道边线HadLaneMarkLinkBoundary
* */
private fun parserHadLaneMarkLinkBoundary(hadLaneMarkLinkList: List<Hadlanemarklink.HadLaneMarkLink>, file: File,
layerName: String= "车道边线非标线类型", layerTableName: String = "HAD_LANE_MARK_LINK_BOUNDARY"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (hadLaneMarkLinkList?.isEmpty()) {
return featureEntityList
}
// 解析道路边线可跨越性
for (hadLaneMarkLink in hadLaneMarkLinkList) {
for (boundary in hadLaneMarkLink.boundaryList) {
val startPoint3d = boundary.paPosition.sIndex
val endPoint3d = boundary.paPosition.eIndex
val boundaryLineString = subLine(hadLaneMarkLink.geometry, startPoint3d, endPoint3d)
val geometryFeatureEntity =
convertDefaultHDEntity(boundaryLineString, boundary, layerName, layerTableName, file)
if (boundary.boundaryType.type!=2) {
geometryFeatureEntity.otherProperties["BOUNDARY_TYPE"] = boundary.boundaryType.type.toString()
featureEntityList.add(geometryFeatureEntity)
} else {
if (boundary.markingList!=null&&boundary.markingList.isNotEmpty()) {
for (mark in boundary.markingList) {
val geometryFeatureEntity =
convertDefaultHDEntity(boundaryLineString, mark, "车道边线标线类型", "HAD_LANE_MARK_LINK_MARKING", file)
geometryFeatureEntity.otherProperties["BOUNDARY_TYPE"] = "2"
geometryFeatureEntity.otherProperties["MARK_TYPE"] = mark.markType.toString()
geometryFeatureEntity.otherProperties["MARK_COLOR"] = mark.markColor.toString()
// 根据mark的横向偏移量重新设置geometry值
val lineString = boundaryLineString as LineString
var degree = Angle.toDegrees(Angle.angle(lineString.startPoint.coordinate, lineString.endPoint.coordinate))
degree = degree+90
val transformation:AffineTransformation = AffineTransformationFactory.createFromControlVectors(
Coordinate(0.toDouble(), 0.toDouble()), Coordinate(sin(degree) *(mark.lateralOffset*7e-9).toDouble(), cos(degree)*mark.lateralOffset*7e-9.toDouble())
)
val transformGeometry = transformation.transform(boundaryLineString)
geometryFeatureEntity.geometry = transformGeometry.toString()
featureEntityList.add(geometryFeatureEntity)
}
}
}
}
}
return featureEntityList;
}
/**
* 处理道路方向
* */
private fun parserRoadDirect(roadLinkList: List<Roadlink.RoadLink>, file: File,
layerName: String= "道路方向", layerTableName: String = "ROAD_LINK_DIRECT"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (roadLinkList?.isEmpty()) {
return featureEntityList
}
for (roadLink in roadLinkList) {
val geometry = NavinfoPbfData.createGeometry(roadLink.geometry)
// 解析道路方向
for (dirct in roadLink.directList) {
val startPoint3d = dirct.paPosition.sIndex
val endPoint3d = dirct.paPosition.eIndex
val directLineString = subLine(roadLink.geometry, startPoint3d, endPoint3d)
val geometryFeatureEntity =
convertDefaultHDEntity(directLineString, dirct, layerName, layerTableName, file)
geometryFeatureEntity.otherProperties["VALUE"] = dirct.value.toString()
featureEntityList.add(geometryFeatureEntity)
}
}
return featureEntityList;
}
/**
* 处理道路的桥属性
* */
private fun parserRoadBrunnel(roadLinkList: List<Roadlink.RoadLink>, file: File,
layerName: String= "桥隧道", layerTableName: String = "ROAD_LINK_BRUNNEL"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (roadLinkList?.isEmpty()) {
return featureEntityList
}
for (roadLink in roadLinkList) {
// 解析桥属性IS_BRUNNEL
for (brunnel in roadLink.isBrunnelList) {
val startPoint3d = brunnel.paPosition.sIndex
val endPoint3d = brunnel.paPosition.eIndex
val brunnelLineString = subLine(roadLink.geometry, startPoint3d, endPoint3d)
val geometryFeatureEntity =
convertDefaultHDEntity(brunnelLineString, brunnel, layerName, layerTableName, file)
geometryFeatureEntity.otherProperties["TYPE"] = brunnel.type.toString()
featureEntityList.add(geometryFeatureEntity)
}
}
return featureEntityList;
}
/**
* 处理道路的移动式桥属性
* */
private fun parserRoadMovBrg(roadLinkList: List<Roadlink.RoadLink>, file: File,
layerName: String= "移动式桥", layerTableName: String = "ROAD_LINK_MOVBRG"): List<GeometryFeatureEntity> {
val featureEntityList = ArrayList<GeometryFeatureEntity>()
if (roadLinkList?.isEmpty()) {
return featureEntityList
}
for (roadLink in roadLinkList) {
// 解析移动式桥属性MOVBRG
for (movbrg in roadLink.movbrgList) {
val startPoint3d = movbrg.paPosition.sIndex
val endPoint3d = movbrg.paPosition.eIndex
val movbrgLineString = subLine(roadLink.geometry, startPoint3d, endPoint3d)
val geometryFeatureEntity =
convertDefaultHDEntity(movbrgLineString, movbrg, layerName, layerTableName, file)
featureEntityList.add(geometryFeatureEntity)
}
}
return featureEntityList;
}
/**
* 读取指定的HD元素数据
* */
private fun convertDefaultHDEntity(geometry: Geometry, generatedMsg: GeneratedMessageV3, layerName: String, layerTableName: String, file: File): GeometryFeatureEntity {
// 处理roadLink
val layerEntity = LayerEntity()
layerEntity.layerName = layerName
layerEntity.layerTableName = layerTableName
layerEntity.fromDataName = file.name
// 转换geometry和属性信息为数据库字段
val renderMap = obtainRenderMap(layerTableName)
val featureEntity =
NavinfoPbfData.createGeometryEntity(geometry, generatedMsg.allFields, renderMap)
featureEntity.name = layerName
featureEntity.layerEntity = layerEntity
return featureEntity
}
private fun obtainRenderMap(kind: String): Map<String, String> {
val renderPropMap = HashMap<String, String>()
renderPropMap.put("navinfo_hd", kind)
return renderPropMap
}
/**
* 根据给定的起终点截取LineString3D
* */
private fun subLine(line: com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.LineString3d,
sPoint: com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d,
ePoint: com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d): Geometry {
var sIndex = 0
var eIndex = 0
for ((index, linePoint) in line.linestringPointsList.withIndex()) {
if (sIndex <= eIndex&&linePoint.equals(sPoint)) {
sIndex = index
} else if (linePoint.equals(ePoint)) {
eIndex = index
break
}
}
if (eIndex>sIndex&&eIndex<line.linestringPointsList.size) {
// 转换为geometry
// 注意因为sublist取的尾数为参数-1所以eIndex需要加1
val coordinateArrays: List<Coordinate> = line.linestringPointsList.subList(sIndex, eIndex+1).stream().map { Coordinate(it.latLon.longitudeDegrees, it.latLon.latitudeDegrees, it.elevation.z) }.toList()
val toTypedArray = coordinateArrays.toTypedArray()
if (toTypedArray.size == 1) {
toTypedArray[1] = toTypedArray[0].copy()
}
// println("toTypedArray点数${toTypedArray.size}sIndex${sIndex}eIndex${eIndex}")
return GeometryTools.getLineStrinGeo(toTypedArray)
}
// 如果没能截取到子线段,则返回第一个点组成的线
return GeometryTools.getLineStrinGeo(
arrayOf(
Coordinate(line.linestringPointsList.get(0).latLon.longitudeDegrees, line.linestringPointsList.get(0).latLon.latitudeDegrees, line.linestringPointsList.get(0).elevation.z),
Coordinate(line.linestringPointsList.get(1).latLon.longitudeDegrees, line.linestringPointsList.get(1).latLon.latitudeDegrees, line.linestringPointsList.get(1).elevation.z))
)
}
}

View File

@@ -0,0 +1,488 @@
package com.navinfo.collect.library.data;
import android.content.Context;
import android.util.Log;
import com.google.protobuf.GeneratedMessageV3;
import com.navinfo.collect.library.data.entity.GeometryFeatureEntity;
import com.navinfo.collect.library.data.entity.LayerEntity;
import com.navinfo.collect.library.map.NILayerManager;
import com.navinfo.collect.library.utils.GeometryTools;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Hadlanelink;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Hadlanemarklink;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Objectarrow;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Objectcrosswalk;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Objectpole;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Objectsymbol;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Objecttrafficlights;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.Resultdata;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.object.BoundaryOuterClass;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.object.Boundarytype;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.object.MarkingOuterClass;
import com.navinfo.onemap.det.sdkpbf.proto.crowdsource.object.Paposition;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.LineString;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmModel;
import kotlin.jvm.internal.Intrinsics;
public class RealmUtils {
private Context mContext;
private static RealmUtils instance;
private Realm realm;
private RealmConfiguration realmConfiguration;
private String defaultDir = NILayerManager.defaultDir;
private String realmName;
private final String NAME = "name";
private final String TYPE = "navi_type";
public void init(Context mContext, String dir, String realmName) {
this.mContext = mContext;
Realm.init(this.mContext);
this.realmName = realmName;
realmConfiguration = new RealmConfiguration.Builder()
.directory(dir == null?new File(defaultDir): new File(dir))
.name(realmName)
.allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true)
.schemaVersion(1)
.deleteRealmIfMigrationNeeded()
.encryptionKey(Arrays.copyOf(new String("encryp").getBytes(StandardCharsets.UTF_8), 64))
.build();
System.out.println("encryp:"+toHexString(Arrays.copyOf(new String("encryp").getBytes(StandardCharsets.UTF_8), 64)));
Realm.setDefaultConfiguration(realmConfiguration);
}
public static RealmUtils getInstance() {
if (instance == null) {
instance = new RealmUtils();
}
return instance;
}
public Realm getRealm() throws Exception {
if (realmConfiguration == null) {
throw new Exception("请先调用Realm.init方法初始化");
}
return Realm.getDefaultInstance();
}
public RealmConfiguration getRealmConfiguration() {
return realmConfiguration;
}
private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* 方法一将byte类型数组转化成16进制字符串
* @explain 字符串拼接
* @param bytes
* @return
*/
public static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
int num;
for (byte b : bytes) {
num = b < 0 ? 256 + b : b;
sb.append(HEX_CHAR[num / 16]).append(HEX_CHAR[num % 16]);
}
return sb.toString();
}
public float getFileSize(){
File file = new File(defaultDir+"/"+realmName);
if(file.exists()&&file.isFile()){
return file.length();
}
return 0;
}
public Map<String, Object> importPbfData(List<String> files) throws IOException {
NavinfoPbfData pbfData = new NavinfoPbfData();
long startTime = System.currentTimeMillis();
RealmUtils var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).beginTransaction();
Iterator fileIterator = files.iterator();
while(fileIterator.hasNext()) {
String file = (String)fileIterator.next();
Log.d("Realm-file:", file);
System.out.print("file:" + file);
Resultdata.ResultData resultData = pbfData.readPbfData((InputStream)(new FileInputStream(new File(file))));
long sqlStartTime = System.currentTimeMillis();
Intrinsics.checkNotNullExpressionValue(resultData, "resultData");
List var40 = resultData.getHadlanelinkList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.hadlanelinkList");
Collection var9 = (Collection)var40;
HashMap extentMapx;
Iterator var12;
Geometry geometry;
GeometryFeatureEntity geometryEntityx;
LayerEntity layerEntity;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "车道中心线");
((Map)extentMapx).put(TYPE, "had_lane_link");
var12 = resultData.getHadlanelinkList().iterator();
while(var12.hasNext()) {
Hadlanelink.HadLaneLink hadLaneLink = (Hadlanelink.HadLaneLink)var12.next();
Intrinsics.checkNotNullExpressionValue(hadLaneLink, "hadLaneLink");
geometry = pbfData.createGeometry((GeneratedMessageV3)hadLaneLink.getGeometry());
geometryEntityx = pbfData.createGeometryEntity(geometry, hadLaneLink.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntityx, "geometryEntity");
geometryEntityx.setLayerEntity(layerEntity);
geometryEntityx.setName((String)extentMapx.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityx);
}
}
var40 = resultData.getHadlanemarklinkList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.hadlanemarklinkList");
var9 = (Collection)var40;
Geometry lanLinkGeometry;
Geometry intersection;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "车道边线");
((Map)extentMapx).put(TYPE, "had_lane_mark_link");
var12 = resultData.getHadlanemarklinkList().iterator();
while(var12.hasNext()) {
Hadlanemarklink.HadLaneMarkLink hadLaneMarkLink = (Hadlanemarklink.HadLaneMarkLink)var12.next();
Intrinsics.checkNotNullExpressionValue(hadLaneMarkLink, "hadLaneMarkLink");
geometry = pbfData.createGeometry((GeneratedMessageV3)hadLaneMarkLink.getGeometry());
Iterator var15 = hadLaneMarkLink.getBoundaryList().iterator();
while(var15.hasNext()) {
BoundaryOuterClass.Boundary boundary = (BoundaryOuterClass.Boundary)var15.next();
Intrinsics.checkNotNullExpressionValue(boundary, "boundary");
Paposition.PaPosition var43 = boundary.getPaPosition();
Intrinsics.checkNotNullExpressionValue(var43, "boundary.paPosition");
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d sPoint = var43.getSIndex();
var43 = boundary.getPaPosition();
Intrinsics.checkNotNullExpressionValue(var43, "boundary.paPosition");
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point3d ePoint = var43.getEIndex();
Coordinate[] var45 = new Coordinate[2];
Intrinsics.checkNotNullExpressionValue(sPoint, "sPoint");
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point2d var10005 = sPoint.getLatLon();
Intrinsics.checkNotNullExpressionValue(var10005, "sPoint.latLon");
double fileIterator0 = var10005.getLongitudeDegrees();
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.Point2d var10006 = sPoint.getLatLon();
Intrinsics.checkNotNullExpressionValue(var10006, "sPoint.latLon");
double fileIterator3 = var10006.getLatitudeDegrees();
com.navinfo.onemap.det.sdkpbf.proto.geometry.Geometry.ElevationMeasure var10007 = sPoint.getElevation();
Intrinsics.checkNotNullExpressionValue(var10007, "sPoint.elevation");
var45[0] = new Coordinate(fileIterator0, fileIterator3, var10007.getZ());
Intrinsics.checkNotNullExpressionValue(ePoint, "ePoint");
var10005 = ePoint.getLatLon();
Intrinsics.checkNotNullExpressionValue(var10005, "ePoint.latLon");
fileIterator0 = var10005.getLongitudeDegrees();
var10006 = ePoint.getLatLon();
Intrinsics.checkNotNullExpressionValue(var10006, "ePoint.latLon");
fileIterator3 = var10006.getLatitudeDegrees();
var10007 = ePoint.getElevation();
Intrinsics.checkNotNullExpressionValue(var10007, "ePoint.elevation");
var45[1] = new Coordinate(fileIterator0, fileIterator3, var10007.getZ());
LineString line = GeometryTools.getLineStrinGeo(var45);
lanLinkGeometry = line.buffer(1.0E-7D, 1, 2);
intersection = geometry.intersection(lanLinkGeometry);
extentMapx.remove("boundary_type");
extentMapx.remove("mark_type");
extentMapx.remove("mark_color");
extentMapx.remove("mark_material");
extentMapx.remove("mark_width");
if (boundary.getBoundaryType() != null) {
Map var46 = (Map)extentMapx;
Boundarytype.BoundaryType2 var10002 = boundary.getBoundaryType();
Intrinsics.checkNotNullExpressionValue(var10002, "boundary.boundaryType");
var46.put("boundary_type", String.valueOf(var10002.getType()));
Boundarytype.BoundaryType2 var49 = boundary.getBoundaryType();
Intrinsics.checkNotNullExpressionValue(var49, "boundary.boundaryType");
if (var49.getType() == 2 && boundary.getMarkingList() != null) {
var40 = boundary.getMarkingList();
Intrinsics.checkNotNullExpressionValue(var40, "boundary.markingList");
Collection var21 = (Collection)var40;
if (!var21.isEmpty()) {
var46 = (Map)extentMapx;
Object var48 = boundary.getMarkingList().get(0);
Intrinsics.checkNotNullExpressionValue(var48, "boundary.markingList[0]");
var46.put("mark_type", String.valueOf(((MarkingOuterClass.Marking)var48).getMarkType()));
var46 = (Map)extentMapx;
var48 = boundary.getMarkingList().get(0);
Intrinsics.checkNotNullExpressionValue(var48, "boundary.markingList[0]");
var46.put("mark_color", String.valueOf(((MarkingOuterClass.Marking)var48).getMarkColor()));
var46 = (Map)extentMapx;
var48 = boundary.getMarkingList().get(0);
Intrinsics.checkNotNullExpressionValue(var48, "boundary.markingList[0]");
var46.put("mark_material", String.valueOf(((MarkingOuterClass.Marking)var48).getMarkMaterial()));
var46 = (Map)extentMapx;
var48 = boundary.getMarkingList().get(0);
Intrinsics.checkNotNullExpressionValue(var48, "boundary.markingList[0]");
var46.put("mark_width", String.valueOf(((MarkingOuterClass.Marking)var48).getMarkWidth()));
}
}
}
GeometryFeatureEntity geometryEntity = pbfData.createGeometryEntity(intersection, boundary.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntity, "geometryEntity");
geometryEntity.setLayerEntity(layerEntity);
geometryEntity.setName((String)extentMapx.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntity);
}
}
}
var40 = resultData.getObjectarrowList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.objectarrowList");
var9 = (Collection)var40;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "道路箭头");
((Map)extentMapx).put(TYPE, "object_arrow");
var12 = resultData.getObjectarrowList().iterator();
label143:
while(true) {
label141:
while(true) {
if (!var12.hasNext()) {
break label143;
}
Objectarrow.ObjectArrow objectArrow = (Objectarrow.ObjectArrow)var12.next();
Intrinsics.checkNotNullExpressionValue(objectArrow, "objectArrow");
geometry = pbfData.createGeometry((GeneratedMessageV3)objectArrow.getGeometry());
geometryEntityx = pbfData.createGeometryEntity(geometry, objectArrow.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntityx, "geometryEntity");
geometryEntityx.setLayerEntity(layerEntity);
geometryEntityx.setName((String)extentMapx.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityx);
Iterator var41 = objectArrow.getLanePidList().iterator();
while(var41.hasNext()) {
String lanLinkPid = (String)var41.next();
Iterator var47 = resultData.getHadlanelinkList().iterator();
while(var47.hasNext()) {
Hadlanelink.HadLaneLink lanLink = (Hadlanelink.HadLaneLink)var47.next();
Intrinsics.checkNotNullExpressionValue(lanLink, "lanLink");
if (lanLinkPid.equals(lanLink.getLaneLinkPid())) {
lanLinkGeometry = pbfData.createGeometry((GeneratedMessageV3)lanLink.getGeometry());
if (lanLinkGeometry.intersects(geometry)) {
intersection = geometry.intersection(lanLinkGeometry);
Intrinsics.checkNotNullExpressionValue(intersection, "intersection");
if (intersection.isValid() && !intersection.isEmpty() && intersection instanceof LineString) {
HashMap extentMap = new HashMap();
((Map)extentMap).put(TYPE, "symbol_object_arrow");
((Map)extentMap).put(NAME, "symbol_object_arrow");
((Map)extentMap).put("arrow_class", String.valueOf(objectArrow.getArrowClass()));
GeometryFeatureEntity geometryEntityxx = pbfData.createGeometryEntity(intersection, (Map)null, (Map)extentMap);
Intrinsics.checkNotNullExpressionValue(geometryEntityxx, "geometryEntity");
geometryEntityxx.setLayerEntity(layerEntity);
geometryEntityxx.setName((String)extentMap.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityxx);
}
continue label141;
}
}
}
}
}
}
}
var40 = resultData.getObjectcrosswalkList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.objectcrosswalkList");
var9 = (Collection)var40;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "人行横道");
((Map)extentMapx).put(TYPE, "object_crosswalk");
var12 = resultData.getObjectcrosswalkList().iterator();
while(var12.hasNext()) {
Objectcrosswalk.ObjectCrossWalk objectCross = (Objectcrosswalk.ObjectCrossWalk)var12.next();
Intrinsics.checkNotNullExpressionValue(objectCross, "objectCross");
geometry = pbfData.createGeometry((GeneratedMessageV3)objectCross.getGeometry());
geometryEntityx = pbfData.createGeometryEntity(geometry, objectCross.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntityx, "geometryEntity");
geometryEntityx.setLayerEntity(layerEntity);
geometryEntityx.setName((String)extentMapx.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityx);
}
}
var40 = resultData.getObjectpoleList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.objectpoleList");
var9 = (Collection)var40;
HashMap extentMap3D;
Iterator var36;
Geometry geometryx;
GeometryFeatureEntity geometryEntityxxx;
GeometryFeatureEntity symbolEntity;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "杆状物");
((Map)extentMapx).put(TYPE, "object_pole");
extentMap3D = new HashMap();
((Map)extentMap3D).put(TYPE, "symbol_object_pole");
((Map)extentMap3D).put(NAME, "symbol_object_pole");
var36 = resultData.getObjectpoleList().iterator();
while(var36.hasNext()) {
Objectpole.ObjectPole objectPole = (Objectpole.ObjectPole)var36.next();
Intrinsics.checkNotNullExpressionValue(objectPole, "objectPole");
geometryx = pbfData.createGeometry((GeneratedMessageV3)objectPole.getGeometry());
geometryEntityxxx = pbfData.createGeometryEntity(geometryx, objectPole.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntityxxx, "geometryEntity");
geometryEntityxxx.setLayerEntity(layerEntity);
geometryEntityxxx.setName((String)extentMapx.get(TYPE));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityxxx);
Intrinsics.checkNotNullExpressionValue(geometryx, "geometry");
symbolEntity = pbfData.createGeometryEntity((Geometry)geometryx.getCentroid(), (Map)null, (Map)extentMap3D);
Intrinsics.checkNotNullExpressionValue(symbolEntity, "symbolEntity");
symbolEntity.setLayerEntity(layerEntity);
symbolEntity.setName((String)extentMap3D.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)symbolEntity);
}
}
var40 = resultData.getObjectsymbolList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.objectsymbolList");
var9 = (Collection)var40;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "对象标志");
((Map)extentMapx).put(TYPE, "object_symbol");
extentMap3D = new HashMap();
((Map)extentMap3D).put(NAME, "symbol_object_symbol");
((Map)extentMap3D).put(TYPE, "symbol_object_symbol");
var36 = resultData.getObjectsymbolList().iterator();
while(var36.hasNext()) {
Objectsymbol.ObjectSymbol objectSymbol = (Objectsymbol.ObjectSymbol)var36.next();
Intrinsics.checkNotNullExpressionValue(objectSymbol, "objectSymbol");
geometryx = pbfData.createGeometry((GeneratedMessageV3)objectSymbol.getGeometry());
geometryEntityxxx = pbfData.createGeometryEntity(geometryx, objectSymbol.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntityxxx, "geometryEntity");
geometryEntityxxx.setLayerEntity(layerEntity);
geometryEntityxxx.setName((String)extentMapx.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityxxx);
Intrinsics.checkNotNullExpressionValue(geometryx, "geometry");
symbolEntity = pbfData.createGeometryEntity((Geometry)geometryx.getCentroid(), (Map)null, (Map)extentMap3D);
Intrinsics.checkNotNullExpressionValue(symbolEntity, "symbolEntity");
symbolEntity.setLayerEntity(layerEntity);
symbolEntity.setName((String)extentMap3D.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)symbolEntity);
}
}
var40 = resultData.getObjecttrafficlightsList();
Intrinsics.checkNotNullExpressionValue(var40, "resultData.objecttrafficlightsList");
var9 = (Collection)var40;
if (!var9.isEmpty()) {
layerEntity = new LayerEntity();
layerEntity.setLayerName("test");
extentMapx = new HashMap();
((Map)extentMapx).put(NAME, "交通灯");
((Map)extentMapx).put(TYPE, "object_traffic");
extentMap3D = new HashMap();
((Map)extentMap3D).put(TYPE, "symbol_object_traffic");
((Map)extentMap3D).put(NAME, "symbol_object_traffic");
var36 = resultData.getObjecttrafficlightsList().iterator();
while(var36.hasNext()) {
Objecttrafficlights.ObjectTrafficLights objectTrrafic = (Objecttrafficlights.ObjectTrafficLights)var36.next();
Intrinsics.checkNotNullExpressionValue(objectTrrafic, "objectTrrafic");
geometryx = pbfData.createGeometry((GeneratedMessageV3)objectTrrafic.getGeometry());
geometryEntityxxx = pbfData.createGeometryEntity(geometryx, objectTrrafic.getAllFields(), (Map)extentMapx);
Intrinsics.checkNotNullExpressionValue(geometryEntityxxx, "geometryEntity");
geometryEntityxxx.setLayerEntity(layerEntity);
geometryEntityxxx.setName((String)extentMapx.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)geometryEntityxxx);
Intrinsics.checkNotNullExpressionValue(geometryx, "geometry");
symbolEntity = pbfData.createGeometryEntity((Geometry)geometryx.getCentroid(), (Map)null, (Map)extentMap3D);
Intrinsics.checkNotNullExpressionValue(symbolEntity, "symbolEntity");
symbolEntity.setLayerEntity(layerEntity);
symbolEntity.setName((String)extentMap3D.get(NAME));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).insertOrUpdate((RealmModel)symbolEntity);
}
}
long sqlEndTime = System.currentTimeMillis();
System.out.println(file + "All-Time:" + (sqlEndTime - sqlStartTime));
}
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.getInstance(var10000.getRealmConfiguration()).commitTransaction();
long endTime = System.currentTimeMillis();
System.out.println("All-Time:" + (endTime - startTime));
var10000 = RealmUtils.getInstance();
Intrinsics.checkNotNullExpressionValue(var10000, "RealmUtils.getInstance()");
Realm.compactRealm(var10000.getRealmConfiguration());
System.out.println("Arrow-All-Time: 数据处理结束");
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("success", true);
resultMap.put("msg", "导入成功");
resultMap.put("data", (endTime - startTime)+"");
return resultMap;
}
}

View File

@@ -0,0 +1,19 @@
package com.navinfo.collect.library.data.dao.impl
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.navinfo.collect.library.data.entity.CheckManager
@Dao
interface ICheckManagerDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg check: CheckManager?)
@Query("SELECT * FROM CheckManager where id =:id")
fun findCheckManagerById(id: Long): CheckManager?
@Query("SELECT * FROM CheckManager")
fun findList(): List<CheckManager>
}

View File

@@ -0,0 +1,68 @@
package com.navinfo.collect.library.data.dao.impl;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.navinfo.collect.library.data.entity.Element;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Dao
public interface IElementDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Element... elements);
@Update
int update(Element[] elements);
@Delete
int delete(Element elements);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void inserts(Element[] elements);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertList(List<Element> elementList);
@Query("DELETE FROM element")
void deleteAll();
@Query("DELETE FROM element where rowId>:start and rowId<:end")
void deleteAll(int start, int end);
@Query("SELECT * FROM element limit :start,:count")
List<Element> findList(int start, int count);
@Query("SELECT * FROM element where 1=1 limit :start,:count ")
Element[] findAll(int start, int count);
@Query("SELECT geometry FROM element where rowId>:value limit :start,:count")
String[] find(int value, int start, int count);
@Query("SELECT * FROM element where uuid =:uuid")
Element findById(String uuid);
@Query("SELECT * FROM element where uuid in (select element_uuid from tileElement where tilex>=:minx and tilex<=:maxx and tiley>=:miny and tiley <=:maxy)")
List<Element> findList(int minx, int maxx, int miny, int maxy);
@Query("SELECT * FROM element where uuid in (select distinct element_uuid from tileElement where tilex IN (:xList) and tiley IN (:yList))")
List<Element> findList(Set<Integer> xList, Set<Integer> yList);
@Query("SELECT * FROM element where display_text like '%'||:keyword||'%' limit :start,:count")
List<Element> findListByKeyword(String keyword, int start, int count);
@Query("SELECT * FROM element where display_text like '%'||:keyword||'%' and layer_id in (:layerIds) limit :start,:count")
List<Element> findListByKeywordLimitLayer(String keyword, Set<String> layerIds, int start, int count);
@Query("SELECT * FROM element where display_text like '%'||:keyword||'%' and layer_id in (Select uuid from layerManager where project_id in (:projectIds)) limit :start,:count")
List<Element> findListByKeywordLimitProject(String keyword, Set<String> projectIds, int start, int count);
}

View File

@@ -0,0 +1,51 @@
package com.navinfo.collect.library.data.dao.impl;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.navinfo.collect.library.data.entity.Element;
import com.navinfo.collect.library.data.entity.LayerManager;
import java.util.List;
import java.util.Set;
@Dao
public interface ILayerManagerDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(LayerManager... layerManagers);
@Update
int updates(LayerManager[] layerManagers);
@Update
int update(LayerManager layerManagers);
@Delete
int delete(LayerManager layerManagers);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void inserts(LayerManager[] layerManagers);
@Query("DELETE FROM layerManager")
void deleteAll();
@Query("DELETE FROM layerManager where rowId>:start and rowId<:end")
void deleteAll(int start, int end);
@Query("SELECT * FROM layerManager where visibility =:visable")
List<LayerManager> findList(int visable);
@Query("SELECT * FROM layerManager")
List<LayerManager> findList();
@Query("SELECT * FROM layerManager where project_id in(:projectIds)")
List<LayerManager> findListByProject(Set<String> projectIds);
@Query("SELECT * FROM layerManager where uuid =:id")
LayerManager findLayerManager(String id);
}

View File

@@ -0,0 +1,46 @@
package com.navinfo.collect.library.data.dao.impl;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.navinfo.collect.library.data.entity.Element;
import com.navinfo.collect.library.data.entity.NiLocation;
import java.util.List;
import java.util.Set;
@Dao
public interface INiLocationDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(NiLocation... niLocations);
@Update
int update(NiLocation niLocation);
@Update
int updateList(NiLocation[] niLocations);
@Delete
int delete(NiLocation niLocations);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void inserts(NiLocation[] niLocations);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertList(List<NiLocation> niLocationList);
@Query("DELETE FROM niLocation")
void deleteAll();
@Query("SELECT * FROM niLocation where uuid=:id ")
NiLocation find(String id);
@Query("SELECT * FROM niLocation where tilex>=:minx and tilex<=:maxx and tiley>=:miny and tiley <=:maxy")
List<NiLocation> findList(int minx, int maxx, int miny, int maxy);
@Query("SELECT * FROM niLocation where tilex>=:minx and tilex<=:maxx and tiley>=:miny and tiley <=:maxy and time>=:startTime and time<=:endTime")
List<NiLocation> timeTofindList(int minx, int maxx, int miny, int maxy,long startTime,long endTime);
}

View File

@@ -0,0 +1,37 @@
//package com.navinfo.collect.library.data.dao.impl;
//
//import androidx.room.Dao;
//import androidx.room.Delete;
//import androidx.room.Insert;
//import androidx.room.OnConflictStrategy;
//import androidx.room.Query;
//import androidx.room.Update;
//import com.navinfo.collect.library.data.entity.Project;
//import java.util.List;
//
//@Dao
//public interface IProjectDao {
// @Insert(onConflict = OnConflictStrategy.REPLACE)
// void insert(Project... projects);
//
// @Update
// int update(Project[] projects);
//
// @Delete
// int delete(Project projects);
//
// @Insert(onConflict = OnConflictStrategy.REPLACE)
// void inserts(Project[] projects);
//
// @Query("DELETE FROM project")
// void deleteAll();
//
// @Query("DELETE FROM project where rowId>:start and rowId<:end")
// void deleteAll(int start, int end);
//
// @Query("SELECT * FROM project")
// List<Project> findList();
//
// @Query("SELECT * FROM project where uuid =:id")
// Project findProject(String id);
//}

View File

@@ -0,0 +1,39 @@
package com.navinfo.collect.library.data.dao.impl;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.navinfo.collect.library.data.entity.Project;
import java.util.List;
@Dao
public interface IProjectManagerDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Project... projects);
@Update
int update(Project[] projects);
@Delete
int delete(Project project);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void inserts(Project[] projects);
@Query("DELETE FROM project")
void deleteAll();
@Query("SELECT * FROM project where project_visibility =:visable")
List<Project> findList(int visable);
@Query("SELECT * FROM project")
List<Project> findList();
@Query("SELECT * FROM project where uuid =:id")
Project findProject(String id);
}

View File

@@ -0,0 +1,41 @@
package com.navinfo.collect.library.data.dao.impl;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.navinfo.collect.library.data.entity.LayerManager;
import com.navinfo.collect.library.data.entity.TileElement;
import java.util.List;
@Dao
public interface ITileElementDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(TileElement... tileElements);
@Update
int update(TileElement[] tileElements);
@Delete
int delete(TileElement tileElements);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void inserts(TileElement[] tileElements);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertList(List<TileElement> tileElementList);
@Query("DELETE FROM tileElement")
void deleteAll();
@Query("DELETE FROM tileElement where element_uuid =:elementId")
void deleteElementId(String elementId);
@Query("DELETE FROM tileElement where rowId>:start and rowId<:end")
void deleteAll(int start,int end);
@Query("SELECT * FROM tileElement where element_uuid =:elementId")
List<TileElement> getElementIdList(String elementId);
}

View File

@@ -0,0 +1,220 @@
package com.navinfo.collect.library.data.dao.impl;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.navinfo.collect.library.data.entity.CheckManager;
import com.navinfo.collect.library.data.entity.Element;
import com.navinfo.collect.library.data.entity.LayerManager;
import com.navinfo.collect.library.data.entity.NiLocation;
import com.navinfo.collect.library.data.entity.Project;
import com.navinfo.collect.library.data.entity.TileElement;
import com.tencent.wcdb.database.SQLiteCipherSpec;
import com.tencent.wcdb.database.SQLiteDatabase;
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory;
import android.os.AsyncTask;
import android.util.Log;
import com.tencent.wcdb.repair.BackupKit;
import com.tencent.wcdb.repair.RecoverKit;
import com.tencent.wcdb.room.db.WCDBDatabase;
import java.util.ArrayList;
import java.util.List;
@Database(entities = {Element.class, TileElement.class, LayerManager.class, Project.class, NiLocation.class, CheckManager.class},version = 1, exportSchema = false)
public abstract class MapLifeDataBase extends RoomDatabase {
// marking the instance as volatile to ensure atomic access to the variable
/**
* 数据库单例对象
*/
private static volatile MapLifeDataBase INSTANCE;
/**
* 要素数据库类
*/
public abstract IElementDao getElementDao();
/**
* 地图坐标库类
*/
public abstract INiLocationDao getNiLocationDao();
/**
* 图层要素数据库类
*/
public abstract ITileElementDao getTileElementDao();
/**
* 图层数据库类
*/
public abstract ILayerManagerDao getLayerManagerDao();
/**
* 项目管理类
*
* @return
*/
public abstract IProjectManagerDao getProjectManagerDao();
/**
* 字段检查项
*/
public abstract ICheckManagerDao getCheckManagerDao();
/**
* 数据库秘钥
*/
private final static String DB_PASSWORD = "123456";
public static MapLifeDataBase getDatabase(final Context context, final String name) {
if (INSTANCE == null) {
synchronized (MapLifeDataBase.class) {
if (INSTANCE == null) {
// [WCDB] To use Room library with WCDB, pass a WCDBOpenHelper factory object
// to the database builder with .openHelperFactory(...). In the factory object,
// you can specify passphrase and cipher options to open or create encrypted
// database, as well as optimization options like asynchronous checkpoint.
SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec()
.setPageSize(1024)
.setSQLCipherVersion(3);
WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory()
.passphrase(DB_PASSWORD.getBytes()) // passphrase to the database, remove this line for plain-text
.cipherSpec(cipherSpec) // cipher to use, remove for default settings
.writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
.asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
MapLifeDataBase.class, name)
// [WCDB] Specify open helper to use WCDB database implementation instead
// of the Android framework.
.openHelperFactory(factory)
// Wipes and rebuilds instead of migrating if no Migration object.
// Migration is not part of this codelab.
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
/**
* Override the onOpen method to populate the database.
* For this sample, we clear the database every time it is created or opened.
* <p>
* If you want to populate the database only when the database is created for the 1st time,
* override RoomDatabase.Callback()#onCreate
*/
private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() {
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
// If you want to keep the data through app restarts,
// comment out the following line.
new PopulateDbAsync(INSTANCE).execute();
}
};
/**
* Populate the database in the background.
* If you want to start with more words, just add them.
*/
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private final ILayerManagerDao mLayerDao;
PopulateDbAsync(MapLifeDataBase db) {
mLayerDao = db.getLayerManagerDao();
}
@Override
protected Void doInBackground(final Void... params) {
// Start the app with a clean database every time.
// Not needed if you only populate on creation.
//mDao.deleteAll();
Log.e("qj", "doInBackground");
return null;
}
}
/**
* 数据恢复
*/
protected boolean recoverData(){
if(INSTANCE!=null){
SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
RecoverKit recover = new RecoverKit(
sqlite, // 要恢复到的目标 DB
sqlite.getPath() + "-backup", // 备份文件
DB_PASSWORD.getBytes() // 加密备份文件的密钥,非 DB 密钥
);
int result = recover.run(false); // fatal 参数传 false 表示遇到错误忽略并继续,
// 若传 true 遇到错误则中止并返回 FAILED
switch (result) {
case RecoverKit.RESULT_OK:
/* 成功 */
Log.e("qj","sRoomDatabaseCallback==RecoverKit成功");
return true;
case RecoverKit.RESULT_CANCELED: /* 取消操作 */
Log.e("qj","sRoomDatabaseCallback==RecoverKit取消操作");
break;
case RecoverKit.RESULT_FAILED: /* 失败 */
Log.e("qj","sRoomDatabaseCallback==RecoverKit失败");
break;
}
recover.release();
}
return false;
}
/**
* 备份数据
*/
protected boolean backup() {
Log.e("qj", "sRoomDatabaseCallback===backup==start");
if (INSTANCE != null) {
//备份文件
SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
BackupKit backup = new BackupKit(
sqlite, // 要备份的 DB
sqlite.getPath() + "-backup", // 备份文件
"123456".getBytes(), // 加密备份文件的密钥,非 DB 密钥
0, null);
int result = backup.run();
switch (result) {
case BackupKit.RESULT_OK:
/* 成功 */
Log.e("qj", "sRoomDatabaseCallback==成功");
return true;
case BackupKit.RESULT_CANCELED:
/* 取消操作 */
Log.e("qj", "sRoomDatabaseCallback==取消操作");
break;
case BackupKit.RESULT_FAILED:
/* 失败 */
Log.e("qj", "sRoomDatabaseCallback==失败");
break;
}
backup.release();
}
Log.e("qj", "sRoomDatabaseCallback===backup==end");
return false;
}
protected void release() {
INSTANCE = null;
}
}

View File

@@ -0,0 +1,6 @@
package com.navinfo.collect.library.data.db;
import androidx.room.RoomDatabase;
public abstract class CipherDataBase extends RoomDatabase {
}

View File

@@ -0,0 +1,4 @@
package com.navinfo.collect.library.data.db;
public interface GeometryDao {
}

View File

@@ -0,0 +1,47 @@
package com.navinfo.collect.library.data.db;
import com.navinfo.collect.library.utils.GeometryTools;
import org.locationtech.jts.geom.Geometry;
import java.util.UUID;
public class GeometryEntity {
private String id = UUID.randomUUID().toString();
private String name;
private String geometry;
private String layerName;
private String style;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGeometry() {
return geometry;
}
public void setGeometry(String wkt) {
if (wkt == null||wkt.isEmpty()) {
return;
}
Geometry geometry = GeometryTools.createGeometry(wkt);
setGeometry(geometry);
}
public void setGeometry(Geometry geometry) {
this.geometry = geometry.toString();
}
}

View File

@@ -0,0 +1,6 @@
package com.navinfo.collect.library.data.db;
public class GeometryProperties {
public String key;
public String value;
}

View File

@@ -0,0 +1,6 @@
package com.navinfo.collect.library.data.db;
public class GeometryTile {
public int tileX;
public int tileY;
}

View File

@@ -0,0 +1,25 @@
package com.navinfo.collect.library.data.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "CheckManager")
class CheckManager(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
//检查项类型
val type: Int,
//检查项名称
val tag: String,
//检查项正则内容
val regexStr: String
) {
fun toJson(): String {
return "{\"id\":$id,\"type\":$type,\"tag\":\"$tag\",\"regexStr\":\"$regexStr\"}"
}
fun toMap(): Map<String, *> {
return return mapOf("id" to id, "type" to type, "tag" to tag, "regexStr" to regexStr)
}
}

View File

@@ -0,0 +1,90 @@
package com.navinfo.collect.library.data.entity
enum class DataLayerItemType {
///未知类型
DataLayerItemTypeUnKnow,
///输入框
DataLayerItemTypeInput,
///输入框集合
DataLayerItemTypeInputArray,
///纯展示文本
DataLayerItemTypeText,
///单选框
DataLayerItemTypeSingleSelection,
///多选框
DataLayerItemTypeMultipleSelection,
///照片
DataLayerItemTypePhoto,
///多级菜单
DataLayerItemTypeMultiLevelMenu
}
data class CustomLayerItem(
///对应的数据库字段名称
val key: String,
///用来显示控件名称
val title: String = key,
///控件类型
val type: DataLayerItemType,
///非必填项
// val nullable: Boolean = true,
///是不是主键
// val primaryKey: Boolean = false,
///默认值
// var value: Any,
///多选或单选的内容,如果 [isSelect] 为 false 可忽略这字段
// var selectOptions: String,
///是否是主名称属性,设置为true地图上会已该字段内容渲染
// val isMainName: Boolean = false,
///简介
val describe: String,
val itemBean: String,
///检查项
// val checkManagerList: List<CheckManager>,
) {
fun toMap(): Map<String, *> {
// val checkManagerMapList = mutableListOf<Map<String, *>>()
// for (check in checkManagerList) {
// checkManagerMapList.add(check.toMap())
// }
return mapOf(
"key" to key,
"title" to title,
"type" to type.ordinal,
// "nullable" to nullable,
// "primaryKey" to primaryKey,
// "value" to value,
// "selectOptions" to selectOptions,
// "isMainName" to isMainName,
"describe" to describe,
// "checkManagerList" to checkManagerMapList,
)
}
companion object {
// fun fromJson(json:JSONObject): CustomLayerItem {
// return CustomLayerItem()
// }
}
}
//class DataLayerItemTypeAdapter {
// @ToJson
// fun toJson(enum: DataLayerItemType): Int {
// return enum.ordinal;
// }
//
// @FromJson
// fun fromJson(type: Int): DataLayerItemType {
// return DataLayerItemType.values()[type];
// }
//}

View File

@@ -0,0 +1,24 @@
package com.navinfo.collect.library.data.entity;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import java.util.UUID;
public class DataBase extends Feature {
@ColumnInfo(name = "geometry")
private String geometry;
public String getGeometry() {
return geometry;
}
public void setGeometry(String geometry) {
this.geometry = geometry;
}
}

View File

@@ -0,0 +1,219 @@
package com.navinfo.collect.library.data.entity;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import com.google.protobuf.Any;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @author qj
* @version V1.0
* @ClassName: Element
* @Date 2022/4/14
* @Description: ${Element}(要素数据)
*/
//@Entity(tableName = "element",indices = {@Index("visibility"),@Index(value = {"maxx", "minx", "maxy", "miny"})})
@Entity(tableName = "element", indices = {@Index("visibility")})
public class Element extends DataBase {
@ColumnInfo(name = "layer_id")
private String LayerId;
@ColumnInfo(name = "display_style")
private String DisplayStyle;
@ColumnInfo(name = "display_text")
private String DisplayText;
@ColumnInfo(name = "start_level")
private int StartLevel;
@ColumnInfo(name = "end_level")
private int EndLevel;
@ColumnInfo(name = "zindex")
private int ZIndex;
@ColumnInfo(name = "visibility")
private int Visibility;
@ColumnInfo(name = "operation_time")
private String OperationTime;
@ColumnInfo(name = "export_time")
private String ExportTime;
@ColumnInfo(name = "t_lifecycle")
private int TLifecycle;
@ColumnInfo(name = "t_status")
private int TStatus;
@Ignore
private Map<String, String> values;
public Map<String, String> getValues() {
return values;
}
public void setValues(Map<String, String> values) {
this.values = values;
}
public String getLayerId() {
return LayerId;
}
public void setLayerId(String layerId) {
this.LayerId = layerId;
}
public String getDisplayStyle() {
return DisplayStyle;
}
public void setDisplayStyle(String displayStyle) {
DisplayStyle = displayStyle;
}
public String getDisplayText() {
return DisplayText;
}
public void setDisplayText(String displayText) {
DisplayText = displayText;
}
public int getStartLevel() {
return StartLevel;
}
public void setStartLevel(int startLevel) {
StartLevel = startLevel;
}
public int getEndLevel() {
return EndLevel;
}
public void setEndLevel(int endLevel) {
EndLevel = endLevel;
}
public int getZIndex() {
return ZIndex;
}
public void setZIndex(int ZIndex) {
this.ZIndex = ZIndex;
}
public int getVisibility() {
return Visibility;
}
public void setVisibility(int visibility) {
Visibility = visibility;
}
public String getOperationTime() {
return OperationTime;
}
public void setOperationTime(String operationTime) {
OperationTime = operationTime;
}
public String getExportTime() {
return ExportTime;
}
public void setExportTime(String exportTime) {
ExportTime = exportTime;
}
public int getTLifecycle() {
return TLifecycle;
}
public void setTLifecycle(int TLifecycle) {
this.TLifecycle = TLifecycle;
}
public int getTStatus() {
return TStatus;
}
public void setTStatus(int TStatus) {
this.TStatus = TStatus;
}
@NotNull
public Map toMap() {
Map map = new HashMap();
map.put("layerId", LayerId);
map.put("uuid", getId());
map.put("geometry", getGeometry());
map.put("displayText", DisplayText);
map.put("displayStyle", DisplayStyle);
map.put("tOperateDate", OperationTime);
map.put("tLifecycle", TLifecycle);
map.put("tStatus", TStatus);
map.put("values", values);
return map;
}
public static Element fromMap(Map<String, Object> map) {
try {
Element element = new Element();
element.setLayerId((String) map.get("layerId"));
element.setId((String) map.get("uuid"));
element.setGeometry((String) map.get("geometry"));
element.setDisplayText((String) map.get("displayText"));
element.setDisplayStyle((String) map.get("displayStyle"));
element.setOperationTime((String) map.get("tOperateDate"));
element.setTLifecycle((Integer) map.get("tLifecycle"));
element.setTStatus((Integer) map.get("tStatus"));
return element;
} catch (Exception e) {
return null;
}
}
public static Element fromJson(String json) {
try {
JSONObject jsonObject = new JSONObject(json);
return fromJson(jsonObject);
} catch (Exception e) {
return null;
}
}
public static Element fromJson(JSONObject jsonObject) {
Element element = new Element();
element.setLayerId(jsonObject.optString("layerId"));
element.setId(jsonObject.optString("uuid"));
element.setGeometry(jsonObject.optString("geometry"));
element.setDisplayText(jsonObject.optString("displayText"));
element.setDisplayStyle(jsonObject.optString("displayStyle"));
element.setOperationTime(jsonObject.optString("tOperateDate"));
element.setTLifecycle(jsonObject.optInt("tLifecycle"));
element.setTStatus(jsonObject.optInt("tStatus"));
return element;
}
}

View File

@@ -0,0 +1,39 @@
package com.navinfo.collect.library.data.entity;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.PrimaryKey;
import java.io.Serializable;
import java.util.UUID;
/**
* @author qj
* @version V1.0
* @ClassName: Feature
* @Date 2022/4/14
* @Description: ${TODO}(数据基类)
*/
public class Feature implements Serializable, Cloneable {
// //主键
// @PrimaryKey(autoGenerate = true)
// public int rowId;
@PrimaryKey()
@ColumnInfo(name = "uuid")
@NonNull
private String id = UUID.randomUUID().toString();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View File

@@ -0,0 +1,237 @@
package com.navinfo.collect.library.data.entity;
import com.navinfo.collect.library.system.Constant;
import com.navinfo.collect.library.utils.GeometryTools;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.oscim.core.MercatorProjection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import io.realm.RealmDictionary;
import io.realm.RealmObject;
import io.realm.RealmSet;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
public class GeometryFeatureEntity extends RealmObject implements Cloneable {
@PrimaryKey
private String id = UUID.randomUUID().toString();
private String name;
@Required
private String geometry;
private byte[] wkb;
private double xmax;
private double xmin;
private double ymax;
private double ymin;
private LayerEntity layerEntity;
private RealmSet<Integer> tileX = new RealmSet<>();
private RealmSet<Integer> tileY = new RealmSet<>();
private RealmDictionary<String> properties = new RealmDictionary<>();
private RealmDictionary<String> otherProperties = new RealmDictionary<>();
public GeometryFeatureEntity() {
}
public GeometryFeatureEntity(String name, String geometry) {
this.name = name;
this.geometry = geometry;
}
public GeometryFeatureEntity(String name, String geometry, double xmax, double xmin, double ymax, double ymin) {
this.name = name;
this.geometry = geometry;
this.xmax = xmax;
this.xmin = xmin;
this.ymax = ymax;
this.ymin = ymin;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getXmax() {
return xmax;
}
public void setXmax(double xmax) {
this.xmax = xmax;
}
public double getXmin() {
return xmin;
}
public void setXmin(double xmin) {
this.xmin = xmin;
}
public double getYmax() {
return ymax;
}
public void setYmax(double ymax) {
this.ymax = ymax;
}
public double getYmin() {
return ymin;
}
public void setYmin(double ymin) {
this.ymin = ymin;
}
public Map<String, String> getProperties() {
if (this.properties == null) {
this.properties = new RealmDictionary<>();
}
return properties;
}
public void addProperties(String k, String v) {
this.properties.put(k, v);
}
public RealmDictionary<String> getOtherProperties() {
if (this.otherProperties == null) {
this.otherProperties = new RealmDictionary<>();
}
return otherProperties;
}
public String getGeometry() {
return geometry;
}
public void setGeometry(String wkt) {
if (wkt == null||wkt.isEmpty()) {
return;
}
Geometry geometry = GeometryTools.createGeometry(wkt);
setGeometry(geometry);
}
public void setGeometry(Geometry geometry) {
this.geometry = geometry.toString();
// 每一次对geometry的更新都会影响到数据的瓦片编号记录数据的20级瓦片编号
getTileXByGeometry(geometry, tileX);
getTileYByGeometry(geometry, tileY);
Envelope envelope = geometry.getBoundary().getEnvelopeInternal();
setXmin(envelope.getMinX());
setXmax(envelope.getMaxX());
setYmin(envelope.getMinY());
setYmax(envelope.getMaxY());
}
public LayerEntity getLayerEntity() {
return layerEntity;
}
public void setLayerEntity(LayerEntity layerEntity) {
this.layerEntity = layerEntity;
}
/**
* 根据给定的geometry计算其横跨的20级瓦片X值
* */
private Set<Integer> getTileXByGeometry(Geometry geometry, Set<Integer> tileXSet) {
// long startTime = System.currentTimeMillis();
if (tileXSet == null) {
tileXSet = new RealmSet<>();
}
if (geometry!=null) {
Geometry envelope = geometry.getEnvelope();
if (envelope!=null) {
Coordinate[] coordinates = envelope.getCoordinates();
// 最小最大x轴坐标索引0位最小x值索引1位最大x值
if (coordinates!=null&&coordinates.length>0) {
double[] minMaxX = new double[]{coordinates[0].x, coordinates[0].x};
for (Coordinate coordinate: coordinates) {
// 获取最大和最小x的值
if (coordinate.x<minMaxX[0]) {
minMaxX[0] = coordinate.x;
}
if (coordinate.x>minMaxX[1]) {
minMaxX[1] = coordinate.x;
}
}
// 分别计算最大和最小x值对应的tile号
int tileX0 = MercatorProjection.longitudeToTileX(minMaxX[0], (byte) Constant.OVER_ZOOM);
int tileX1 = MercatorProjection.longitudeToTileX(minMaxX[1], (byte) Constant.OVER_ZOOM);
int minTileX = tileX0 <= tileX1? tileX0: tileX1;
int maxTileX = tileX0 <= tileX1? tileX1: tileX0;
for (int i = minTileX; i <= maxTileX; i++) {
tileXSet.add(i);
}
}
}
}
// System.out.println("XGeometry-time:"+(System.currentTimeMillis()-startTime));
return tileXSet;
}
/**
* 根据给定的geometry计算其横跨的20级瓦片Y值
* */
private Set<Integer> getTileYByGeometry(Geometry geometry, Set<Integer> tileYSet) {
// long startTime = System.currentTimeMillis();
if (tileYSet == null) {
tileYSet = new RealmSet<>();
}
Geometry envelope = geometry.getEnvelope();
if (envelope!=null) {
Coordinate[] coordinates = envelope.getCoordinates();
// 最小最大x轴坐标索引0位最小x值索引1位最大y值
if (coordinates!=null&&coordinates.length>0) {
double[] minMaxY = new double[]{coordinates[0].y, coordinates[0].y};
for (Coordinate coordinate: coordinates) {
// 获取最大和最小y的值
if (coordinate.y<minMaxY[0]) {
minMaxY[0] = coordinate.y;
}
if (coordinate.y>minMaxY[1]) {
minMaxY[1] = coordinate.y;
}
}
// 分别计算最大和最小x值对应的tile号
int tileY0 = MercatorProjection.latitudeToTileY(minMaxY[0], (byte) Constant.OVER_ZOOM);
int tileY1 = MercatorProjection.latitudeToTileY(minMaxY[1], (byte) Constant.OVER_ZOOM);
int minTileY = tileY0 <= tileY1? tileY0: tileY1;
int maxTileY = tileY0 <= tileY1? tileY1: tileY0;
for (int i = minTileY; i <= maxTileY; i++) {
tileYSet.add(i);
}
}
}
// System.out.println("YGeometry-time:"+(System.currentTimeMillis()-startTime));
return tileYSet;
}
public byte[] getWkb() {
return wkb;
}
public void setWkb(byte[] wkb) {
this.wkb = wkb;
}
}

View File

@@ -0,0 +1,81 @@
package com.navinfo.collect.library.data.entity;
import androidx.room.ColumnInfo;
import androidx.room.TypeConverter;
import java.io.Serializable;
import java.util.Objects;
/**
* @author qj
* @version V1.0
* @ClassName: GeometryEntity
* @Date 2022/4/14
* @Description: ${TODO}(几何基类)
*/
public class GeometryIndexEntity implements Serializable,Cloneable{
@ColumnInfo(name = "geometry")
private String geometry;
@ColumnInfo(name = "xmax")
private double xMax;
@ColumnInfo(name = "xmin")
private double xMin;
@ColumnInfo(name = "ymax")
private double yMax;
@ColumnInfo(name = "ymin")
private double yMin;
public String getGeometry() {
return geometry;
}
public void setGeometry(String geometry) {
this.geometry = geometry;
}
public double getxMax() {
return xMax;
}
public void setxMax(double xMax) {
this.xMax = xMax;
}
public double getxMin() {
return xMin;
}
public void setxMin(double xMin) {
this.xMin = xMin;
}
public double getyMax() {
return yMax;
}
public void setyMax(double yMax) {
this.yMax = yMax;
}
public double getyMin() {
return yMin;
}
public void setyMin(double yMin) {
this.yMin = yMin;
}
public GeometryIndexEntity() {
super();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
}
}

View File

@@ -0,0 +1,66 @@
package com.navinfo.collect.library.data.entity;
import org.locationtech.jts.geom.Geometry;
import java.util.List;
import java.util.UUID;
import io.realm.RealmObject;
import io.realm.annotations.Ignore;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.Required;
public class LayerEntity extends RealmObject {
@Required
@PrimaryKey
private String layerName;
private String fromDataName;
private int GeomType;
private String layerTableName;
@Ignore
private List<Geometry> featureList;
public LayerEntity() {
}
public String getLayerName() {
return layerName;
}
public void setLayerName(String layerName) {
this.layerName = layerName;
}
public String getFromDataName() {
return fromDataName;
}
public void setFromDataName(String fromDataName) {
this.fromDataName = fromDataName;
}
public int getGeomType() {
return GeomType;
}
public void setGeomType(int geomType) {
GeomType = geomType;
}
public List<Geometry> getFeatureList() {
return featureList;
}
public void setFeatureList(List<Geometry> featureList) {
this.featureList = featureList;
}
public String getLayerTableName() {
return layerTableName;
}
public void setLayerTableName(String layerTableName) {
this.layerTableName = layerTableName;
}
}

View File

@@ -0,0 +1,199 @@
package com.navinfo.collect.library.data.entity;
import android.util.Log;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import org.jetbrains.annotations.Nullable;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* @author qj
* @version V1.0
* @ClassName: LayerManager
* @Date 2022/4/14
* @Description: ${LayerManager}(图层管理)
*/
@Entity(tableName = "layerManager")
public class LayerManager extends Feature {
///项目Id
@ColumnInfo(name = "project_id")
private String projectId;
///图层名称
@ColumnInfo(name = "layer_name")
private String layerName;
///图层级别
@ColumnInfo(name = "zindex")
private int ZIndex;
///图层是否显示
@ColumnInfo(name = "visibility")
private boolean visibility;
///导出时间
@ColumnInfo(name = "export_time")
private String exportTime;
///导入时间
@ColumnInfo(name = "import_time")
private String importTime;
@ColumnInfo(name = "bundle")
private String bundle;
///图层表述信息
@ColumnInfo(name = "describe")
private String describe;
///点线面类型
@ColumnInfo(name = "geometryType")
private int geometryType;
///来源c
@ColumnInfo(name = "source")
private String source;
@ColumnInfo(name = "style")
private String style;
///每个字段的样式和控制条件
@Ignore
private List<CustomLayerItem> itemList;
public List<CustomLayerItem> getItemList() {
return itemList;
}
public void setItemList(List<CustomLayerItem> itemList) {
this.itemList = itemList;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public void setDescribe(String describe) {
this.describe = describe;
}
public String getDescribe() {
return describe;
}
public int getGeometryType() {
return geometryType;
}
public void setGeometryType(int geometryType) {
this.geometryType = geometryType;
}
public String getLayerName() {
return layerName;
}
public void setLayerName(String layerName) {
this.layerName = layerName;
}
public int getZIndex() {
return ZIndex;
}
public void setZIndex(int zIndex) {
this.ZIndex = zIndex;
}
public boolean getVisibility() {
return visibility;
}
public void setVisibility(boolean visibility) {
this.visibility = visibility;
}
public String getExportTime() {
return exportTime;
}
public void setExportTime(String exportTime) {
this.exportTime = exportTime;
}
public String getImportTime() {
return importTime;
}
public void setImportTime(String importTime) {
this.importTime = importTime;
}
public String getBundle() {
return bundle;
}
public void setBundle(String bundle) {
this.bundle = bundle;
}
public String getProjectId() {
return projectId;
}
public void setProjectId(String projectId) {
this.projectId = projectId;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
@Override
public String toString() {
return "LayerManager{" +
"id='" + getId() + '\'' +
",projectId='" + projectId + '\'' +
", layerName='" + layerName + '\'' +
", ZIndex=" + ZIndex +
", visibility=" + visibility +
", exportTime='" + exportTime + '\'' +
", importTime='" + importTime + '\'' +
", bundle='" + bundle + '\'' +
", describe='" + describe + '\'' +
", geometryType='" + geometryType + '\'' +
", source='" + source + '\'' +
", style='" + style + '\'' +
'}';
}
public Map toMap() {
Map map = new HashMap();
map.put("uuid", getId());
map.put("layerName", getLayerName());
map.put("ZIndex", ZIndex);
map.put("visibility", getVisibility());
map.put("exportTime", exportTime);
map.put("import_time", getImportTime());
map.put("describe", getDescribe());
map.put("geometryType", getGeometryType());
map.put("source", source);
map.put("style", style);
return map;
}
}

View File

@@ -0,0 +1,55 @@
package com.navinfo.collect.library.data.entity;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class LayerProperties {
private String name;
private int fieldType = FieldType.STRING.getTypeCode(); /*默认是字符串类型*/
public LayerProperties() {
}
public enum FieldType {
STRING(0), NUM(1);
int typeCode;
FieldType(int typeCode) {
this.typeCode = typeCode;
}
public int getTypeCode() {
return typeCode;
}
public FieldType getFieldType(int typeCode) {
for (FieldType fieldType: FieldType.values()) {
if (fieldType.getTypeCode() == typeCode) {
return fieldType;
}
}
return FieldType.STRING;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public FieldType getFieldType() {
FieldType fieldType = FieldType.STRING;
try {
fieldType = fieldType.getFieldType(this.fieldType);
} catch (Exception e) {
}
return fieldType;
}
public void setFieldType(FieldType fieldType) {
this.fieldType = fieldType.typeCode;
}
}

View File

@@ -0,0 +1,300 @@
package com.navinfo.collect.library.data.entity;
import android.os.Bundle;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Index;
/**
* 表示地图的地理位置类。
*/
@Entity(tableName = "niLocation", indices = {@Index("tilex"),@Index("tiley")})
public class NiLocation extends Feature{
@ColumnInfo(name = "longitude")
private double longitude;//纬度坐标
@ColumnInfo(name = "latitude")
private double latitude;//经度坐标
@ColumnInfo(name = "direction")
private double direction;//定位方位
@ColumnInfo(name = "altitude")
private double altitude;//海拔高度 如果返回0.0,说明没有返回海拔高度
@ColumnInfo(name = "radius")
private double radius;//定位精度
@ColumnInfo(name = "time")
private String time;//定位时间 毫秒时间距离1970年 1月 1日 00:00:00 GMT的时间
@ColumnInfo(name = "adCode")
private String adCode;// 区域编码
@ColumnInfo(name = "country")
private String country;// 所属国家
@ColumnInfo(name = "province")
private String province;// 所属省名称
@ColumnInfo(name = "city")
private String city;// 所属城市名称
@ColumnInfo(name = "district")
private String district;// 所属区(县)名称
@ColumnInfo(name = "cityCode")
private String cityCode;// 城市编码
@ColumnInfo(name = "provider")
private String provider;// 提供者名称
@ColumnInfo(name = "speed")
private float speed;// 定位速度
@ColumnInfo(name = "floor")
private String floor;// 楼层
@ColumnInfo(name = "poiId")
private String poiId;// 室内地图POI的id
@ColumnInfo(name = "satelliteNumber")
private int satelliteNumber;// 卫星数目
@ColumnInfo(name = "address")
private String address;// 地址
@ColumnInfo(name = "street")
private String street;// 乡镇
@ColumnInfo(name = "town")
private String town;// 街道
@ColumnInfo(name = "streetNumber")
private String streetNumber;// 街道号码
@ColumnInfo(name = "errorInfo")
private String errorInfo;// 定位失败描述信息
@ColumnInfo(name = "errorCode")
private String errorCode;// 错误码
@ColumnInfo(name = "tilex")
private int tilex;
@ColumnInfo(name = "tiley")
private int tiley;
private boolean isAccouracy;
private boolean isSpeed;
private boolean isAltitude;
private boolean isBearing;
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getDirection() {
return direction;
}
public void setDirection(double direction) {
this.direction = direction;
}
public double getAltitude() {
return altitude;
}
public void setAltitude(double altitude) {
this.altitude = altitude;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getAdCode() {
return adCode;
}
public void setAdCode(String adCode) {
this.adCode = adCode;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getProvider() {
return provider;
}
public void setProvider(String provider) {
this.provider = provider;
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
public String getFloor() {
return floor;
}
public void setFloor(String floor) {
this.floor = floor;
}
public String getPoiId() {
return poiId;
}
public void setPoiId(String poiId) {
this.poiId = poiId;
}
public int getSatelliteNumber() {
return satelliteNumber;
}
public void setSatelliteNumber(int satelliteNumber) {
this.satelliteNumber = satelliteNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public boolean isAccouracy() {
return isAccouracy;
}
public void setAccouracy(boolean accouracy) {
isAccouracy = accouracy;
}
public boolean isSpeed() {
return isSpeed;
}
public void setSpeed(boolean speed) {
isSpeed = speed;
}
public boolean isAltitude() {
return isAltitude;
}
public void setAltitude(boolean altitude) {
isAltitude = altitude;
}
public boolean isBearing() {
return isBearing;
}
public void setBearing(boolean bearing) {
isBearing = bearing;
}
public int getTilex() {
return tilex;
}
public void setTilex(int tilex) {
this.tilex = tilex;
}
public int getTiley() {
return tiley;
}
public void setTiley(int tiley) {
this.tiley = tiley;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
public String getStreetNumber() {
return streetNumber;
}
public void setStreetNumber(String streetNumber) {
this.streetNumber = streetNumber;
}
public String getErrorInfo() {
return errorInfo;
}
public void setErrorInfo(String errorInfo) {
this.errorInfo = errorInfo;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}

View File

@@ -0,0 +1,77 @@
package com.navinfo.collect.library.data.entity;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
/**
* 项目
*/
@Entity(tableName = "project")
public class Project extends Feature {
//项目名称
@ColumnInfo(name = "project_name")
private String name;
///创建时间
@ColumnInfo(name = "project_time")
private String createTime;
///项目描述信息
@ColumnInfo(name = "project_describe")
private String describe;
///项目是否显示
@ColumnInfo(name = "project_visibility")
private boolean visibility;
///任务圈
@ColumnInfo(name = "project_geometry")
private String geometry;
///任务圈显隐
@ColumnInfo(name = "project_geometry_visibility")
private boolean geometryVisibility;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
public boolean getVisibility() {
return visibility;
}
public void setVisibility(boolean visibility) {
this.visibility = visibility;
}
public String getGeometry() {
return geometry;
}
public void setGeometry(String geometry) {
this.geometry = geometry;
}
public boolean getGeometryVisibility() {
return geometryVisibility;
}
public void setGeometryVisibility(boolean geometryVisibility) {
this.geometryVisibility = geometryVisibility;
}
}

View File

@@ -0,0 +1,72 @@
package com.navinfo.collect.library.data.entity;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import java.util.Objects;
import java.util.UUID;
/**
* @author qj
* @version V1.0
* @ClassName: TileElement
* @Date 2022/4/14
* @Description: ${TileElement}(关联表)
*/
@Entity(tableName = "tileElement",indices = {@Index("tilex"),@Index("tiley"),@Index("element_uuid")})
public class TileElement extends Feature{
@ColumnInfo(name = "tilex")
private int tilex;
@ColumnInfo(name = "tiley")
private int tiley;
@ColumnInfo(name = "element_uuid")
private String elementId;
public int getTilex() {
return tilex;
}
public void setTilex(int tilex) {
this.tilex = tilex;
}
public int getTiley() {
return tiley;
}
public void setTiley(int tiley) {
this.tiley = tiley;
}
public String getElementId() {
return elementId;
}
public void setElementId(String elementId) {
this.elementId = elementId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TileElement that = (TileElement) o;
return tilex == that.tilex && tiley == that.tiley && Objects.equals(elementId, that.elementId);
}
@Override
public int hashCode() {
return Objects.hash(tilex, tiley, elementId);
}
@Override
public String toString() {
return "TileElement{" +
"tilex=" + tilex +
", tiley=" + tiley +
", elementId='" + elementId + '\'' +
'}';
}
}

View File

@@ -0,0 +1,141 @@
package com.navinfo.collect.library.data.flutter
import android.content.Context
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.data.NIDataController
import com.navinfo.collect.library.data.flutter.flutterhandler.*
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterDataController(
id: Int,
context: Context,
binaryMessenger: BinaryMessenger,
activity: FlutterBaseActivity,
) : NIDataController(context, activity), MethodChannel.MethodCallHandler {
private val mMethodChannel: MethodChannel = MethodChannel(
binaryMessenger,
"com.navinfo.collect/data_$id"
)
private val flutterDataLayerHandler: FlutterDataLayerHandler
private val flutterDataElementHandler: FlutterDataElementHandler
private val flutterDataProjectHandler: FlutterDataProjectHandler
private val flutterDataNiLocationHandler: FlutterDataNiLocationHandler
val flutterDataCameraHandler: FlutterDataCameraHandler
init {
mMethodChannel.setMethodCallHandler(this)
flutterDataLayerHandler = FlutterDataLayerHandler(mContext, mDateBase)
flutterDataElementHandler = FlutterDataElementHandler(mContext, mMethodChannel, mDateBase)
flutterDataProjectHandler = FlutterDataProjectHandler(mContext, mDateBase)
flutterDataNiLocationHandler = FlutterDataNiLocationHandler(mContext, mDateBase)
flutterDataCameraHandler =
FlutterDataCameraHandler(mContext, mMethodChannel, activity, mDateBase)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
/**
* 数据图层操作部分
*/
//创建数据图层
FlutterDataProtocolKeys.DateLayerProtocol.kDataCreateDataLayer -> {
flutterDataLayerHandler.createDataLayerTable(call, result);
}
//获取所有数据图层
FlutterDataProtocolKeys.DateLayerProtocol.kDataGetDataLayerList -> {
flutterDataLayerHandler.getDataLayerList(call, result);
}
//获取某个数据图层
FlutterDataProtocolKeys.DateLayerProtocol.kDataGetDataLayer -> {
flutterDataLayerHandler.getDataLayer(call, result);
}
/**
* 数据操作部分
*/
//保存数据
FlutterDataProtocolKeys.DataElementProtocol.kDataSaveElementData -> {
flutterDataElementHandler.saveElementData(call, result)
}
//删除数据
FlutterDataProtocolKeys.DataElementProtocol.kDataDeleteElementData -> {
flutterDataElementHandler.deleteElementData(call, result)
}
//捕捉数据
FlutterDataProtocolKeys.DataElementProtocol.kDataSnapElementDataList -> {
flutterDataElementHandler.snapElementDataList(call, result)
}
// 导入Pbf数据
FlutterDataProtocolKeys.DataElementProtocol.kImportPbfData -> {
flutterDataElementHandler.importPbfData2Realm(call, result)
}
//查询数据详细信息模板
FlutterDataProtocolKeys.DataElementProtocol.kDataQueryElementDeepInfo -> {
flutterDataElementHandler.queryElementDeepInfo(call, result)
}
//数据搜索
FlutterDataProtocolKeys.DataElementProtocol.kDataSearchData -> {
flutterDataElementHandler.searchData(call, result)
}
/**
* 项目管理
*/
//获取项目列表
FlutterDataProtocolKeys.DataProjectProtocol.kDataGetDataProjectList -> {
flutterDataProjectHandler.getProjectList(call, result);
}
//保存项目
FlutterDataProtocolKeys.DataProjectProtocol.kDataSaveDataProject -> {
flutterDataProjectHandler.saveProject(call, result);
}
/**
* 轨迹操作部分
*/
//保存轨迹数据
FlutterDataProtocolKeys.DataNiLocationProtocol.kDataSaveNiLocationData -> {
flutterDataNiLocationHandler.saveNiLocationData(call, result)
}
/**
* 检查项部分
*/
//获取所有检查项
FlutterDataProtocolKeys.DataCheckProtocol.kDataGetCheckManagerList -> {
flutterDataElementHandler.queryCheckManagerList(call, result)
}
//根据id获取检查项
FlutterDataProtocolKeys.DataCheckProtocol.kDataGetCheckManagerListByIds -> {
flutterDataElementHandler.queryCheckManagerListByIds(call, result)
}
//打开摄像头
FlutterDataProtocolKeys.DataCameraProtocol.kDataOpenCamera -> {
flutterDataCameraHandler.openCamera(call, result)
}
///ocr批量识别
FlutterDataProtocolKeys.DataCameraProtocol.kDataOCRBatchResults -> {
flutterDataCameraHandler.ocrBatch(call, result)
}
}
}
override fun release() {
super.release()
mMethodChannel.setMethodCallHandler(null)
}
}

View File

@@ -0,0 +1,94 @@
package com.navinfo.collect.library.data.flutter
object FlutterDataProtocolKeys {
/**
* 数据图层管理
*/
object DateLayerProtocol {
/**
* 获取数据层列表
*/
const val kDataGetDataLayerList = "flutter_nimap/DataLayer/getDataLayerList";
/**
* 获取某个数据层列表
*/
const val kDataGetDataLayer = "flutter_nimap/DataLayer/getDataLayer";
/**
* 创建数据层
*/
const val kDataCreateDataLayer = "flutter_nimap/DataLayer/createDataLayer";
}
/**
* 数据操作
*/
object DataElementProtocol {
//保存数据
const val kDataSaveElementData = "flutter_nimap/ElementData/saveElementData";
///删除数据
const val kDataDeleteElementData = "flutter_nimap/ElementData/deleteElementData";
//查询数据
const val kDataSnapElementDataList = "flutter_nimap/ElementData/snapElementDataList";
// 导入pbf数据
const val kImportPbfData = "flutter_nimap/HDData/importPBF";
//查询数据详细信息
const val kDataQueryElementDeepInfo = "flutter_nimap/ElementData/queryElementDeepInfo";
///按名称搜索数据
const val kDataSearchData = "flutter_nimap/ElementData/queryElementByName"
}
/**
* 数据操作
*/
object DataNiLocationProtocol {
//保存数据
const val kDataSaveNiLocationData = "flutter_nimap/NiLocationData/saveNiLocationData";
///删除数据
const val kDataDeleteNiLocationData = "flutter_nimap/NiLocationData/deleteNiLocationData";
}
object DataProjectProtocol {
/**
* 获取项目列表
*/
const val kDataGetDataProjectList = "flutter_nimap/Project/getDataProjectList";
/**
* 保存项目
*/
const val kDataSaveDataProject = "flutter_nimap/Project/saveDataProject";
}
object DataCheckProtocol {
///获取检查项列表
const val kDataGetCheckManagerList = "flutter_nimap/CheckManager/getDataCheckManagerList";
///根据id获取检查项列表
const val kDataGetCheckManagerListByIds =
"flutter_nimap/CheckManager/getDataCheckManagerListByIds";
}
object DataCameraProtocol {
const val kDataOpenCamera = "flutter_nimap/openCamera";
const val kDataOCRResults = "flutter_nimap/ocrResults";
///批量识别
const val kDataOCRBatchResults = "flutter_nimap/ocrBatch";
///ocr 批量回调进度
const val kDataOCRBatchProgress = "flutter_nimap/ocrBatchProgress";
}
}

View File

@@ -0,0 +1,67 @@
package com.navinfo.collect.library.data.flutter.flutterhandler
import android.content.Context
import android.util.Log
import com.baidu.ai.edge.ui.view.model.BasePolygonResultModel
import com.baidu.ai.edge.ui.view.model.OcrViewResultModel
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.flutter.FlutterDataProtocolKeys
import com.navinfo.collect.library.data.handler.DataCameraHandler
import com.navinfo.collect.library.data.handler.OnOCRBatchListener
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterDataCameraHandler(
context: Context,
methodChannel: MethodChannel,
activity: FlutterBaseActivity,
dataBase: MapLifeDataBase
) :
DataCameraHandler(context, activity, dataBase) {
private val _methodChannel = methodChannel
fun openCamera(call: MethodCall, result: MethodChannel.Result) {
super.openCamera()
result.success(true)
}
fun sendOcrResults(path: String, basePolygonResultModels: List<BasePolygonResultModel>) {
_methodChannel.invokeMethod(
FlutterDataProtocolKeys.DataCameraProtocol.kDataOCRResults,
DataConversion.toOcrList(path, basePolygonResultModels)
)
}
fun ocrBatch(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is String) {
super.ocrBatch(
call.arguments as String,
object : OnOCRBatchListener {
override fun onProgress(total: Int, current: Int) {
Log.e("jingo", "OCRManager 线程名称2 ${Thread.currentThread().name}")
Log.e("jingo", "OCR识别 当前第 $current 张,总共 $total");
val map = mutableMapOf<String, Int>()
map["total"] = total
map["current"] = current + 1
_methodChannel.invokeMethod(
FlutterDataProtocolKeys.DataCameraProtocol.kDataOCRBatchProgress,
map
)
}
override suspend fun onResult(list: List<Map<String, Any>>) {
Log.e("jingo", "OCRManager 线程名称2 ${Thread.currentThread().name}")
_methodChannel.invokeMethod(
FlutterDataProtocolKeys.DataCameraProtocol.kDataOCRBatchResults,
DataConversion.toFlutterOcrList(list)
)
}
}
)
}
result.success(true)
}
}

View File

@@ -0,0 +1,245 @@
package com.navinfo.collect.library.data.flutter.flutterhandler
import android.content.Context
import android.util.Log
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.RealmUtils
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.Element
import com.navinfo.collect.library.data.entity.LayerManager
import com.navinfo.collect.library.data.entity.Project
import com.navinfo.collect.library.data.flutter.FlutterDataProtocolKeys
import com.navinfo.collect.library.data.handler.DataElementHandler
import com.navinfo.collect.library.data.search.*
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.json.JSONObject
/**
* 数据操作
*/
class FlutterDataElementHandler(
context: Context,
methodChannel: MethodChannel,
dataBase: MapLifeDataBase
) :
DataElementHandler(context, dataBase), OnGetSearchDataResultListener {
val _methodChannel = methodChannel
init {
setListener(this)
}
/**
* 保存数据
*/
fun saveElementData(call: MethodCall, result: MethodChannel.Result) = try {
if (call.arguments is Map<*, *>) {
val element = Element.fromMap(call.arguments as MutableMap<String, Any>?);
val valueMap = call.argument<Map<String, Any>>("values")
saveData(element, valueMap) { res, error ->
if (res) {
result.success("$res")
} else {
result.success(error)
}
}
} else {
result.success("数据格式错误")
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
Log.e("jingo", e.toString())
result.success("数据格式错误")
}
/**
* 删除数据
*/
fun deleteElementData(call: MethodCall, result: MethodChannel.Result) = try {
if (call.arguments is Map<*, *>) {
val element = Element()
element.layerId = call.argument("layerId")
element.id = call.argument("uuid")
element.geometry = call.argument("geometry")
element.displayText = call.argument("displayText")
element.displayStyle = call.argument("displayStyle")
element.operationTime = call.argument("tOperateDate")
element.tLifecycle = call.argument<Int>("tLifecycle")!!
element.tStatus = call.argument<Int>("tStatus")!!
deleteData(element) { res, message ->
if (res) {
result.success("success")
} else {
result.success(message)
}
};
} else {
result.success("数据格式错误")
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
Log.e("jingo", e.toString())
result.success("数据格式错误")
}
/**
* 复制数据
*/
fun copyElementData(call: MethodCall, result: MethodChannel.Result) = try {
if (call.arguments is Map<*, *>) {
} else {
result.success("数据格式错误")
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
Log.e("jingo", e.toString())
result.success("数据格式错误")
}
fun importPbfData2Realm(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is List<*>) {
val pbfFiles: List<String> = call.arguments as List<String>
try {
val importResult = RealmUtils.getInstance().importPbfData(pbfFiles)
result.success(importResult)
} catch (exeception: Exception) {
result.error("-1", exeception.message, exeception)
}
}
}
/**
* 捕捉数据
*/
fun snapElementDataList(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is String) {
snapElementDataList(call.arguments as String) {
result.success(DataConversion.toElementMapList(it))
}
}
}
/**
* 查询数据深度信息模板
*/
fun queryElementDeepInfo(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is Map<*, *>) {
val id = call.argument<String>("id")
val layerId = call.argument<String>("layerId")
if (id != null && layerId != null) {
queryElementDeepInfo(id, layerId) { layerManager, itemList ->
if (layerManager != null) {
val map = layerManager.toMap()
map["layerItems"] = DataConversion.customLayerItemsToMapList(itemList)
result.success(map)
} else {
result.error("-1","没有这条数据的拓展模板","")
}
}
}
}
}
/**
* 根据渲染名称查询数据
*/
fun searchData(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is String) {
try {
val jsonObject = JSONObject(call.arguments as String)
val keyword = jsonObject.getString("keyword")
val pageNum = jsonObject.getInt("pageNum")
val pageCapacity = jsonObject.getInt("pageCapacity")
val startTime = jsonObject.getInt("startTime")
val endTime = jsonObject.getInt("endTime")
val projectArray = jsonObject.getJSONArray("projectItemList")
val layerArray = jsonObject.getJSONArray("layerItemList")
val fieldArray = jsonObject.getJSONArray("fieldItemList")
val projectItemList = ArrayList<OptionProjectItem>()
val layerItemList = ArrayList<OptionLayerItem>()
val fieldItemList = ArrayList<OptionFieldItem>()
for (i in 0 until projectArray.length()) {
val item = OptionProjectItem(projectArray.getString(i))
projectItemList.add(item)
}
for (i in 0 until layerArray.length()) {
val layerObject = layerArray.getJSONObject(i)
val item = OptionLayerItem(
layerObject.optString("projectId"),
layerObject.optString("layerId")
)
layerItemList.add(item)
}
for (i in 0 until fieldArray.length()) {
val fieldObject = fieldArray.getJSONObject(i)
val item = OptionFieldItem(
fieldObject.optString("projectId"),
fieldObject.optString("layerId"),
fieldObject.optString("fieldName")
)
fieldItemList.add(item)
}
val option =
SearchDataOption.Builder().setKeyword(keyword).setStartTime(startTime)
.setEndTime(endTime).setFieldItems(fieldItemList)
.setLayerItems(layerItemList).setProjectItems(projectItemList)
.setPageNum(pageNum).setPageCapacity(pageCapacity).build()
searchData(option) {
// result.success(DataConversion.toElementMapList(it))
}
result.success("");
} catch (e: Exception) {
println("$e")
result.error("-1", "查询参数解析错误", "$e")
}
}
}
/**
* 获取检查项列表
*/
fun queryCheckManagerList(call: MethodCall, result: MethodChannel.Result) {
queryCheckManagerList() { list ->
result.success(DataConversion.toCheckManagerMapList(list));
}
}
/**
* 根据id获取检查项列表
*/
fun queryCheckManagerListByIds(call: MethodCall, result: MethodChannel.Result) {
queryCheckManagerList() { list ->
result.success(DataConversion.toCheckManagerMapList(list));
}
}
override fun onGetElementResult(elementList: List<Element>) {
_methodChannel.invokeMethod(
FlutterDataProtocolKeys.DataElementProtocol.kDataSearchData,
DataConversion.toElementMapList(elementList)
)
}
override fun onGetLayerResult(layer: LayerManager) {
}
override fun onGetProjectResult(project: Project) {
}
override fun onError(msg: String, keyword: String) {
}
}

View File

@@ -0,0 +1,114 @@
package com.navinfo.collect.library.data.flutter.flutterhandler
import android.content.Context
import android.util.Log
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.CustomLayerItem
import com.navinfo.collect.library.data.entity.DataLayerItemType
import com.navinfo.collect.library.data.handler.DataLayerHandler
import com.navinfo.collect.library.data.entity.LayerManager
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.json.JSONArray
import org.json.JSONObject
/**
* 数据图层管理
*/
class FlutterDataLayerHandler(context: Context, dataBase: MapLifeDataBase) :
DataLayerHandler(context, dataBase) {
fun createDataLayerTable(call: MethodCall, result: MethodChannel.Result) {
try {
if (call.arguments is String) {
val jsonObject = JSONObject(call.arguments as String)
val layer = LayerManager()
layer.id = jsonObject.optString("uuid")
layer.projectId = jsonObject.optString("projectId")
layer.geometryType = jsonObject.optInt("geometryType")
layer.layerName = jsonObject.optString("layerName")
layer.style = jsonObject.optString("style")
layer.importTime = jsonObject.optString("import_time")
layer.describe = jsonObject.optString("describe")
layer.visibility = jsonObject.optBoolean("visibility")
val jsonArrayItems = JSONArray(jsonObject.optString("layerItems"))
layer.bundle = jsonArrayItems.toString()
var itemList = mutableListOf<CustomLayerItem>();
for (i in 0 until jsonArrayItems.length()) {
val jsonObjectItem: JSONObject = jsonArrayItems[i] as JSONObject;
val item = CustomLayerItem(
key = jsonObjectItem.optString("key"),
type = DataLayerItemType.values()[jsonObjectItem.optInt("type")],
title = jsonObjectItem.optString("title"),
describe = jsonObjectItem.optString("describe"),
itemBean = jsonObjectItem.optString("itemBean"),
)
itemList.add(item)
}
// val list = DataConversion.listMapToCustomLayerItemsList(itemList)
createTable(layer, itemList) { res, _ ->
result.success(res)
}
} else {
result.success(false)
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
Log.e("jingo", e.toString())
result.success(false)
}
}
/**
* 获取全部数据图层信息
*/
fun getDataLayerList(call: MethodCall, result: MethodChannel.Result) {
getDataLayerList { list ->
val newList = mutableListOf<Map<*, *>>()
for (item in list) {
val map = mapOf(
"uuid" to item.id,
"projectId" to item.projectId,
"geometryType" to item.geometryType,
"layerName" to item.layerName,
"import_time" to item.importTime,
"describe" to item.describe,
"visibility" to item.visibility,
"layerItems" to item.bundle,
"style" to item.style
)
newList.add(map)
}
result.success(newList)
}
}
/**
* 获取某个数据图层
*/
fun getDataLayer(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is String) {
getDataLayer(call.arguments as String) { layer ->
result.success(
mapOf(
"uuid" to layer.id,
"projectId" to layer.projectId,
"geometryType" to layer.geometryType,
"layerName" to layer.layerName,
"import_time" to layer.importTime,
"describe" to layer.describe,
"visibility" to layer.visibility,
"layerItems" to layer.bundle,
"style" to layer.style
)
)
}
} else {
result.success("false")
}
}
}

View File

@@ -0,0 +1,92 @@
package com.navinfo.collect.library.data.flutter.flutterhandler
import android.content.Context
import android.util.Log
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.NiLocation
import com.navinfo.collect.library.data.handler.DataNiLocationHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import java.text.SimpleDateFormat
import java.util.*
/**
* 数据操作
*/
class FlutterDataNiLocationHandler(context: Context, dataBase: MapLifeDataBase) :
DataNiLocationHandler(context, dataBase) {
/**
* 保存数据
*/
fun saveNiLocationData(call: MethodCall, result: MethodChannel.Result) = try {
if (call.arguments is Map<*, *>) {
val niLocation = NiLocation()
niLocation.id = call.argument("uuid")
niLocation.longitude = call.argument<Double>("longitude")!!
niLocation.latitude = call.argument<Double>("latitude")!!
niLocation.altitude = call.argument<Double>("altitude")!!
niLocation.radius = call.argument<Double>("radius")!!
niLocation.direction = call.argument<Double>("direction")!!
niLocation.time = call.argument("time")!!
if(niLocation.time.length==19){
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val dDate: Date = simpleDateFormat.parse(niLocation.time)
niLocation.time = dDate.time.toString()
}
niLocation.speed = call.argument<Float>("speed")!!
niLocation.country = call.argument("country")
niLocation.province = call.argument("province")
niLocation.city = call.argument("city")
niLocation.district = call.argument("district")
niLocation.street = call.argument("street")
niLocation.town = call.argument("town")
niLocation.adCode = call.argument("adCode")
niLocation.cityCode = call.argument("cityCode")
niLocation.streetNumber = call.argument("streetNumber")
niLocation.errorCode = call.argument<String?>("errorCode").toString()
niLocation.errorInfo = call.argument("errorInfo")
saveDataNiLocation(niLocation) { res, error ->
if (res) {
result.success("$res")
} else {
result.success(error)
}
}
} else {
result.success("数据格式错误")
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
Log.e("jingo", e.toString())
result.success("数据格式错误")
}
/**
* 删除数据
*/
fun deleteNiLocationData(call: MethodCall, result: MethodChannel.Result) = try {
if (call.arguments is Map<*, *>) {
val niLocation = NiLocation()
niLocation.id = call.argument("uuid")
deleteData(niLocation) { res, message ->
if (res) {
result.success("success")
} else {
result.success(message)
}
};
} else {
result.success("数据格式错误")
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Log.e("jingo", e.stackTraceToString())
Log.e("jingo", e.toString())
result.success("数据格式错误")
}
}

View File

@@ -0,0 +1,64 @@
package com.navinfo.collect.library.data.flutter.flutterhandler
import android.content.Context
import android.util.Log
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.handler.DataProjectHandler
import com.navinfo.collect.library.data.entity.Project
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
/**
* 项目管理
*/
class FlutterDataProjectHandler(context: Context, dataBase: MapLifeDataBase) :
DataProjectHandler(context, dataBase) {
fun saveProject(call: MethodCall, result: MethodChannel.Result) {
try {
if (call.arguments is Map<*, *>) {
// "style": style,
val project = Project();
//项目名称
project.id = call.argument("uuid")
project.name = call.argument("name")
project.createTime = call.argument("createTime")
project.describe = call.argument("describe")
project.visibility = call.argument<Boolean>("visibility") == false
project.geometry = call.argument("geometry")
project.geometryVisibility = call.argument<Boolean>("geometryVisibility") == false
saveProject(project) { res, _ ->
result.success(res)
};
} else {
result.success(false)
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) };
Log.e("jingo", e.stackTraceToString());
Log.e("jingo", e.toString());
result.success(false)
}
}
fun getProjectList(call: MethodCall, result: MethodChannel.Result) {
getProjectList { list ->
val newList = mutableListOf<Map<*, *>>()
for (item in list) {
val map = mapOf(
"uuid" to item.id,
"name" to item.name,
"createTime" to item.createTime,
"describe" to item.describe,
"visibility" to item.visibility,
"geometry" to item.geometry,
"geometryVisibility" to item.geometryVisibility
)
newList.add(map)
}
result.success(newList)
};
}
}

View File

@@ -0,0 +1,9 @@
package com.navinfo.collect.library.data.handler
import android.content.Context
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
open class BaseDataHandler(context: Context, dataBase: MapLifeDataBase) {
protected val mContext: Context = context;
protected val mDataBase: MapLifeDataBase = dataBase;
}

View File

@@ -0,0 +1,223 @@
package com.navinfo.collect.library.data.handler
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.ExifInterface
import android.util.Log
import com.baidu.ai.edge.ui.util.ImageUtil
import com.baidu.ai.edge.ui.view.model.OcrViewResultModel
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.ocr.OCRManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.*
import java.util.*
interface OnOCRBatchListener {
fun onProgress(total: Int, current: Int)
suspend fun onResult(list: List<Map<String, Any>>)
}
open class DataCameraHandler(
context: Context,
activity: FlutterBaseActivity,
dataBase: MapLifeDataBase
) :
BaseDataHandler(context, dataBase) {
private val mActivity: FlutterBaseActivity = activity
init {
OCRManager.instance.init(activity)
}
fun openCamera() {
OCRManager.instance.openCamera(mActivity)
}
/**
* 批量OCR识别
*/
fun ocrBatch(filePath: String, listener: OnOCRBatchListener) {
mActivity.launch(Dispatchers.IO) {
Log.e("jingo", "OCRManager 线程开始 ${Thread.currentThread().name}")
val file = File(filePath)
val resultList = mutableListOf<Map<String, Any>>()
if (file.isDirectory) {
val fileList = file.listFiles()
val bitmapList = mutableListOf<String>()
for (item in fileList!!) {
if (item.isFile) {
if (checkIsImageFile(item.name)) {
bitmapList.add(item.path)
}
}
}
val bfw: BufferedWriter
val csvFile = File("$filePath/ocr.csv")
val out: FileOutputStream
val osw: OutputStreamWriter
try {
out = FileOutputStream(csvFile)
//用excel打开中文会乱码所以用GBK编译
osw = OutputStreamWriter(out, "GBK")
bfw = BufferedWriter(osw)
//第一行表头数据
bfw.write("图片路径和名称,")
bfw.write("识别结果序号,")
bfw.write("识别结果内容,")
bfw.write("置信度,")
bfw.write("识别面积,")
bfw.write("图片大小,")
bfw.write("识别区域,")
//写好表头后换行
bfw.newLine()
for (i in 0 until bitmapList.size) {
val path = bitmapList[i]
val bitmap: Bitmap? = readFile(path)
var exif = ExifInterface(path)
val exifRotation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL
)
val rotation = ImageUtil.exifToDegrees(exifRotation)
val rotateBitmap = ImageUtil.createRotateBitmap(bitmap, rotation)
val list = OCRManager.instance.ocr(rotateBitmap)
// val list = ocrBitmap(path)
if (list != null) {
for (o in list) {
bfw.write("$path,")
bfw.write("${o.index},")
bfw.write("${o.name},")
bfw.write("${o.confidence.toString()},")
val pointList = o.bounds
bfw.write("${(pointList[3].y - pointList[0].y) * (pointList[2].x - pointList[0].x)},")
bfw.write("${rotateBitmap.width} ${rotateBitmap.height},")
bfw.write("${o.bounds[0].x} ${o.bounds[0].y};${o.bounds[1].x} ${o.bounds[1].y};${o.bounds[2].x} ${o.bounds[2].y};${o.bounds[3].x} ${o.bounds[3].y},")
bfw.newLine()
}
bfw.newLine()
withContext(Dispatchers.Main) {
listener.onProgress(bitmapList.size, i)
}
val m1 = mutableMapOf<String, Any>();
m1["data"] = list;
m1["width"] = rotateBitmap.width
m1["height"] = rotateBitmap.height
m1["path"] = path
resultList.add(m1)
}
rotateBitmap.recycle()
}
//将缓存数据写入文件
bfw.flush()
//释放缓存
bfw.close()
osw.close()
out.close()
} catch (e: Throwable) {
}
//将缓存数据写入文件
withContext(Dispatchers.Main) {
Log.e("jingo", "OCRManager 线程名称2 ${Thread.currentThread().name}")
listener.onResult(resultList)
}
} else if (file.isFile && checkIsImageFile(file.name)) {
val list = ocrBitmap(filePath)
if (list != null) {
withContext(Dispatchers.Main) {
Log.e("jingo", "OCRManager 线程名称2 ${Thread.currentThread().name}")
listener.onProgress(1, 1)
}
val m = mutableMapOf<String, List<OcrViewResultModel>>()
m[file.name] = list
resultList.add(m)
}
withContext(Dispatchers.Main) {
Log.e("jingo", "OCRManager 线程名称2 ${Thread.currentThread().name}")
listener.onResult(resultList)
}
}
}
}
private fun ocrBitmap(path: String): List<OcrViewResultModel>? {
try {
val bitmap: Bitmap? = readFile(path)
var exif = ExifInterface(path)
val exifRotation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL
)
val rotation = ImageUtil.exifToDegrees(exifRotation)
val rotateBitmap = ImageUtil.createRotateBitmap(bitmap, rotation)
val res = OCRManager.instance.ocr(rotateBitmap)
rotateBitmap.recycle()
return res
} catch (e: IOException) {
Log.e("jingo", "图像识别,获取图像信息失败 ${e.printStackTrace()}")
}
return null
}
/**
* 检查是不是bitmap文件
*/
private fun checkIsImageFile(fName: String): Boolean {
val isImageFile: Boolean
// 获取扩展名
val fileEnd = fName.substring(
fName.lastIndexOf(".") + 1,
fName.length
).lowercase(Locale.getDefault())
isImageFile =
fileEnd == "jpg" || fileEnd == "png" || fileEnd == "webp" || fileEnd == "jpeg" || fileEnd == "bmp"
return isImageFile
}
/**
* 读取bitmap文件
*/
private fun readFile(path: String): Bitmap? {
var stream: FileInputStream? = null
try {
stream = FileInputStream(path)
return BitmapFactory.decodeStream(stream)
} catch (e: FileNotFoundException) {
e.printStackTrace()
} finally {
if (stream != null) {
try {
stream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
return null
}
// private fun onOcrBitmap(
// bitmap, confidence,
// object: OcrListener {
// override fun onResult(models: List<BasePolygonResultModel>) {
// if (models == null) {
// listener.onResult(null)
// return
// }
// ocrResultModelCache = models
// listener.onResult(models)
// }
// })
}

View File

@@ -0,0 +1,584 @@
package com.navinfo.collect.library.data.handler
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase.CONFLICT_NONE
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.*
import com.navinfo.collect.library.data.entity.DataLayerItemType.*
import com.navinfo.collect.library.data.search.OnGetSearchDataResultListener
import com.navinfo.collect.library.data.search.SearchDataOption
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.GeometryToolsKt
import io.realm.RealmSet
import org.oscim.core.MercatorProjection
import java.util.*
import kotlin.collections.ArrayList
import kotlin.concurrent.fixedRateTimer
import kotlin.concurrent.thread
/**
* 数据库操作
*/
open class
DataElementHandler(context: Context, dataBase: MapLifeDataBase) :
BaseDataHandler(context, dataBase) {
private var mListener: OnGetSearchDataResultListener? = null
private var lastSearchTime = 0
private var timer: Timer? = null
fun setListener(listener: OnGetSearchDataResultListener) {
this.mListener = listener
}
/**
* 保存数据
*/
fun saveData(
element: Element,
map: Map<String, Any>?,
callback: (res: Boolean, errorString: String) -> Unit
) {
thread(start = true) {
try {
if (map != null) {
val cursor =
mDataBase.openHelper.writableDatabase.query(
"Select * from \"${element.layerId}\" where uuid=?",
arrayOf(element.id)
)
val contentValues = ContentValues() //存储信息
for ((key, value) in map) {
when (value) {
is String -> contentValues.put(key, value)
is Long -> contentValues.put(key, value)
is Int -> contentValues.put(key, value)
is Double -> contentValues.put(key, value)
is ByteArray -> contentValues.put(key, value)
is Boolean -> contentValues.put(key, value)
is Float -> contentValues.put(key, value)
is Short -> contentValues.put(key, value)
is Byte -> contentValues.put(key, value)
}
}
contentValues.put("uuid", element.id);
cursor.moveToFirst()
if (cursor.count > 0) {
mDataBase.openHelper.writableDatabase.update(
"'${element.layerId}'",
CONFLICT_NONE,
contentValues,
"uuid = ? ",
arrayOf(element.id)
)
} else {
mDataBase.openHelper.writableDatabase.insert(
"'${element.layerId}'",//element.layerId,
CONFLICT_NONE,
contentValues
).toInt()
}
cursor.close()
}
//resetCoordinate(element)
element.tLifecycle = 2
//优先删除已有数据下面会重新计算最新的tile
mDataBase.tileElementDao.deleteElementId(element.id)
val list = ArrayList<TileElement>()
try {
if (element.geometry != null) {
val tileX = RealmSet<Int>()
GeometryToolsKt.getTileXByGeometry(element.geometry, tileX)
val tileY = RealmSet<Int>()
GeometryToolsKt.getTileYByGeometry(element.geometry, tileY)
//遍历存储tile对应的x与y的值
tileX.forEach { x ->
tileY.forEach { y ->
val tile = TileElement()
tile.elementId = element.id
tile.tilex = x
tile.tiley = y
list.add(tile)
}
}
}
mDataBase.tileElementDao.insertList(list)
mDataBase.elementDao.insert(element)
} catch (e: java.lang.Exception) {
}
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
}
}
}
/**
* 删除数据
*/
fun deleteData(element: Element, callback: (res: Boolean, errorString: String) -> Unit) {
thread(start = true) {
try {
mDataBase.openHelper.writableDatabase.delete(
"'${element.layerId}'",
"uuid=?",
arrayOf("'${element.id}'")
)
mDataBase.elementDao.delete(element);
} catch (e: Throwable) {
Log.e("jingo", "删除数据报错 ${e.message}");
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
}
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
}
}
// /**
// * 根据给定的geometry计算其横跨的20级瓦片Y值
// */
// private fun getTileYByGeometry(geometry: Geometry, tileYSet: MutableSet<Int?>): Set<Int?>? {
// var tileYSet: MutableSet<Int?>? = tileYSet
// val startTime = System.currentTimeMillis()
// if (tileYSet == null) {
// tileYSet = RealmSet()
// }
// val envelope = geometry.envelope
// if (envelope != null) {
// val coordinates = envelope.coordinates
// // 最小最大x轴坐标索引0位最小x值索引1位最大y值
// if (coordinates != null && coordinates.isNotEmpty()) {
// val minMaxY = doubleArrayOf(coordinates[0].y, coordinates[0].y)
// for (coordinate in coordinates) {
// // 获取最大和最小y的值
// if (coordinate.y < minMaxY[0]) {
// minMaxY[0] = coordinate.y
// }
// if (coordinate.y > minMaxY[1]) {
// minMaxY[1] = coordinate.y
// }
// }
// // 分别计算最大和最小x值对应的tile号
// val tileY0 = MercatorProjection.latitudeToTileY(minMaxY[0], 20.toByte())
// val tileY1 = MercatorProjection.latitudeToTileY(minMaxY[1], 20.toByte())
// val minTileY = if (tileY0 <= tileY1) tileY0 else tileY1
// val maxTileY = if (tileY0 <= tileY1) tileY1 else tileY0
// println("getTileYByGeometry$envelope===$minTileY===$maxTileY")
//
// for (i in minTileY..maxTileY) {
// tileYSet.add(i)
// }
// }
// }
// println("YGeometry-time:" + (System.currentTimeMillis() - startTime))
// return tileYSet
// }
/**
* 计算数据最大最小坐标
*/
private fun resetCoordinate(element: Element) {
when {
element.geometry.startsWith("POINT") -> {
var geoPoint = GeometryTools.createGeoPoint(element.geometry)
val tile = TileElement()
tile.elementId = element.id
val minLatitude = Math.max(
MercatorProjection.LATITUDE_MIN,
MercatorProjection.tileYToLatitude(
(geoPoint.latitude.toLong() + 1).toLong(),
20
)
)
val minLongitude = Math.max(
-180.0,
MercatorProjection.tileXToLongitude(geoPoint.longitude.toLong(), 20)
)
/* element.maxx = (geoPoint.longitude * Constant.CONVERSION_FACTOR).toFloat()
element.minx = element.maxx
element.maxy = (geoPoint.latitude * Constant.CONVERSION_FACTOR).toFloat()
element.miny = element.maxy*/
}
element.geometry.startsWith("LINESTRING") -> {
}
element.geometry.startsWith("POLYGON") -> {
}
}
}
/**
* 捕捉数据
*/
fun snapElementDataList(
polygon: String,
callback: (list: List<Element>) -> Unit
) {
thread(start = true) {
val geometry = GeometryTools.createGeometry(polygon)
if (geometry != null) {
//计算tileX号
val tileX = RealmSet<Int>()
GeometryToolsKt.getTileXByGeometry(polygon, tileX)
//计算tileY号
val tileY = RealmSet<Int>()
GeometryToolsKt.getTileYByGeometry(polygon, tileY)
//读取数据库获取数据
val list = mDataBase.elementDao.findList(tileX, tileY)
val elements = java.util.ArrayList<Element>()
//几何遍历判断数据包括或者相交
list.forEach { element ->
if (element != null && element.geometry != null) {
val geometryTemp = GeometryTools.createGeometry(element.geometry)
if (geometryTemp != null && geometry.contains(geometryTemp) || geometry.intersects(
geometryTemp
)
) {
elements.add(element)
}
}
}
var cursor: Cursor? = null
try {
for (e in elements) {
// val layer: LayerManager =
// mDataBase.layerManagerDao.findLayerManager(e.layerId)
e.values = mutableMapOf<String, String>()
// MoshiUtil.fromJson<List<CustomLayerItem>>(layer.bundle)
cursor =
mDataBase.openHelper.readableDatabase.query("select * from \"${e.layerId}\" where uuid = \"${e.id}\"")
while (cursor.moveToNext()) {
for (index in 0 until cursor.columnNames.size) {
val key = cursor.getColumnName(index)
val value = cursor.getString(index)
e.values[key] = value
}
}
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
} finally {
cursor?.close()
}
Handler(Looper.getMainLooper()).post {
callback.invoke(elements)
}
} else {
Handler(Looper.getMainLooper()).post {
callback.invoke(listOfNotNull())
}
}
}
}
/**
* 查询数据深度信息模板
*/
fun queryElementDeepInfo(
id: String,
layerId: String,
callback: (layer: LayerManager?, itemList: List<CustomLayerItem>?) -> Unit
) {
thread(start = true) {
val layerManager = mDataBase.layerManagerDao.findLayerManager(layerId)
var layerItems = listOf<CustomLayerItem>()
if (layerManager != null) {
layerItems = DataConversion.jsonToLayerItemsList(layerManager.bundle)
var cursor: Cursor? = null
try {
cursor =
mDataBase.openHelper.readableDatabase.query("select * from \"$layerId\" where uuid = \"$id\"")
while (cursor.moveToNext()) {
for (layerItem in layerItems) {
val index = cursor.getColumnIndex(layerItem.key)
when (layerItem.type) {
DataLayerItemTypeInput -> {
// layerItem.value = cursor.getString(index)
}
DataLayerItemTypeInputArray -> TODO()
DataLayerItemTypeText -> TODO()
DataLayerItemTypeSingleSelection -> {
// layerItem.value = cursor.getString(index)
}
DataLayerItemTypeMultipleSelection -> TODO()
}
}
}
} catch (e: Throwable) {
e.message?.let { Log.e("jingo", it) }
} finally {
cursor?.close()
}
}
Handler(Looper.getMainLooper()).post {
callback.invoke(layerManager, layerItems)
}
}
}
// fun queryElementByName(
// name: String,
// start: Int,
// total: Int,
// callback: (list: List<Element>) -> Unit
// ) {
// thread(start = true) {
// if (name.isNotEmpty()) {
// //读取数据库获取数据
// val elements = mDataBase.elementDao.findListByKeyword(name, start, total)
// var cursor: Cursor? = null
// try {
// for (e in elements) {
//// val layer: LayerManager =
//// mDataBase.layerManagerDao.findLayerManager(e.layerId)
// e.values = mutableMapOf<String, String>()
//// MoshiUtil.fromJson<List<CustomLayerItem>>(layer.bundle)
// cursor =
// mDataBase.openHelper.readableDatabase.query("select * from \"${e.layerId}\" where uuid = \"${e.id}\"")
// while (cursor.moveToNext()) {
// for (index in 0 until cursor.columnNames.size) {
// val key = cursor.getColumnName(index)
// val value = cursor.getString(index)
// e.values[key] = value
// }
//
// }
// }
// } catch (e: Throwable) {
// Log.e("jingo", e.message)
// } finally {
// cursor?.close()
// }
// Handler(Looper.getMainLooper()).post {
// callback.invoke(elements)
// }
// } else {
// Handler(Looper.getMainLooper()).post {
// callback.invoke(listOfNotNull())
// }
// }
// }
// }
fun searchData(option: SearchDataOption, callback: (list: List<Element>) -> Unit) {
val nowTime = System.currentTimeMillis()
if (nowTime - lastSearchTime < 1500 && timer != null) {
timer?.cancel()
timer = null
}
timer = fixedRateTimer("", false, 1500, 10000) {
thread(start = true) {
var cursor: Cursor? = null
try {
val db = mDataBase.openHelper.readableDatabase;
val elementList = mutableListOf<Element>()
if (option.layerItemList.isEmpty() && option.projectItemList.isEmpty() && option.fieldItemList.isEmpty()) {
elementList.addAll(
mDataBase.elementDao.findListByKeyword(
option.keyword,
option.pageNum * option.pageCapacity,
option.pageCapacity
)
)
for (e in elementList) {
e.values = mutableMapOf<String, String>()
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
cursor =
db.query("select * from \"${e.layerId}\" where uuid = \"${e.id}\"")
while (cursor.moveToNext()) {
for (index in 0 until cursor.columnNames.size) {
val key = cursor.getColumnName(index)
val value = cursor.getString(index)
e.values[key] = value
}
}
}
} else {
if (option.fieldItemList.isNotEmpty()) {
for (item in option.fieldItemList) {
val valuesMap = mutableMapOf<String, String>()
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
val sql =
"select * from \"${item.layerId}\" where ${item.fieldName} like '%${option.keyword}%' limit ${option.pageNum * option.pageCapacity},${option.pageCapacity} "
cursor = db.query(sql)
var uuid = ""
while (cursor.moveToNext()) {
for (index in 0 until cursor.columnNames.size) {
val key = cursor.getColumnName(index)
val value = cursor.getString(index)
if (key == "uuid") {
uuid = value;
}
valuesMap[key] = value
}
val e = mDataBase.elementDao.findById(uuid);
e.values = valuesMap
elementList.add(e)
for (layer in option.layerItemList) {
if (layer.layerId == item.layerId) {
option.layerItemList.remove(layer)
break
}
}
for (project in option.projectItemList) {
if (project.projectId == item.projectId) {
var his = false;
for (layer in option.layerItemList) {
if (layer.projectId == project.projectId) {
his = true
break
}
}
if (!his) {
option.projectItemList.remove(project)
}
break
}
}
}
}
}
if (option.layerItemList.isNotEmpty()) {
val layerSet = RealmSet<String>();
for (layer in option.layerItemList) {
layerSet.add(layer.layerId)
for (project in option.projectItemList) {
if (project.projectId == layer.projectId) {
option.projectItemList.remove(project)
break
}
}
}
val elements = mDataBase.elementDao.findListByKeywordLimitLayer(
option.keyword,
layerSet,
option.pageNum * option.pageCapacity,
option.pageCapacity
)
for (e in elements) {
e.values = mutableMapOf<String, String>()
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
cursor =
db.query("select * from \"${e.layerId}\" where uuid = \"${e.id}\"")
while (cursor.moveToNext()) {
for (index in 0 until cursor.columnNames.size) {
val key = cursor.getColumnName(index)
val value = cursor.getString(index)
e.values[key] = value
}
}
}
elementList.addAll(elements)
}
if (option.projectItemList.isNotEmpty()) {
val projectSet = RealmSet<String>();
for (project in option.projectItemList) {
projectSet.add(project.projectId)
}
val elements = mDataBase.elementDao.findListByKeywordLimitProject(
option.keyword,
projectSet,
option.pageNum * option.pageCapacity,
option.pageCapacity
)
elementList.addAll(elements)
for (e in elementList) {
e.values = mutableMapOf<String, String>()
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
cursor =
db.query("select * from \"${e.layerId}\" where uuid = \"${e.id}\"")
while (cursor.moveToNext()) {
for (index in 0 until cursor.columnNames.size) {
val key = cursor.getColumnName(index)
val value = cursor.getString(index)
e.values[key] = value
}
}
}
}
}
Handler(Looper.getMainLooper()).post {
mListener?.onGetElementResult(elementList)
// callback.invoke(elementList)
}
} catch (e: Exception) {
println(e)
} finally {
cursor?.close()
}
}
timer?.cancel();
timer = null;
}
}
/**
* 获取所有检查项标签
*/
fun queryCheckManagerList(callback: (list: List<CheckManager>) -> Unit) {
thread(start = true) {
val list = mDataBase.checkManagerDao.findList()
Handler(Looper.getMainLooper()).post {
callback.invoke(list)
}
}
}
}

View File

@@ -0,0 +1,268 @@
package com.navinfo.collect.library.data.handler
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.sqlite.db.SupportSQLiteDatabase
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.CheckManager
import com.navinfo.collect.library.data.entity.CustomLayerItem
import com.navinfo.collect.library.data.entity.DataLayerItemType
import com.navinfo.collect.library.data.entity.LayerManager
import org.json.JSONArray
import org.json.JSONObject
import kotlin.concurrent.thread
/**
* 数据库操作
*/
open class DataLayerHandler(context: Context, dataBase: MapLifeDataBase) :
BaseDataHandler(context, dataBase) {
/**
* 根据json创建数据库
* [
* {"key":"name","type":"TEXT","nullable":true},
* {"key":"address","type":"TEXT","nullable":true},
* {"key":"type","type":"INTEGER","nullable":false},
* {"key":"longitude","type":"REAL","nullable":false},
* {"key":"latitude","type":"REAL","nullable":false},
* {"key":"id","type":"INTEGER","nullable":false,"primaryKey":true}
* ]
*
*
* _db.execSQL("CREATE TABLE IF NOT EXISTS `edit_pois` (`rowId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `postCode` TEXT, `address` TEXT, `kindCode` TEXT, `uuid` TEXT, `geometry` TEXT, `maxx` REAL NOT NULL, `minx` REAL NOT NULL, `maxy` REAL NOT NULL, `miny` REAL NOT NULL)");
_db.execSQL("CREATE TABLE IF NOT EXISTS `element` (`rowId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `display_style` TEXT, `display_text` TEXT, `start_level` INTEGER NOT NULL, `end_level` INTEGER NOT NULL, `zindex` INTEGER NOT NULL, `visibility` INTEGER NOT NULL, `operation_time` TEXT, `export_time` TEXT, `t_lifecycle` INTEGER NOT NULL, `t_status` INTEGER NOT NULL, `bundle` TEXT, `uuid` TEXT, `geometry` TEXT, `maxx` REAL NOT NULL, `minx` REAL NOT NULL, `maxy` REAL NOT NULL, `miny` REAL NOT NULL)");
_db.execSQL("CREATE TABLE IF NOT EXISTS `layerElement` (`rowId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uuid` TEXT, `layer_uuid` TEXT, `element_uuid` TEXT)");
_db.execSQL("CREATE TABLE IF NOT EXISTS `layerManager` (`rowId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uuid` TEXT, `layer_name` TEXT, `zindex` INTEGER NOT NULL, `visibility` INTEGER NOT NULL, `export_time` TEXT, `import_time` TEXT, `bundle` TEXT)");
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7a041262c922535fc32b56d4dd16ea92')");
*
*/
fun createTable(
layer: LayerManager,
list: List<CustomLayerItem>,
callback: (res: Boolean, errorString: String) -> Unit
) {
thread(start = true) {
try {
val sql = StringBuffer();
val database: SupportSQLiteDatabase = mDataBase.openHelper.writableDatabase
val locLayer = mDataBase.layerManagerDao.findLayerManager(layer.id);
if (locLayer != null) {
sql.append("CREATE TABLE IF NOT EXISTS '${layer.id}temp' ( uuid TEXT NOT NULL, ")
val columnBuffer = StringBuffer()
columnBuffer.append("uuid")
var count = 0;
//比对旧的数据库表,看看哪些字段需要更改
val items = DataConversion.jsonToLayerItemsList(locLayer.bundle)
for (i in list.indices) {
if (i > 0) {
sql.append(", ")
}
sql.append("'${list[i].key}' ")
sql.append(layerItemTypeToDBType(list[i].type))
for (j in items.indices) {
//这里只根据id是否相同进行了判断如果类型变换了话会有风险需要应用层做限制
if (items[j].key == list[i].key) {
columnBuffer.append(",")
columnBuffer.append(items[j].key)
count++
break
}
}
}
sql.append(")")
if (count == items.size && count == list.size) {
mDataBase.layerManagerDao.update(layer)
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
} else {
var b = true
val sql2 =
"insert into \"${layer.id}temp\"($columnBuffer) select $columnBuffer from \"${layer.id}\""
try {
database.beginTransaction()
database.execSQL(sql.toString())
database.execSQL(sql2)
database.execSQL("drop TABLE \"${layer.id}\"")
database.execSQL("ALTER TABLE \"${layer.id}temp\" RENAME TO \"${layer.id}\"")
database.setTransactionSuccessful()
} catch (e: Throwable) {
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
b = false
} finally {
database.endTransaction()
}
if (b) {
mDataBase.layerManagerDao.update(layer)
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
}
}
} else {
sql.append("CREATE TABLE IF NOT EXISTS '${layer.id}' ( uuid TEXT NOT NULL, ")
for (i in list.indices) {
if (i > 0) {
sql.append(", ")
}
sql.append("'${list[i].key}' ")
sql.append(layerItemTypeToDBType(list[i].type))
}
sql.append(")")
mDataBase.layerManagerDao.insert(layer)
mDataBase.openHelper.writableDatabase.execSQL(sql.toString())
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
}
} catch (e: Throwable) {
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
}
}
}
/**
* 将数据图层自定义子表所有配置转成JSON形式
* (现在用在向数据库插入数据图层表时,主要用于原生层)
*/
private fun customLayerItemListToBundle(list: List<CustomLayerItem>): String {
val jsonArray = JSONArray()
for (item in list) {
val jsonObject = JSONObject()
jsonObject.put("key", item.key)
jsonObject.put("title", item.title)
jsonObject.put("type", item.type.ordinal)
// jsonObject.put("nullable", item.nullable)
// jsonObject.put("primaryKey", item.primaryKey)
// jsonObject.put("value", item.value)
// jsonObject.put("selectOptions", item.selectOptions)
// jsonObject.put("isMainName", item.isMainName)
jsonObject.put("describe", item.describe)
val checkIdsArray = JSONArray()
// for (c in item.checkManagerList) {
// checkIdsArray.put(c.id)
// }
jsonObject.put(
"checkManagerIds", checkIdsArray
)
jsonArray.put(jsonObject)
}
return jsonArray.toString()
}
/**
* 将字段的控件类型,转换成数据库字段类型
*
* enum LayerItemType {
///输入框
layerItemTypeInput,
///输入框集合
layerItemTypeInputArray,
///纯展示文本
layerItemTypeText,
///单选框
layerItemTypeSingleSelection,
///多选框
layerItemTypeMultipleSelection
///菜单
layerItemTypeMultiLevelMenu
}
*/
private fun layerItemTypeToDBType(type: DataLayerItemType): String {
when (type) {
DataLayerItemType.DataLayerItemTypeInput -> return "TEXT"
}
return "TEXT";
}
/**
* 查询获取图层列表
*/
fun getDataLayerList(callback: (list: List<LayerManager>) -> Unit) {
thread(start = true) {
val list = mDataBase.layerManagerDao.findList();
// ///获取拓展部分
// for (l in list) {
// l.itemList = getItemList(l.bundle);
// }
Handler(Looper.getMainLooper()).post {
callback.invoke(list)
}
}
}
/**
* 解析dataLayer的bundle部分
*/
private fun getItemList(bundle: String): List<CustomLayerItem>? {
val itemList: MutableList<CustomLayerItem> = ArrayList()
if (bundle != null) {
try {
val jsonArray = JSONArray(bundle)
for (i in 0 until jsonArray.length()) {
val itemObject = jsonArray.getJSONObject(i)
val checkManagerList = mutableListOf<CheckManager>()
val idArray = itemObject.optJSONArray("checkManagerIds")
if (idArray != null) {
for (j in 0 until idArray.length()) {
val id = idArray[j] as Int
val check = mDataBase.checkManagerDao.findCheckManagerById(id.toLong())
if (check != null)
checkManagerList.add(check)
}
}
val item = CustomLayerItem(
key = itemObject.optString("key"),
title = itemObject.optString("title"),
type = DataLayerItemType.values()[itemObject.optInt("type")],
// nullable = itemObject.optBoolean("nullable", true),
// primaryKey = itemObject.optBoolean("primaryKey", false),
// value = itemObject.opt("value"),
// selectOptions = itemObject.optString("selectOptions"),
// isMainName = itemObject.optBoolean("isMainName"),
describe = itemObject.optString("describe"),
// checkManagerList =
itemBean = ""
)
itemList.add(item)
}
} catch (e: Exception) {
Log.e("jingo", "CustomLayerItem 列表创建失败 " + e.message)
}
}
return itemList
}
/**
* 查询某个获取图层
*/
fun getDataLayer(layerId: String, callback: (layer: LayerManager) -> Unit) {
thread(start = true) {
val layer = mDataBase.layerManagerDao.findLayerManager(layerId);
layer.itemList = getItemList(layer.bundle);
Handler(Looper.getMainLooper()).post {
callback.invoke(layer)
}
}
}
}

View File

@@ -0,0 +1,107 @@
package com.navinfo.collect.library.data.handler
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase.CONFLICT_NONE
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.*
import com.navinfo.collect.library.data.entity.DataLayerItemType.*
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.GeometryToolsKt
import io.realm.RealmSet
import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.io.WKTReader
import org.oscim.core.GeoPoint
import org.oscim.core.MercatorProjection
import kotlin.concurrent.thread
/**
* 数据库操作
*/
open class
DataNiLocationHandler(context: Context, dataBase: MapLifeDataBase) :
BaseDataHandler(context, dataBase) {
/**
* 保存数据
*/
fun saveDataNiLocation(
niLocation: NiLocation,
callback: (res: Boolean, errorString: String) -> Unit
) {
thread(start = true) {
try {
val geometry = GeometryTools.createGeometry(
GeoPoint(
niLocation.latitude,
niLocation.longitude
)
)
val tileX = RealmSet<Int>()
GeometryToolsKt.getTileXByGeometry(geometry.toString(), tileX)
val tileY = RealmSet<Int>()
GeometryToolsKt.getTileYByGeometry(geometry.toString(), tileY)
//遍历存储tile对应的x与y的值
tileX.forEach { x ->
tileY.forEach { y ->
niLocation.tilex = x
niLocation.tiley = y
}
}
val niLocationLoad = mDataBase.niLocationDao.find(niLocation.id);
if(niLocationLoad!=null){
mDataBase.niLocationDao.update(niLocation)
}else{
mDataBase.niLocationDao.insert(niLocation)
}
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
} catch (e: Throwable) {
e.message?.let { Log.e("qj", it) }
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
}
}
}
/**
* 删除数据
*/
fun deleteData(niLocation: NiLocation, callback: (res: Boolean, errorString: String) -> Unit) {
thread(start = true) {
try {
mDataBase.openHelper.writableDatabase.delete(
"'niLocation'",
"uuid=?",
arrayOf("'${niLocation.id}'")
)
mDataBase.niLocationDao.delete(niLocation);
} catch (e: Throwable) {
Log.e("jingo", "删除数据报错 ${e.message}");
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
}
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
}
}
}

View File

@@ -0,0 +1,50 @@
package com.navinfo.collect.library.data.handler
import android.content.Context
import android.os.Handler
import android.os.Looper
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.Project
import kotlin.concurrent.thread
/**
* 数据库操作
*/
open class DataProjectHandler(context: Context, dataBase: MapLifeDataBase) :
BaseDataHandler(context, dataBase) {
fun saveProject(
project: Project,
callback: (res: Boolean, errorString: String) -> Unit
) {
thread(start = true) {
try {
mDataBase.projectManagerDao.insert(project)
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
} catch (e: Throwable) {
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "${e.message}")
}
}
}
}
/**
* 查询获取图层列表
*/
fun getProjectList(callback: (list: List<Project>) -> Unit) {
thread(start = true) {
val list = mDataBase.projectManagerDao.findList();
Handler(Looper.getMainLooper()).post {
callback.invoke(list)
}
}
}
}

View File

@@ -0,0 +1,12 @@
package com.navinfo.collect.library.data.search
import com.navinfo.collect.library.data.entity.Element
import com.navinfo.collect.library.data.entity.LayerManager
import com.navinfo.collect.library.data.entity.Project
interface OnGetSearchDataResultListener {
fun onGetElementResult(elementList: List<Element>)
fun onGetLayerResult(layer: LayerManager)
fun onGetProjectResult(project: Project)
fun onError(msg:String,keyword:String)
}

View File

@@ -0,0 +1,8 @@
package com.navinfo.collect.library.data.search
class OptionFieldItem constructor(
val projectId: String,
val layerId: String,
val fieldName: String
) {
}

View File

@@ -0,0 +1,4 @@
package com.navinfo.collect.library.data.search
class OptionLayerItem constructor(val projectId: String, val layerId: String) {
}

View File

@@ -0,0 +1,5 @@
package com.navinfo.collect.library.data.search
class OptionProjectItem constructor(val projectId: String) {
}

View File

@@ -0,0 +1,109 @@
package com.navinfo.collect.library.data.search
class SearchDataOption private constructor(
/**
* 关键字
*/
val keyword: String,
/**
* 当前页数
*/
val pageNum: Int,
/**
* 每页最多数量
*/
val pageCapacity: Int,
/**
* 在工程级别范围内搜索
*/
val projectItemList: ArrayList<OptionProjectItem>,
/**
* 在图层级别范围内搜
*/
val layerItemList: ArrayList<OptionLayerItem>,
/**
* 搜索某个工程下,某个图层下的,某个字段
*/
val fieldItemList: ArrayList<OptionFieldItem>,
/**
* 时间范围,开始时间
*/
val startTime: Int,
/**
* 时间范围,结束时间
*/
val endTime: Int
) {
private constructor (builder: Builder) : this(
builder.keyword,
builder.pageNum,
builder.pageCapacity,
builder.projectItemList,
builder.layerItemList,
builder.fieldItemList,
builder.startTime,
builder.endTime,
)
class Builder {
var keyword: String = ""
private set
var pageNum: Int = 0
private set
var pageCapacity: Int = 20
private set
var projectItemList = ArrayList<OptionProjectItem>()
private set
var layerItemList = ArrayList<OptionLayerItem>()
private set
var fieldItemList = ArrayList<OptionFieldItem>()
private set
var startTime: Int = -1
private set
var endTime: Int = -1
private set
fun build() = SearchDataOption(this)
fun setKeyword(id: String) = apply {
this.keyword = id;
}
fun setStartTime(time: Int) = apply {
this.startTime = time;
}
fun setEndTime(time: Int) = apply {
this.endTime = time;
}
fun setPageNum(num: Int) = apply {
this.pageNum = num;
}
fun setPageCapacity(capacity: Int) = apply {
this.pageCapacity = capacity;
}
fun setLayerItems(list: ArrayList<OptionLayerItem>) = apply {
this.layerItemList = list
}
fun setProjectItems(list: ArrayList<OptionProjectItem>) = apply {
this.projectItemList = list
}
fun setFieldItems(list: ArrayList<OptionFieldItem>) = apply {
this.fieldItemList = list
}
}
}

View File

@@ -0,0 +1,10 @@
package com.navinfo.collect.library.importExport
import android.content.Context
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
open class ImportExportController(context: Context, dataBase: MapLifeDataBase) {
protected val mContext: Context = context;
protected val mDataBase: MapLifeDataBase = dataBase;
}

View File

@@ -0,0 +1,54 @@
package com.navinfo.collect.library.importExport.flutter
import android.content.Context
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.importExport.ImportExportController
import com.navinfo.collect.library.importExport.flutter.flutterhandler.FlutterImportFileHandler
import com.navinfo.collect.library.importExport.flutter.flutterhandler.FlutterShpFileHandler
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterImportExportController(
id: Int,
context: Context,
binaryMessenger: BinaryMessenger,
dataBase: MapLifeDataBase,
) : ImportExportController(context, dataBase), MethodChannel.MethodCallHandler {
private val mMethodChannel: MethodChannel = MethodChannel(
binaryMessenger,
"com.navinfo.collect/importOrExport_$id"
)
private val flutterShpFileHandler: FlutterShpFileHandler =
FlutterShpFileHandler(context, mMethodChannel, mDataBase)
private val flutterImportFileHandler: FlutterImportFileHandler =
FlutterImportFileHandler(context, mMethodChannel, mDataBase)
init {
mMethodChannel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
/**
* shp文件操作
*/
//获取shp文件信息
FlutterImportExportProtocolKeys.ShpFileProtocol.kGetImportShpFileInfo -> {
flutterShpFileHandler.getImportShpFileInfo(call, result)
}
//导入shp数据
FlutterImportExportProtocolKeys.ShpFileProtocol.kImportShpData -> {
flutterShpFileHandler.importShpData(call, result)
}
//导入检查项数据
FlutterImportExportProtocolKeys.MainProtocol.kGetImportCheckFileInfo ->{
flutterImportFileHandler.importCheckData(call,result)
}
}
}
}

View File

@@ -0,0 +1,30 @@
package com.navinfo.collect.library.importExport.flutter
class FlutterImportExportProtocolKeys {
/**
* SHP文件操作
*/
object ShpFileProtocol {
/**
* 获取SHP文件信息
*/
const val kGetImportShpFileInfo = "flutter_nimap/ShpFile/getImportShpFileInfo";
/**
* 导入SHP数据
*/
const val kImportShpData = "flutter_nimap/ShpFile/ImportShpData";
}
object MainProtocol{
/**
* 导入检查项数据
*/
const val kGetImportCheckFileInfo =
"flutter_nimap/ShpFile/getImportCheckFileInfo";
}
}

View File

@@ -0,0 +1,31 @@
package com.navinfo.collect.library.importExport.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.importExport.handler.ImportFileHandler
import com.navinfo.collect.library.system.Constant
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterImportFileHandler(
context: Context,
methodChannel: MethodChannel,
dataBase: MapLifeDataBase,
) : ImportFileHandler(context, dataBase) {
/**
* 获取shp文件属性信息
*/
fun importCheckData(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is String) {
importCheckFileInfo("${call.arguments}") { bSuccess, message ->
if (bSuccess) {
result.success(message)
} else {
result.error("1", message, "")
}
}
}
}
}

View File

@@ -0,0 +1,62 @@
package com.navinfo.collect.library.importExport.flutter.flutterhandler
import android.content.Context
import android.os.Environment
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.importExport.handler.ShpFileHandler
import com.navinfo.collect.library.system.Constant
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterShpFileHandler(
context: Context,
methodChannel: MethodChannel,
dataBase: MapLifeDataBase,
) : ShpFileHandler(context, dataBase) {
/**
* 获取shp文件属性信息
*/
fun getImportShpFileInfo(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is String) {
// .path + "/yongfeng/yongfengpolygon.shp"
// val path = call.arguments["path"];
getImportShpFileInfo("${call.arguments}") { bSuccess, message ->
if (bSuccess) {
result.success(message)
} else {
result.error("1", message, "")
}
}
}
}
/**
* 导入shp文件数据
*/
fun importShpData(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is Map<*, *>) {
var path = "";
var layerId = "";
if (call.hasArgument("path")) {
path = call.argument<String>("path").toString()
// path = Environment.getExternalStorageDirectory()
// .path + "/yongfeng/yongfengpolygon.shp"
}
if (call.hasArgument("layerId")) {
layerId = call.argument<String>("layerId").toString()
}
if (path.isNotEmpty() && layerId.isNotEmpty()) {
importShpData("$path", layerId) { bSuccess, message ->
if (bSuccess) {
result.success(true)
} else {
result.error("-1", message, "")
}
}
}
}
}
}

View File

@@ -0,0 +1,9 @@
package com.navinfo.collect.library.importExport.handler
import android.content.Context
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
open class ImportExportBaseHandler(context: Context, dataBase: MapLifeDataBase) {
protected val mContext: Context = context
protected val mDataBase: MapLifeDataBase = dataBase
}

View File

@@ -0,0 +1,56 @@
package com.navinfo.collect.library.importExport.handler
import android.content.Context
import android.os.Looper
import android.util.Log
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.CheckManager
import org.json.JSONObject
import java.io.File
import kotlin.concurrent.thread
open class ImportFileHandler(context: Context, dataBase: MapLifeDataBase) :
ImportExportBaseHandler(context, dataBase) {
init {
}
fun importCheckFileInfo(path: String, callback: (bSuccess: Boolean, message: String) -> Unit) {
thread(start = true) {
try {
val file = File(path)
if (file.exists()) {
val inputStream = file.inputStream()
inputStream.bufferedReader().useLines { lines ->
try {
val iterator = lines.iterator()
while (iterator.hasNext()) {
var json = iterator.next();
val jsonObject = JSONObject(json)
val type = jsonObject.optInt("type", 0)
val tag = jsonObject.optString("tag", "未命名")
var regex = jsonObject.optString("regexStr")
if (regex.startsWith("/") && regex.endsWith("/")) {
regex = regex.substring(1, regex.length - 1)
}
val check = CheckManager(type = type, tag = tag, regexStr = regex)
mDataBase.checkManagerDao.insert(check)
}
} catch (e: Exception) {
e.message?.let { Log.e("jingo", it) }
}
}
// inputStream.close()
}
} catch (e: Exception) {
e.message?.let { Log.e("jingo", it) }
}
android.os.Handler(Looper.getMainLooper()).post {
callback.invoke(true, "")
}
}
}
}

View File

@@ -0,0 +1,207 @@
package com.navinfo.collect.library.importExport.handler
import android.content.Context
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.navinfo.collect.library.data.DataConversion
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.entity.TileElement
import com.navinfo.collect.library.utils.GeometryToolsKt
import com.navinfo.collect.library.utils.StringUtil
import io.realm.RealmSet
import org.gdal.gdal.gdal
import org.gdal.ogr.*
import org.gdal.osr.SpatialReference
import org.json.JSONObject
import java.io.File
import kotlin.concurrent.thread
open class ShpFileHandler(context: Context, dataBase: MapLifeDataBase) :
ImportExportBaseHandler(context, dataBase) {
val strDriverName = "ESRI Shapefile"
init {
Log.e("jingo", "ShpFileHandler 初始化!!!!!")
ogr.RegisterAll()
gdal.AllRegister()
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
// 为了使属性表字段支持中文,请添加下面这句
gdal.SetConfigOption("SHAPE_ENCODING", "CP936")
}
fun getImportShpFileInfo(path: String, callback: (bSuccess: Boolean, message: String) -> Unit) {
try {
val file: File = File(path);
if (file.exists()) {
//创建一个文件根据strDriverName扩展名自动判断驱动类型
val oDriver: org.gdal.ogr.Driver = ogr.GetDriverByName(strDriverName)
if (oDriver == null) {
Log.e("jingo", "$strDriverName 驱动不可用!");
callback(false, "$strDriverName 驱动不可用!")
}
val dataSource: DataSource = oDriver.Open(path)
val layer: Layer = dataSource.GetLayer(0)
// for (i in 0 until dataSource.GetLayerCount()) {
val layerItem = dataSource.GetLayer(0);
// Log.e("jingo", "图层名称:${layerItem.GetName()}")
//空间参考坐标系
// val spatialReference:SpatialReference = layerItem.GetSpatialRef()
//图层范围
// val layerExtent: DoubleArray = layerItem.GetExtent()
// }
val geomType = getGeomType(layerItem.GetGeomType())
Log.e("jingo", "图层数据类型:${layerItem.GetGeomType()}")
//获取图层信息
val featureDefn: FeatureDefn = layer.GetLayerDefn()
val fieldCount = featureDefn.GetFieldCount()
val stringBuffer = StringBuffer()
for (i in 0 until fieldCount) {
val fieldDefn: FieldDefn = featureDefn.GetFieldDefn(i)
//得到属性字段类型
// val fieldType = fieldDefn.GetFieldType()
// val fieldTypeName = fieldDefn.GetFieldTypeName(fieldType)
//得到属性字段名称
val fieldName = fieldDefn.GetName()
if (stringBuffer.isNotEmpty()) {
stringBuffer.append(";")
}
stringBuffer.append(fieldName)
}
val jsonString =
"{\"layerName\":\"${layerItem.GetName()}\",\"geomType\":$geomType,\"keys\":\"$stringBuffer\"}"
callback(true, jsonString)
// //读取空间信息及属性列表
// for (i in 0 until fieldCount) {
// val feature: Feature = layer.GetFeature(i.toLong())
// for ((key, value) in map) {
// val fvalue = feature.GetFieldAsString(value)
// Log.e("jingo", "属性名称:$value 属性值:$fvalue")
// }
// }
}
} catch (e: Exception) {
callback(false, "${e.message}")
}
}
private fun getGeomType(type: Int): Int {
when (type) {
ogr.wkbPoint -> return 0
ogr.wkbPolygon -> return 2
}
return -1
}
fun importShpData(
path: String,
mapLayerId: String,
callback: (bSuccess: Boolean, message: String) -> Unit
) {
thread(start = true) {
try {
val mapLayer = mDataBase.layerManagerDao.findLayerManager(mapLayerId)
if (mapLayer != null) {
val mapLayerItemList = DataConversion.jsonToLayerItemsList(mapLayer.bundle)
var mainName = ""
// for (item in mapLayerItemList) {
// if (item.isMainName) {
// mainName = item.key
// break
// }
// }
val file = File(path);
if (file.exists()) {
val oDriver: org.gdal.ogr.Driver = ogr.GetDriverByName(strDriverName)
if (oDriver == null) {
Log.e("jingo", "$strDriverName 驱动不可用!");
callback(false, "$strDriverName 驱动不可用!")
}
val dataSource: DataSource = oDriver.Open(path)
val layer: Layer = dataSource.GetLayer(0)
val layerItem = dataSource.GetLayer(0)
//获取图层信息
val featureDefn: FeatureDefn = layer.GetLayerDefn()
val fieldCount = featureDefn.GetFieldCount()
val db = mDataBase.openHelper.readableDatabase
db.beginTransaction()
for (i in 0 until layer.GetFeatureCount()) {
val feature = layer.GetFeature(i)
val geometry = feature.GetGeometryRef()
val stringNameBuffer = StringBuffer()
val stringValueBuffer = StringBuffer()
var displayText = ""
for (i in 0 until fieldCount) {
val fieldDefn: FieldDefn = featureDefn.GetFieldDefn(i)
//得到属性字段名称
val fieldName = fieldDefn.GetName()
val fieldValue = feature.GetFieldAsString(fieldName)
stringNameBuffer.append(",'")
stringNameBuffer.append(fieldName)
stringNameBuffer.append("'")
stringValueBuffer.append(",'")
stringValueBuffer.append(fieldValue)
stringValueBuffer.append("'")
if (mainName == fieldName) {
displayText = fieldValue
}
}
val uuid = StringUtil.createUUID()
val wkt = geometry.ExportToWkt()
val nowTime = StringUtil.getYYYYMMDDHHMMSSS();
val masterPoint = GeometryToolsKt.getMasterPoint(wkt)
var jsonObject = JSONObject(mapLayer.style)
jsonObject.put(
"masterPoint",
masterPoint
)
val style = jsonObject.toString()
val sql =
"insert into '$mapLayerId' ('uuid'${stringNameBuffer}) values ('$uuid'${stringValueBuffer})"
val sql2 =
"insert into 'element' ('layer_id','display_style','display_text','visibility','export_time','t_lifecycle','t_status','geometry','uuid','start_level','end_level','zindex','operation_time') values ('$mapLayerId','$style','$displayText','0','$nowTime','2','1','${wkt}','$uuid',0,0,0,'$nowTime')"
Log.e("jingo",sql)
Log.e("jingo",sql2)
db.execSQL(sql)
db.execSQL(sql2)
if (geometry != null) {
val tileX = RealmSet<Int>()
GeometryToolsKt.getTileXByGeometry(wkt, tileX)
val tileY = RealmSet<Int>()
GeometryToolsKt.getTileYByGeometry(wkt, tileY)
//遍历存储tile对应的x与y的值
tileX.forEach { x ->
tileY.forEach { y ->
val sql3 =
"insert into 'tileElement' ('tilex','tiley','element_uuid','uuid') values ('$x','$y','$uuid','${StringUtil.createUUID()}')"
db.execSQL(sql3)
}
}
}
}
db.setTransactionSuccessful()
db.endTransaction()
Handler(Looper.getMainLooper()).post {
callback.invoke(true, "SHP导入成功")
}
}
}else{
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "没有对应的图层")
}
}
} catch (e: Exception) {
Log.e("导入数据出错", e.toString());
Handler(Looper.getMainLooper()).post {
callback.invoke(false, "SHP导入失败")
}
}
}
}
}

View File

@@ -0,0 +1,331 @@
package com.navinfo.collect.library.map;
import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Location;
import android.os.Environment;
import android.text.TextPaint;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.badlogic.gdx.maps.MapGroupLayer;
import com.navinfo.collect.library.R;
import com.navinfo.collect.library.map.layers.NIPolygonLayer;
import com.navinfo.collect.library.map.source.NavinfoMapRastorTileSource;
import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource;
import com.navinfo.collect.library.utils.DistanceUtil;
import com.navinfo.collect.library.utils.GeometryTools;
import com.navinfo.collect.library.utils.StringUtil;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Polygon;
import org.oscim.android.canvas.AndroidBitmap;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.event.Event;
import org.oscim.layers.Layer;
import org.oscim.layers.LocationLayer;
import org.oscim.layers.marker.ItemizedLayer;
import org.oscim.layers.marker.MarkerInterface;
import org.oscim.layers.marker.MarkerItem;
import org.oscim.layers.marker.MarkerSymbol;
import org.oscim.layers.tile.bitmap.BitmapTileLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.vector.geometries.Drawable;
import org.oscim.layers.vector.geometries.PointDrawable;
import org.oscim.layers.vector.geometries.PolygonDrawable;
import org.oscim.layers.vector.PathLayer;
import org.oscim.layers.vector.geometries.Style;
import org.oscim.map.Map;
import org.oscim.tiling.source.OkHttpEngine;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
public class NILayerManager implements ItemizedLayer.OnItemGestureListener {
private Map vtmMap;
public static String defaultDir = Environment.getExternalStorageDirectory() + "/" + "NavinfoCollect";
private String defaultLocalMapPath = defaultDir + "/maps/";
//图层管理
private java.util.Map<String, Layer> layersMap = new HashMap<String, Layer>();
//默认marker图层
private ItemizedLayer mDefaultMarkerLayer;
//定位图层
private LocationLayer mLocationLayer;
private NIPolygonLayer mPolygonLayer;
private List<MarkerItem> mPathMakers = new ArrayList<>();
private Location mCurrentLocation; // 当前位置信息
public static final String MARQUEE_MARKER_LAYER = "MarqueeMarker";
private Context mCon;
private java.util.Map<String, Layer> vectorLayerMap; // 维护vector图层的map数据key为图层名称一般对应为矢量数据的数据源value为图层
public NILayerManager(Context context, Map vtmMap) {
this.vtmMap = vtmMap;
this.mCon = context;
//新增marker图标样式
AndroidBitmap mDefaultBitmap =
new AndroidBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.marker));
MarkerSymbol markerSymbol = new MarkerSymbol(mDefaultBitmap, MarkerSymbol.HotspotPlace.BOTTOM_CENTER);
//新增marker图层
mDefaultMarkerLayer = new ItemizedLayer(
vtmMap,
new ArrayList<MarkerInterface>(),
markerSymbol,
this
);
addLayer("defaultMarkerLayer", mDefaultMarkerLayer, NIMapView.LAYER_GROUPS.VECTOR.ordinal());
//定位图层
mLocationLayer = new LocationLayer(vtmMap);
addLayer("locationLayer", mLocationLayer, NIMapView.LAYER_GROUPS.ALLWAYS_SHOW_GROUP.ordinal());
if (this.vectorLayerMap == null) {
this.vectorLayerMap = new HashMap<>();
}
}
public Layer getRasterTileLayer(Context mContext, String url, String tilePath, boolean useCache) {
if (this.vtmMap == null) {
throw new IllegalStateException("无法获取到map对象");
}
OkHttpClient.Builder builder = new OkHttpClient.Builder();
NavinfoMapRastorTileSource mTileSource = NavinfoMapRastorTileSource.builder(url).tilePath(tilePath).httpFactory(new OkHttpEngine.OkHttpFactory(builder)).build();
// 如果使用缓存
if (useCache) {
File cacheDirectory = new File(defaultDir, "tiles-raster");
int cacheSize = 300 * 1024 * 1024; // 300 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
// mTileSource.setHttpEngine(new OkHttpEngine.OkHttpFactory(builder));
// mTileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example"));
// mTileSource.setCache(new TileCache(mContext, defaultDir, url.substring(url.indexOf(":")+1)));
BitmapTileLayer rasterLayer = new BitmapTileLayer(this.vtmMap, mTileSource);
return rasterLayer;
}
// 初始化请求在线底图数据
public Layer getDefaultVectorLayer(boolean useCache) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (useCache) {
// Cache the tiles into file system
File cacheDirectory = new File(defaultDir, "tiles-vector");
int cacheSize = 200 * 1024 * 1024; // 200 MB
Cache cache = new Cache(cacheDirectory, cacheSize);
builder.cache(cache);
}
NavinfoMultiMapFileTileSource tileSource = NavinfoMultiMapFileTileSource.builder()
.apiKey("4wTLZyXcQym31pxC_HGy7Q") // Put a proper API key
.httpFactory(new OkHttpEngine.OkHttpFactory(builder))
//.locale("en")
.build();
HashMap<String, String> headerMap = new HashMap<>();
headerMap.put("token", "eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRJZCI6MTAzLCJ1c2VyTmFtZSI6ImFkbWluIiwidXNlcklkIjoxLCJ1c2VyR3JvdXAiOiLnoJTlj5Hpg6giLCJvcmdJZCI6MSwiaWF0IjoxNjMwOTk4MzI5LCJleHAiOjE2MzEwODQ3Mjl9.0wFm8mAA9dCC2FmZj-u1dhxTFDRYx8AqVnh2C88hitk");
tileSource.setHttpRequestHeaders(headerMap);
VectorTileLayer l = new VectorTileLayer(this.vtmMap, tileSource);
return l;
}
public void addLayer(String tag, Layer layer) {
if (!layersMap.containsKey(tag)) {
layersMap.put(tag, layer);
vtmMap.layers().add(layer);
}
}
public void addLayer(String tag, Layer layer, int group) {
if (!layersMap.containsKey(tag)) {
layersMap.put(tag, layer);
vtmMap.layers().add(layer, group);
}
}
public void addLayer(int index, String tag, Layer layer) {
if (!layersMap.containsKey(tag)) {
layersMap.put(tag, layer);
vtmMap.layers().add(index, layer);
}
}
public boolean containsLayer(String tag) {
return layersMap.containsKey(tag);
}
public Layer getLayer(String tag) {
return layersMap.get(tag);
}
public void removeLayer(String tag) {
if (layersMap.containsKey(tag)) {
Layer layer = layersMap.remove(tag);
vtmMap.layers().remove(layer);
}
}
/**
* 返回默认marker图层
*
* @return mDefaultMarkerLayer
*/
public ItemizedLayer getDefaultMarkerLayer() {
return mDefaultMarkerLayer;
}
/**
* 返回定位图层
*
* @return mLocationLayer
*/
public LocationLayer getLocationLayer() {
return mLocationLayer;
}
@Override
public boolean onItemSingleTapUp(int index, Object item) {
return false;
}
@Override
public boolean onItemLongPress(int index, Object item) {
return false;
}
/**
* 定位
* @param lon
* @param lat
* @param time
*/
public void jumpToPosition(double lon, double lat, long time) {
MapPosition mapPosition = vtmMap.getMapPosition();
mapPosition.setPosition(lat, lon);
vtmMap.animator().animateTo(time, mapPosition);
}
/**
* 定位
* @param lon
* @param lat
* @param zoomLevel
*/
public void jumpToPosition(double lon, double lat, int zoomLevel) {
MapPosition mapPosition = vtmMap.getMapPosition();
if (mapPosition.getZoomLevel() < zoomLevel) {
mapPosition.setZoomLevel(zoomLevel);
}
mapPosition.setPosition(lat, lon);
vtmMap.animator().animateTo(300, mapPosition);
}
public void addMarker2MarkerLayer(MarkerInterface markerItem, Bitmap defaultBitmap, String layerName, int layerGroup) {
if (markerItem == null) {
return;
}
if (vectorLayerMap != null) {
if (!vectorLayerMap.containsKey(layerName) || vectorLayerMap.get(layerName) == null) {
MarkerSymbol symbol = new MarkerSymbol(defaultBitmap, MarkerSymbol.HotspotPlace.BOTTOM_CENTER);
vectorLayerMap.put(layerName, new ItemizedLayer(vtmMap, symbol));
}
ItemizedLayer itemizedLayer = (ItemizedLayer) vectorLayerMap.get(layerName);
itemizedLayer.addItem(markerItem);
if (!vtmMap.layers().contains(itemizedLayer)) {
vtmMap.layers().add(itemizedLayer, layerGroup);
}
itemizedLayer.update();
}
}
public void addMarker2MarkerLayer(MarkerInterface markerItem, Bitmap defaultBitmap, String layerName, int layerGroup, ItemizedLayer.OnItemGestureListener listener) {
if (markerItem == null) {
return;
}
if (vectorLayerMap != null) {
if (!vectorLayerMap.containsKey(layerName) || vectorLayerMap.get(layerName) == null) {
MarkerSymbol symbol = new MarkerSymbol(defaultBitmap, MarkerSymbol.HotspotPlace.BOTTOM_CENTER);
vectorLayerMap.put(layerName, new ItemizedLayer(vtmMap, new ArrayList<MarkerInterface>(), symbol, listener));
}
ItemizedLayer itemizedLayer = (ItemizedLayer) vectorLayerMap.get(layerName);
itemizedLayer.addItem(markerItem);
if (!vtmMap.layers().contains(itemizedLayer)) {
vtmMap.layers().add(itemizedLayer, layerGroup);
}
itemizedLayer.update();
}
}
//删除marker
public void removeMarker(MarkerItem markerItem) {
if (vectorLayerMap != null && vectorLayerMap.containsKey("Marker")) {
ItemizedLayer itemizedLayer = (ItemizedLayer) vectorLayerMap.get("Marker");
if (itemizedLayer.getItemList() != null && itemizedLayer.getItemList().size() > 0) {
itemizedLayer.removeItem(markerItem);
}
}
}
/**
* @param markerItem marker
* @param layerName 图层
*/
public void removeMarker(MarkerItem markerItem, String layerName) {
if (vectorLayerMap != null && layerName != null && vectorLayerMap.containsKey(layerName)) {
ItemizedLayer itemizedLayer = (ItemizedLayer) vectorLayerMap.get(layerName);
if (itemizedLayer.getItemList() != null && itemizedLayer.getItemList().size() > 0) {
itemizedLayer.removeItem(markerItem);
}
}
}
/**
* 在地图中心增加marker
*/
public void showEditMapGraphical(String geometry, int type) {
}
//增加marker
public MarkerItem addMarker(GeoPoint geopoint, Bitmap bitmap) {
if (geopoint != null && bitmap != null) {
MarkerItem markerItem = new MarkerItem(StringUtil.Companion.createUUID(), "", geopoint.getLatitude() + "," + geopoint.getLongitude(), geopoint);
MarkerSymbol markerSymbol = new MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.BOTTOM_CENTER);
markerItem.setMarker(markerSymbol);
addMarker2MarkerLayer(markerItem, bitmap, "", NIMapView.LAYER_GROUPS.OTHER.ordinal());
return markerItem;
}
return null;
}
public Location getCurrentLocation() {
return mCurrentLocation;
}
}

View File

@@ -0,0 +1,8 @@
package com.navinfo.collect.library.map
import android.location.Location
class NILocation(provider: String) : Location(provider) {
var radius = 0f
}

View File

@@ -0,0 +1,386 @@
package com.navinfo.collect.library.map;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.View;
import com.navinfo.collect.library.utils.CacheTileProgress;
import com.navinfo.collect.library.utils.TileDownloader;
import com.yanzhenjie.kalle.Kalle;
import com.yanzhenjie.kalle.download.Download;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.layers.Layer;
import org.oscim.layers.tile.bitmap.BitmapTileLayer;
import org.oscim.map.Map;
import org.oscim.tiling.source.UrlTileSource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
/**
* 定义 NavinfoMap 地图对象的操作方法与接口
*/
public class NIMap {
/**
*
*/
private Map map;
/**
* 地图控件
*/
private NIMapView mMapView;
/**
* 指北针显隐
*/
private boolean enableCompassImage = true;
/**
* 用户位置显示图层
* */
// private NaviLocationLayer locationLayer;
/**
* 构造函数
*/
public NIMap(NIMapView niMapView) {
this.mMapView = niMapView;
this.map = mMapView.getVtmMap();
}
/**
* 获取地图的当前状态
*
* @return
*/
public Map getVtmMap() {
return map;
}
/**
* 获取地图最大缩放级别
*
* @return
*/
public float getMaxZoomLevel() {
return map.viewport().getMaxZoomLevel();
}
/**
* 获取地图最小缩放级别
*
* @return
*/
public float getMinZoomLevel() {
return map.viewport().getMinZoomLevel();
}
/**
* 设置指南针是否显示
*
* @param enable
*/
public void setCompassEnable(boolean enable) {
this.enableCompassImage = enable;
if (mMapView != null && mMapView.getCompassImage() != null) {
mMapView.getCompassImage().setVisibility(enable ? View.VISIBLE : View.GONE);
mMapView.getCompassImage().setEnabled(enable);
}
}
/**
* 获取指北针显隐控制
*
* @return true 显示 false 隐藏
*/
public boolean isEnableCompassImage() {
return enableCompassImage;
}
/**
* 设置指南针自定义图标
*
* @param icon
*/
public void setCompassIcon(Bitmap icon) {
if (mMapView != null && mMapView.getCompassImage() != null) {
mMapView.getCompassImage().setImageBitmap(icon);
}
}
/**
* 设置地图显示大小等级
*
* @param level
*/
public void setFontSizeLevel(int level) {
}
/**
* 设置地图最大以及最小缩放级别
*
* @param max
* @param min
*/
public void setMaxAndMinZoomLevel(int max, int min) {
map.viewport().setMaxZoomLevel(max);
map.viewport().setMinZoomLevel(min);
}
/**
* 放大
*
* @param animate 是否动画过渡
*/
public void zoomIn(boolean animate) {
MapPosition mapPosition = map.getMapPosition();
mapPosition.setZoom(mapPosition.getZoom() + 1);
if (animate) {
map.animator().animateTo(mapPosition);
} else {
map.setMapPosition(mapPosition);
}
}
/**
* 缩小地图
*
* @param animate 是否动画过渡
*/
public void zoomOut(boolean animate) {
MapPosition mapPosition = map.getMapPosition();
mapPosition.setZoom(mapPosition.getZoom() - 1);
if (animate) {
map.animator().animateTo(mapPosition);
} else {
map.setMapPosition(mapPosition);
}
}
/**
* 设置定位数据, 只有先允许定位图层后设置数据才会生效,参见 setMyLocationEnabled(boolean)
*
* @param data
*/
// public void setMyLocationData(Location data) {
// if (locationLayer == null) {
// return;
// }
// locationLayer.setPosition(data.getLatitude(), data.getLongitude(), data.getAccuracy());
// }
// public void setMyLocationData(double lat, double lon, float accuracy) {
// if (locationLayer == null) {
// return;
// }
// locationLayer.setPosition(lat, lon, accuracy);
// }
/**
* 设置是否允许定位图层
*
* @param enabled
*/
// public void setMyLocationEnabled(Context mContext, boolean enabled) {
// initLocaitonLayer(mContext);
// locationLayer.setEnabled(enabled);
// }
// private void initLocaitonLayer(Context mContext) {
// if (map == null) {
// throw new IllegalStateException("map不可用无法显示当前位置");
// }
// if (locationLayer == null) {
// locationLayer = new NaviLocationLayer(mContext, map);
// }
// }
/**
* 设置地图
* */
public void setMapPosition(double latitude, double longitude, int zoomLevel) {
double scale = 1 << zoomLevel;
getVtmMap().setMapPosition(latitude, longitude, scale);
}
public void animateMapPosition(double latitude, double longitude, int zoomLevel, int duration) {
if (duration < 0) {
duration = 500;
}
if (zoomLevel <= 0) {
zoomLevel = getVtmMap().getMapPosition().zoomLevel;
}
double scale = 1 << zoomLevel;
MapPosition mapPosition = new MapPosition(latitude, longitude, scale);
getVtmMap().animator().animateTo(duration, mapPosition);
}
/**
* 下载离线矢量地图
* */
public void downloadVectorMap(String url, DownloadProgress downloadProgress) {
Kalle.Download.get(url).directory(NILayerManager.defaultDir).onProgress(new Download.ProgressBar() {
@Override
public void onProgress(int progress, long byteCount, long speed) {
downloadProgress.onProgress(progress, byteCount, speed);
}
});
}
/**
* 缓存urlTilesource对应的数据
* */
public List<FutureTask> cacheUrlTileMap(Rect rect, int minZoomLevel, int maxZoomLevel, CacheTileProgress progress) {
List<Layer> layerList = getVtmMap().layers();
List<UrlTileSource> urlTileSourceList = new ArrayList<>();
if (layerList!=null&&!layerList.isEmpty()) {
for (int i = 0; i < layerList.size(); i++) {
Layer layer = layerList.get(i);
if (layer instanceof BitmapTileLayer && ((BitmapTileLayer) layer).getTileSource() instanceof UrlTileSource) {
UrlTileSource urlTileSource = (UrlTileSource) ((BitmapTileLayer) layer).getTileSource();
urlTileSourceList.add(urlTileSource);
}
}
}
// 根据rect获取对应的地理坐标
GeoPoint leftTopGeoPoint = map.viewport().fromScreenPoint(rect.left, rect.top);
GeoPoint rightBottomGeoPoint = map.viewport().fromScreenPoint(rect.right, rect.bottom);
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
List<FutureTask> futureTaskList = new ArrayList<>();
progress.setLayerCount(urlTileSourceList.size());
for (int i = 0; i < urlTileSourceList.size(); i++) {
UrlTileSource urlTileSource = urlTileSourceList.get(i);
int finalI = i;
progress.setLayerId(i);
Callable callable = TileDownloader.getInstance().downloadRasterTile(urlTileSource, leftTopGeoPoint, rightBottomGeoPoint, (byte) minZoomLevel, (byte) maxZoomLevel, progress);
FutureTask futureTask = new FutureTask(callable);
futureTaskList.add(futureTask);
}
if (futureTaskList!=null&&!futureTaskList.isEmpty()){
for (int i = 0; i < futureTaskList.size(); i++) {
scheduledExecutorService.submit(futureTaskList.get(i));
}
scheduledExecutorService.shutdown();
}
return futureTaskList;
}
public void cancelCacheTileMap() {
TileDownloader.getInstance().setCanDownloadRasterTile(false);
}
public interface DownloadProgress {
Download.ProgressBar DEFAULT = new Download.ProgressBar() {
@Override
public void onProgress(int progress, long byteCount, long speed) {
}
};
/**
* Download onProgress changes.
*/
void onProgress(int progress, long byteCount, long speed);
}
/**
* 设置地图单击事件监听者
*
* @param listener
*/
public void setOnMapClickListener(OnMapClickListener listener) {
mMapView.setOnMapClickListener(listener);
}
/**
* 设置地图双击事件监听者
*
* @param listener
*/
public void setOnMapDoubleClickListener(OnMapDoubleClickListener listener) {
mMapView.setOnMapDoubleClickListener(listener);
}
/**
* 设置地图长按事件监听者
*
* @param listener
*/
public void setOnMapLongClickListener(OnMapLongClickListener listener) {
mMapView.setOnMapLongClickListener(listener);
}
/**
* @param listener
*/
public void setOnMapTouchListener(OnMapTouchListener listener) {
mMapView.setOnMapTouchListener(listener);
}
/**
* 地图单击事件监听接口
*/
public static interface OnMapClickListener {
/**
* 地图单击事件回调函数
*
* @param point
*/
void onMapClick(GeoPoint point);
/**
* 地图内 Poi 单击事件回调函数
*
* @param poi
*/
void onMapPoiClick(GeoPoint poi);
}
/**
* 地图双击事件监听接口
*/
public static interface OnMapDoubleClickListener {
/**
* 地图双击事件监听回调函数
*
* @param point
*/
void onMapDoubleClick(GeoPoint point);
}
/**
* 地图长按事件监听接口
*/
public static interface OnMapLongClickListener {
/**
* 地图长按事件监听回调函数
*
* @param point
*/
void onMapLongClick(GeoPoint point);
}
/**
* 用户触摸地图时回调接口
*/
public static interface OnMapTouchListener {
/**
* 当用户触摸地图时回调函数
*
* @param event
*/
void onTouch(MotionEvent event);
}
}

View File

@@ -0,0 +1,49 @@
package com.navinfo.collect.library.map
import android.content.Context
import com.navinfo.collect.library.map.handler.*
import com.navinfo.collect.library.map.maphandler.MeasureLayerHandler
import com.navinfo.collect.library.map.handler.ViewportHandler
/**
* 地图控制器
*/
open class NIMapController(
context: Context,
options: NIMapOptions? = null,
mapView: NIMapView? = null,
) {
private val mContext = context
internal var mMapView: NIMapView =
mapView ?: NIMapView(mContext, options)
val animationHandler: AnimationHandler by lazy { AnimationHandler(mContext, mMapView) }
val markerHandle: MarkHandler by lazy { MarkHandler(mContext, mMapView) }
val locationLayerHandler: LocationLayerHandler by lazy {
LocationLayerHandler(
mContext,
mMapView
)
};
val lineHandler: LineHandler by lazy { LineHandler(mContext, mMapView) };
val polygonHandler: PolygonHandler by lazy { PolygonHandler(mContext, mMapView) };
val viewportHandler: ViewportHandler by lazy { ViewportHandler(mContext, mMapView) }
val measureLayerHandler: MeasureLayerHandler by lazy { MeasureLayerHandler(mContext, mMapView) };
/**
* 刷新地图
*/
fun upDateMap(redraw: Boolean = true) {
if (redraw) {
mMapView.vtmMap.events.fire(org.oscim.map.Map.CLEAR_EVENT, mMapView.vtmMap.mapPosition)
}
mMapView.vtmMap.updateMap(redraw)
}
open fun release() {
mMapView.onDestroy()
}
}

View File

@@ -0,0 +1,154 @@
package com.navinfo.collect.library.map;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.navinfo.collect.library.R;
import com.navinfo.collect.library.data.entity.Element;
import com.navinfo.collect.library.utils.GeometryTools;
import org.oscim.core.GeoPoint;
import org.oscim.core.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NIMapCopyView extends View {
Paint paint;
private List<Element> pointList = new ArrayList<>();
private Map<String, Bitmap> bitmapMap = new HashMap<>();
private Map<String, List<Point>> linesMap = new HashMap<>();
private NIMapView mNiMapView;
public NIMapCopyView(Context context, NIMapView mapView) {
this(context, null, 0);
this.mNiMapView = mapView;
}
public NIMapCopyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, -1);
}
public NIMapCopyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, -1);
}
public NIMapCopyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
paint = new Paint();
paint.setColor(context.getColor(R.color.default_red));
paint.setStrokeWidth(5);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Element element : pointList) {
List<Point> lines = linesMap.get(element.getId());
if (lines != null && lines.size() > 0) {
for (int i = 0; i < lines.size() - 1; i++) {
canvas.drawLine((float) lines.get(i).x, (float) lines.get(i).y,
(float) lines.get(i + 1).x, (float) lines.get(i + 1).y, paint);
}
Bitmap bitmap = bitmapMap.get(element.getId());
if (bitmap != null) {
canvas.drawBitmap(bitmap, (float) lines.get(0).x - bitmap.getWidth() / 2, (float) lines.get(0).y - bitmap.getHeight(), paint);
}
bitmapMap.remove(element.getId());
bitmap.recycle();
bitmap = null;
}
}
}
public void setPointList(List<Element> pointList) {
if (pointList == null || pointList.size() == 0) {
this.pointList.clear();
this.bitmapMap.clear();
this.linesMap.clear();
invalidate();
return;
}
this.pointList = pointList;
initData(pointList);
invalidate();
}
private void initData(List<Element> pointList) {
for (Element element : pointList) {
List<GeoPoint> list = GeometryTools.getGeoPoints(element.getGeometry());
List<Point> lines = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
GeoPoint geoPoint = list.get(i);
Point point1 = new Point();
this.mNiMapView.getVtmMap().viewport().toScreenPoint(geoPoint, false, point1);
lines.add(point1);
}
linesMap.put(element.getId(), lines);
Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), getBitmapId(element));
bitmapMap.put(element.getId(), bitmap);
}
}
private int getBitmapId(Element element) {
int resId = -1;
if (element.getTStatus() == 2) {
if (element.getTLifecycle() == 0) {
if (resId == -1) {
resId = R.mipmap.map_icon_line_pr;
}
} else {
if (resId == -1) {
resId = R.mipmap.map_icon_line_add;
}
}
} else if (element.getTStatus() == 3) {
if (element.getTLifecycle() == 0) {
if (resId == -1) {
resId = R.mipmap.map_icon_polygon_pr;
}
} else {
if (resId == -1) {
resId = R.mipmap.map_icon_polygon_add;
}
}
} else {
if (element.getTLifecycle() == 0) {
if (resId == -1) {
resId = R.mipmap.map_icon_point_pr;
}
} else {
if (resId == -1) {
resId = R.mipmap.map_icon_point_add;
}
}
}
return resId;
}
public Map<String, List<GeoPoint>> getGeoPointsMap() {
Map<String, List<GeoPoint>> map = new HashMap<>();
for (Element element : pointList) {
List<GeoPoint> list = new ArrayList<>();
List<Point> lines = linesMap.get(element.getId());
if (lines.size() > 0) {
for (Point point : lines) {
GeoPoint geoPoint = this.mNiMapView.getVtmMap().viewport().fromScreenPoint((float) point.x, (float) point.y);
list.add(geoPoint);
}
}
map.put(element.getId(), list);
}
return map;
}
}

View File

@@ -0,0 +1,52 @@
package com.navinfo.collect.library.map
import org.json.JSONObject
data class NIMapOptions(
val showCompassControl: Boolean = true,//指南针是否显示
val showZoomControl: Boolean = true, //是否显示zoom按钮
val zoomLevel: Double = 13.0, /// 地图比例尺初始级别
val coordinate: NICoordinate = NICoordinate(39.907375, 116.391349),
) {
companion object {
fun fromJson(json: String): NIMapOptions {
var options: NIMapOptions
try {
val json = JSONObject(json)
val showCompassControl = json.optBoolean("showZoomControl", true)
val showZoomControl = json.optBoolean("showZoomControl", true)
val zoomLevel = json.optDouble("zoomLevel", 13.0)
val geometryObject = json.optJSONObject("coordinate")
var coor = NICoordinate.fromJson(geometryObject)
if (coor == null)
coor == NICoordinate(39.907375, 116.391349)
options = NIMapOptions(
showCompassControl = showCompassControl,
showZoomControl = showZoomControl,
zoomLevel = zoomLevel,
coordinate = coor!!,
)
} catch (e: Exception) {
options = NIMapOptions()
}
return options;
}
}
}
data class NICoordinate(val latitude: Double, val longitude: Double) {
companion object {
fun fromJson(json: JSONObject): NICoordinate? {
try {
return NICoordinate(
json.optDouble("latitude"), json.optDouble("longitude")
)
} catch (e: Exception) {
}
return null;
}
}
}

View File

@@ -0,0 +1,924 @@
package com.navinfo.collect.library.map;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import androidx.annotation.Nullable;
import com.navinfo.collect.library.R;
import com.navinfo.collect.library.map.layers.NaviMapScaleBar;
import com.navinfo.collect.library.map.source.MapLifeDBTileSource;
import com.navinfo.collect.library.map.source.MapLifeNiLocationTileDataSource;
import com.navinfo.collect.library.map.source.MapLifeNiLocationTileSource;
import com.navinfo.collect.library.system.Constant;
import org.oscim.android.MapPreferences;
import org.oscim.android.MapView;
import org.oscim.core.GeoPoint;
import org.oscim.android.theme.AssetsRenderTheme;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.event.Event;
import org.oscim.event.Gesture;
import org.oscim.event.GestureListener;
import org.oscim.layers.GroupLayer;
import org.oscim.layers.Layer;
import org.oscim.layers.TileGridLayer;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.OsmTileLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook;
import org.oscim.map.Map;
import org.oscim.renderer.GLViewport;
import org.oscim.theme.IRenderTheme;
import org.oscim.theme.ThemeLoader;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import org.oscim.tiling.source.mapfile.MultiMapFileTileSource;
import java.io.File;
/**
* 一个显示地图的视图View。它负责从服务端获取地图数据。它将会捕捉屏幕触控手势事件
*/
public final class NIMapView extends RelativeLayout {
/**
* VTM地图
*/
private MapView mapView;
/**
* NavinfoMap 地图对象的操作方法与接口
*/
// private NIMap map;
/**
* 定位图标
*/
protected ImageView compassImage;
/**
* logo图标
*/
protected ImageView logoImage;
/**
* 图片旋转
*/
private NIRotateAnimation mRotateAnimation;
/**
* 之前的旋转角度
*/
private float mLastRotateZ = 0;
/**
* 缩放按钮
*/
private ImageView zoomInImage, zoomOutImage;
private View zoomLayout;
/**
* 地图状态设置
*/
private NIMapOptions options;
/**
* 地图图层管理器
*/
private NILayerManager mLayerManager;
private Layer baseRasterLayer, defaultVectorTileLayer, defaultVectorLabelLayer, gridLayer;
protected Context mContext;
private MapPreferences mPrefs;
protected String mapFilePath = Constant.ROOT_PATH+"/map";
protected GroupLayer baseGroupLayer; // 用于盛放所有基础底图的图层组,便于统一管理
public NIMapView(Context context, NIMapOptions options) {
this(context, null, 0);
this.options = options;
initOptions();
}
/**
* 地图的单击事件监听
*/
private NIMap.OnMapClickListener mapClickListener;
/**
* 地图的双击事件监听
*/
private NIMap.OnMapDoubleClickListener mapDoubleClickListener;
/**
* 地图的长按事件监听
*/
private NIMap.OnMapLongClickListener mapLongClickListener;
/**
* 地图的触摸事件
*/
private NIMap.OnMapTouchListener touchListener;
public NIMapView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NIMapView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public NIMapView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView(context);
}
private void initView(Context context) {
View rootView = LayoutInflater.from(context).inflate(R.layout.base_map_layout, this, true);
this.mContext = context;
mapView = rootView.findViewById(R.id.base_map_view);
// map = new NIMap(this);
compassImage = rootView.findViewById(R.id.navinfo_map_compass);
initMapGroup(); // 初始化图层组
mLayerManager = new NILayerManager(context, getVtmMap());
logoImage = rootView.findViewById(R.id.navinfo_map_logo);
mRotateAnimation = new NIRotateAnimation(compassImage);
mPrefs = new MapPreferences(NIMapView.class.getName(), mContext);
getVtmMap().events.bind(new Map.UpdateListener() {
@Override
public void onMapEvent(Event e, MapPosition mapPosition) {
//旋转
if (mLastRotateZ != mapPosition.bearing) {
mRotateAnimation.startRotationZ(mLastRotateZ, mapPosition.bearing);
mLastRotateZ = mapPosition.bearing;
}
//增加控制联动效果
// if (map != null && map.isEnableCompassImage()) {
//2D,正北隐藏
if (compassImage.getVisibility() != View.VISIBLE && (mapPosition.tilt != 0 || mapPosition.bearing != 0)) {
compassImage.setVisibility(View.VISIBLE);
} else if (compassImage.getVisibility() == View.VISIBLE && mapPosition.tilt == 0 && mapPosition.bearing == 0) {
compassImage.clearAnimation();
compassImage.setVisibility(View.GONE);
}
// } else {
// compassImage.clearAnimation();
// compassImage.setVisibility(View.GONE);
// }
}
});
// 增加比例尺图层
NaviMapScaleBar naviMapScaleBar = new NaviMapScaleBar(getVtmMap());
naviMapScaleBar.initScaleBarLayer(GLViewport.Position.BOTTOM_LEFT, 25, 60);
if (gridLayer == null) {
gridLayer = new TileGridLayer(getVtmMap());
getVtmMap().layers().add(gridLayer, LAYER_GROUPS.ALLWAYS_SHOW_GROUP.groupIndex);
gridLayer.setEnabled(false);
}
compassImage.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MapPosition mapPosition = getVtmMap().getMapPosition();
mapPosition.setBearing(0);
mapPosition.setTilt(0);
getVtmMap().animator().animateTo(300, mapPosition);
}
});
zoomInImage = rootView.findViewById(R.id.navinfo_map_zoom_in);
zoomInImage.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
zoomIn(arg0);
}
});
zoomOutImage = rootView.findViewById(R.id.navinfo_map_zoom_out);
zoomOutImage.setImageResource(R.drawable.icon_map_zoom_out);
zoomOutImage.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
zoomOut(arg0);
}
});
mapView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (touchListener != null) {
touchListener.onTouch(event);
}
return false;
}
});
zoomLayout = rootView.findViewById(R.id.navinfo_map_zoom_layer);
initMap();
}
/**
* 地图初始化参数
*/
private void initOptions() {
if (options != null) {
if (options.getShowZoomControl()) {
zoomLayout.setVisibility(VISIBLE);
} else {
zoomLayout.setVisibility(GONE);
}
MapPosition mapPosition = getVtmMap().getMapPosition();
mapPosition.setZoom(options.getZoomLevel());
mapPosition.setPosition(options.getCoordinate().getLatitude(), options.getCoordinate().getLongitude());
getVtmMap().animator().animateTo(100, mapPosition);
}
}
/**
* 初始化地图
*/
private void initMap() {
switchBaseMapType(BASE_MAP_TYPE.CYCLE_MAP);
switchTileVectorLayerTheme(MAP_THEME.DEFAULT);
initVectorTileLayer();
initMapLifeSource();
}
/**
* 增加作业渲染
*/
LabelLayer labelLayer;
/**
* 作业数据图层
*/
VectorTileLayer vectorTileLayer;
/**
* 作业数据渲染图层
*/
MapLifeDBTileSource mapLifeDBTileSource;
/**
* 轨迹渲染图层
*/
MapLifeNiLocationTileSource mapLifeNiLocationTileSource;
/**
* 轨迹数据图层
*/
VectorTileLayer vectorNiLocationTileLayer;
/**
* 增加作业渲染
*/
LabelLayer labelNiLocationLayer;
public void initMapLifeSource() {
mapLifeDBTileSource = new MapLifeDBTileSource(this.mContext, Constant.ROOT_PATH + "/coremap.db");
mapLifeNiLocationTileSource = new MapLifeNiLocationTileSource(this.mContext,Constant.ROOT_PATH + "/coremap.db");
vectorTileLayer = new VectorTileLayer(mapView.map(), mapLifeDBTileSource);
vectorNiLocationTileLayer = new VectorTileLayer(mapView.map(),mapLifeNiLocationTileSource);
mapView.map().layers().add(vectorNiLocationTileLayer,LAYER_GROUPS.VECTOR_TILE.groupIndex);
mapView.map().layers().add(vectorTileLayer,LAYER_GROUPS.VECTOR_TILE.groupIndex);
labelLayer = new LabelLayer(mapView.map(), vectorTileLayer, new LabelTileLoaderHook(), 15);
mapView.map().layers().add(labelLayer,LAYER_GROUPS.VECTOR_TILE.groupIndex);
labelNiLocationLayer = new LabelLayer(mapView.map(), vectorNiLocationTileLayer, new LabelTileLoaderHook(), 15);
mapView.map().layers().add(labelNiLocationLayer,LAYER_GROUPS.VECTOR_TILE.groupIndex);
switchTileVectorLayerTheme(null);
mapView.map().updateMap(true);
MapPosition mapPosition = new MapPosition();
mapPosition.setZoomLevel(18);
mapPosition.setPosition(40.091692296269144, 116.26712172082546);
//116.26712172082546 40.091692296269144
mapView.map().animator().animateTo(mapPosition);
}
public void dataLayerUpdate() {
switchTileVectorLayerTheme(null);
}
private void initMapGroup() {
for (LAYER_GROUPS groups : LAYER_GROUPS.values()) {
getVtmMap().layers().addGroup(groups.groupIndex);
}
}
/**
* 切换基础底图样式
*/
public void switchBaseMapType(BASE_MAP_TYPE type) {
if (baseRasterLayer != null) {
getVtmMap().layers().remove(baseRasterLayer);
baseRasterLayer = null;
getVtmMap().updateMap();
}
baseRasterLayer = mLayerManager.getRasterTileLayer(mContext, type.url, type.tilePath, true);
getVtmMap().layers().add(baseRasterLayer, LAYER_GROUPS.BASE_RASTER.groupIndex);
getVtmMap().updateMap();
}
/**
* 移除基础底图样式
*/
public void removeBaseMap() {
if (baseRasterLayer != null) {
getVtmMap().layers().remove(baseRasterLayer);
baseRasterLayer = null;
getVtmMap().updateMap();
}
}
public void initVectorTileLayer(){
if (baseGroupLayer == null) {
baseGroupLayer = new GroupLayer(getVtmMap());
}
for (Layer layer : baseGroupLayer.layers) {
getVtmMap().layers().remove(layer);
}
baseGroupLayer.layers.clear();
File baseMapFolder = new File(mapFilePath);
if (!baseMapFolder.exists()) {
return;
}
File[] mapFileList = baseMapFolder.listFiles();
if (mapFileList != null && mapFileList.length > 0) {
MultiMapFileTileSource multiMapFileTileSource = new MultiMapFileTileSource();
for (File mapFile : mapFileList) {
if (!mapFile.exists() || !mapFile.getName().endsWith(".map")) {
continue;
}
MapFileTileSource mTileSource = new MapFileTileSource();
mTileSource.setPreferredLanguage("zh");
if (mTileSource.setMapFile(mapFile.getAbsolutePath())) {
multiMapFileTileSource.add(mTileSource);
}
}
VectorTileLayer baseMapLayer = new OsmTileLayer(getVtmMap());
baseMapLayer.setTileSource(multiMapFileTileSource);
baseGroupLayer.layers.add(baseMapLayer);
if (getTheme(null) != null)
baseMapLayer.setTheme(getTheme(null));
baseGroupLayer.layers.add(new BuildingLayer(getVtmMap(), baseMapLayer));
baseGroupLayer.layers.add(new LabelLayer(getVtmMap(), baseMapLayer));
for (Layer layer : baseGroupLayer.layers) {
if (layer instanceof LabelLayer) {
getVtmMap().layers().add(layer, LAYER_GROUPS.VECTOR.groupIndex);
} else {
getVtmMap().layers().add(layer, LAYER_GROUPS.BASE_VECTOR.groupIndex);
}
}
}
}
//获取渲染资源
public IRenderTheme getTheme(final String styleId) {
AssetsRenderTheme theme = new AssetsRenderTheme(mContext.getAssets(), null, "default.xml");
if (styleId == null || "".equals(styleId.trim())) {
switch (2) {
case 0:
theme = new AssetsRenderTheme(mContext.getAssets(), null, "default.xml");
break;
case 1:
theme = new AssetsRenderTheme(mContext.getAssets(), null, "osmarender.xml");
break;
case 2:
theme = new AssetsRenderTheme(mContext.getAssets(), null, "tronrender.xml");
break;
}
}
return ThemeLoader.load(theme);
}
public void addDefaultVectorTileLayer(MAP_THEME theme) {
if (defaultVectorTileLayer != null) {
getVtmMap().layers().remove(defaultVectorTileLayer);
defaultVectorTileLayer = null;
getVtmMap().updateMap();
}
defaultVectorTileLayer = mLayerManager.getDefaultVectorLayer(true);
getVtmMap().layers().add(defaultVectorTileLayer, LAYER_GROUPS.VECTOR_TILE.groupIndex);
defaultVectorLabelLayer = new LabelLayer(getVtmMap(), (VectorTileLayer) defaultVectorTileLayer);
getVtmMap().layers().add(defaultVectorLabelLayer, LAYER_GROUPS.VECTOR_TILE.groupIndex);
if (theme != null) {
switchTileVectorLayerTheme(theme);
}
getVtmMap().updateMap();
}
public void setBaseRasterVisiable(boolean visiable) {
if (baseRasterLayer != null) {
baseRasterLayer.setEnabled(visiable);
getVtmMap().updateMap();
}
}
/**
* 基础
*/
public enum BASE_MAP_TYPE {
OPEN_STREET_MAP("Open Street Map", "http://a.tile.openstreetmap.org", "/{Z}}/{X}/{Y}.png"), // openStreetMap底图
CYCLE_MAP("Cycle Map", "http://c.tile.opencyclemap.org/cycle", "/{Z}}/{X}/{Y}.png"), // cyclemap底图
S_MAP("SMap", "http://smap.navinfo.com/gateway/smap-raster-map/raster/basemap/tile", "z={Z}&x={X}&y={Y}"), // cyclemap底图
TRANSPORT_MAP("Transport Map", "http://b.tile2.opencyclemap.org/transport", "/{Z}}/{X}/{Y}.png"); // TransportMap底图
String title;
String url;
String tilePath;
BASE_MAP_TYPE(String title, String url, String tilePath) {
this.title = title;
this.url = url;
this.tilePath = tilePath;
}
public String getTitle() {
return title;
}
public String getUrl() {
return url;
}
public String getTilePath() {
return tilePath;
}
}
/**
* 网格图层是否显示
*/
public void setGridLayerVisiable(boolean visiable) {
if (gridLayer != null) {
gridLayer.setEnabled(visiable);
getVtmMap().updateMap();
}
}
/**
* 图层组定义
*/
public enum LAYER_GROUPS {
BASE_RASTER(0)/*栅格底图*/, BASE_VECTOR(1)/*矢量底图*/,
RASTER_TILE(2)/*栅格网格*/, VECTOR_TILE(3)/*矢量网格*/,
VECTOR(4)/*矢量图层组*/, OTHER(5)/*其他图层*/,
ALLWAYS_SHOW_GROUP(6), OPERATE(7)/*操作图层组*/;
int groupIndex;
LAYER_GROUPS(int groupIndex) {
this.groupIndex = groupIndex;
}
public int getGroupIndex() {
return groupIndex;
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
public enum GRAVITY {
LEFT_TOP,
RIGHT_TOP,
LEFT_BOTTOM,
RIGHT_BOTTOM
}
/**
* 用户重载这个方法时必须调用父类的这个方法 用于NIMapView保存地图状态
*
* @param context
* @param bundle
*/
public void onCreate(Context context, Bundle bundle) {
}
/**
* 当Activity暂停的时候调用地图暂停
*/
public void onPause() {
if (mapView != null) {
if (mPrefs != null)
mPrefs.save(getVtmMap());
mapView.onPause();
}
}
/**
* 当Activity唤醒时调用地图唤醒
*/
public void onResume() {
if (mapView != null) {
if (mPrefs != null)
mPrefs.load(getVtmMap());
mapView.onResume();
}
}
/**
* 用户重载这个方法时必须调用父类的这个方法 用于NIMapView保存地图状态
*
* @param bundle
*/
public void onSaveInstanceState(Bundle bundle) {
}
/**
* 当Activity销毁时调用地图的销毁
*/
public void onDestroy() {
try{
if (mapView != null) {
mapView.onDestroy();
}
}catch (Exception e){
}
}
/**
* @param child
* @param params
*/
public void addView(View child, ViewGroup.LayoutParams params) {
super.addView(child, params);
}
/**
* 从NIMapView中移除一个子View
*
* @param view
*/
public void removeView(View view) {
super.removeView(view);
}
/**
* 获取地图控制器
*
* @return
*/
// public NIMap getMap() {
// return map;
// }
/**
* 获取VTM-Map
*
* @return
*/
public Map getVtmMap() {
if (mapView != null)
return mapView.map();
return null;
}
/**
* 获取当前地图级别对应比例尺大小
*
* @return
*/
public int getMapLevel() {
if (mapView != null && mapView.map() != null)
return mapView.map().getMapPosition().getZoomLevel();
return 0;
}
/**
* @param view
*/
public void zoomIn(View view) {
if (view != null) {
if (view.isEnabled()) {
MapPosition mapPosition = mapView.map().getMapPosition();
mapPosition.setZoom(mapPosition.getZoom() + 1);
mapView.map().animator().animateTo(mapPosition);
// map.zoomIn(true);
}
view.setEnabled(false);
view.postDelayed(new Runnable() {
@Override
public void run() {
view.setEnabled(true);
}
}, 300);
}
}
/**
* @param view
*/
public void zoomOut(View view) {
if (view != null) {
if (view.isEnabled()) {
MapPosition mapPosition = mapView.map().getMapPosition();
mapPosition.setZoom(mapPosition.getZoom() - 1);
mapView.map().animator().animateTo(mapPosition);
// map.zoomOut(true);
}
view.setEnabled(false);
view.postDelayed(new Runnable() {
@Override
public void run() {
view.setEnabled(true);
}
}, 300);
}
}
/**
* 设置MotionEvent
*
* @param event
*/
public void setUpViewEventToNIMapView(MotionEvent event) {
}
/**
* 设置缩放按钮位置
*
* @param position 按钮位置
*/
public void setZoomControlPosition(GRAVITY position) {
if (zoomLayout != null) {
setLayoutParams(position, zoomLayout);
}
}
/**
* 设置缩放按钮位置
*
* @param position 按钮位置
*/
public void setLogoPosition(GRAVITY position) {
if (logoImage != null) {
setLayoutParams(position, logoImage);
}
}
/**
* 设置缩放按钮位置
*
* @param position 按钮位置
*/
public void setCompassPosition(GRAVITY position) {
if (compassImage != null) {
setLayoutParams(position, compassImage);
}
}
/**
* 根据GRAVITY生成对应的layoutParams
*
* @param position 按钮相对于父布局的位置
* @param view 被设置显示位置的view
*/
private void setLayoutParams(GRAVITY position, View view) {
LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
if (layoutParams.getRules() != null) {
for (int i = 0; i < layoutParams.getRules().length; i++) {
layoutParams.removeRule(i);
}
}
switch (position) {
case LEFT_TOP:
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
break;
case RIGHT_TOP:
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
break;
case LEFT_BOTTOM:
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
break;
case RIGHT_BOTTOM:
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
break;
}
view.setLayoutParams(layoutParams);
}
/**
* 设置是否显示缩放控件
*
* @param show
*/
public void showZoomControls(boolean show) {
if (zoomLayout != null) {
if (show) {
zoomLayout.setVisibility(VISIBLE);
} else {
zoomLayout.setVisibility(GONE);
}
}
}
/**
* 设置是否显示缩放控件
*
* @param show
*/
public void showCompass(boolean show) {
// if (map != null) {
// map.setCompassEnable(show);
// }
if (compassImage != null) {
compassImage.setVisibility(show ? View.VISIBLE : View.GONE);
compassImage.setEnabled(show);
}
}
/**
* 获取指北针
*/
protected ImageView getCompassImage() {
return compassImage;
}
public enum MAP_THEME {
DEFAULT(0), NEWTRON(1), OSMAGRAY(2),
OSMARENDER(3), TRONRENDER(4);
int themeId;
MAP_THEME(int themeId) {
this.themeId = themeId;
}
public MAP_THEME getMapTheme(int themeId) {
MAP_THEME theme = DEFAULT;
switch (themeId) {
case 1:
theme = NEWTRON;
break;
case 2:
theme = OSMAGRAY;
break;
case 3:
theme = OSMARENDER;
break;
case 4:
theme = TRONRENDER;
break;
}
return theme;
}
}
public void switchTileVectorLayerTheme(MAP_THEME styleId) {
// 如果不包含vectorlayer则设置theme无效
boolean bHis = false;
for (Layer layer : getVtmMap().layers()) {
if (layer instanceof VectorTileLayer) {
bHis = true;
break;
}
}
if (!bHis) {
getVtmMap().updateMap(true);
return;
}
if (styleId == null) {
getVtmMap().setTheme(new AssetsRenderTheme(mContext.getAssets(), "", "navdefault.xml"), true);
} else {
switch (styleId) {
case NEWTRON:
getVtmMap().setTheme(VtmThemes.NEWTRON, true);
break;
case OSMAGRAY:
getVtmMap().setTheme(VtmThemes.OSMAGRAY, true);
break;
case OSMARENDER:
getVtmMap().setTheme(VtmThemes.OSMARENDER, true);
break;
case TRONRENDER:
getVtmMap().setTheme(VtmThemes.TRONRENDER, true);
break;
default:
getVtmMap().setTheme(new AssetsRenderTheme(mContext.getAssets(), "", "editormarker.xml"), true);
break;
}
}
getVtmMap().updateMap();
}
public NILayerManager getLayerManager() {
return mLayerManager;
}
// 地图点击事件对应的图层
private class MapEventsReceiver extends Layer implements GestureListener {
public MapEventsReceiver(Map map) {
super(map);
}
@Override
public boolean onGesture(Gesture g, org.oscim.event.MotionEvent e) {
GeoPoint geoPoint = mMap.viewport().fromScreenPoint(e.getX(), e.getY());
if (g instanceof Gesture.Tap) { // 单击事件
if (mapClickListener != null) {
mapClickListener.onMapClick(geoPoint);
}
} else if (g instanceof Gesture.DoubleTap) { // 双击
if (mapDoubleClickListener != null) {
mapDoubleClickListener.onMapDoubleClick(geoPoint);
}
} else if (g instanceof Gesture.LongPress) { // 长按
if (mapLongClickListener != null) {
mapLongClickListener.onMapLongClick(geoPoint);
}
}
setOnMapClickListener(new NIMap.OnMapClickListener() {
@Override
public void onMapClick(GeoPoint point) {
}
@Override
public void onMapPoiClick(GeoPoint poi) {
}
});
return false;
}
}
/**
* 设置地图的点击事件
*/
public void setOnMapClickListener(@Nullable NIMap.OnMapClickListener listener) {
this.mapClickListener = listener;
}
/**
* 设置地图的双击事件
* 注:默认情况下,双击会自动放大地图
*/
public void setOnMapDoubleClickListener(@Nullable NIMap.OnMapDoubleClickListener listener) {
this.mapDoubleClickListener = listener;
}
/**
* 设置地图长按事件
*
* @param listener
*/
public void setOnMapLongClickListener(@Nullable NIMap.OnMapLongClickListener listener) {
this.mapLongClickListener = listener;
}
/**
* 设置地图的触摸事件
*
* @param listener
*/
public void setOnMapTouchListener(@Nullable NIMap.OnMapTouchListener listener) {
this.touchListener = listener;
}
}

View File

@@ -0,0 +1,109 @@
package com.navinfo.collect.library.map;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
import android.widget.ImageView;
/*
*com.nmp.widget
*zhjch
*2021/6/24
*22:29
*说明(图片旋转)
*/
public class NIRotateAnimation extends Animation {
private float mFromX;
private float mToX;
private float mFromZ;
private float mToZ;
private float mCenterX;
private float mCenterY;
private final float mDepthZ = 0;
private final boolean mReverse = true;
private Camera mCamera;
private ImageView mImageView;
private float mPivotX;
private float mPivotY;
public NIRotateAnimation(ImageView imageView) {
mImageView = imageView;
// 计算中心点
mCenterX = imageView.getWidth() / 2.0f;
mCenterY = imageView.getHeight() / 2.0f;
setDuration(10);
setFillAfter(true);
//匀速旋转
setInterpolator(new LinearInterpolator());
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
mPivotX = resolveSize(Animation.RELATIVE_TO_SELF, 0.5f, width, parentWidth);
mPivotY = resolveSize(Animation.RELATIVE_TO_SELF, 0.5f, height, parentHeight);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float degrees = mFromZ + ((mToZ - mFromZ) * interpolatedTime);
float scale = getScaleFactor();
final Matrix matrix = t.getMatrix();
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
//保存一次camera初始状态用于restore()
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
final float fromX = mFromX;
float degreesX = fromX + ((mToX - fromX) * interpolatedTime);
//围绕Y轴旋转degrees度
camera.rotateX(degreesX);
// //行camera中取出矩阵赋值给matrix
camera.getMatrix(matrix);
camera.restore();
//camera恢复到初始状态继续用于下次的计算
if (mPivotX == 0.0f && mPivotY == 0.0f) {
matrix.preRotate(degrees);//它也是用matrix来实现旋转的,不是matrix的按z轴旋转和它一样, 是它就是这样实现的.
} else {
matrix.preRotate(degrees, mPivotX * scale, mPivotY * scale);
}
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
public void startRotationX(float start, float end) {
// Create a new 3D rotation with the supplied parameter
// The animation listener is used to trigger the next animation
//final Rotate3dAnimation rotation =new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
mFromX = start;
mToX = end;
mImageView.startAnimation(this);
}
public void startRotationZ(float start, float end) {
// Create a new 3D rotation with the supplied parameter
// The animation listener is used to trigger the next animation
//final Rotate3dAnimation rotation =new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);
mFromZ = start;
mToZ = end;
mImageView.startAnimation(this);
}
}

View File

@@ -0,0 +1,219 @@
package com.navinfo.collect.library.map.flutter
import android.content.Context
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.map.NIMapController
import com.navinfo.collect.library.map.NIMapOptions
import com.navinfo.collect.library.map.flutter.flutterhandler.*
import com.navinfo.collect.library.map.flutter.maphandler.FlutterMeasureLayerHandler
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterMapController(
id: Int,
context: Context,
binaryMessenger: BinaryMessenger,
options: NIMapOptions,
) : NIMapController(context, options), MethodChannel.MethodCallHandler {
private val mMethodChannel: MethodChannel = MethodChannel(
binaryMessenger,
"com.navinfo.collect/mapView_$id"
)
private val flutterMapBaseControlHandler: FlutterMapBaseControlHandler =
FlutterMapBaseControlHandler(context, mMethodChannel, mMapView)
private val flutterAnimationHandler: FlutterAnimationHandler by lazy {
FlutterAnimationHandler(context, mMapView)
}
private val flutterMarkerHandler: FlutterMarkerHandler by lazy {
FlutterMarkerHandler(context, mMapView)
}
private val flutterLocationHandler: FlutterLocationLayerHandler by lazy {
FlutterLocationLayerHandler(context, mMapView)
}
private val flutterLineHandler: FlutterLineHandler by lazy {
FlutterLineHandler(context, mMapView)
}
private val flutterPolygonHandler: FlutterPolygonHandler by lazy {
FlutterPolygonHandler(context, mMapView)
}
private val flutterViewportHandler: FlutterViewportHandler by lazy {
FlutterViewportHandler(context, mMapView)
}
private val flutterLayerManagerHandler: FlutterLayerManagerHandler =
FlutterLayerManagerHandler(context, mMapView)
init {
mMethodChannel.setMethodCallHandler(this)
}
private val flutterMeasureLayerHandler: FlutterMeasureLayerHandler by lazy {
FlutterMeasureLayerHandler(context, mMapView)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
/**
* 地图基础操作部分
*/
//刷新地图
FlutterMapProtocolKeys.kMapUpdateMap -> {
flutterMapBaseControlHandler.updateMap(call, result)
}
/**
* 地图动画效果控制协议
*/
//根据屏幕像素移动地图
FlutterMapProtocolKeys.AnimationProtocol.kMapAnimationByPixel -> {
flutterAnimationHandler.animation(call, result)
}
//地图缩小
FlutterMapProtocolKeys.AnimationProtocol.kMapAnimationZoomOut -> {
flutterAnimationHandler.zoomOut(call, result)
}
//地图放大
FlutterMapProtocolKeys.AnimationProtocol.kMapAnimationZoomIn -> {
flutterAnimationHandler.zoomIn(call, result)
}
/**
* 地图Marker控制协议
*/
//增加或更新marker
FlutterMapProtocolKeys.MarkerProtocol.kMapAddMarkerMethod -> {
flutterMarkerHandler.addMarker(call, result)
}
//删除marker
FlutterMapProtocolKeys.MarkerProtocol.kMapRemoveMarkerMethod -> {
flutterMarkerHandler.removeMarker(call, result)
}
/**
* 地图定位信息控制协议
*/
//更新定位信息
FlutterMapProtocolKeys.LocationProtocol.kMapUpdateLocationDataMethod -> {
flutterLocationHandler.updateCurrentLocation(call, result)
}
/**
* 线数据协议
*/
//绘制线时的打点
FlutterMapProtocolKeys.LineProtocol.kMapAddDrawLinePointMethod -> {
flutterLineHandler.addDrawLinePoint(call, result)
}
//清除正在绘制的线
FlutterMapProtocolKeys.LineProtocol.kMapCleanDrawLineMethod -> {
flutterLineHandler.clean(call, result)
}
//添加线数据
FlutterMapProtocolKeys.LineProtocol.kMapAddDrawLineMethod -> {
flutterLineHandler.addDrawLine(call, result)
}
/**
* 面数据协议
*/
//绘制面时的打点
FlutterMapProtocolKeys.PolygonProtocol.kMapAddDrawPolygonPointMethod -> {
flutterPolygonHandler.addDrawPolygonPoint(call, result)
}
/**
* 面数据协议
*/
//绘制面时的打点
FlutterMapProtocolKeys.PolygonProtocol.kMapAddDrawPolygonNiPointMethod -> {
flutterPolygonHandler.addDrawPolygonNiPoint(call, result)
}
//绘制面
FlutterMapProtocolKeys.PolygonProtocol.kMapAddDrawPolygonMethod -> {
flutterPolygonHandler.addDrawPolygon(call, result)
}
//清除正在绘制的面
FlutterMapProtocolKeys.PolygonProtocol.kMapCleanDrawPolygonMethod -> {
flutterPolygonHandler.clean(call, result)
}
/**
* 视窗操作
*/
//设置地图中心点的偏移量
FlutterMapProtocolKeys.ViewportProtocol.kMapViewportSetViewCenterMethod -> {
flutterViewportHandler.setMapViewCenter(call, result)
}
//获取几何扩展后的外接矩形
FlutterMapProtocolKeys.ViewportProtocol.kMapViewportGetBoundingBoxMethod -> {
flutterViewportHandler.getBoundingBoxWkt(call, result)
}
//坐标转屏幕点
FlutterMapProtocolKeys.ViewportProtocol.kMapViewportToScreenPointMethod -> {
flutterViewportHandler.toScreenPoint(call, result)
}
//屏幕点转坐标
FlutterMapProtocolKeys.ViewportProtocol.kMapViewportFromScreenPointMethod -> {
flutterViewportHandler.fromScreenPoint(call, result)
}
/**
* 底图切换控制协议
*/
//切换底图
FlutterMapProtocolKeys.LayerManagerProtocol.kMapSwitchRasterTileLayerMethod -> {
flutterLayerManagerHandler.switchRasterTileLayer(call, result)
}
//获取支持的底图
FlutterMapProtocolKeys.LayerManagerProtocol.kMapGetRasterTileLayerListMethod -> {
flutterLayerManagerHandler.getBaseRasterTileLayerList(call, result)
}
/**
* 底图切换控制协议
*/
//切换底图
FlutterMapProtocolKeys.LayerManagerProtocol.kMapSwitchRasterTileLayerMethod -> {
flutterLayerManagerHandler.switchRasterTileLayer(call, result)
}
//获取支持的底图
FlutterMapProtocolKeys.LayerManagerProtocol.kMapGetRasterTileLayerListMethod -> {
flutterLayerManagerHandler.getBaseRasterTileLayerList(call, result)
}
//绘制线或者面
FlutterMapProtocolKeys.LayerManagerProtocol.kMapDrawLineOrPolygonMethod -> {
flutterMeasureLayerHandler.drawLineOrPolygon(call, result);
}
//清理绘制线或者面
FlutterMapProtocolKeys.LayerManagerProtocol.kMapCleanDrawLineOrPolygonMethod -> {
flutterMeasureLayerHandler.clean();
}
//绘制线或者面
FlutterMapProtocolKeys.LayerManagerProtocol.kMapEditLineOrPolygonMethod -> {
flutterLayerManagerHandler.editLineOrPolygon(call, result)
}
}
}
override fun release() {
super.release()
mMethodChannel.setMethodCallHandler(null)
}
}

View File

@@ -0,0 +1,86 @@
package com.navinfo.collect.library.map.flutter
import com.navinfo.collect.library.map.NIMapOptions
import com.navinfo.collect.library.map.NIMapView
import org.json.JSONArray
import org.json.JSONObject
import org.oscim.core.GeoPoint
import org.oscim.layers.marker.MarkerItem
/**
* 和flutter层进行数据传递时的数据格式转换
*/
class FlutterMapConversion {
companion object {
// flutter json 转成原生对象
/**
* 地图初始配置信息转换
*/
fun flutterToNIMapOptions(args: String): NIMapOptions {
return NIMapOptions.fromJson(args)
// return MoshiUtil.fromJson<NIMapOptions>(args)!!;
// val moshi = Moshi.Builder().build()
// val jsonAdapter: JsonAdapter<NIMapOptions> = moshi.adapter(NIMapOptions::class.java)
// return jsonAdapter.fromJson(args)!!
}
//原生转给flutter
/**
* marker 转json
*/
fun markerToJson(marker: MarkerItem): String {
return "{\"id\":\"${marker.title}\",\"description\":\"${marker.description}\",\"geoPoint\":{\"longitude\":${marker.geoPoint.longitude},\"latitude\":${marker.geoPoint.latitude}}}"
}
/**
* line转json
*/
fun lineToJson(list: List<GeoPoint>): String {
var jsonArray = JSONArray();
for (point in list) {
val jsonObject = JSONObject();
jsonObject.put("latitude", point.latitude)
jsonObject.put("longitude", point.longitude)
jsonObject.put("latitudeE6", point.latitudeE6)
jsonObject.put("longitudeE6", point.longitudeE6)
jsonArray.put(jsonObject)
}
return jsonArray.toString()
}
/**
* 地图转json
*/
fun baseMapTypeToJson(list: Array<NIMapView.BASE_MAP_TYPE>): String {
var jsonArray = JSONArray();
//循环输出 值
for (baseMapType in list) {
val jsonObject = JSONObject();
jsonObject.put("title", baseMapType.title)
jsonObject.put("url", baseMapType.url)
jsonObject.put("tilePath", baseMapType.tilePath)
jsonArray.put(jsonObject)
}
return jsonArray.toString()
}
fun toGeoPointMapList(list: List<GeoPoint>): List<*> {
val newList = mutableListOf<Map<*, *>>()
for (item in list) {
newList.add(
mapOf(
"latitude" to item.latitude,
"longitude" to item.longitude,
"latitudeE6" to item.latitudeE6,
"longitudeE6" to item.longitudeE6,
),
)
}
return newList
}
}
}

View File

@@ -0,0 +1,120 @@
package com.navinfo.collect.library.map.flutter
object FlutterMapProtocolKeys {
///刷新地图
const val kMapUpdateMap = "flutter_nimap/base/UpdateMap";
/**
* 地图动画控制协议
*/
object AnimationProtocol {
// 按像素移动地图中心点
const val kMapAnimationByPixel = "flutter_nimap/animation/AnimationByPixel"
///地图缩小
const val kMapAnimationZoomOut = "flutter_nimap/animation/AnimationZoomOut";
///地图放大
const val kMapAnimationZoomIn = "flutter_nimap/animation/AnimationZoomIn";
}
/**
* marker控制协议
*/
object MarkerProtocol {
// 添加marker
const val kMapAddMarkerMethod = "flutter_nimap/marker/addMarker"
// 删除marker
const val kMapRemoveMarkerMethod = "flutter_nimap/marker/removeMarker";
}
/**
* 定位信息控制协议
*/
object LocationProtocol {
// 动态更新我的位置数据
const val kMapUpdateLocationDataMethod = "flutter_nimap/location/updateLocationData"
}
/**
* 线数据控制协议
*/
object LineProtocol {
// 线数据打点
const val kMapAddDrawLinePointMethod = "flutter_nimap/line/addDrawLinePoint";
// 清除画线功能
const val kMapCleanDrawLineMethod = "flutter_nimap/line/cleanDrawLine"
// 添加线数据
const val kMapAddDrawLineMethod = "flutter_nimap/line/addDrawLine"
}
/**
* 线数据控制协议
*/
object PolygonProtocol {
// 线数据打点
const val kMapAddDrawPolygonPointMethod = "flutter_nimap/Polygon/addDrawPolygonPoint";
// 线数据打点
const val kMapAddDrawPolygonNiPointMethod = "flutter_nimap/Polygon/addDrawPolygonNiPoint";
// 添加面数据
const val kMapAddDrawPolygonMethod = "flutter_nimap/Polygon/addDrawPolygon"
// 清除画线功能
const val kMapCleanDrawPolygonMethod = "flutter_nimap/Polygon/cleanDrawPolygon"
}
/**
* 地图view操作
*/
object ViewportProtocol {
// 设置地图中心点
const val kMapViewportSetViewCenterMethod = "flutter_nimap/Viewport/SetViewCenter";
//获取几何扩展后的外接矩形
const val kMapViewportGetBoundingBoxMethod = "flutter_nimap/Viewport/GetBoundingBox";
//坐标转屏幕点
const val kMapViewportToScreenPointMethod = "flutter_nimap/Viewport/ToScreenPoint";
//屏幕点转坐标
const val kMapViewportFromScreenPointMethod = "flutter_nimap/Viewport/FromScreenPoint";
}
/**
* 原生地图通知flutter命令
*/
object MapCallBackProtocol {
// 用户操作地图,状态回调
const val kMapEventCallback = "flutter_nimap/mapCallBack/kMapEventCallback";
// 用户单击地图,回调点击坐标
const val kMapOnClickCallback = "flutter_nimap/mapCallBack/kMapOnClickCallback";
}
/**
* LayerManager控制协议
*/
object LayerManagerProtocol {
// 切换RasterTileLayer
const val kMapSwitchRasterTileLayerMethod = "flutter_nimap/LayerManager/switchRasterTileLayer";
// 移除RasterTileLayer
const val kMapRemoveRasterTileLayerMethod = "flutter_nimap/LayerManager/removeRasterTileLayer"
// 获取RasterTileLayer
const val kMapGetRasterTileLayerListMethod = "flutter_nimap/LayerManager/getRasterTileLayerList"
// 绘制线或者面
const val kMapDrawLineOrPolygonMethod = "flutter_nimap/LayerManager/drawLineOrPolygon"
// 清理绘制线或者面
const val kMapCleanDrawLineOrPolygonMethod = "flutter_nimap/LayerManager/cleanDrawLineOrPolygon"
// 编辑线或者面
const val kMapEditLineOrPolygonMethod = "flutter_nimap/LayerManager/editLineOrPolygon"
}
}

View File

@@ -0,0 +1,62 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.handler.AnimationHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
class FlutterAnimationHandler(
context: Context,
mapView: NIMapView
) :
AnimationHandler(context, mapView) {
/**
* 使用像素移动地图
*/
fun animation(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("xPixel") && call.hasArgument("yPixel")) {
val x = call.argument<Double>("xPixel")
val y = call.argument<Double>("yPixel")
var time = 200;
if (call.hasArgument("animateDurationMs")) {
time = call.argument<Int>("animateDurationMs")!!;
}
super.animationByPixel(x!!.toInt(), y!!.toInt(), time.toLong())
result.success(true)
} else if (call.hasArgument("latitude") && call.hasArgument("longitude")) {
var time = 200;
if (call.hasArgument("animateDurationMs")) {
time = call.argument<Int>("animateDurationMs")!!;
}
animationByLonLat(
call.argument<Double>("latitude") as Double,
call.argument<Double>("longitude") as Double,
time.toLong()
)
result.success(true)
} else {
result.error("-1", "像素坐标错误", "")
}
}
/**
* 地图缩小
*/
fun zoomOut(call: MethodCall, result: MethodChannel.Result) {
super.zoomOut()
result.success(true)
}
/**
* 地图放大
*/
fun zoomIn(call: MethodCall, result: MethodChannel.Result) {
super.zoomIn()
result.success(true)
}
}

View File

@@ -0,0 +1,52 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.handler.LayerManagerHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
/**
* 图层操作控制
*/
class FlutterLayerManagerHandler(context: Context, mapView: NIMapView) :
LayerManagerHandler(context, mapView) {
//切换底图
fun switchRasterTileLayer(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("url") && call.hasArgument("tilePath")) {
}
val url = call.argument<String>("url")
val tilePath = call.argument<String>("tilePath")
val cache = call.argument<Boolean>("cache")
switchRasterTileLayer(url, tilePath, cache)
}
fun removeRasterTileLayer(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("url")) {
val url = call.argument<String>("url")
removeRasterTileLayer(url!!);
result.success(true)
}
}
//获取支持底图内容
fun getBaseRasterTileLayerList(call: MethodCall, result: MethodChannel.Result) {
getBaseRasterTileLayerList { baseMapJson ->
result.success(baseMapJson)
}
}
//编辑线或者面
fun editLineOrPolygon(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("type")&&call.hasArgument("geometry")) {
val type = call.argument<Int>("type")
val geometry = call.argument<String>("geometry")
if (type != null) {
editLineOrPolygon(geometry!!,type)
}
}
}
}

View File

@@ -0,0 +1,48 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.flutter.FlutterMapConversion
import com.navinfo.collect.library.map.handler.LineHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.oscim.core.GeoPoint
/**
* 线数据操作控制
*/
class FlutterLineHandler(context: Context, mapView: NIMapView) :
LineHandler(context, mapView) {
/**
* 给线数据增加一个点,如果是经纬度就用经纬度,如果是屏幕坐标就转换成经纬度
*/
fun addDrawLinePoint(call: MethodCall, result: MethodChannel.Result) {
val list = addDrawLinePoint(
GeoPoint(
mMapView.vtmMap.mapPosition.latitude,
mMapView.vtmMap.mapPosition.longitude
)
)
result.success(FlutterMapConversion.lineToJson(list))
}
fun clean(call: MethodCall, result: MethodChannel.Result) {
clean()
result.success(true)
}
fun addDrawLine(call: MethodCall, result: MethodChannel.Result) {
clean()
val pointList = mutableListOf<GeoPoint>();
if (call.arguments is List<*>) {
for (item in call.arguments as List<*>) {
if (item is Map<*, *>) {
pointList.add(GeoPoint(item["latitude"] as Double, item["longitude"] as Double))
}
}
}
addDrawLine(pointList);
result.success(true)
}
}

View File

@@ -0,0 +1,61 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NILocation
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.handler.LocationLayerHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.oscim.core.GeoPoint
class FlutterLocationLayerHandler(context: Context, mapView: NIMapView) :
LocationLayerHandler(context, mapView) {
var bFirst = true;
/**
* 设置当前定位信息
*/
fun updateCurrentLocation(call: MethodCall, result: MethodChannel.Result) {
var bTracking = true;
if (call.hasArgument("tracking")) {
bTracking = call.argument<Boolean>("tracking") == true
}
var locationMap = call.argument<Map<*, *>>("location");
if (locationMap != null) {
if (locationMap.containsKey("latitude") && locationMap.containsKey("longitude")) {
val longitude = locationMap["longitude"]
val latitude = locationMap["latitude"]
val location = NILocation("GPS");
if (latitude is Double && longitude is Double) {
location.latitude = latitude
location.longitude = longitude
} else {
return result.success(false)
}
if (locationMap.containsKey("direction")) {
val direction = locationMap["direction"]
if (direction is Float)
location.bearing = direction
}
if (locationMap.containsKey("altitude")) {
val altitude = locationMap["altitude"]
if (altitude is Double)
location.altitude = altitude
}
if (locationMap.containsKey("radius")) {
val radius = locationMap["radius"]
if (radius is Float)
location.radius = radius
}
setCurrentLocation(location)
if (bFirst || bTracking) {
mMapView.vtmMap.animator().animateTo(GeoPoint(latitude, longitude))
bFirst = false;
}
}
}
return result.success(true)
}
}

View File

@@ -0,0 +1,78 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.flutter.FlutterMapProtocolKeys
import com.navinfo.collect.library.map.handler.MapBaseControlHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.oscim.event.Gesture
import org.oscim.event.GestureListener
import org.oscim.event.MotionEvent
import org.oscim.layers.Layer
import org.oscim.map.Map
class FlutterMapBaseControlHandler(
context: Context,
methodChannel: MethodChannel,
mapView: NIMapView
) :
MapBaseControlHandler(context, mapView) {
init {
mMapView.vtmMap.events.bind(Map.UpdateListener { e, _ ->
when (e) {
Map.MOVE_EVENT -> methodChannel.invokeMethod(
FlutterMapProtocolKeys.MapCallBackProtocol.kMapEventCallback,
mapOf("MapEvent" to 0)
);
Map.SCALE_EVENT -> methodChannel.invokeMethod(
FlutterMapProtocolKeys.MapCallBackProtocol.kMapEventCallback,
mapOf("MapEvent" to 1)
);
Map.ROTATE_EVENT -> methodChannel.invokeMethod(
FlutterMapProtocolKeys.MapCallBackProtocol.kMapEventCallback,
mapOf("MapEvent" to 2)
);
Map.TILT_EVENT -> methodChannel.invokeMethod(
FlutterMapProtocolKeys.MapCallBackProtocol.kMapEventCallback,
mapOf("MapEvent" to 3)
);
}
})
mMapView.layerManager.addLayer(
"pointSnapLayer",
MapEventsReceiver(methodChannel, mMapView.vtmMap)
)
}
private class MapEventsReceiver(methodChannel: MethodChannel, map: Map?) : Layer(map),
GestureListener {
private val _methodChannel = methodChannel;
override fun onGesture(g: Gesture, e: MotionEvent): Boolean {
if (g is Gesture.Tap) {
val p = mMap.viewport().fromScreenPoint(e.x, e.y)
_methodChannel.invokeMethod(
FlutterMapProtocolKeys.MapCallBackProtocol.kMapOnClickCallback,
mapOf(
"latitude" to p.latitude,
"longitude" to p.longitude,
"longitudeE6" to p.longitudeE6,
"latitudeE6" to p.latitudeE6,
)
)
}
return false
}
}
/**
* 刷新地图
*/
fun updateMap(call: MethodCall, result: MethodChannel.Result) {
var redraw = call.argument<Boolean>("redraw") ?: true
upDateMap(redraw);
result.success(true)
}
}

View File

@@ -0,0 +1,50 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.flutter.FlutterMapConversion
import com.navinfo.collect.library.map.handler.MarkHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.oscim.core.GeoPoint
import org.oscim.layers.marker.MarkerItem
class FlutterMarkerHandler(context: Context, mapView: NIMapView) :
MarkHandler(context, mapView) {
fun addMarker(call: MethodCall, result: MethodChannel.Result) {
val marker: MarkerItem;
val description = call.argument<String>("description")
val title = call.argument<String>("title")
if (call.hasArgument("xPixel") && call.hasArgument("yPixel")) {
val x = call.argument<Double>("xPixel")
val y = call.argument<Double>("yPixel")
val description = call.argument<String>("description")
val geoPoint =
mMapView.vtmMap.viewport().fromScreenPoint(x!!.toFloat(), y!!.toFloat())
marker = addMarker(geoPoint, title, description)
} else if (call.hasArgument("longitude") && call.hasArgument("latitude")) {
val lon = call.argument<Double>("longitude")
val lat = call.argument<Double>("latitude")
marker = addMarker(GeoPoint(lat!!, lon!!), title, description)
} else {
marker = addMarker(
GeoPoint(
mMapView.vtmMap.mapPosition.latitude,
mMapView.vtmMap.mapPosition.longitude
), title, description
)
}
result.success(FlutterMapConversion.markerToJson(marker));
}
fun removeMarker(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("title")) {
val title = call.argument<String>("title")
removeMarker(title!!);
result.success(true)
}
}
}

View File

@@ -0,0 +1,33 @@
package com.navinfo.collect.library.map.flutter.maphandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.maphandler.MeasureLayerHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
/**
* 测距操作控制
*/
class FlutterMeasureLayerHandler(context: Context, mapView: NIMapView) :
MeasureLayerHandler(context, mapView) {
/**
* 给面数据增加一个点,如果是经纬度就用经纬度,如果是屏幕坐标就转换成经纬度
*/
fun drawLineOrPolygon(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("type")) {
val type = call.argument<Int>("type")
if (type != null) {
drawLineOrPolygon(type)
}
}
}
fun clean(call: MethodCall, result: MethodChannel.Result) {
clean()
result.success(true)
}
}

View File

@@ -0,0 +1,63 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.flutter.FlutterMapConversion
import com.navinfo.collect.library.map.handler.PolygonHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.oscim.core.GeoPoint
/**
* 面据操作控制
*/
class FlutterPolygonHandler(context: Context, mapView: NIMapView) :
PolygonHandler(context, mapView) {
/**
* 给面数据增加一个点,如果是经纬度就用经纬度,如果是屏幕坐标就转换成经纬度
*/
fun addDrawPolygonPoint(call: MethodCall, result: MethodChannel.Result) {
val list = addDrawPolygonPoint(
GeoPoint(
mMapView.vtmMap.mapPosition.latitude,
mMapView.vtmMap.mapPosition.longitude
)
)
result.success(FlutterMapConversion.lineToJson(list));
}
/**
* 给面数据增加一个点,如果是经纬度就用经纬度,如果是屏幕坐标就转换成经纬度
*/
fun addDrawPolygonNiPoint(call: MethodCall, result: MethodChannel.Result) {
if (call.hasArgument("longitude")&&call.hasArgument("latitude")) {
val x = call.argument<Double>("longitude")
val y = call.argument<Double>("latitude")
val list = addDrawPolygonPoint(GeoPoint(y!!, x!!))
result.success(FlutterMapConversion.lineToJson(list))
}
}
fun addDrawPolygon(call: MethodCall, result: MethodChannel.Result) {
clean()
val pointList = mutableListOf<GeoPoint>();
if (call.arguments is List<*>) {
for (item in call.arguments as List<*>) {
if (item is Map<*, *>) {
pointList.add(GeoPoint(item["latitude"] as Double, item["longitude"] as Double))
}
}
}
addDrawPolygon(pointList);
result.success(true)
}
fun clean(call: MethodCall, result: MethodChannel.Result) {
clean()
result.success(true)
}
}

View File

@@ -0,0 +1,82 @@
package com.navinfo.collect.library.map.flutter.flutterhandler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.handler.ViewportHandler
import com.navinfo.collect.library.utils.GeometryTools
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import org.oscim.core.GeoPoint
class FlutterViewportHandler(context: Context, mapView: NIMapView) :
ViewportHandler(context, mapView) {
/**
* 设置地图中心偏移量 [-1,1]之间
*/
fun setMapViewCenter(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is Map<*, *>) {
val x = call.argument<Double>("xPivot")
val y = call.argument<Double>("yPivot")
val mapPosition = mMapView.vtmMap.mapPosition;
setMapViewCenter(x!!.toFloat(), y!!.toFloat())
mMapView.vtmMap.animator().animateTo(mapPosition)
}
}
/**
* 获取几何的外接矩形,返回矩形的左上,右下两个坐标
*/
fun getBoundingBoxWkt(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is Map<*, *>) {
val lat = call.argument<Double>("latitude")
val lon = call.argument<Double>("longitude")
val snapType = call.argument<Int>("snapType")
val distance = call.argument<Int>("distance")
val geoPoint = GeoPoint(lat!!, lon!!);
val map = getBoundingBoxWkt(geoPoint, GeometryTools.SNAP_TYPE.values()[snapType!!], distance!!)
result.success(map)
}
}
/**
* 坐标转屏幕点
*/
fun toScreenPoint(call: MethodCall, result: MethodChannel.Result) {
if (call.arguments is Map<*, *>) {
val lat = call.argument<Double>("latitude")
val lon = call.argument<Double>("longitude")
val geoPoint = GeoPoint(lat!!, lon!!);
val map = toScreenPoint(geoPoint)
result.success(map)
}
}
/**
* 屏幕点转坐标
*/
fun fromScreenPoint(call: MethodCall, result: MethodChannel.Result) {
print("qj===fromScreenPoint")
if (call.arguments is Map<*, *>) {
val px = call.argument<Double>("px")
val py = call.argument<Double>("py")
print("qj===px:$px==py:$py")
if(px!=null&&py!=null){
val map = fromScreenPoint(px.toFloat(),py.toFloat())
result.success(map)
}else{
result.success("")
}
}
}
}

View File

@@ -0,0 +1,29 @@
package com.navinfo.collect.library.map.flutter.plugin
import androidx.annotation.NonNull
import androidx.lifecycle.Lifecycle
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference
class FlutterLifecycleAdapter {
private val TAG = "FlutterLifecycleAdapter"
/**
* Returns the lifecycle object for the activity a plugin is bound to.
*
*
* Returns null if the Flutter engine version does not include the lifecycle extraction code.
* (this probably means the Flutter engine version is too old).
*/
companion object {
@NonNull
fun getActivityLifecycle(
@NonNull activityPluginBinding: ActivityPluginBinding
): Lifecycle {
val reference = activityPluginBinding.lifecycle as HiddenLifecycleReference
return reference.lifecycle
}
}
}

View File

@@ -0,0 +1,75 @@
package com.navinfo.collect.library.map.flutter.plugin
import android.view.View
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import com.navinfo.collect.library.data.flutter.FlutterDataController
import com.navinfo.collect.library.importExport.flutter.FlutterImportExportController
import com.navinfo.collect.library.map.flutter.FlutterMapController
import com.navinfo.collect.library.map.NIMapView
import io.flutter.plugin.platform.PlatformView
class FlutterMapView(
mapController: FlutterMapController,
dataController: FlutterDataController,
importExportController: FlutterImportExportController,
lifecycleProxy: LifecycleProxy
) :
PlatformView, DefaultLifecycleObserver {
private val mMapController: FlutterMapController = mapController
private val mDataController: FlutterDataController = dataController
private val mImportExportController: FlutterImportExportController = importExportController
private val mapView: NIMapView = mMapController.mMapView
private var mIsDisposed = false
private val mLifecycleProxy: LifecycleProxy = lifecycleProxy;
init {
var lifecycle: Lifecycle? = mLifecycleProxy.getLifecycle()
lifecycle?.addObserver(this)
}
override fun getView(): View {
return mapView
}
override fun dispose() {
if (mIsDisposed) {
return
}
mIsDisposed = true
mMapController.release()
mDataController.release()
val lifecycle: Lifecycle? = mLifecycleProxy.getLifecycle()
lifecycle?.removeObserver(this)
}
override fun onPause(owner: LifecycleOwner) {
if (!mIsDisposed) {
mapView.onPause()
}
super.onPause(owner)
}
override fun onResume(owner: LifecycleOwner) {
if (!mIsDisposed) {
mapView.onResume()
}
super.onResume(owner)
}
override fun onStop(owner: LifecycleOwner) {}
override fun onDestroy(owner: LifecycleOwner) {
if (!mIsDisposed) {
mMapController.release()
mDataController.release()
// mapView = null
}
}
}

View File

@@ -0,0 +1,77 @@
package com.navinfo.collect.library.map.flutter.plugin
import android.content.Context
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.data.dao.impl.MapLifeDataBase
import com.navinfo.collect.library.data.flutter.FlutterDataController
import com.navinfo.collect.library.importExport.flutter.FlutterImportExportController
import com.navinfo.collect.library.map.NIMapOptions
import com.navinfo.collect.library.map.flutter.FlutterMapConversion
import com.navinfo.collect.library.map.flutter.FlutterMapController
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
class FlutterMapViewFactory(
messenger: BinaryMessenger,
lifecycleProxy: LifecycleProxy,
activity: FlutterBaseActivity,
) :
PlatformViewFactory(StandardMessageCodec.INSTANCE) {
private val binaryMessenger: BinaryMessenger = messenger
private var mLifecycleProxy: LifecycleProxy = lifecycleProxy
lateinit var mapController: FlutterMapController
lateinit var dataController: FlutterDataController
private val activity: FlutterBaseActivity = activity
override fun create(context: Context?, id: Int, args: Any?): PlatformView {
mapController = buildMapController(context!!, id, args!!)
dataController = buildDataController(context, id, activity)
val importExportController =
buildImportExportController(context, id, dataController.mDateBase)
return FlutterMapView(
mapController,
dataController,
importExportController,
mLifecycleProxy
)
}
/**
* 创建地图控制器
*/
private fun buildMapController(
context: Context,
viewId: Int,
args: Any,
): FlutterMapController {
val options: NIMapOptions = FlutterMapConversion.flutterToNIMapOptions(args.toString())
return FlutterMapController(viewId, context, binaryMessenger, options)
}
/**
* 创建数据控制器
*/
private fun buildDataController(
context: Context,
viewId: Int,
activity: FlutterBaseActivity
): FlutterDataController {
return FlutterDataController(viewId, context, binaryMessenger, activity)
}
/**
* 创建文件导入导出
*/
private fun buildImportExportController(
context: Context,
viewId: Int,
dataBase: MapLifeDataBase
): FlutterImportExportController {
return FlutterImportExportController(viewId, context, binaryMessenger, dataBase)
}
}

View File

@@ -0,0 +1,165 @@
package com.navinfo.collect.library.map.flutter.plugin
import android.app.Activity
import android.app.Application
import android.os.Bundle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import com.navinfo.collect.FlutterBaseActivity
import com.navinfo.collect.library.system.Constant
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.BinaryMessenger
object FlutterMapViewFlutterPlugin : ActivityAware, FlutterPlugin {
private const val NATIVE_VIEW_TYPE_ID = "com.navinfo.collect/mapView"
private var mLifecycle: Lifecycle? = null
private lateinit var mActivity:FlutterBaseActivity
// //旧方法
// fun registerWith(registry: PluginRegistry) {
// val key = FlutterMapViewFlutterPlugin::class.java.canonicalName
// if (registry.hasPlugin(key)) {
// return
// }
// val registrar = registry.registrarFor(key)
// registrar.platformViewRegistry()
// .registerViewFactory(NATIVE_VIEW_TYPE_ID, FlutterMapViewFactory(registrar.messenger()))
// }
//新方法
fun registerWith(
flutterEngine: FlutterEngine,
activity: FlutterBaseActivity,
rootPath: String = ""
): FlutterMapViewFactory {
mActivity = activity
var lifecycleProxy: LifecycleProxy = if (activity is LifecycleOwner) {
object : LifecycleProxy {
override fun getLifecycle(): Lifecycle {
return (activity as LifecycleOwner).lifecycle
}
}
} else {
ActivityLifecycleProxy(activity)
}
if (rootPath != "") {
Constant.ROOT_PATH = rootPath;
}
val factory =
FlutterMapViewFactory(flutterEngine.dartExecutor.binaryMessenger, lifecycleProxy,activity)
flutterEngine.platformViewsController.registry.registerViewFactory(
NATIVE_VIEW_TYPE_ID,
factory
)
return factory
}
private class ActivityLifecycleProxy(activity: Activity) :
LifecycleProxy, Application.ActivityLifecycleCallbacks, LifecycleOwner {
private val mLifecycle = LifecycleRegistry(this)
private var mRegistrarActivityHashCode: Int = activity.hashCode()
override fun getLifecycle(): Lifecycle {
return mLifecycle
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
if (activity.hashCode() != mRegistrarActivityHashCode) {
return
}
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
override fun onActivityStarted(activity: Activity) {
if (activity.hashCode() != mRegistrarActivityHashCode) {
return
}
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
override fun onActivityResumed(activity: Activity) {
if (activity.hashCode() != mRegistrarActivityHashCode) {
return
}
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
override fun onActivityPaused(activity: Activity) {
if (activity.hashCode() != mRegistrarActivityHashCode) {
return
}
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
override fun onActivityStopped(activity: Activity) {
if (activity.hashCode() != mRegistrarActivityHashCode) {
return
}
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
if (activity.hashCode() != mRegistrarActivityHashCode) {
return
}
mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
init {
activity.application.registerActivityLifecycleCallbacks(this)
}
}
//首次绑定到Activity
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
mLifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding)
}
//由于某些原因导致暂时解绑
override fun onDetachedFromActivityForConfigChanges() {
onDetachedFromActivity()
}
//恢复绑定
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
onAttachedToActivity(binding)
}
//解绑
override fun onDetachedFromActivity() {
mLifecycle = null
}
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
// val mMessenger: BinaryMessenger = binding.binaryMessenger
binding.platformViewRegistry.registerViewFactory(
NATIVE_VIEW_TYPE_ID,
FlutterMapViewFactory(binding.binaryMessenger, object : LifecycleProxy {
override fun getLifecycle(): Lifecycle? {
return mLifecycle
}
}, mActivity)
)
// // 单独配置获取版本的消息通道,和地图实例的消息通道无关
// val methodChannel = MethodChannel(
// mMessenger,
// Constants.NATIVE_SDK_VERSION_CHANNEL
// )
// methodChannel.setMethodCallHandler(this)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
// val binaryMessenger = binding.binaryMessenger
// mOfflineHandler.unInit(binaryMessenger)
}
}

View File

@@ -0,0 +1,39 @@
package com.navinfo.collect.library.map.flutter.plugin
import android.content.Context
import android.view.View
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import com.navinfo.collect.library.map.NIMapCopyView
import com.navinfo.collect.library.map.NIMapView
import io.flutter.plugin.platform.PlatformView
class FlutterNiMapCopyView(context:Context,niMapView: NIMapView,
lifecycleProxy: LifecycleProxy
) :
PlatformView, DefaultLifecycleObserver {
private val copyView: NIMapCopyView = NIMapCopyView(context,niMapView);
private var mIsDisposed = false
private val mLifecycleProxy: LifecycleProxy = lifecycleProxy;
init {
var lifecycle: Lifecycle? = mLifecycleProxy.getLifecycle()
lifecycle?.addObserver(this)
}
override fun getView(): View {
return copyView
}
override fun dispose() {
if (mIsDisposed) {
return
}
mIsDisposed = true
val lifecycle: Lifecycle? = mLifecycleProxy.getLifecycle()
lifecycle?.removeObserver(this)
}
}

View File

@@ -0,0 +1,27 @@
package com.navinfo.collect.library.map.flutter.plugin
import android.content.Context
import com.navinfo.collect.library.data.flutter.FlutterDataController
import com.navinfo.collect.library.map.NIMapOptions
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.flutter.FlutterMapConversion
import com.navinfo.collect.library.map.flutter.FlutterMapController
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
class FlutterNiMapCopyViewFactory(
private val messenger: BinaryMessenger,
lifecycleProxy: LifecycleProxy
) :
PlatformViewFactory(StandardMessageCodec.INSTANCE) {
private val binaryMessenger: BinaryMessenger = messenger
private var mLifecycleProxy: LifecycleProxy = lifecycleProxy
override fun create(context: Context, id: Int, args: Any?): PlatformView {
return FlutterNiMapCopyView(context,args as NIMapView, mLifecycleProxy)
}
}

View File

@@ -0,0 +1,127 @@
//package com.navinfo.collect.library.map.flutter.plugin
//
//import android.app.Activity
//import android.app.Application
//import android.os.Bundle
//import androidx.lifecycle.Lifecycle
//import androidx.lifecycle.LifecycleOwner
//import androidx.lifecycle.LifecycleRegistry
//import com.navinfo.collect.library.system.Constant
//import io.flutter.embedding.engine.FlutterEngine
//import io.flutter.embedding.engine.plugins.FlutterPlugin
//import io.flutter.embedding.engine.plugins.activity.ActivityAware
//import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
//import io.flutter.plugin.common.BinaryMessenger
//
//object FlutterNiMapCopyViewFlutterPlugin : ActivityAware, FlutterPlugin {
// private const val NATIVE_VIEW_TYPE_ID = "com.navinfo.collect/copyView"
// private var mLifecycle: Lifecycle? = null
//
// //新方法
// fun registerWith(flutterEngine: FlutterEngine, activity: Activity, rootPath: String = "") {
// var lifecycleProxy: LifecycleProxy = if (activity is LifecycleOwner) {
// object : LifecycleProxy {
// override fun getLifecycle(): Lifecycle {
// return (activity as LifecycleOwner).lifecycle
// }
// }
// } else {
// ActivityLifecycleProxy(activity)
// }
// if (rootPath != "") {
// Constant.ROOT_PATH = rootPath;
// }
// flutterEngine.platformViewsController.registry.registerViewFactory(
// NATIVE_VIEW_TYPE_ID,
// FlutterMapViewFactory(flutterEngine.dartExecutor.binaryMessenger, lifecycleProxy)
// )
// }
//
// private class ActivityLifecycleProxy(activity: Activity) :
// LifecycleProxy, Application.ActivityLifecycleCallbacks, LifecycleOwner {
// private val mLifecycle = LifecycleRegistry(this)
// private var mRegistrarActivityHashCode: Int = activity.hashCode()
// override fun getLifecycle(): Lifecycle {
// return mLifecycle
// }
//
// override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
// if (activity.hashCode() != mRegistrarActivityHashCode) {
// return
// }
// mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
// }
//
//
// override fun onActivityStarted(activity: Activity) {
// if (activity.hashCode() != mRegistrarActivityHashCode) {
// return
// }
// mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
// }
//
// override fun onActivityResumed(activity: Activity) {
// if (activity.hashCode() != mRegistrarActivityHashCode) {
// return
// }
// mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
// }
//
// override fun onActivityPaused(activity: Activity) {
// if (activity.hashCode() != mRegistrarActivityHashCode) {
// return
// }
// mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
// }
//
// override fun onActivityStopped(activity: Activity) {
// if (activity.hashCode() != mRegistrarActivityHashCode) {
// return
// }
// mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
// }
//
// override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
// override fun onActivityDestroyed(activity: Activity) {
// if (activity.hashCode() != mRegistrarActivityHashCode) {
// return
// }
// mLifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
// }
//
// init {
// activity.application.registerActivityLifecycleCallbacks(this)
// }
// }
//
// override fun onAttachedToActivity(binding: ActivityPluginBinding) {
// mLifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding)
// }
//
// override fun onDetachedFromActivityForConfigChanges() {
// onDetachedFromActivity()
// }
//
// override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
// onAttachedToActivity(binding)
// }
//
// override fun onDetachedFromActivity() {
// mLifecycle = null
// }
//
// override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
// binding.platformViewRegistry.registerViewFactory(
// NATIVE_VIEW_TYPE_ID,
// FlutterMapViewFactory(binding.binaryMessenger, object : LifecycleProxy {
// override fun getLifecycle(): Lifecycle? {
// return mLifecycle
// }
// })
// )
//
// }
//
// override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
// }
//}

View File

@@ -0,0 +1,7 @@
package com.navinfo.collect.library.map.flutter.plugin
import androidx.lifecycle.Lifecycle
interface LifecycleProxy {
fun getLifecycle(): Lifecycle?
}

View File

@@ -0,0 +1,70 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition
/**
* 控制地图状态相关操作
*/
open class AnimationHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView) {
/**
* 根据屏幕像素移动
*
* xPixel 屏幕横坐标xPixel屏幕纵坐标
*/
fun animationByPixel(xPixel: Int, yPixel: Int, time: Long = 200) {
val geoPoint =
mMapView.vtmMap.viewport().fromScreenPoint(xPixel.toFloat(), yPixel.toFloat())
mMapView.vtmMap.animator().animateTo(time, geoPoint)
}
/**
* 根据经纬度移动
*
* latitude longitude经纬度
**
*/
fun animationByLonLat(latitude: Double, longitude: Double, time: Long = 200) {
mMapView.vtmMap.animator().animateTo(time, GeoPoint(latitude, longitude))
}
/**
* 根据经纬度zoom值 移动
*
* latitude longitude经纬度
**
*/
fun animationByZoom(latitude: Double, longitude: Double, zoomLevel: Int) {
val mapPosition: MapPosition = mMapView.vtmMap.mapPosition
if (mapPosition.getZoomLevel() < zoomLevel) {
mapPosition.setZoomLevel(zoomLevel)
}
mapPosition.setPosition(latitude, longitude)
mMapView.vtmMap.animator().animateTo(300, mapPosition)
}
/**
* 缩小地图
*/
fun zoomOut() {
val mapPosition: MapPosition = mMapView.vtmMap.mapPosition
mapPosition.zoom = mapPosition.zoom - 1
mMapView.vtmMap.animator().animateTo(mapPosition)
}
/**
* 放大地图
*/
fun zoomIn() {
val mapPosition: MapPosition = mMapView.vtmMap.mapPosition
mapPosition.zoom = mapPosition.zoom + 1
mMapView.vtmMap.animator().animateTo(mapPosition)
}
}

View File

@@ -0,0 +1,9 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
open class BaseHandler(context:Context, mapView: NIMapView) {
protected val mContext:Context = context
protected val mMapView: NIMapView = mapView
}

View File

@@ -0,0 +1,46 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.NIMapView.LAYER_GROUPS
import com.navinfo.collect.library.map.flutter.FlutterMapConversion
import org.oscim.layers.Layer
/**
* Layer 操作
*/
open class LayerManagerHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView) {
//增加RasterTileLayer
fun switchRasterTileLayer(
url: String?,
filePath: String? = "",
cache: Boolean? = false,
): Boolean {
mMapView.removeBaseMap()
val layer: Layer =
mMapView.layerManager.getRasterTileLayer(mContext, url, filePath, cache!!)
if (layer != null) {
mMapView.vtmMap.layers().add(layer, LAYER_GROUPS.BASE_RASTER.groupIndex)
mMapView.vtmMap.clearMap()
return true
}
return false
}
//删除RasterTileLayer
fun removeRasterTileLayer(url: String) {
}
fun getBaseRasterTileLayerList(callback: (baseMapJson: String) -> Unit) {
val strJson = FlutterMapConversion.baseMapTypeToJson(NIMapView.BASE_MAP_TYPE.values())
callback.invoke(strJson)
}
fun editLineOrPolygon(geometry: String,type: Int){
mMapView.layerManager.showEditMapGraphical(geometry,type)
}
}

View File

@@ -0,0 +1,376 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import android.graphics.BitmapFactory
import android.widget.Toast
import com.navinfo.collect.library.R
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.StringUtil
import org.oscim.android.canvas.AndroidBitmap
import org.oscim.backend.canvas.Bitmap
import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition
import org.oscim.event.Event
import org.oscim.layers.marker.ItemizedLayer
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem
import org.oscim.layers.marker.MarkerSymbol
import org.oscim.layers.vector.PathLayer
import org.oscim.layers.vector.geometries.Style
import org.oscim.map.Map
open class LineHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView), Map.UpdateListener {
private var editIndex: Int = -1;
private val mPathMakers: MutableList<MarkerItem> = mutableListOf()
//绘制线 引导线样式
private val newTempStyle: Style
//绘制线 样式
private val lineStyle: Style
//线型编辑时的样式
private val editTempStyle: Style
//新增线数据
private val mPathLayer: PathLayer
//新增线数据引线
private val mPathLayerTemp: PathLayer
//线路端点图标
private val mPathMarkerBitmap: Bitmap
//线路端点marker
private val mEndpointLayer: ItemizedLayer
private var bDrawLine = false
init {
mMapView.vtmMap.events.bind(this)
//新增线数据图层和线样式
lineStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.draw_line_blue1_color, null))
.strokeWidth(4f)
.fillColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fillAlpha(0.5f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fixed(true)
.build()
newTempStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.transparent, null))
.stipple(30)
.stippleWidth(30f)
.strokeWidth(4f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fixed(true)
.randomOffset(false)
.build()
editTempStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.transparent, null))
.stipple(30)
.stippleWidth(30f)
.strokeWidth(8f)
.strokeColor(context.resources.getColor(R.color.draw_line_red_color, null))
.fixed(true)
.randomOffset(false)
.build()
mPathLayer = PathLayer(mMapView.vtmMap, lineStyle)
mMapView.layerManager.addLayer(
"defaultLineLayer",
mPathLayer,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mPathLayerTemp = if (mMapView.layerManager.containsLayer("guideLineLayer")) {
mMapView.layerManager.getLayer("guideLineLayer") as PathLayer
} else {
PathLayer(mMapView.vtmMap, newTempStyle)
}
mMapView.layerManager.addLayer(
"guideLineLayer",
mPathLayerTemp,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mPathMarkerBitmap = AndroidBitmap(
BitmapFactory.decodeResource(
mContext.resources,
R.mipmap.icon_path_maker
)
)
val markerSymbol = MarkerSymbol(mPathMarkerBitmap, MarkerSymbol.HotspotPlace.CENTER)
//新增marker图层
mEndpointLayer = if (mMapView.layerManager.containsLayer("endpointLayer")) {
mMapView.layerManager.getLayer("endpointLayer") as ItemizedLayer
} else
//新增marker图层
ItemizedLayer(
mMapView.vtmMap,
java.util.ArrayList<MarkerInterface>(),
markerSymbol,
null
)
mMapView.layerManager.addLayer(
"endpointLayer",
mEndpointLayer,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mEndpointLayer.setOnItemGestureListener(object : OnItemGestureListener<MarkerInterface> {
override fun onItemSingleTapUp(index: Int, item: MarkerInterface): Boolean {
if (bDrawLine) {
for (i in mPathMakers.indices) {
val item1 = mPathMakers[i]
if (item === item1) {
mMapView.vtmMap.animator().animateTo(
GeoPoint(
item.getPoint().latitude,
item.getPoint().longitude
)
)
editIndex = i
mPathLayerTemp.setStyle(editTempStyle)
val list: MutableList<GeoPoint> = mutableListOf()
if (editIndex == 0 || editIndex == mPathMakers.size - 1) {
list.add(item.getPoint())
list.add(item.getPoint())
} else {
list.add(mPathMakers[editIndex - 1].geoPoint)
list.add(item.getPoint())
list.add(mPathMakers[editIndex + 1].geoPoint)
}
mPathLayerTemp.setPoints(list)
return false
}
}
}
return false
}
override fun onItemLongPress(index: Int, item: MarkerInterface): Boolean {
return false
}
})
}
fun addDrawLinePoint(geoPoint: GeoPoint): List<GeoPoint> {
if (!bDrawLine) {
mPathLayer.isEnabled = true
mPathLayerTemp.isEnabled = true
mEndpointLayer.isEnabled = true
bDrawLine = true
}
//编辑点
if (editIndex > -1) {
if (mPathLayer.points.size > 0) {
var list: MutableList<GeoPoint> = mutableListOf<GeoPoint>()
list.addAll(mPathLayer.points)
if (list.size > 3) {
if (editIndex == 0) {
val listNew = mutableListOf<GeoPoint>()
listNew.add(geoPoint)
listNew.add(list[1])
list.removeAt(0)
if (GeometryTools.isLineStringCrosses(list, listNew)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
} else if (editIndex == list.size - 1) {
val listNew = mutableListOf<GeoPoint>()
listNew.add(geoPoint)
listNew.add(list[editIndex - 1])
list.removeAt(editIndex)
if (GeometryTools.isLineStringCrosses(list, listNew)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
} else if (editIndex == 1) {
val listNew = mutableListOf<GeoPoint>()
listNew.add(list[0])
listNew.add(geoPoint)
listNew.add(list[2])
list = list.subList(2, list.size)
if (GeometryTools.isLineStringCrosses(list, listNew)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
} else if (editIndex == list.size - 2) {
val listNew = mutableListOf<GeoPoint>()
listNew.add(list[list.size - 1])
listNew.add(geoPoint)
listNew.add(list[editIndex - 1])
list = list.subList(0, list.size - 2)
if (GeometryTools.isLineStringCrosses(list, listNew)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
} else {
val listNew = mutableListOf<GeoPoint>()
listNew.add(list[editIndex - 1])
listNew.add(geoPoint)
listNew.add(list[editIndex + 1])
val list1: MutableList<GeoPoint> = mutableListOf();
list1.addAll(list.subList(0, editIndex))
val list2: MutableList<GeoPoint> = mutableListOf()
list2.addAll(list.subList(editIndex + 1, list.size))
if (GeometryTools.isLineStringCrosses(list1, listNew)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
if (GeometryTools.isLineStringCrosses(list2, listNew)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
}
}
if (editIndex < mPathLayer.getPoints().size) {
mPathLayer.points.removeAt(editIndex)
val list2: MutableList<GeoPoint> = mutableListOf<GeoPoint>()
list2.addAll(mPathLayer.points)
list2.add(editIndex, geoPoint)
mPathLayer.setPoints(list2)
}
}
if (mPathMakers.size > editIndex) {
mEndpointLayer.removeItem(mPathMakers[editIndex])
mPathMakers.removeAt(editIndex)
val markerItem = MarkerItem(StringUtil.createUUID(), "", "", geoPoint)
mEndpointLayer.addItem(markerItem)
mPathMakers.add(editIndex, markerItem)
mPathLayerTemp.setStyle(newTempStyle)
val list: MutableList<GeoPoint> = mutableListOf()
// if (NMPFragmentManager.getInstance()
// .getNewDataBottomType() === 3 && mPathMakers.size > 1
// ) {
// list.add(mPathMakers[0].geoPoint)
// list.add(geoPoint)
// list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
// } else {
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
list.add(geoPoint)
// }
mPathLayerTemp.setPoints(list)
}
editIndex = -1
} else { //新增点
val points: List<GeoPoint> = mPathLayer.points
if (points.size > 2) {
val list: MutableList<GeoPoint> = mutableListOf()
list.add(geoPoint)
list.add(points[points.size - 1])
val bCross = GeometryTools.isLineStringCrosses(points, list)
if (bCross) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPathLayer.points
}
}
mPathLayer.addPoint(geoPoint)
val markerItem = MarkerItem(StringUtil.createUUID(), "", "", geoPoint)
mEndpointLayer.addItem(markerItem)
mPathMakers.add(markerItem)
}
return mPathLayer.points
}
fun addDrawLine(list: List<GeoPoint>) {
for(item in list){
addDrawLinePoint(item)
}
}
override fun onMapEvent(e: Event, mapPosition: MapPosition) {
if (!bDrawLine)
return
// if (mMapView.centerPixel[1] > mMapView.vtmMap.height / 2) {
// val geoPoint =
// mMapView.vtmMap.viewport()
// .fromScreenPoint(
// mMapView.centerPixel[0],
// mMapView.vtmMap.height - mMapView.centerPixel[1]
// )
// mapPosition.setPosition(geoPoint)
// }
if (e === Map.POSITION_EVENT) {
if (mPathLayer.points.size > 0) {
if (editIndex > -1) {
val list: MutableList<GeoPoint> = mutableListOf()
if (editIndex == 0 || editIndex == mPathMakers.size - 1) {
list.add(mPathMakers[editIndex].geoPoint)
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
} else {
list.add(mPathMakers[editIndex - 1].geoPoint)
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
list.add(mPathMakers[editIndex + 1].geoPoint)
}
mPathLayerTemp.setPoints(list)
// crossText.setText("")
} else {
val list: MutableList<GeoPoint> = mutableListOf()
list.add(mPathLayer.points[mPathLayer.points.size - 1])
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
mPathLayerTemp.setPoints(list)
if (mPathLayer.points.size > 0) {
val listDis: MutableList<GeoPoint> = mutableListOf()
listDis.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
// val distance: Double =
// GeometryTools.getDistance(listDis)
// if (distance < 1000) crossText.setText(
// distance as Int.toString() + "米"
// ) else {
// val d = distance / 1000.0
// val bg = BigDecimal(d)
// val f1 =
// bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
//// crossText.setText(f1.toString() + "公里")
// }
} else {
// crossText.setText("")
}
}
}
}
}
fun clean() {
mPathLayer.clearPath()
mPathLayer.isEnabled = false
mPathLayerTemp.clearPath()
mPathLayerTemp.isEnabled = false
mEndpointLayer.removeAllItems()
mEndpointLayer.isEnabled = false
mPathMakers.clear()
editIndex = -1
bDrawLine = false
}
}

View File

@@ -0,0 +1,23 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import com.navinfo.collect.library.map.NILocation
import com.navinfo.collect.library.map.NIMapView
open class LocationLayerHandler(context: Context, mapView:NIMapView) :
BaseHandler(context, mapView) {
private var mCurrentLocation: NILocation? = null
/**
* 设置当前位置信息
*/
fun setCurrentLocation(location: NILocation) {
this.mCurrentLocation = location
mMapView.layerManager.locationLayer.setPosition(
location.latitude,
location.longitude,
location.radius
)
}
}

View File

@@ -0,0 +1,18 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
open class MapBaseControlHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView) {
/**
* 刷新地图
*/
fun upDateMap(redraw: Boolean = true) {
if (redraw) {
mMapView.vtmMap.events.fire(org.oscim.map.Map.CLEAR_EVENT, mMapView.vtmMap.mapPosition)
}
mMapView.vtmMap.updateMap(redraw)
}
}

View File

@@ -0,0 +1,75 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.utils.StringUtil
import org.oscim.core.GeoPoint
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem
/**
* marker 操作
*/
open class MarkHandler(context: Context, mapView:NIMapView) :
BaseHandler(context, mapView), OnItemGestureListener<MarkerInterface> {
//增加marker
fun addMarker(
geoPoint: GeoPoint,
title: String?,
description: String? = ""
): MarkerItem {
var marker: MarkerItem? = null
for (e in mMapView.layerManager.defaultMarkerLayer.itemList) {
if (e is MarkerItem && e.title == title) {
marker = e;
break;
}
}
if (marker == null) {
var tempTitle = title;
if (tempTitle.isNullOrBlank()) {
tempTitle = StringUtil.createUUID();
}
val marker = MarkerItem(
tempTitle,
description,
geoPoint
)
mMapView.layerManager.defaultMarkerLayer.addItem(marker);
mMapView.vtmMap.updateMap(true)
return marker
} else {
marker.description = description
marker.geoPoint = geoPoint
mMapView.layerManager.defaultMarkerLayer.removeItem(marker)
mMapView.layerManager.defaultMarkerLayer.addItem(marker)
mMapView.vtmMap.updateMap(true)
return marker
}
}
fun removeMarker(title: String) {
var marker: MarkerItem? = null
for (e in mMapView.layerManager.defaultMarkerLayer.itemList) {
if (e is MarkerItem && e.title == title) {
marker = e;
break;
}
}
if (marker != null) {
mMapView.layerManager.defaultMarkerLayer.removeItem(marker)
mMapView.vtmMap.updateMap(true)
}
}
override fun onItemSingleTapUp(index: Int, item: MarkerInterface): Boolean {
return false
}
override fun onItemLongPress(index: Int, item: MarkerInterface): Boolean {
return false
}
}

View File

@@ -0,0 +1,431 @@
package com.navinfo.collect.library.map.maphandler
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.text.TextPaint
import android.widget.Toast
import com.navinfo.collect.library.R
import com.navinfo.collect.library.map.NILayerManager
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.handler.BaseHandler
import com.navinfo.collect.library.map.layers.NIPolygonLayer
import com.navinfo.collect.library.utils.DistanceUtil
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.StringUtil.Companion.createUUID
import org.oscim.android.canvas.AndroidBitmap
import org.oscim.backend.CanvasAdapter
import org.oscim.backend.canvas.Bitmap
import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition
import org.oscim.event.Event
import org.oscim.layers.marker.ItemizedLayer
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem
import org.oscim.layers.marker.MarkerSymbol
import org.oscim.layers.vector.PathLayer
import org.oscim.layers.vector.geometries.Style
import org.oscim.map.Map
import java.math.BigDecimal
open class MeasureLayerHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView), Map.UpdateListener {
private var editIndex: Int = -1;//线修型的时候,用来表示是不是正在修型,修的第几个点
private val mPathMakers: MutableList<MarkerItem> = mutableListOf()
private var bDrawLine = false
private val bDrawPoint = false
private var mAreaLayer: ItemizedLayer
//绘制线 样式
private val lineStyle: Style
private val newTempStyle: Style
//线型编辑时的样式
private val editTempStyle: Style
//新增线数据引线
private var mPathLayerTemp: PathLayer
//新增线数据
private var mPathLayer: PathLayer
//线路端点图标
private var mPathMarkerBitmap: Bitmap
private var bDrawPolygon = false
private var mPolygonLayer: NIPolygonLayer
init {
//新增线数据图层和线样式
lineStyle = Style.builder().scaleZoomLevel(20).buffer(1.0)
.stippleColor(context.resources.getColor(R.color.draw_line_blue1_color, null))
.strokeWidth(4f)
.fillColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fillAlpha(0.5f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fillColor(context.resources.getColor(R.color.draw_line_red_color,null))
.stippleWidth(4f)
.fixed(true)
.build()
newTempStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.transparent, null))
.stipple(30)
.stippleWidth(30f)
.strokeWidth(4f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fixed(true)
.randomOffset(false)
.build()
editTempStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.transparent, null))
.stipple(30)
.stippleWidth(30f)
.strokeWidth(8f)
.strokeColor(context.resources.getColor(R.color.draw_line_red_color, null))
.fixed(true)
.randomOffset(false)
.build()
mPolygonLayer = NIPolygonLayer(
mMapView.vtmMap,
lineStyle
)
mMapView.layerManager.addLayer(
"meatureLayer",
mPolygonLayer,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mPathLayerTemp = if (mMapView.layerManager.containsLayer("meatureLineLayer")) {
mMapView.layerManager.getLayer("meatureLineLayer") as PathLayer
} else {
PathLayer(mMapView.vtmMap, newTempStyle)
}
mMapView.layerManager.addLayer(
"meatureLineLayer",
mPathLayerTemp,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mPathMarkerBitmap = AndroidBitmap(
BitmapFactory.decodeResource(
context.resources,
R.mipmap.icon_path_maker
)
)
val markerSymbol = MarkerSymbol(mPathMarkerBitmap, MarkerSymbol.HotspotPlace.CENTER)
mAreaLayer = ItemizedLayer(mMapView.vtmMap, ArrayList(), markerSymbol, null)
mPathLayer = PathLayer(mMapView.vtmMap, lineStyle)
mMapView.vtmMap.layers().add(mPathLayer, NIMapView.LAYER_GROUPS.OTHER.ordinal)
}
open fun drawLineOrPolygon(type: Int) {
bDrawLine = true
//画面
if (type == 3) {
if (mPolygonLayer == null) {
mPolygonLayer = NIPolygonLayer(mMapView.vtmMap, lineStyle)
mMapView.vtmMap.layers().add(mPolygonLayer, NIMapView.LAYER_GROUPS.OTHER.ordinal)
} else if (!mPolygonLayer.isEnabled) {
mPolygonLayer.isEnabled = true
}
} else {
if (mPathLayer == null) {
mPathLayer = PathLayer(mMapView.vtmMap, lineStyle)
mMapView.vtmMap.layers().add(mPathLayer, NIMapView.LAYER_GROUPS.OTHER.ordinal)
} else if (!mPathLayer.isEnabled()) {
mPathLayer.setEnabled(true)
}
}
//上一个点的引线
if (mPathLayerTemp == null) {
mPathLayerTemp = PathLayer(mMapView.vtmMap, newTempStyle)
mMapView.vtmMap.layers().add(mPathLayerTemp, NIMapView.LAYER_GROUPS.OTHER.ordinal)
} else if (!mPathLayerTemp.isEnabled) {
mPathLayerTemp.isEnabled = true
}
val geoPoint: GeoPoint =
GeoPoint(mMapView.vtmMap.getMapPosition().getLatitude(), mMapView.vtmMap.getMapPosition().getLongitude())
//编辑点
if (editIndex > -1) {
if (mPathMakers.size > editIndex) {
mMapView.layerManager.removeMarker(mPathMakers[editIndex], NILayerManager.MARQUEE_MARKER_LAYER)
mPathMakers.removeAt(editIndex)
if (mPathMarkerBitmap == null) {
mPathMarkerBitmap = AndroidBitmap(
BitmapFactory.decodeResource(
mContext.getResources(),
R.mipmap.icon_path_maker
)
)
}
val markerItem = MarkerItem(createUUID(), "", "", geoPoint)
val markerSymbol = MarkerSymbol(mPathMarkerBitmap, MarkerSymbol.HotspotPlace.CENTER)
markerItem.marker = markerSymbol
mMapView.layerManager.addMarker2MarkerLayer(
markerItem,
mPathMarkerBitmap,
NILayerManager.MARQUEE_MARKER_LAYER,
NIMapView.LAYER_GROUPS.OTHER.ordinal,
itemGestureListener
)
mPathMakers.add(editIndex, markerItem)
if (mPathLayer != null && mPathLayer.getPoints().size > 0) {
val list: MutableList<GeoPoint> = mPathLayer.getPoints()
if (editIndex < list.size) {
list.removeAt(editIndex)
val list2: MutableList<GeoPoint> = java.util.ArrayList(list)
list2.add(editIndex, geoPoint)
mPathLayer.setPoints(list2)
}
} else if (mPolygonLayer != null && mPolygonLayer.points.size > 0) {
val list = mPolygonLayer.points
if (editIndex < list.size) {
list.removeAt(editIndex)
val list2: MutableList<GeoPoint> = java.util.ArrayList(list)
list2.add(editIndex, geoPoint)
mPolygonLayer.setPoints(list2)
}
}
if (mPathLayerTemp != null) {
mPathLayerTemp.setStyle(newTempStyle)
val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>()
if (type == 3 && mPathMakers.size > 1) {
list.add(mPathMakers[0].geoPoint)
list.add(geoPoint)
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
} else {
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
list.add(geoPoint)
}
mPathLayerTemp.setPoints(list)
}
}
editIndex = -1
} else { //新增点
if (type == 3) {
val points: MutableList<GeoPoint> = java.util.ArrayList(mPolygonLayer.points)
if (points.size > 2) {
val list: MutableList<GeoPoint> = java.util.ArrayList()
points.add(points[0])
list.add(points[0])
list.add(geoPoint)
list.add(mPolygonLayer.points[mPolygonLayer.points.size - 1])
val bCross = GeometryTools.isPolygonCrosses(points, list)
if (bCross == true) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return
}
}
mPolygonLayer.addPoint(geoPoint)
} else {
val points: List<GeoPoint> = mPathLayer.getPoints()
if (points.size > 2) {
val list: MutableList<GeoPoint> = java.util.ArrayList()
list.add(geoPoint)
list.add(points[points.size - 1])
val bCross = GeometryTools.isLineStringCrosses(points, list)
if (bCross == true) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return
}
}
mPathLayer.addPoint(geoPoint)
}
if (mPathMarkerBitmap == null) {
mPathMarkerBitmap = AndroidBitmap(
BitmapFactory.decodeResource(
mContext.getResources(),
R.mipmap.icon_path_maker
)
)
}
val markerItem = MarkerItem(createUUID(), "", "", geoPoint)
val markerSymbol = MarkerSymbol(mPathMarkerBitmap, MarkerSymbol.HotspotPlace.CENTER)
markerItem.marker = markerSymbol
mMapView.layerManager.addMarker2MarkerLayer(
markerItem,
mPathMarkerBitmap,
NILayerManager.MARQUEE_MARKER_LAYER,
NIMapView.LAYER_GROUPS.OTHER.ordinal,
itemGestureListener
)
mPathMakers.add(markerItem)
}
showAreaLayer()
}
open fun drawLineBackspace() {
if (mPathLayer != null && mPathLayer.getPoints().size > 0) {
val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>(mPathLayer.getPoints())
val point = list[mPathLayer.getPoints().size - 1]
list.remove(point)
mPathLayer.setPoints(list)
mMapView.layerManager.jumpToPosition(point.longitude, point.latitude, 0)
} else if (mPolygonLayer != null && mPolygonLayer.points.size > 0) {
val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>(mPolygonLayer.points)
val point = list[mPolygonLayer.points.size - 1]
list.remove(point)
mPolygonLayer.setPoints(list)
mMapView.layerManager.jumpToPosition(point!!.longitude, point.latitude, 0)
}
if (mPathMakers.size > 0) {
var item: MarkerItem? = mPathMakers[mPathMakers.size - 1]
mMapView.layerManager.removeMarker(item, NILayerManager.MARQUEE_MARKER_LAYER)
mPathMakers.remove(item)
item = null
}
if (mPathMakers.size == 0 && mPathLayerTemp != null) {
mPathLayerTemp.clearPath()
}
editIndex = -1
if (mPathLayerTemp != null) {
mPathLayerTemp.setStyle(newTempStyle)
}
}
/**
* 隐藏面积计算
*/
open fun hideAreaLayer() {
if (mAreaLayer != null) {
mAreaLayer.removeAllItems()
mMapView.vtmMap.layers().remove(mAreaLayer)
}
}
/**
* 显示面积计算
*/
open fun showAreaLayer() {
if (mAreaLayer != null) {
mAreaLayer.removeAllItems()
mMapView.vtmMap.layers().remove(mAreaLayer)
}
if (mPolygonLayer != null && mPolygonLayer.points.size > 2) {
val list: MutableList<GeoPoint> = ArrayList(mPolygonLayer.points)
val area = DistanceUtil.planarPolygonAreaMeters2(list)
var areaString: String
if (area < 1000000) {
areaString = area.toString()+"平方米"
} else if (area < 10000000000.0){
val d = area / 1000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
areaString = f1.toString() + "平方公里"
} else {
val d = area / 10000000000.0
val bg = BigDecimal(d)
val f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
areaString = f1.toString() + "万平方公里"
}
val textPaint = TextPaint()
textPaint.textSize = 13 * CanvasAdapter.getScale()
textPaint.color = Color.BLUE
val width = Math.ceil(textPaint.measureText(areaString).toDouble()).toInt()
val fontMetrics = textPaint.fontMetrics
val height =
Math.ceil((Math.abs(fontMetrics.bottom) + Math.abs(fontMetrics.top)).toDouble())
.toInt()
val bitmap = android.graphics.Bitmap.createBitmap(
width,
height,
android.graphics.Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
canvas.drawText(areaString, 0f, Math.abs(fontMetrics.ascent), textPaint)
val bitmap2: Bitmap = AndroidBitmap(bitmap)
val markerSymbol = MarkerSymbol(bitmap2, MarkerSymbol.HotspotPlace.CENTER)
mAreaLayer = ItemizedLayer(mMapView.vtmMap, ArrayList(), markerSymbol, null)
mMapView.vtmMap.layers().add(mAreaLayer)
list.add(list[0])
val polygon = GeometryTools.createPolygon(list)
val point = polygon.centroid
val item = MarkerItem(areaString, "", GeoPoint(point.coordinate.y, point.coordinate.x))
mAreaLayer.removeAllItems()
mAreaLayer.addItem(item)
mAreaLayer.update()
}
}
open fun removeLine() {
bDrawLine = false
editIndex = -1
for (item in mPathMakers) {
mMapView.layerManager.removeMarker(item, NILayerManager.MARQUEE_MARKER_LAYER)
}
mPathMakers.clear()
if (mPathLayer != null) {
mPathLayer.clearPath()
mPathLayer.isEnabled = false
}
if (mPolygonLayer != null) {
mPolygonLayer.clearPath()
mPolygonLayer.isEnabled = false
}
if (mPathLayerTemp != null) {
mPathLayerTemp.clearPath()
mPathLayerTemp.isEnabled = false
mPathLayerTemp.setStyle(newTempStyle)
}
hideAreaLayer()
}
fun clean() {
removeLine()
mMapView.vtmMap.updateMap(true)
}
override fun onMapEvent(e: Event?, mapPosition: MapPosition?) {
}
private val itemGestureListener: OnItemGestureListener<*> =
object : OnItemGestureListener<MarkerInterface> {
override fun onItemSingleTapUp(index: Int, item: MarkerInterface): Boolean {
if (bDrawLine) {
for (i in mPathMakers.indices) {
val item1 = mPathMakers[i]
if (item === item1) {
mMapView.layerManager.jumpToPosition(item.getPoint().longitude, item.getPoint().latitude, 0)
editIndex = i
if (mPathLayerTemp != null) {
mPathLayerTemp.setStyle(editTempStyle)
val list: MutableList<GeoPoint> = java.util.ArrayList<GeoPoint>()
if (editIndex == 0 || editIndex == mPathMakers.size - 1) {
list.add(item.geoPoint as Nothing)
list.add(item.geoPoint as Nothing)
} else {
list.add(mPathMakers[editIndex - 1].geoPoint as Nothing)
list.add(item.geoPoint as Nothing)
list.add(mPathMakers[editIndex + 1].geoPoint as Nothing)
}
mPathLayerTemp.setPoints(list)
}
return true
}
}
}
return false
}
override fun onItemLongPress(index: Int, item: MarkerInterface): Boolean {
return false
}
}
}

View File

@@ -0,0 +1,380 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import android.graphics.BitmapFactory
import android.util.Log
import android.widget.Toast
import com.navinfo.collect.library.R
import com.navinfo.collect.library.map.NILayerManager
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.layers.NIPolygonLayer
import com.navinfo.collect.library.utils.GeometryTools
import com.navinfo.collect.library.utils.StringUtil
import com.navinfo.collect.library.utils.StringUtil.Companion.createUUID
import org.oscim.android.canvas.AndroidBitmap
import org.oscim.backend.canvas.Bitmap
import org.oscim.core.GeoPoint
import org.oscim.core.MapPosition
import org.oscim.event.Event
import org.oscim.layers.marker.ItemizedLayer
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem
import org.oscim.layers.marker.MarkerSymbol
import org.oscim.layers.vector.PathLayer
import org.oscim.layers.vector.geometries.Style
import org.oscim.map.Map
open class PolygonHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView), Map.UpdateListener {
private var editIndex: Int = -1;
private val mPathMakers: MutableList<MarkerItem> = mutableListOf()
//绘制线 引导线样式
private val newTempStyle: Style
//绘制线 样式
private val lineStyle: Style
//线型编辑时的样式
private val editTempStyle: Style
//新增线数据引线
private var mPathLayerTemp: PathLayer
//线路端点图标
private var mPathMarkerBitmap: Bitmap
//线路端点marker
private val mEndpointLayer: ItemizedLayer
private var bDrawPolygon = false
private var mPolygonLayer: NIPolygonLayer
init {
mMapView.vtmMap.events.bind(this)
//新增线数据图层和线样式
lineStyle = Style.builder().scaleZoomLevel(20).buffer(1.0)
.stippleColor(context.resources.getColor(R.color.draw_line_blue1_color, null))
.strokeWidth(4f)
.fillColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fillAlpha(0.5f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fillColor(context.resources.getColor(R.color.draw_line_red_color, null))
.stippleWidth(4f)
.fixed(true)
.build()
newTempStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.transparent, null))
.stipple(30)
.stippleWidth(30f)
.strokeWidth(4f)
.strokeColor(context.resources.getColor(R.color.draw_line_blue2_color, null))
.fixed(true)
.randomOffset(false)
.build()
editTempStyle = Style.builder()
.stippleColor(context.resources.getColor(R.color.transparent, null))
.stipple(30)
.stippleWidth(30f)
.strokeWidth(8f)
.strokeColor(context.resources.getColor(R.color.draw_line_red_color, null))
.fixed(true)
.randomOffset(false)
.build()
mPolygonLayer = NIPolygonLayer(
mMapView.vtmMap,
lineStyle
)
mMapView.layerManager.addLayer(
"defaultPolygonLayer",
mPolygonLayer,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mPathLayerTemp = if (mMapView.layerManager.containsLayer("guideLineLayer")) {
mMapView.layerManager.getLayer("guideLineLayer") as PathLayer
} else {
PathLayer(mMapView.vtmMap, newTempStyle)
}
mMapView.layerManager.addLayer(
"guideLineLayer",
mPathLayerTemp,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mPathMarkerBitmap = AndroidBitmap(
BitmapFactory.decodeResource(
mContext.resources,
R.mipmap.icon_path_maker
)
)
val markerSymbol = MarkerSymbol(mPathMarkerBitmap, MarkerSymbol.HotspotPlace.CENTER)
mEndpointLayer = if (mMapView.layerManager.containsLayer("endpointLayer")) {
mMapView.layerManager.getLayer("endpointLayer") as ItemizedLayer
} else
//新增marker图层
ItemizedLayer(
mMapView.vtmMap,
java.util.ArrayList<MarkerInterface>(),
markerSymbol,
null
)
mMapView.layerManager.addLayer(
"endpointLayer",
mEndpointLayer,
NIMapView.LAYER_GROUPS.VECTOR.ordinal
)
mEndpointLayer.setOnItemGestureListener(object : OnItemGestureListener<MarkerInterface> {
override fun onItemSingleTapUp(index: Int, item: MarkerInterface): Boolean {
if (bDrawPolygon) {
for (i in mPathMakers.indices) {
val item1 = mPathMakers[i]
if (item === item1) {
mMapView.vtmMap.animator().animateTo(
GeoPoint(
item.getPoint().latitude,
item.getPoint().longitude
)
)
editIndex = i
mPathLayerTemp.setStyle(editTempStyle)
val list: MutableList<GeoPoint> = mutableListOf()
if (editIndex == 0 || editIndex == mPathMakers.size - 1) {
list.add(item.getPoint())
list.add(item.getPoint())
} else {
list.add(mPathMakers[editIndex - 1].geoPoint)
list.add(item.getPoint())
list.add(mPathMakers[editIndex + 1].geoPoint)
}
mPathLayerTemp.setPoints(list)
return false
}
}
}
return false
}
override fun onItemLongPress(index: Int, item: MarkerInterface): Boolean {
return false
}
})
}
fun addDrawPolygonPoint(geoPoint: GeoPoint): List<GeoPoint> {
if (!bDrawPolygon) {
mPolygonLayer.isEnabled = true
mPathLayerTemp.isEnabled = true
mEndpointLayer.isEnabled = true
bDrawPolygon = true
}
//编辑点
if (editIndex > -1) {
if (mPolygonLayer.points.size > 0) {
val list: MutableList<GeoPoint> = mutableListOf()
list.addAll(mPolygonLayer.points)
if (list.size > 3) {
val newList: MutableList<GeoPoint> = mutableListOf()
if (editIndex == 0) {
newList.add(list[list.size - 1])
newList.add(geoPoint)
newList.add(list[editIndex + 1])
} else if (editIndex == list.size - 1) {
newList.add(list[0])
newList.add(geoPoint)
newList.add(list[editIndex - 1])
} else {
newList.add(list[editIndex - 1])
newList.add(geoPoint)
newList.add(list[editIndex + 1])
}
val newList2: MutableList<GeoPoint> = mutableListOf()
for (i in editIndex + 1 until list.size) {
newList2.add(list[i])
}
for (i in 0 until editIndex) {
newList2.add(list[i])
}
if (GeometryTools.isLineStringCrosses(newList, newList2)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPolygonLayer.points
}
}
if (editIndex < list.size) {
list.removeAt(editIndex)
val list2: MutableList<GeoPoint> = mutableListOf()
list2.addAll(list)
list2.add(editIndex, geoPoint)
mPolygonLayer.setPoints(list2)
}
}
if (mPathMakers.size > editIndex) {
mEndpointLayer.removeItem(mPathMakers[editIndex])
mPathMakers.removeAt(editIndex)
val markerItem = MarkerItem(StringUtil.createUUID(), "", "", geoPoint)
mEndpointLayer.addItem(markerItem)
mPathMakers.add(editIndex, markerItem)
mPathLayerTemp.setStyle(newTempStyle)
val list: MutableList<GeoPoint> = mutableListOf()
if (mPathMakers.size > 1) {
list.add(mPathMakers[0].geoPoint)
list.add(geoPoint)
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
} else {
list.add(mPathMakers[mPathMakers.size - 1].geoPoint)
list.add(geoPoint)
}
mPathLayerTemp.setPoints(list)
}
editIndex = -1
} else { //新增点
val points: MutableList<GeoPoint> = mutableListOf()
points.addAll(mPolygonLayer.points)
if (points.size > 2) {
val list: MutableList<GeoPoint> = mutableListOf()
points.add(points[0])
list.add(points[0])
list.add(geoPoint)
list.add(mPolygonLayer.points[mPolygonLayer.points.size - 1])
if (GeometryTools.isPolygonCrosses(points, list)) {
Toast.makeText(mContext, "不能交叉", Toast.LENGTH_SHORT).show()
return mPolygonLayer.points
}
}
mPolygonLayer.addPoint(geoPoint)
val markerItem = MarkerItem(StringUtil.createUUID(), "", "", geoPoint)
mEndpointLayer.addItem(markerItem)
mPathMakers.add(markerItem)
}
return mPolygonLayer.points
}
fun addDrawPolygon(list: List<GeoPoint>) {
for (item in list) {
addDrawPolygonPoint(item)
}
}
override fun onMapEvent(e: Event, mapPosition: MapPosition) {
if (!bDrawPolygon)
return
// if (mMapView.centerPixel[1] > mMapView.vtmMap.height / 2) {
// val geoPoint =
// mMapView.vtmMap.viewport()
// .fromScreenPoint(
// mMapView.centerPixel[0],
// mMapView.vtmMap.height - mMapView.centerPixel[1]
// )
// mapPosition.setPosition(geoPoint)
// }
if (e === Map.POSITION_EVENT) {
if (mPolygonLayer.points.size > 0) {
if (editIndex > -1) {
val list: MutableList<GeoPoint> =
mutableListOf()
if (editIndex == 0 || editIndex == mPathMakers.size - 1) {
list.add(mPathMakers[editIndex].geoPoint)
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
} else {
list.add(mPathMakers[editIndex - 1].geoPoint)
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
list.add(mPathMakers[editIndex + 1].geoPoint)
}
mPathLayerTemp.setPoints(list)
// crossText.setText("")
} else {
val list: MutableList<GeoPoint> =
mutableListOf()
if (mPolygonLayer.points.size > 1) {
list.add(mPolygonLayer.points[0])
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
list.add(
mPolygonLayer.points[mPolygonLayer.points.size - 1]
)
} else {
list.add(
mPolygonLayer.points[mPolygonLayer.points.size - 1]
)
list.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
}
mPathLayerTemp.setPoints(list)
if (mPolygonLayer.points.size > 1) {
val list1: MutableList<GeoPoint> =
mutableListOf()
list1.addAll(mPolygonLayer.points)
list1.add(
GeoPoint(
mapPosition.latitude,
mapPosition.longitude
)
)
list1.add(mPolygonLayer.points[0])
//// val area: Double =
//// GeometryTools.PlanarPolygonAreaMeters2(list1)
//// if (area < 1000000) crossText.setText(
//// area as Int.toString
//// () + "平方米"
//// ) else if (area < 10000000000.0) {
//// val d = area / 1000000.0
//// val bg = BigDecimal(d)
//// val f1 =
//// bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
//// crossText.setText(f1.toString() + "平方公里")
//// } else {
//// val d = area / 10000000000.0
//// val bg = BigDecimal(d)
//// val f1 =
//// bg.setScale(1, BigDecimal.ROUND_HALF_UP).toDouble()
//// crossText.setText(f1.toString() + "万平方公里")
//// }
// } else {
//// crossText.setText("")
// }
}
}
}
}
}
fun clean() {
mPolygonLayer.clearPath()
mPolygonLayer.isEnabled = false
mPathLayerTemp.clearPath()
mPathLayerTemp.isEnabled = false
mEndpointLayer.removeAllItems()
mEndpointLayer.isEnabled = false
mPathMakers.clear()
editIndex = -1
bDrawPolygon = false
}
}

Some files were not shown because too many files have changed in this diff Show More