地圖聚合演算法
⑴ 高德地圖點聚合演算法實現與思考
為了實現在地圖上對大量的標注點進行聚合顯示,使都有標注點根據中心點以及縮放比例的變化動態排列並完成點聚合的功能。現提供基於高德地圖SDK的點聚合實現方式。
以下分別為兩種放縮比例下標注點的聚合情況效果圖:
在預研前期,我考慮了數據從後台獲取的方式,在地圖上添加overlay的方式,但是考慮到用戶的操作會要求所有數據必須實時生成並展現,這意味著每次縮放比例和中心點的改變都要訪問伺服器以重載數據,實現起來難度較大,並且對伺服器和客戶端都造成了較大的壓力。
在閱讀高德開放平台提供的API時發現高德地圖示例中心在2017年2月10日更新了 點聚合效果示例 。
其中 receivedData 可以通過後台獲取或本地生成,包含經度、緯度以及 pID ,即每一個標注點的唯一ID。 mapView regionDidChangeAnimated: 方法在mapView區域變化時自動調用,重算 annotation ,初始化時手動調用一次,使標注點以聚合的形式載入到地圖上。
注意:此處必須要使用多線程
在 mapView viewForAnnotation: 方法中
這樣,就在四叉樹演算法的基礎上完成了點聚合功能的實現。
MACluster地址:
https://github.com/fusugz/MACluster.git
⑵ 百度地圖點聚合顯示
聚合前有引用一個聚合的JS類庫的,其實點聚合的效果的達到是網路地圖介面有個方法是根據可視區域進行分若干個格子,然後根據點的經緯度在哪個格子裡面,再根據每個格子裡面的多少個經緯度來進行聚合。
new BMapLib.MarkerClusterer(map, {markers:markers}); 這句話就是調用markerClusterer類去干分格子然後計算經緯度在格子里頭的數量後並且顯示的過程
⑶ android地圖縮小放大的時候maker之間聚合是什麼原理
<1>GeoPoint
表示一個地理坐標點,存放經度和緯度,以微度的整數形式存儲。
方法
GeoPoint(int latitudeE6, int longitudeE6)用給定的經緯度構造一個GeoPoint
方法介紹:
public int getLatitudeE6()
返回GeoPoint的緯度,單位微度
public int getLongitudeE6()
返回GeoPoint的經度,單位微度
public void setLatitudeE6(int latitudeE6)
設置GeoPoint的緯度,單位微度
public void setLongitudeE6(int longitudeE6)
設置GeoPoint的經度,單位微度
<2>介面 Projection
該介面用來在屏幕像素x/y坐標系和地球經緯度坐標系之間進行轉換,通過 MapView.getProjection()來取得映射類。
GeoPoint fromPixels(int x, int y)
該方法用給定的像素坐標創建一個新的GeoPoint。
給定的像素點是以MapView的左上角為原點的坐標系統,MapView提供了這個像素轉換器(PixelConverter)。 參數:result -
搜索結果iError - 錯誤號,0表示正確返回
Point toPixels(GeoPoint in, Point out)
把給定的GeoPoint變換到相對於MapView左上角的屏幕像素坐標。MapView提供了這種投影變換。 參數:in - 待變換的一對經緯度out
- 一個用於輸出預先存在的對象;如果為空,將返回一個新分配的像素點。
<3>MapController
處理地圖移動和縮放的工具類。
返回類型方法
voidanimateTo(GeoPoint point)對以給定的點GeoPoint,開始動畫顯示地圖。
voidanimateTo(GeoPoint point, Message message)對以給定的GeoPoint,開始動畫顯示地圖。
booleanonKey(View v, int keyCode, KeyEvent event)處理按鍵事件,把事件變換為適度的地圖平移。
voidscrollBy(int x, int y)按照給定的像素數據量滾動。
voidsetCenter(GeoPoint point)在給定的中心點GeoPoint上設置地圖視圖。
intsetZoom(int zoomLevel)設置地圖的縮放級別。
voidstopAnimation(boolean
jumpToFinish)終止所有未完成的動畫,有條件的把地圖中心修正到已完成的特殊動畫的偏移量上去。
voidstopPanning()重新設置平移狀態,使地圖靜止。
booleanzoomIn()放大一個級別。
booleanzoomInFixing(int xPixel, int yPixel)放大一個級別。
booleanzoomOut()縮小一個級別。
booleanzoomOutFixing(int xPixel, int yPixel)縮小一個級別。
voidzoomToSpan(int latSpanE6, int lonSpanE6)嘗試調整地圖的縮放,以便顯示給定的經緯度范圍。
<4>MapView
一個顯示地圖的視圖,當被焦點選中時,它能捕獲按鍵事件和觸摸手勢去平移和縮放地圖。
返回類型方法
booleancanCoverCenter()檢查當前是否有地圖貼片覆蓋地圖中心點。
protected booleancheckLayoutParams (android.view.ViewGroup.LayoutParams
p)僅檢查p是否是的一個MapView.LayoutParams實例。
voidcomputeScroll()捕獲滾動事件,用它們去平移地圖。
voiddisplayZoomControls(boolean takeFocus)顯示縮放控制項,可以選擇是否請求焦點選中以便通過按鍵訪問。
protected
android.view.ViewGroup.()返回一個Layout參數的集合,其中參數帶有ViewGroup.LayoutParams.WRAP_CONTENT的寬度,ViewGroup.LayoutParams.WRAP_CONTENT高度和坐標(0,0)。
protected
android.view.ViewGroup.(android.view.ViewGroup.LayoutParams
p)
android.view.ViewGroup.(AttributeSet
attrs)
MapControllergetController()返回地圖的MapController,這個對象可用於控制和驅動平移和縮放。
intgetLatitudeSpan()當前緯線的跨度(從地圖的上邊緣到下邊緣),十進制度×1,000,000。
intgetLongitudeSpan()當前經度的跨度(從地圖的左邊緣到地圖的右邊緣),單位:十進制的度×1,000,000。
GeoPointgetMapCenter()返回當前地圖中心點位置,做為一個GeoPoint(經度、緯度)的對象。
intgetMaxZoomLevel()返回當前視圖中心點的最大縮放級別。
java.util.ListgetOverlays()獲取Overlay列表。
ProjectiongetProjection()獲取屏幕像素坐標和經緯度對之間的轉換。
ViewgetZoomControls()已過時。
intgetZoomLevel()返回當前地圖的縮放級別。
booleanisSatellite()
booleanisStreetView()
booleanisTraffic()是否顯示交通流量。
protected voidonDetachedFromWindow()當被分離調用,清除縮放控制項。
protected voidonDraw(Canvas canvas)
voidonFocusChanged(boolean hasFocus, int direction, Rect
previouslyFocusedRect)當這個視圖的焦點狀態變化時被視圖系統調用。
booleanonKeyDown(int keyCode, KeyEvent event)把按鍵傳送到overlay。
booleanonKeyUp(int keyCode, KeyEvent event)把按鍵傳送到overlay。
protected voidonLayout(boolean flag, int l, int t, int r, int b)
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)
voidonRestoreInstanceState(Bundle state)把MapView的狀態恢復到一個Bundle。
voidonSaveInstanceState(Bundle state)把MapView的狀態存儲到一個Bundle中。
protected voidonSizeChanged(int w, int h, int oldw, int
oldh)重新調整地圖對象的尺寸。
booleanonTouchEvent(MotionEvent
event)首先把touch事件傳送到overlay,如果它不處理它們,就把事件再傳送到手勢探測器,然後分發探測到的手勢。
booleanonTrackballEvent(MotionEvent
event)把trackball事件首先傳送到overlay,如果它們不處理消息,嘗試取平移和點擊。
voidonWindowFocusChanged(boolean hasFocus)當包含這個視圖的窗口得到或是去焦點時被調用。
voidpreLoad()
voidsetDrawOverlayWhenZooming(boolean bDraw)設置在縮放動畫過程中是否繪制overlay,默認為不繪制。
如果繪制,在覆蓋物很多的情況下效率會有損失。 自1.1版本之後支持。
voidsetBuiltInZoomControls(boolean on)設置是否啟用內置的縮放控制項。
voidsetReticleDrawMode(com..mapapi.MapView.ReticleDrawMode
mode)暫不支持。
voidsetSatellite(boolean on)設置是否打開衛星圖。
voidsetStreetView(boolean on)暫不支持。
voidsetTraffic(boolean on)設置是否打開交通流量圖層。
voidregMapViewListener(BMapManager bmapMan, MKMapViewListener
listener)注冊地圖顯示事件監聽器。
<5>MyLocationOverlay
一個負責顯示用戶當前位置的Overlay。
Overlay是一個覆蓋,它繪制用戶當前在地圖上的位置(精準度),和/或一個嵌入的指南針。子類能覆蓋方法dispatchTap()去處理對當前位置的點擊。
為了開啟這個overlay的功能,需要去調用enableMyLocation()和/或enableCompass(),
或調用Activity中的Activity.onResume()方法。記住,當在後台是,要在Activity中的Activity.onPause()方法中調用相應的disableMyLocation()和/或disableCompass()關閉這個功能。
返回類型方法
voiddisableCompass()關閉指南針的更新。
voiddisableMyLocation()停止位置更新。
protected booleandispatchTap()在「我的位置」坐標上處理點擊事件。
booleandraw(Canvas canvas, MapView mapView, boolean shadow, long
when)繪制方法。
protected voiddrawCompass(android.graphics.Canvas canvas, float
bearing)繪制指南針。
protected voiddrawMyLocation(Canvas canvas, MapView mapView,
android.location.Location lastFix, GeoPoint myLocation, long when)繪制「我的位置」點。
booleanenableCompass()開啟指南針更新功能。
booleanenableMyLocation()嘗試開啟MyLocation功能,並向MKLocationManager.GPS_PROVIDER和MKLocationManager.NETWORK_PROVIDER注冊更新。
LocationgetLastFix()返回一個位置,對應於最近設定的用戶位置。
GeoPointgetMyLocation()返回一個GeoPoint,對應於一個最近設定的用戶位置。
floatgetOrientation()返回最近設定的的指南針朝向。
booleanisCompassEnabled()檢查指南針小部件是否被顯示。
booleanisMyLocationEnabled()
voidonAccuracyChanged(Sensor sensor, int accuracy)
voidonLocationChanged(Location location)監聽並獲取位置更新。
voidonProviderDisabled(java.lang.String provider)
voidonProviderEnabled(java.lang.String provider)
voidonSensorChanged(SensorEvent event)當指南針的值變換時,由SensorManager調用。
booleanonSnapToItem(int x, int y, android.graphics.Point snapPoint, MapView
mapView)檢查給定的(x,y)是否和引起當前行為(如縮放)的item足夠靠近。
booleanonTap(GeoPoint p, MapView mapView)檢查點擊的位置是否非常接近於當前的位置(如果已知)。
booleanrunOnFirstFix(java.lang.Runnable
runnable)把一個runnable加入隊列,一旦收到一個位置信息,這個runnable就被執行。
<6>Overlay
Overlay是一個基類,它表示可以顯示在地圖上方的覆蓋overlay。
添加一個overlay時,從這個基類派生出一個子類,創建一個實例,然後把它加入到一個列表中。這個列表通過調用MapView.getOverlays()得到。為了允許用戶觸摸去對齊一個點,子類應當實現Overlay.Snappable介面。
返回類型方法
booleandraw(Canvas canvas, MapView mapView, boolean
shadow)在地圖上繪制overlay。
booleandraw(Canvas canvas, MapView mapView, boolean shadow, long
when)專門繪制動畫overlay的調用。
protected static voiddrawAt(Canvas canvas, Drawable drawable, int x, int y,
boolean bShadow)在某個偏移位置畫一個Drawable的便捷方法。
booleanonKeyDown(int keyCode, KeyEvent event, MapView
mapView)處理一個按鍵被按下的事件。
booleanonKeyUp(int keyCode, KeyEvent event, MapView mapView)處理一個按鍵放開事件。
booleanonTap(GeoPoint p, MapView mapView)處理一個「點擊」事件。
booleanonTouchEvent(MotionEvent e, MapView mapView)處理一個觸摸事件。
booleanonTrackballEvent(MotionEvent e, MapView mapView)處理一個軌跡球事件。
⑷ 關於百度地圖API聚合問題。待高手指教。
這個跟javascript函數作用域有關系的,因為「click」事件只會當你點擊時,才會觸發。而這個時候ifonWin 顯然是最後一個對象了。所以你要在mypt.addEventListener("click", function(){this.openInfoWindow(createInfoWin(i));});
function createInfoWin(i){
return new BMap.InfoWindow("我的地理位置:<br>我是第【"+i+"】個點");
},
這樣應該行了
⑸ 百度地圖聚合功能自定義聚合文字
研究網路地圖聚合源碼發現,如果打算自定義文字需要修改兩處:
一、修改 BMapLib.MarkerClusterer.js 插件中 Cluster.prototype.updateClusterMarker 方法,實現過程如下:
方法中: this._clusterMarker.setText(this._markers.length); 表示, 聚合點顯示的文字內容是 當前 Cluster 類 _markers 屬性 的 長度;
二、修改 TextIconOverlay.js 中的 構造方法 和 樣式方法
查看 TextIconOverlay.js 的源碼發現, text 只支持 數字類型的值,而且和 styles 屬性綁定,需要修改constructor 方法, 和 設置屬性的方法。
如上,知道了聚合的文字是 Cluster.prototype.updateClusterMarker 方法 , 那麼我們需要進行以下步驟:
通過查看網路地圖聚合源碼,發現 Cluster 類調用了 marker 的 getPosition 和 getMap 方法,我們需要自定義這倆方法如下:
最終,我們實現了自定義 網路地圖點聚合文字 信息。
附Github: https://github.com/sphenginx/vue-slider
類 BMapLib.MarkerClusterer
⑹ 微信小程序地圖聚合以及軌跡回放
公司項目需要實現小程序地圖的聚合以及軌跡回放,效果要與PC端一直。其中,軌跡回放還需要包含開始、暫停、結束三個按鈕。效果圖如下:
1、添加圖標
2、聚合,其中,如果發現聚合點不開的情況,可以把grikSize的值設置小一點,默認值為60
3、點擊圖標,獲取addMarker設置的 Id 值
4、定時畫線條
同時,畫線條之前,還需要清除按鈕