Merge branch 'master' of gitlab.navinfo.com:CollectVehicle/OneMapQS
This commit is contained in:
commit
465afbda86
@ -2,7 +2,6 @@ package com.navinfo.omqs
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.navinfo.omqs.db.MyRealmModule
|
|
||||||
import com.navinfo.omqs.tools.FileManager
|
import com.navinfo.omqs.tools.FileManager
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
@ -25,7 +24,7 @@ class OMQSApplication : Application() {
|
|||||||
.directory(File(Constant.DATA_PATH))
|
.directory(File(Constant.DATA_PATH))
|
||||||
.name("OMQS.realm")
|
.name("OMQS.realm")
|
||||||
.encryptionKey(password)
|
.encryptionKey(password)
|
||||||
.modules(Realm.getDefaultModule(), MyRealmModule())
|
// .modules(Realm.getDefaultModule(), MyRealmModule())
|
||||||
.schemaVersion(1)
|
.schemaVersion(1)
|
||||||
.build()
|
.build()
|
||||||
Realm.setDefaultConfiguration(config)
|
Realm.setDefaultConfiguration(config)
|
||||||
|
@ -2,6 +2,6 @@ package com.navinfo.omqs.db
|
|||||||
|
|
||||||
import com.navinfo.collect.library.data.entity.QsRecordBean
|
import com.navinfo.collect.library.data.entity.QsRecordBean
|
||||||
|
|
||||||
@io.realm.annotations.RealmModule(classes = [QsRecordBean::class])
|
//@io.realm.annotations.RealmModule(classes = [QsRecordBean::class])
|
||||||
class MyRealmModule {
|
//class MyRealmModule {
|
||||||
}
|
//}
|
@ -4,7 +4,6 @@ import com.navinfo.collect.library.utils.GeometryToolsKt
|
|||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
import io.realm.RealmSet
|
import io.realm.RealmSet
|
||||||
import io.realm.annotations.PrimaryKey
|
import io.realm.annotations.PrimaryKey
|
||||||
import io.realm.annotations.RealmClass
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,7 +13,7 @@ import io.realm.annotations.RealmClass
|
|||||||
* @Date 2016/1/12
|
* @Date 2016/1/12
|
||||||
* @Description: ${TODO}(质检对象)
|
* @Description: ${TODO}(质检对象)
|
||||||
*/
|
*/
|
||||||
@RealmClass
|
//@RealmClass
|
||||||
open class QsRecordBean @JvmOverloads constructor(
|
open class QsRecordBean @JvmOverloads constructor(
|
||||||
/**
|
/**
|
||||||
* id 主键
|
* id 主键
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.navinfo.collect.library.map.cluster
|
||||||
|
|
||||||
|
import org.oscim.core.GeoPoint
|
||||||
|
import org.oscim.layers.marker.MarkerItem
|
||||||
|
|
||||||
|
/*
|
||||||
|
*com.nmp.map.cluster
|
||||||
|
*zhjch
|
||||||
|
*2021/12/10
|
||||||
|
*10:51
|
||||||
|
*说明()
|
||||||
|
*/
|
||||||
|
class ClusterMarkerItem(uid: Any?, title: String?, description: String?, geoPoint: GeoPoint?) :
|
||||||
|
MarkerItem(uid, title, description, geoPoint) {
|
||||||
|
var clusterList: List<Int> = ArrayList()
|
||||||
|
|
||||||
|
constructor(title: String?, description: String?, geoPoint: GeoPoint?) : this(
|
||||||
|
null,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
geoPoint
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Hannes Janetzek
|
||||||
|
* Copyright 2016 Izumi Kawashima
|
||||||
|
* Copyright 2017 Longri
|
||||||
|
* Copyright 2017-2018 devemux86
|
||||||
|
* Copyright 2017 nebular
|
||||||
|
* Copyright 2017 Wolfgang Schramm
|
||||||
|
*
|
||||||
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.navinfo.collect.library.map.cluster
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.text.TextPaint
|
||||||
|
import android.util.Log
|
||||||
|
import com.navinfo.collect.library.R
|
||||||
|
import org.oscim.android.canvas.AndroidBitmap
|
||||||
|
import org.oscim.backend.CanvasAdapter
|
||||||
|
import org.oscim.backend.canvas.Bitmap
|
||||||
|
import org.oscim.core.MercatorProjection
|
||||||
|
import org.oscim.core.PointF
|
||||||
|
import org.oscim.core.Tile
|
||||||
|
import org.oscim.layers.marker.*
|
||||||
|
import org.oscim.renderer.GLViewport
|
||||||
|
import org.oscim.renderer.bucket.SymbolItem
|
||||||
|
import org.oscim.utils.FastMath
|
||||||
|
import org.oscim.utils.geom.GeometryUtils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An extension to the MarkerRenderer with item clustering support.
|
||||||
|
*/
|
||||||
|
open class ClusterMarkerRenderer : MarkerRenderer {
|
||||||
|
private var mContext: Context? = null
|
||||||
|
protected var mStyleBackground = CLUSTER_COLORBACK
|
||||||
|
protected var mStyleForeground = CLUSTER_COLORTEXT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discrete scale step, used to trigger reclustering on significant scale change
|
||||||
|
*/
|
||||||
|
private var mScalePow = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map scale to cluster the marker
|
||||||
|
*/
|
||||||
|
private var mClusterScale = 0.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We use a flat Sparse array to calculate the clusters. The sparse array models a 2D map where every (x,y) denotes
|
||||||
|
* a grid slot, ie. 64x64dp. For efficiency I use a linear sparsearray with ARRindex = SLOTypos * max_x + SLOTxpos"
|
||||||
|
*/
|
||||||
|
// private final SparseIntArray mGridMap = new SparseIntArray(200); // initial space for 200 markers, that's not a lot of memory, and in most cases will avoid resizing the array
|
||||||
|
private val mGridMap =
|
||||||
|
HashMap<Int, Any?>() // initial space for 200 markers, that's not a lot of memory, and in most cases will avoid resizing the array
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to enable clustering or disable the functionality
|
||||||
|
*/
|
||||||
|
private val mClusteringEnabled: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a clustered marker renderer
|
||||||
|
*
|
||||||
|
* @param markerLayer The owner layer
|
||||||
|
* @param defaultSymbol The default symbol
|
||||||
|
* @param style The desired style, or NULL to disable clustering
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
context: Context?,
|
||||||
|
markerLayer: MarkerLayer?,
|
||||||
|
defaultSymbol: MarkerSymbol?,
|
||||||
|
style: ClusterStyle?
|
||||||
|
) : super(markerLayer, defaultSymbol) {
|
||||||
|
mContext = context
|
||||||
|
mClusteringEnabled = style != null
|
||||||
|
if (mClusteringEnabled) {
|
||||||
|
setClusterStyle(style!!.foreground, style.background)
|
||||||
|
for (k in 0..CLUSTER_MAXSIZE) {
|
||||||
|
// cache bitmaps so render thread never creates them
|
||||||
|
// we create CLUSTER_MAXSIZE bitmaps. Bigger clusters will show like "+"
|
||||||
|
getClusterBitmap(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(
|
||||||
|
markerLayer: MarkerLayer, defaultSymbol: MarkerSymbol, style: ClusterStyle?
|
||||||
|
) : super(markerLayer, defaultSymbol) {
|
||||||
|
mClusteringEnabled = style != null
|
||||||
|
if (mClusteringEnabled) {
|
||||||
|
setClusterStyle(style!!.foreground, style.background)
|
||||||
|
for (k in 0..CLUSTER_MAXSIZE) {
|
||||||
|
// cache bitmaps so render thread never creates them
|
||||||
|
// we create CLUSTER_MAXSIZE bitmaps. Bigger clusters will show like "+"
|
||||||
|
getClusterBitmap(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the cluster icon style. This is called by the constructor and cannot be made public because
|
||||||
|
* we pre-cache the icons at construction time so the renderer does not have to create them while rendering
|
||||||
|
*
|
||||||
|
* @param backgroundColor Background color
|
||||||
|
* @param foregroundColor text & border color
|
||||||
|
*/
|
||||||
|
private fun setClusterStyle(foregroundColor: Int, backgroundColor: Int) {
|
||||||
|
mStyleBackground = backgroundColor
|
||||||
|
mStyleForeground = foregroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override fun populate(size: Int) {
|
||||||
|
repopulateCluster(size, mClusterScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repopulates item list clustering close markers. This is triggered from update() when
|
||||||
|
* a significant change in scale has happened.
|
||||||
|
*
|
||||||
|
* @param size Item list size
|
||||||
|
* @param scale current map scale
|
||||||
|
*/
|
||||||
|
private fun repopulateCluster(size: Int, scale: Double) {
|
||||||
|
/* the grid slot size in px. increase to group more aggressively. currently set to marker size */
|
||||||
|
if (mMapPosition.zoomLevel == 15) {
|
||||||
|
MAP_GRID_SIZE_DP = 128
|
||||||
|
} else {
|
||||||
|
MAP_GRID_SIZE_DP = 64
|
||||||
|
}
|
||||||
|
val GRIDSIZE = ClusterUtils.getPixels(MAP_GRID_SIZE_DP.toFloat())
|
||||||
|
|
||||||
|
/* the factor to map into Grid Coordinates (discrete squares of GRIDSIZE x GRIDSIZE) */
|
||||||
|
val factor = scale / GRIDSIZE
|
||||||
|
val tmp = arrayOfNulls<Clustered>(size)
|
||||||
|
|
||||||
|
// clear grid map to count items that share the same "grid slot"
|
||||||
|
mGridMap.clear()
|
||||||
|
for (i in 0 until size) {
|
||||||
|
tmp[i] = Clustered()
|
||||||
|
val it = tmp[i]
|
||||||
|
it!!.item = mMarkerLayer.createItem(i)
|
||||||
|
|
||||||
|
/* pre-project points */MercatorProjection.project(it.item.point, mMapPoint)
|
||||||
|
it.px = mMapPoint.x
|
||||||
|
it.py = mMapPoint.y
|
||||||
|
|
||||||
|
// items can be declared non-clusterable
|
||||||
|
if (it.item !is NonClusterable) {
|
||||||
|
val absposx = (it.px * factor).toInt()
|
||||||
|
// absolute item X position in the grid
|
||||||
|
val absposy = (it.py * factor).toInt()
|
||||||
|
// absolute item Y position
|
||||||
|
val maxcols = factor.toInt()
|
||||||
|
// Grid number of columns
|
||||||
|
val itemGridIndex = absposx + absposy * maxcols // Index in the sparsearray map
|
||||||
|
|
||||||
|
// we store in the linear sparsearray the index of the marker,
|
||||||
|
// ie, index = y * maxcols + x; array[index} = markerIndex
|
||||||
|
|
||||||
|
// Lets check if there's already an item in the grid slot
|
||||||
|
// final int storedIndexInGridSlot = mGridMap.get(itemGridIndex, -1);
|
||||||
|
var list: ArrayList<Int>? = null
|
||||||
|
if (mGridMap.containsKey(itemGridIndex)) {
|
||||||
|
list = mGridMap[itemGridIndex] as ArrayList<Int>?
|
||||||
|
}
|
||||||
|
if (list == null) {
|
||||||
|
list = ArrayList()
|
||||||
|
list.add(i)
|
||||||
|
if (it.item is ClusterMarkerItem) {
|
||||||
|
(it.item as ClusterMarkerItem).clusterList = list
|
||||||
|
}
|
||||||
|
mGridMap[itemGridIndex] = list
|
||||||
|
// no item at that grid position. The grid slot is free so let's
|
||||||
|
// store this item "i" (we identify every item by its InternalItem index)
|
||||||
|
// mGridMap.put(itemGridIndex, i);
|
||||||
|
//Log.v(TAG, "UNclustered item at " + itemGridIndex);
|
||||||
|
} else {
|
||||||
|
// at that grid position there's already a marker index
|
||||||
|
// mark this item as clustered out, so it will be skipped in the update() call
|
||||||
|
it.clusteredOut = true
|
||||||
|
list.add(i)
|
||||||
|
for (n in list) {
|
||||||
|
val item: MarkerInterface = mMarkerLayer.createItem(n)
|
||||||
|
if (item is ClusterMarkerItem) {
|
||||||
|
(item as ClusterMarkerItem).clusterList = list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// and increment the count on its "parent" that will from now on act as a cluster
|
||||||
|
tmp[list[0]]!!.clusterSize++
|
||||||
|
|
||||||
|
//Log.v(TAG, "Clustered item at " + itemGridIndex + ", \'parent\' size " + (tmp[storedIndexInGridSlot].clusterSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All ready for update. */synchronized(this) {
|
||||||
|
mUpdate = true
|
||||||
|
mItems = tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun update(v: GLViewport) {
|
||||||
|
val scale: Double = Tile.SIZE * v.pos.scale
|
||||||
|
if (mClusteringEnabled) {
|
||||||
|
/*
|
||||||
|
Clustering check: If clustering is enabled and there's been a significant scale change
|
||||||
|
trigger repopulation and return. After repopulation, this will be called again
|
||||||
|
*/
|
||||||
|
|
||||||
|
// (int) log of scale gives us adequate steps to trigger clustering
|
||||||
|
val scalePow = FastMath.log2(scale.toInt())
|
||||||
|
if (scalePow != mScalePow) {
|
||||||
|
mScalePow = scalePow
|
||||||
|
mClusterScale = scale
|
||||||
|
|
||||||
|
// post repopulation to the main thread
|
||||||
|
mMarkerLayer.map().post(Runnable { repopulateCluster(mItems.size, scale) })
|
||||||
|
|
||||||
|
// and get out of here
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!v.changed() && !mUpdate) return
|
||||||
|
mUpdate = false
|
||||||
|
val mx: Double = v.pos.x
|
||||||
|
val my: Double = v.pos.y
|
||||||
|
|
||||||
|
//int changesInvisible = 0;
|
||||||
|
//int changedVisible = 0;
|
||||||
|
var numVisible = 0
|
||||||
|
|
||||||
|
// Increase view to show items that are partially visible
|
||||||
|
mMarkerLayer.map().viewport().getMapExtents(mBox, (Tile.SIZE shr 1).toFloat())
|
||||||
|
val flip: Long = (Tile.SIZE * v.pos.scale).toLong() shr 1
|
||||||
|
if (mItems == null) {
|
||||||
|
if (buckets.get() != null) {
|
||||||
|
buckets.clear()
|
||||||
|
compile()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val angle = Math.toRadians(v.pos.bearing.toDouble())
|
||||||
|
val cos = Math.cos(angle).toFloat()
|
||||||
|
val sin = Math.sin(angle).toFloat()
|
||||||
|
|
||||||
|
/* check visibility */for (itm in mItems) {
|
||||||
|
val it = itm as Clustered
|
||||||
|
it.changes = false
|
||||||
|
it.x = ((it.px - mx) * scale).toFloat()
|
||||||
|
it.y = ((it.py - my) * scale).toFloat()
|
||||||
|
if (it.x > flip) it.x -= (flip shl 1).toFloat() else if (it.x < -flip) it.x += (flip shl 1).toFloat()
|
||||||
|
if (it.clusteredOut || !GeometryUtils.pointInPoly(it.x, it.y, mBox, 8, 0)) {
|
||||||
|
// either properly invisible, or clustered out. Items marked as clustered out mean there's another item
|
||||||
|
// on the same-ish position that will be promoted to cluster marker, so this particular item is considered
|
||||||
|
// invisible
|
||||||
|
if (it.visible && !it.clusteredOut) {
|
||||||
|
// it was previously visible, but now it won't
|
||||||
|
it.changes = true
|
||||||
|
// changes to invible
|
||||||
|
//changesInvisible++;
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// item IS definitely visible
|
||||||
|
it.dy = sin * it.x + cos * it.y
|
||||||
|
if (!it.visible) {
|
||||||
|
it.visible = true
|
||||||
|
//changedVisible++;
|
||||||
|
}
|
||||||
|
numVisible++
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.debug(numVisible + " " + changedVisible + " " + changesInvisible);
|
||||||
|
|
||||||
|
/* only update when zoomlevel changed, new items are visible
|
||||||
|
* or more than 10 of the current items became invisible */
|
||||||
|
//if ((numVisible == 0) && (changedVisible == 0 && changesInvisible < 10))
|
||||||
|
// return;
|
||||||
|
buckets.clear()
|
||||||
|
if (numVisible == 0) {
|
||||||
|
compile()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
/* keep position for current state */mMapPosition.copy(v.pos)
|
||||||
|
mMapPosition.bearing = -mMapPosition.bearing
|
||||||
|
|
||||||
|
// why do we sort ? z-index?
|
||||||
|
sort(mItems, 0, mItems.size)
|
||||||
|
//log.debug(Arrays.toString(mItems));
|
||||||
|
for (itm in mItems) {
|
||||||
|
val it = itm as Clustered
|
||||||
|
|
||||||
|
// skip invisible AND clustered-out
|
||||||
|
if (!it.visible || it.clusteredOut) continue
|
||||||
|
if (it.changes) {
|
||||||
|
it.visible = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val s: SymbolItem = SymbolItem.pool.get()
|
||||||
|
if (it.clusterSize > 0) {
|
||||||
|
// this item will act as a cluster, just use a proper bitmap
|
||||||
|
// depending on cluster size, instead of its marker
|
||||||
|
val bitmap = getClusterBitmap(it.clusterSize + 1)
|
||||||
|
s.set(it.x, it.y, bitmap, true)
|
||||||
|
s.offset = PointF(0.5f, 0.5f)
|
||||||
|
s.billboard = true // could be a parameter
|
||||||
|
} else {
|
||||||
|
// normal item, use its marker
|
||||||
|
var symbol: MarkerSymbol? = it.item.marker
|
||||||
|
if (symbol == null) symbol = mDefaultMarker
|
||||||
|
symbol?.let { symbol ->
|
||||||
|
s.set(it.x, it.y, symbol.bitmap, true)
|
||||||
|
s.offset = symbol.hotspot
|
||||||
|
s.billboard = symbol.isBillboard
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
mSymbolLayer.pushSymbol(s)
|
||||||
|
}
|
||||||
|
buckets.set(mSymbolLayer)
|
||||||
|
buckets.prepare()
|
||||||
|
compile()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a bitmap for a given cluster size
|
||||||
|
*
|
||||||
|
* @param size The cluster size. Can be greater than CLUSTER_MAXSIZE.
|
||||||
|
* @return A somewhat cool bitmap to be used as the cluster marker
|
||||||
|
*/
|
||||||
|
open fun getClusterBitmap(size: Int): Bitmap? {
|
||||||
|
var size = size
|
||||||
|
val strValue: String
|
||||||
|
if (size >= CLUSTER_MAXSIZE) {
|
||||||
|
// restrict cluster indicator size. Bigger clusters will show as "+" instead of ie. "45"
|
||||||
|
size = CLUSTER_MAXSIZE
|
||||||
|
strValue = "+"
|
||||||
|
} else {
|
||||||
|
strValue = size.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// return cached bitmap if exists. cache hit !
|
||||||
|
if (mClusterBitmaps[size] != null) return mClusterBitmaps[size]
|
||||||
|
|
||||||
|
// create and cache bitmap. This is unacceptable inside the GL thread,
|
||||||
|
// so we'll call this routine at the beginning to pre-cache all bitmaps
|
||||||
|
// Can customize cluster bitmap here
|
||||||
|
//
|
||||||
|
// Canvas canvas = new Canvas(bitmap);
|
||||||
|
// TextPaint textPaint = new TextPaint();
|
||||||
|
// textPaint.setColor(Color.WHITE);
|
||||||
|
// int width = (int) Math.ceil(textPaint.measureText(strValue));
|
||||||
|
// android.graphics.Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
|
||||||
|
// int height = (int) Math.ceil(Math.abs(fontMetrics.bottom) + Math.abs(fontMetrics.top));
|
||||||
|
// textPaint.setTextSize(13 * CanvasAdapter.getScale());
|
||||||
|
// canvas.drawText(strValue, 0, Math.abs(fontMetrics.ascent), textPaint);
|
||||||
|
val textPaint = TextPaint()
|
||||||
|
val h: Float = 13 * CanvasAdapter.getScale()
|
||||||
|
textPaint.textSize = h
|
||||||
|
textPaint.strokeWidth = 2f
|
||||||
|
textPaint.color = Color.WHITE
|
||||||
|
val bitmap = BitmapFactory.decodeResource(
|
||||||
|
mContext!!.resources, R.mipmap.map_icon_cluster
|
||||||
|
).copy(android.graphics.Bitmap.Config.ARGB_8888, true)
|
||||||
|
val canvas = Canvas(bitmap)
|
||||||
|
val w = textPaint.getTextWidths(strValue, FloatArray(strValue.length))
|
||||||
|
val textRect = Rect()
|
||||||
|
textPaint.getTextBounds(strValue, 0, strValue.length, textRect)
|
||||||
|
canvas.drawText(
|
||||||
|
strValue,
|
||||||
|
((bitmap.width - textRect.width()) / 2 - 4).toFloat(),
|
||||||
|
((bitmap.height + textRect.height()) / 2).toFloat(),
|
||||||
|
textPaint
|
||||||
|
)
|
||||||
|
val bitmapNew: Bitmap = AndroidBitmap(bitmap)
|
||||||
|
// Canvas canvas = CanvasAdapter.newCanvas();
|
||||||
|
// canvas.setBitmap(bitmapNew);
|
||||||
|
// mSize = ClusterUtils.getPixels(sizedp);
|
||||||
|
// int halfsize = mSize >> 1;
|
||||||
|
// final int noneClippingRadius = halfsize - getPixels(2);
|
||||||
|
// Paint mPaintText = CanvasAdapter.newPaint();
|
||||||
|
// draw the number at the center
|
||||||
|
// canvas.drawText(strValue,
|
||||||
|
// (canvas.getWidth() - mPaintText.getTextWidth(strValue)) * 0.5f,
|
||||||
|
// (canvas.getHeight() + mPaintText.getTextHeight(strValue)) * 0.5f,
|
||||||
|
// mPaintText);
|
||||||
|
// ClusterUtils.ClusterDrawable drawable = new ClusterUtils.ClusterDrawable(
|
||||||
|
// MAP_MARKER_CLUSTER_SIZE_DP - CLUSTER_MAXSIZE + size, // make size dependent on cluster size
|
||||||
|
// mStyleForeground,
|
||||||
|
// mStyleBackground,
|
||||||
|
// strValue
|
||||||
|
// );
|
||||||
|
mClusterBitmaps[size] = bitmapNew
|
||||||
|
return mClusterBitmaps[size]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to wrap the cluster icon style properties
|
||||||
|
*/
|
||||||
|
class ClusterStyle
|
||||||
|
/**
|
||||||
|
* Creates the Cluster style
|
||||||
|
*
|
||||||
|
* @param fore Foreground (border and text) color
|
||||||
|
* @param back Background (circle) color
|
||||||
|
*/(val foreground: Int, val background: Int)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Max number to display inside a cluster icon
|
||||||
|
*/
|
||||||
|
protected const val CLUSTER_MAXSIZE = 999
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default color of number inside the icon. Would be super-cool to cook this into the map theme
|
||||||
|
*/
|
||||||
|
private const val CLUSTER_COLORTEXT = -0x7fff40
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default color of circle background
|
||||||
|
*/
|
||||||
|
private const val CLUSTER_COLORBACK = -0x1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map Cluster Icon Size. This is the biggest size for clusters of CLUSTER_MAXSIZE elements. Smaller clusters will be slightly smaller
|
||||||
|
*/
|
||||||
|
protected const val MAP_MARKER_CLUSTER_SIZE_DP = 48
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clustering grid square size, decrease to cluster more aggresively. Ideally this value is the typical marker size
|
||||||
|
*/
|
||||||
|
private var MAP_GRID_SIZE_DP = 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cached bitmaps database, we will cache cluster bitmaps from 1 to MAX_SIZE
|
||||||
|
* and always use same bitmap for efficiency
|
||||||
|
*/
|
||||||
|
protected var mClusterBitmaps = arrayOfNulls<Bitmap>(CLUSTER_MAXSIZE + 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for instantiating this renderer via a factory, so the layer construction semantic is more pleasing to the eye
|
||||||
|
*
|
||||||
|
* @param defaultSymbol Default symbol to use if the Marker is not assigned a symbol
|
||||||
|
* @param style Cluster icon style, or NULL to disable clustering functionality
|
||||||
|
* @return A factory to be passed to the ItemizedLayer constructor in order to enable the cluster functionality
|
||||||
|
*/
|
||||||
|
fun factory(defaultSymbol: MarkerSymbol, style: ClusterStyle?): MarkerRendererFactory {
|
||||||
|
return MarkerRendererFactory { markerLayer ->
|
||||||
|
ClusterMarkerRenderer(
|
||||||
|
markerLayer, defaultSymbol, style
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 nebular
|
||||||
|
* Copyright 2017 devemux86
|
||||||
|
* Copyright 2017 Wolfgang Schramm
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.navinfo.collect.library.map.cluster
|
||||||
|
|
||||||
|
import org.oscim.backend.CanvasAdapter
|
||||||
|
import org.oscim.backend.canvas.Bitmap
|
||||||
|
import org.oscim.backend.canvas.Canvas
|
||||||
|
import org.oscim.backend.canvas.Paint
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple utility class to make clustered markers functionality self-contained.
|
||||||
|
* Includes a method to translate between DPs and PXs and a circular icon generator.
|
||||||
|
*/
|
||||||
|
object ClusterUtils {
|
||||||
|
/**
|
||||||
|
* Get pixels from DPs
|
||||||
|
*
|
||||||
|
* @param dp Value in DPs
|
||||||
|
* @return Value in PX according to screen density
|
||||||
|
*/
|
||||||
|
fun getPixels(dp: Float): Int {
|
||||||
|
return (CanvasAdapter.getScale() * dp).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClusterDrawable(sizedp: Int, foregroundColor: Int, backgroundColor: Int, text: String) {
|
||||||
|
private val mPaintText = CanvasAdapter.newPaint()
|
||||||
|
private val mPaintCircle = CanvasAdapter.newPaint()
|
||||||
|
private val mPaintBorder = CanvasAdapter.newPaint()
|
||||||
|
private var mSize = 0
|
||||||
|
private var mText: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a circle with a number inside
|
||||||
|
*
|
||||||
|
* @param sizedp Size in DPs
|
||||||
|
* @param foregroundColor Foreground
|
||||||
|
* @param backgroundColor Background
|
||||||
|
* @param text Text inside. Will only work for a single character!
|
||||||
|
*/
|
||||||
|
init {
|
||||||
|
setup(sizedp, foregroundColor, backgroundColor)
|
||||||
|
setText(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setup(sizedp: Int, foregroundColor: Int, backgroundColor: Int) {
|
||||||
|
mSize = getPixels(sizedp.toFloat())
|
||||||
|
mPaintText.setTextSize(getPixels((sizedp * 0.6666666).toInt().toFloat()).toFloat())
|
||||||
|
mPaintText.color = foregroundColor
|
||||||
|
mPaintCircle.color = backgroundColor
|
||||||
|
mPaintCircle.style = Paint.Style.FILL
|
||||||
|
mPaintBorder.color = foregroundColor
|
||||||
|
mPaintBorder.style = Paint.Style.STROKE
|
||||||
|
mPaintBorder.strokeWidth = 2.0f * CanvasAdapter.getScale()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setText(text: String) {
|
||||||
|
mText = text
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun draw(canvas: Canvas) {
|
||||||
|
val halfsize = mSize shr 1
|
||||||
|
val noneClippingRadius = halfsize - getPixels(2f)
|
||||||
|
|
||||||
|
// fill
|
||||||
|
canvas.drawCircle(
|
||||||
|
halfsize.toFloat(),
|
||||||
|
halfsize.toFloat(),
|
||||||
|
noneClippingRadius.toFloat(),
|
||||||
|
mPaintCircle
|
||||||
|
)
|
||||||
|
// outline
|
||||||
|
canvas.drawCircle(
|
||||||
|
halfsize.toFloat(),
|
||||||
|
halfsize.toFloat(),
|
||||||
|
noneClippingRadius.toFloat(),
|
||||||
|
mPaintBorder
|
||||||
|
)
|
||||||
|
// draw the number at the center
|
||||||
|
canvas.drawText(
|
||||||
|
mText,
|
||||||
|
(canvas.width - mPaintText.getTextWidth(mText)) * 0.5f,
|
||||||
|
(canvas.height + mPaintText.getTextHeight(mText)) * 0.5f,
|
||||||
|
mPaintText
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bitmap: Bitmap
|
||||||
|
get() {
|
||||||
|
var width = mSize
|
||||||
|
var height = mSize
|
||||||
|
width = if (width > 0) width else 1
|
||||||
|
height = if (height > 0) height else 1
|
||||||
|
val bitmap = CanvasAdapter.newBitmap(width, height, 0)
|
||||||
|
val canvas = CanvasAdapter.newCanvas()
|
||||||
|
canvas.setBitmap(bitmap)
|
||||||
|
draw(canvas)
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 nebular
|
||||||
|
* Copyright 2017 devemux86
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.navinfo.collect.library.map.cluster
|
||||||
|
|
||||||
|
import org.oscim.layers.marker.InternalItem
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension for clustered items.
|
||||||
|
*/
|
||||||
|
class Clustered : InternalItem() {
|
||||||
|
/**
|
||||||
|
* If this is >0, this item will be displayed as a cluster circle, with size clusterSize+1.
|
||||||
|
*/
|
||||||
|
var clusterSize = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is true, this item is hidden (because it's represented by another InternalItem acting as cluster.
|
||||||
|
*/
|
||||||
|
var clusteredOut = false
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 nebular
|
||||||
|
* Copyright 2017 devemux86
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.navinfo.collect.library.map.cluster
|
||||||
|
|
||||||
|
import org.oscim.core.GeoPoint
|
||||||
|
import org.oscim.layers.marker.MarkerItem
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a MarkerItem is created using this convenience class instead of MarkerItem,
|
||||||
|
* this specific item will not be clusterable.
|
||||||
|
*/
|
||||||
|
class NonClusterable : MarkerItem {
|
||||||
|
constructor(title: String?, description: String?, geoPoint: GeoPoint?) : super(
|
||||||
|
null,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
geoPoint
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(uid: Any?, title: String?, description: String?, geoPoint: GeoPoint?) : super(
|
||||||
|
uid,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
geoPoint
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.navinfo.collect.library.map.handler
|
package com.navinfo.collect.library.map.handler
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
import org.oscim.core.GeoPoint
|
import org.oscim.core.GeoPoint
|
||||||
import org.oscim.core.MapPosition
|
import org.oscim.core.MapPosition
|
||||||
@ -8,7 +9,7 @@ import org.oscim.core.MapPosition
|
|||||||
/**
|
/**
|
||||||
* 控制地图状态相关操作
|
* 控制地图状态相关操作
|
||||||
*/
|
*/
|
||||||
open class AnimationHandler(context: Context, mapView: NIMapView) :
|
open class AnimationHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView) {
|
BaseHandler(context, mapView) {
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,32 +1,48 @@
|
|||||||
package com.navinfo.collect.library.map.handler
|
package com.navinfo.collect.library.map.handler
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.navinfo.collect.library.R
|
||||||
import com.navinfo.collect.library.data.entity.QsRecordBean
|
import com.navinfo.collect.library.data.entity.QsRecordBean
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
|
import com.navinfo.collect.library.map.cluster.ClusterMarkerItem
|
||||||
|
import com.navinfo.collect.library.map.cluster.ClusterMarkerRenderer
|
||||||
|
import com.navinfo.collect.library.map.layers.MyItemizedLayer
|
||||||
import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource
|
import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource
|
||||||
import com.navinfo.collect.library.system.Constant
|
import com.navinfo.collect.library.system.Constant
|
||||||
|
import com.navinfo.collect.library.utils.GeometryTools
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.kotlin.where
|
import io.realm.kotlin.where
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import org.locationtech.jts.geom.Geometry
|
||||||
|
import org.oscim.android.canvas.AndroidBitmap
|
||||||
import org.oscim.backend.CanvasAdapter
|
import org.oscim.backend.CanvasAdapter
|
||||||
|
import org.oscim.backend.canvas.Bitmap
|
||||||
import org.oscim.backend.canvas.Paint
|
import org.oscim.backend.canvas.Paint
|
||||||
|
import org.oscim.core.GeoPoint
|
||||||
import org.oscim.layers.GroupLayer
|
import org.oscim.layers.GroupLayer
|
||||||
|
import org.oscim.layers.marker.*
|
||||||
import org.oscim.layers.tile.buildings.BuildingLayer
|
import org.oscim.layers.tile.buildings.BuildingLayer
|
||||||
import org.oscim.layers.tile.vector.VectorTileLayer
|
import org.oscim.layers.tile.vector.VectorTileLayer
|
||||||
import org.oscim.layers.tile.vector.labeling.LabelLayer
|
import org.oscim.layers.tile.vector.labeling.LabelLayer
|
||||||
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
|
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
|
||||||
import org.oscim.tiling.source.mapfile.MapFileTileSource
|
import org.oscim.tiling.source.mapfile.MapFileTileSource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Layer 操作
|
* Layer 操作
|
||||||
*/
|
*/
|
||||||
class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
|
open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView) {
|
BaseHandler(context, mapView) {
|
||||||
private var baseGroupLayer // 用于盛放所有基础底图的图层组,便于统一管理
|
private var baseGroupLayer // 用于盛放所有基础底图的图层组,便于统一管理
|
||||||
: GroupLayer? = null
|
: GroupLayer? = null
|
||||||
@ -42,6 +58,17 @@ class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
|
|||||||
|
|
||||||
private lateinit var paint: Paint
|
private lateinit var paint: Paint
|
||||||
|
|
||||||
|
//画布
|
||||||
|
private lateinit var canvas: org.oscim.backend.canvas.Canvas
|
||||||
|
private lateinit var itemizedLayer: MyItemizedLayer
|
||||||
|
private lateinit var markerRendererFactory: MarkerRendererFactory
|
||||||
|
private val markerItemsNames = mutableListOf<MarkerInterface>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文字大小
|
||||||
|
*/
|
||||||
|
private val NUM_13 = 13
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initMap()
|
initMap()
|
||||||
}
|
}
|
||||||
@ -122,47 +149,356 @@ class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始话质检数据图层
|
||||||
|
*/
|
||||||
private fun initQsRecordDataLayer() {
|
private fun initQsRecordDataLayer() {
|
||||||
|
canvas = CanvasAdapter.newCanvas()
|
||||||
paint = CanvasAdapter.newPaint()
|
paint = CanvasAdapter.newPaint()
|
||||||
paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL)
|
paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL)
|
||||||
paint.setTextSize(13 * CanvasAdapter.getScale())
|
paint.setTextSize(NUM_13 * CanvasAdapter.getScale())
|
||||||
paint.strokeWidth = 2 * CanvasAdapter.getScale()
|
paint.strokeWidth = 2 * CanvasAdapter.getScale()
|
||||||
paint.color = Color.parseColor(mDefaultTextColor)
|
paint.color = Color.parseColor(mDefaultTextColor)
|
||||||
|
val bitmapPoi: Bitmap = AndroidBitmap(
|
||||||
|
BitmapFactory.decodeResource(
|
||||||
|
mContext.resources,
|
||||||
|
R.mipmap.map_icon_blue2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val symbol = MarkerSymbol(bitmapPoi, MarkerSymbol.HotspotPlace.BOTTOM_CENTER)
|
||||||
|
markerRendererFactory = MarkerRendererFactory { markerLayer ->
|
||||||
|
object : ClusterMarkerRenderer(
|
||||||
|
mContext,
|
||||||
|
markerLayer,
|
||||||
|
symbol,
|
||||||
|
ClusterStyle(
|
||||||
|
org.oscim.backend.canvas.Color.WHITE,
|
||||||
|
org.oscim.backend.canvas.Color.BLUE
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// override fun getClusterBitmap(size: Int): Bitmap? {
|
||||||
|
// return super.getclusterbitmap(size)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var resId = R.mipmap.map_icon_point_add
|
||||||
|
|
||||||
mContext.lifecycleScope.launch(Dispatchers.IO) {
|
mContext.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
var list = mutableListOf<QsRecordBean>()
|
||||||
|
|
||||||
val realm = Realm.getDefaultInstance()
|
val realm = Realm.getDefaultInstance()
|
||||||
realm.executeTransaction {
|
realm.executeTransaction {
|
||||||
val list = realm.where<QsRecordBean>().findAll()
|
val objects =realm.where<QsRecordBean>().findAll()
|
||||||
paint.setColor(Color.parseColor(mDefaultTextColor))
|
list = realm.copyFromRealm(objects)
|
||||||
}
|
}
|
||||||
realm.close()
|
realm.close()
|
||||||
|
|
||||||
|
itemizedLayer =
|
||||||
|
MyItemizedLayer(
|
||||||
|
mMapView.vtmMap,
|
||||||
|
mutableListOf(),
|
||||||
|
markerRendererFactory,
|
||||||
|
object : MyItemizedLayer.OnItemGestureListener {
|
||||||
|
override fun onItemSingleTapUp(
|
||||||
|
layer: MyItemizedLayer?,
|
||||||
|
list: MutableList<Int>?,
|
||||||
|
nearest: Int
|
||||||
|
): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemLongPress(
|
||||||
|
layer: MyItemizedLayer?,
|
||||||
|
list: MutableList<Int>?,
|
||||||
|
nearest: Int
|
||||||
|
): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for (item in list) {
|
||||||
|
val bitmap: Bitmap = createTextMarkerBitmap(mContext, item.description, resId)
|
||||||
|
if (item.t_lifecycle != 2) {
|
||||||
|
val geometry: Geometry? = GeometryTools.createGeometry(item.geometry)
|
||||||
|
if (geometry != null) {
|
||||||
|
var geoPoint: GeoPoint? = null
|
||||||
|
if (geometry.geometryType != null) {
|
||||||
|
when (geometry.geometryType.uppercase(Locale.getDefault())) {
|
||||||
|
"POINT" -> geoPoint =
|
||||||
|
GeoPoint(geometry.coordinate.y, geometry.coordinate.x)
|
||||||
|
// "LINESTRING" -> {
|
||||||
|
// val lineString = geometry as LineString
|
||||||
|
// if (lineString != null && lineString.coordinates.size > 0) {
|
||||||
|
// geoPoint = GeoPoint(
|
||||||
|
// lineString.coordinates[0].y,
|
||||||
|
// lineString.coordinates[0].x
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// val drawableLine: Drawable =
|
||||||
|
// convertGeometry2Drawable(geometry, lineStyle)
|
||||||
|
// if (drawableLine != null) {
|
||||||
|
// dataVectorLayer.add(drawableLine)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// "POLYGON" -> {
|
||||||
|
// val polygon = geometry as Polygon
|
||||||
|
// if (polygon != null && polygon.coordinates.size > 0) {
|
||||||
|
// geoPoint = GeoPoint(
|
||||||
|
// polygon.coordinates[0].y,
|
||||||
|
// polygon.coordinates[0].x
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// val drawablePolygon: Drawable =
|
||||||
|
// convertGeometry2Drawable(geometry, polygonStyle)
|
||||||
|
// if (drawablePolygon != null) {
|
||||||
|
// dataVectorLayer.add(drawablePolygon)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (geoPoint != null) {
|
||||||
|
var geoMarkerItem: MarkerItem
|
||||||
|
// if (item.getType() === 1) {
|
||||||
|
geoMarkerItem = ClusterMarkerItem(
|
||||||
|
1, item.id, item.description, geoPoint
|
||||||
|
)
|
||||||
|
// } else {
|
||||||
|
// geoMarkerItem = MarkerItem(
|
||||||
|
// ePointTemp.getType(),
|
||||||
|
// ePointTemp.getId(),
|
||||||
|
// ePointTemp.getStyleText(),
|
||||||
|
// geoPoint
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
markerItemsNames.add(geoMarkerItem)
|
||||||
|
val markerSymbol =
|
||||||
|
MarkerSymbol(bitmap, MarkerSymbol.HotspotPlace.CENTER)
|
||||||
|
geoMarkerItem.marker = markerSymbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itemizedLayer.addItems(markerItemsNames)
|
||||||
|
addLayer(itemizedLayer, NIMapView.LAYER_GROUPS.OPERATE)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
itemizedLayer.map().updateMap(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文字和图片拼装,文字换行
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @param text
|
||||||
|
* @param resId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private fun createTextMarkerBitmap(context: Context, text: String, resId: Int): Bitmap {
|
||||||
|
var text: String? = text
|
||||||
|
return if (text == null || text.trim { it <= ' ' }.isEmpty()) {
|
||||||
|
val drawable = ResourcesCompat.getDrawable(context.resources, resId, null)
|
||||||
|
val originBitmap = android.graphics.Bitmap.createBitmap(
|
||||||
|
drawable!!.intrinsicWidth,
|
||||||
|
drawable.intrinsicHeight * 2,
|
||||||
|
android.graphics.Bitmap.Config.ARGB_8888
|
||||||
|
)
|
||||||
|
val androidCanvas = Canvas(originBitmap)
|
||||||
|
val startX = (originBitmap.width - drawable.intrinsicWidth) / 2
|
||||||
|
drawable.setBounds(
|
||||||
|
startX, 0, startX + drawable.intrinsicWidth, drawable.intrinsicHeight
|
||||||
|
)
|
||||||
|
drawable.draw(androidCanvas)
|
||||||
|
val bitmap: Bitmap = AndroidBitmap(originBitmap)
|
||||||
|
canvas.setBitmap(bitmap)
|
||||||
|
bitmap
|
||||||
|
} else {
|
||||||
|
val drawable = ResourcesCompat.getDrawable(context.resources, resId, null)
|
||||||
|
val textList: MutableList<String> = ArrayList()
|
||||||
|
val fontSize: Float = NUM_13 * CanvasAdapter.getScale()
|
||||||
|
paint.setTextSize(fontSize)
|
||||||
|
var maxWidth = 0f
|
||||||
|
//最多4行,一行7个
|
||||||
|
if (text.trim { it <= ' ' }.length > 24) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 4).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
if (text.trim { it <= ' ' }.length > 28) text = text.substring(0, 26) + "..."
|
||||||
|
val temp1 = text.substring(0, 7)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(7)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
val temp2 = text.substring(0, 7)
|
||||||
|
textList.add(temp2)
|
||||||
|
text = text.substring(7)
|
||||||
|
var newWidth = paint.getTextWidth(temp2)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
val temp3 = text.substring(0, 7)
|
||||||
|
textList.add(temp3)
|
||||||
|
text = text.substring(7)
|
||||||
|
newWidth = paint.getTextWidth(temp3)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
textList.add(text)
|
||||||
|
newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 21) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 4).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 6)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(6)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
val temp2 = text.substring(0, 6)
|
||||||
|
textList.add(temp2)
|
||||||
|
text = text.substring(6)
|
||||||
|
var newWidth = paint.getTextWidth(temp2)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
val temp3 = text.substring(0, 6)
|
||||||
|
textList.add(temp3)
|
||||||
|
text = text.substring(6)
|
||||||
|
newWidth = paint.getTextWidth(temp3)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
textList.add(text)
|
||||||
|
newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 18) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 3).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 7)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(7)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
val temp2 = text.substring(0, 7)
|
||||||
|
textList.add(temp2)
|
||||||
|
text = text.substring(7)
|
||||||
|
var newWidth = paint.getTextWidth(temp2)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
textList.add(text)
|
||||||
|
newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 18) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 3).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 7)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(7)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
val temp2 = text.substring(0, 7)
|
||||||
|
textList.add(temp2)
|
||||||
|
text = text.substring(7)
|
||||||
|
var newWidth = paint.getTextWidth(temp2)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
textList.add(text)
|
||||||
|
newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 14) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 3).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 6)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(6)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
val temp2 = text.substring(0, 6)
|
||||||
|
textList.add(temp2)
|
||||||
|
text = text.substring(6)
|
||||||
|
var newWidth = paint.getTextWidth(temp2)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
textList.add(text)
|
||||||
|
newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 12) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 2).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 7)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(7)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
textList.add(text)
|
||||||
|
val newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 10) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 2).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 6)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(6)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
textList.add(text)
|
||||||
|
val newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else if (text.trim { it <= ' ' }.length > 7) {
|
||||||
|
val size = (drawable!!.intrinsicHeight / 2).toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
val temp1 = text.substring(0, 5)
|
||||||
|
textList.add(temp1)
|
||||||
|
text = text.substring(5)
|
||||||
|
maxWidth = paint.getTextWidth(temp1)
|
||||||
|
textList.add(text)
|
||||||
|
val newWidth = paint.getTextWidth(text)
|
||||||
|
if (newWidth > maxWidth) {
|
||||||
|
maxWidth = newWidth
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val size = drawable!!.intrinsicHeight.toFloat()
|
||||||
|
if (size < fontSize) paint.setTextSize(size)
|
||||||
|
textList.add(text)
|
||||||
|
maxWidth = paint.getTextWidth(text)
|
||||||
|
}
|
||||||
|
paint.color = Color.parseColor(mDefaultTextColor)
|
||||||
|
val originBitmap = android.graphics.Bitmap.createBitmap(
|
||||||
|
if (drawable.intrinsicWidth > maxWidth) drawable.intrinsicWidth else maxWidth.toInt(),
|
||||||
|
drawable.intrinsicHeight * 2,
|
||||||
|
android.graphics.Bitmap.Config.ARGB_4444
|
||||||
|
)
|
||||||
|
val androidCanvas = Canvas(originBitmap)
|
||||||
|
val startX = (originBitmap.width - drawable.intrinsicWidth) / 2
|
||||||
|
drawable.setBounds(
|
||||||
|
startX, 0, startX + drawable.intrinsicWidth, drawable.intrinsicHeight
|
||||||
|
)
|
||||||
|
drawable.draw(androidCanvas)
|
||||||
|
val bitmap: Bitmap = AndroidBitmap(originBitmap)
|
||||||
|
canvas.setBitmap(bitmap)
|
||||||
|
var startHeight = (drawable.intrinsicHeight + paint.getTextHeight(text)).toInt()
|
||||||
|
for (txt in textList) {
|
||||||
|
canvas.drawText(
|
||||||
|
txt, (bitmap.width - paint.getTextWidth(txt)) / 2, startHeight.toFloat(), paint
|
||||||
|
)
|
||||||
|
startHeight += paint.getTextHeight(txt).toInt()
|
||||||
|
}
|
||||||
|
bitmap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun getRasterTileLayer(
|
|
||||||
// url: String?,
|
|
||||||
// tilePath: String?,
|
|
||||||
// useCache: Boolean
|
|
||||||
// ): Layer {
|
|
||||||
// val builder = OkHttpClient.Builder()
|
|
||||||
// val mTileSource =
|
|
||||||
// NavinfoMapRastorTileSource.builder(url).tilePath(tilePath)
|
|
||||||
// .httpFactory(OkHttpFactory(builder)).build()
|
|
||||||
// // 如果使用缓存
|
|
||||||
// if (useCache) {
|
|
||||||
// val cacheDirectory =
|
|
||||||
// File(Constant.MAP_PATH, "cache")
|
|
||||||
// val cacheSize = 300 * 1024 * 1024 // 300 MB
|
|
||||||
// val cache = Cache(cacheDirectory, cacheSize.toLong())
|
|
||||||
// builder.cache(cache)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return BitmapTileLayer(mMapView.vtmMap, mTileSource)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础
|
* 基础
|
||||||
*/
|
*/
|
||||||
@ -170,14 +506,10 @@ enum class BASE_MAP_TYPE(// TransportMap底图
|
|||||||
var title: String, var url: String, var tilePath: String
|
var title: String, var url: String, var tilePath: String
|
||||||
) {
|
) {
|
||||||
OPEN_STREET_MAP(
|
OPEN_STREET_MAP(
|
||||||
"Open Street Map",
|
"Open Street Map", "http://a.tile.openstreetmap.org", "/{Z}}/{X}/{Y}.png"
|
||||||
"http://a.tile.openstreetmap.org",
|
|
||||||
"/{Z}}/{X}/{Y}.png"
|
|
||||||
), // openStreetMap底图
|
), // openStreetMap底图
|
||||||
CYCLE_MAP(
|
CYCLE_MAP(
|
||||||
"Cycle Map",
|
"Cycle Map", "http://c.tile.opencyclemap.org/cycle", "/{Z}}/{X}/{Y}.png"
|
||||||
"http://c.tile.opencyclemap.org/cycle",
|
|
||||||
"/{Z}}/{X}/{Y}.png"
|
|
||||||
), // cyclemap底图
|
), // cyclemap底图
|
||||||
S_MAP(
|
S_MAP(
|
||||||
"SMap",
|
"SMap",
|
||||||
@ -185,9 +517,7 @@ enum class BASE_MAP_TYPE(// TransportMap底图
|
|||||||
"z={Z}&x={X}&y={Y}"
|
"z={Z}&x={X}&y={Y}"
|
||||||
), // cyclemap底图
|
), // cyclemap底图
|
||||||
TRANSPORT_MAP(
|
TRANSPORT_MAP(
|
||||||
"Transport Map",
|
"Transport Map", "http://b.tile2.opencyclemap.org/transport", "/{Z}}/{X}/{Y}.png"
|
||||||
"http://b.tile2.opencyclemap.org/transport",
|
|
||||||
"/{Z}}/{X}/{Y}.png"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package com.navinfo.collect.library.map.handler
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.navinfo.collect.library.R
|
import com.navinfo.collect.library.R
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
import com.navinfo.collect.library.utils.GeometryTools
|
import com.navinfo.collect.library.utils.GeometryTools
|
||||||
@ -21,7 +22,7 @@ import org.oscim.layers.vector.PathLayer
|
|||||||
import org.oscim.layers.vector.geometries.Style
|
import org.oscim.layers.vector.geometries.Style
|
||||||
import org.oscim.map.Map
|
import org.oscim.map.Map
|
||||||
|
|
||||||
open class LineHandler(context: Context, mapView: NIMapView) :
|
open class LineHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView), Map.UpdateListener {
|
BaseHandler(context, mapView), Map.UpdateListener {
|
||||||
|
|
||||||
private var editIndex: Int = -1;
|
private var editIndex: Int = -1;
|
||||||
|
@ -3,6 +3,7 @@ package com.navinfo.collect.library.map.handler
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.baidu.location.BDAbstractLocationListener
|
import com.baidu.location.BDAbstractLocationListener
|
||||||
import com.baidu.location.BDLocation
|
import com.baidu.location.BDLocation
|
||||||
import com.baidu.location.LocationClient
|
import com.baidu.location.LocationClient
|
||||||
@ -13,7 +14,7 @@ import com.navinfo.collect.library.map.NIMapView
|
|||||||
import org.oscim.layers.LocationLayer
|
import org.oscim.layers.LocationLayer
|
||||||
|
|
||||||
|
|
||||||
class LocationLayerHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
|
class LocationLayerHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler(context, mapView) {
|
||||||
|
|
||||||
private var mCurrentLocation: BDLocation? = null
|
private var mCurrentLocation: BDLocation? = null
|
||||||
private var bFirst = true
|
private var bFirst = true
|
||||||
|
@ -2,6 +2,7 @@ package com.navinfo.collect.library.map.handler
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.navinfo.collect.library.R
|
import com.navinfo.collect.library.R
|
||||||
import com.navinfo.collect.library.map.GeoPoint
|
import com.navinfo.collect.library.map.GeoPoint
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
@ -16,7 +17,7 @@ import org.oscim.layers.marker.MarkerSymbol
|
|||||||
/**
|
/**
|
||||||
* marker 操作
|
* marker 操作
|
||||||
*/
|
*/
|
||||||
class MarkHandler(context: Context, mapView: NIMapView) :
|
class MarkHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView) {
|
BaseHandler(context, mapView) {
|
||||||
|
|
||||||
// //默认marker图层
|
// //默认marker图层
|
||||||
|
@ -6,6 +6,7 @@ import android.graphics.Canvas
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.text.TextPaint
|
import android.text.TextPaint
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.navinfo.collect.library.R
|
import com.navinfo.collect.library.R
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
import com.navinfo.collect.library.map.handler.BaseHandler
|
import com.navinfo.collect.library.map.handler.BaseHandler
|
||||||
@ -29,7 +30,7 @@ import org.oscim.layers.vector.geometries.Style
|
|||||||
import org.oscim.map.Map
|
import org.oscim.map.Map
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
open class MeasureLayerHandler(context: Context, mapView: NIMapView) :
|
open class MeasureLayerHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView), Map.UpdateListener {
|
BaseHandler(context, mapView), Map.UpdateListener {
|
||||||
|
|
||||||
private var editIndex: Int = -1;//线修型的时候,用来表示是不是正在修型,修的第几个点
|
private var editIndex: Int = -1;//线修型的时候,用来表示是不是正在修型,修的第几个点
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.navinfo.collect.library.R
|
import com.navinfo.collect.library.R
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
import com.navinfo.collect.library.map.layers.NIPolygonLayer
|
import com.navinfo.collect.library.map.layers.NIPolygonLayer
|
||||||
@ -23,7 +24,7 @@ import org.oscim.layers.vector.PathLayer
|
|||||||
import org.oscim.layers.vector.geometries.Style
|
import org.oscim.layers.vector.geometries.Style
|
||||||
import org.oscim.map.Map
|
import org.oscim.map.Map
|
||||||
|
|
||||||
open class PolygonHandler(context: Context, mapView: NIMapView) :
|
open class PolygonHandler(context: AppCompatActivity, mapView: NIMapView) :
|
||||||
BaseHandler(context, mapView), Map.UpdateListener {
|
BaseHandler(context, mapView), Map.UpdateListener {
|
||||||
|
|
||||||
private var editIndex: Int = -1;
|
private var editIndex: Int = -1;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package com.navinfo.collect.library.map.handler
|
package com.navinfo.collect.library.map.handler
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.navinfo.collect.library.map.NIMapView
|
import com.navinfo.collect.library.map.NIMapView
|
||||||
import com.navinfo.collect.library.utils.GeometryTools
|
import com.navinfo.collect.library.utils.GeometryTools
|
||||||
import org.oscim.core.GeoPoint
|
import org.oscim.core.GeoPoint
|
||||||
import org.oscim.core.Point
|
import org.oscim.core.Point
|
||||||
|
|
||||||
open class ViewportHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
|
open class ViewportHandler(context: AppCompatActivity, mapView: NIMapView) : BaseHandler(context, mapView) {
|
||||||
/**
|
/**
|
||||||
* Set pivot horizontal / vertical relative to view center in [-1, 1].
|
* Set pivot horizontal / vertical relative to view center in [-1, 1].
|
||||||
* e.g. pivotY 0.5 is usually preferred for navigation, moving center to 25% of view height.
|
* e.g. pivotY 0.5 is usually preferred for navigation, moving center to 25% of view height.
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
package com.navinfo.collect.library.map.layers;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.oscim.backend.CanvasAdapter;
|
||||||
|
import org.oscim.core.Box;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.event.Gesture;
|
||||||
|
import org.oscim.event.MotionEvent;
|
||||||
|
import org.oscim.layers.marker.ItemizedLayer;
|
||||||
|
import org.oscim.layers.marker.MarkerInterface;
|
||||||
|
import org.oscim.layers.marker.MarkerRendererFactory;
|
||||||
|
import org.oscim.layers.marker.MarkerSymbol;
|
||||||
|
import org.oscim.map.Map;
|
||||||
|
import org.oscim.map.Viewport;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*com.nmp.map.layer
|
||||||
|
*zhjch
|
||||||
|
*2021/12/9
|
||||||
|
*15:32
|
||||||
|
*说明()
|
||||||
|
*/
|
||||||
|
public class MyItemizedLayer extends ItemizedLayer {
|
||||||
|
private OnItemGestureListener mOnItemGestureListener;
|
||||||
|
private final ActiveItem mActiveItemSingleTap;
|
||||||
|
private final ActiveItem mActiveItemLongPress;
|
||||||
|
|
||||||
|
public MyItemizedLayer(Map map, MarkerSymbol defaultMarker) {
|
||||||
|
this(map, new ArrayList<>(), defaultMarker, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyItemizedLayer(Map map, List<MarkerInterface> list, MarkerSymbol defaultMarker, OnItemGestureListener listener) {
|
||||||
|
super(map, list, defaultMarker, null);
|
||||||
|
mOnItemGestureListener = listener;
|
||||||
|
this.mActiveItemSingleTap = new NamelessClass_2();
|
||||||
|
this.mActiveItemLongPress = new NamelessClass_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyItemizedLayer(Map map, MarkerRendererFactory markerRendererFactory) {
|
||||||
|
this(map, new ArrayList<>(), markerRendererFactory, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
class NamelessClass_2 implements ActiveItem {
|
||||||
|
NamelessClass_2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean run(List list1, int nearest) {
|
||||||
|
if (mOnItemGestureListener != null) {
|
||||||
|
return mOnItemGestureListener.onItemSingleTapUp(MyItemizedLayer.this, list1, nearest);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NamelessClass_1 implements ActiveItem {
|
||||||
|
NamelessClass_1() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean run(List list1, int nearest) {
|
||||||
|
if (mOnItemGestureListener != null) {
|
||||||
|
return mOnItemGestureListener.onItemLongPress(MyItemizedLayer.this, list1, nearest);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyItemizedLayer(Map map, List<MarkerInterface> list, MarkerRendererFactory markerRendererFactory, OnItemGestureListener listener) {
|
||||||
|
super(map, list, markerRendererFactory, null);
|
||||||
|
mOnItemGestureListener = listener;
|
||||||
|
this.mActiveItemSingleTap = new NamelessClass_2();
|
||||||
|
this.mActiveItemLongPress = new NamelessClass_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onGesture(Gesture g, MotionEvent e) {
|
||||||
|
if (!this.isEnabled()) {
|
||||||
|
return false;
|
||||||
|
} else if (g instanceof Gesture.Tap) {
|
||||||
|
return this.activateSelectedItems(e, this.mActiveItemSingleTap);
|
||||||
|
} else {
|
||||||
|
return g instanceof Gesture.LongPress ? this.activateSelectedItems(e, this.mActiveItemLongPress) : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean activateSelectedItems(MotionEvent event, ActiveItem task) {
|
||||||
|
int size = this.mItemList.size();
|
||||||
|
|
||||||
|
Log.e("jingo", "地图点击 size =" + size);
|
||||||
|
if (size == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int eventX = (int) event.getX() - this.mMap.getWidth() / 2;
|
||||||
|
int eventY = (int) event.getY() - this.mMap.getHeight() / 2;
|
||||||
|
Viewport mapPosition = this.mMap.viewport();
|
||||||
|
Box box = mapPosition.getBBox((Box) null, Tile.SIZE / 2);
|
||||||
|
box.map2mercator();
|
||||||
|
box.scale(1000000.0D);
|
||||||
|
int nearest = -1;
|
||||||
|
int inside = -1;
|
||||||
|
// double insideY = -1.7976931348623157E308D;
|
||||||
|
double dist = (double) (20.0F * CanvasAdapter.getScale() * 20.0F * CanvasAdapter.getScale());
|
||||||
|
List list = new ArrayList();
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
MarkerInterface item = (MarkerInterface) this.mItemList.get(i);
|
||||||
|
if (box.contains((double) item.getPoint().longitudeE6, (double) item.getPoint().latitudeE6)) {
|
||||||
|
mapPosition.toScreenPoint(item.getPoint(), this.mTmpPoint);
|
||||||
|
float dx = (float) ((double) eventX - this.mTmpPoint.x);
|
||||||
|
float dy = (float) ((double) eventY - this.mTmpPoint.y);
|
||||||
|
MarkerSymbol it = item.getMarker();
|
||||||
|
if (it == null) {
|
||||||
|
continue;
|
||||||
|
// it = this.mMarkerRenderer.mDefaultMarker;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.isInside(dx, dy)) {// && this.mTmpPoint.y > insideY) {
|
||||||
|
// insideY = this.mTmpPoint.y;
|
||||||
|
inside = i;
|
||||||
|
list.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inside < 0) {
|
||||||
|
double d = (double) (dx * dx + dy * dy);
|
||||||
|
if (d <= dist) {
|
||||||
|
dist = d;
|
||||||
|
nearest = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inside >= 0) {
|
||||||
|
nearest = inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nearest >= 0 && task.run(list, nearest)) {
|
||||||
|
this.mMarkerRenderer.update();
|
||||||
|
this.mMap.render();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ActiveItem {
|
||||||
|
boolean run(List list, int nearest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnItemGestureListener(OnItemGestureListener listener) {
|
||||||
|
this.mOnItemGestureListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemGestureListener {
|
||||||
|
boolean onItemSingleTapUp(MyItemizedLayer layer, List<Integer> list, int nearest);
|
||||||
|
|
||||||
|
boolean onItemLongPress(MyItemizedLayer layer, List<Integer> list, int nearest);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user