[Pkg-javascript-commits] [leaflet-markercluster] 151/219: Externalized bound and wLatLng computations
Jonas Smedegaard
dr at jones.dk
Sat May 7 09:39:29 UTC 2016
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository leaflet-markercluster.
commit 7bbf70e478894355f886967494fe33401d7c2890
Author: ghybs <ghybs1 at gmail.com>
Date: Tue Oct 20 14:58:36 2015 +0400
Externalized bound and wLatLng computations
for cluster._addChild and MCG._removeLayer, only the cluster position is set.
_bounds and _wLatLng must be recomputed by calling _recalculateBounds manually within each method that uses the 2 above private methods.
Also re-factored _recalculateBounds to compute the weighted position more simply.
---
src/MarkerCluster.js | 102 ++++++++++++++++++++++++++++++----------------
src/MarkerClusterGroup.js | 49 +++++++++++++++++-----
2 files changed, 106 insertions(+), 45 deletions(-)
diff --git a/src/MarkerCluster.js b/src/MarkerCluster.js
index 2ce3190..90d387f 100644
--- a/src/MarkerCluster.js
+++ b/src/MarkerCluster.js
@@ -11,6 +11,7 @@ L.MarkerCluster = L.Marker.extend({
this._childClusters = [];
this._childCount = 0;
this._iconNeedsUpdate = true;
+ this._boundsNeedUpdate = true;
this._bounds = new L.LatLngBounds();
@@ -99,7 +100,9 @@ L.MarkerCluster = L.Marker.extend({
_addChild: function (new1, isNotificationFromChild) {
this._iconNeedsUpdate = true;
- this._expandBounds(new1);
+
+ this._boundsNeedUpdate = true;
+ this._setClusterCenter(new1);
if (new1 instanceof L.MarkerCluster) {
if (!isNotificationFromChild) {
@@ -119,34 +122,65 @@ L.MarkerCluster = L.Marker.extend({
}
},
- //Expand our bounds and tell our parent to
- _expandBounds: function (marker) {
- var addedCount,
- addedLatLng = marker._wLatLng || marker._latlng;
+ /**
+ * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position.
+ * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet.
+ * @private
+ */
+ _setClusterCenter: function (child) {
+ if (!this._cLatLng) {
+ // when clustering, take position of the first point as the cluster center
+ this._cLatLng = child._cLatLng || child._latlng;
+ }
+ },
- if (marker instanceof L.MarkerCluster) {
- this._bounds.extend(marker._bounds);
- addedCount = marker._childCount;
- } else {
- this._bounds.extend(addedLatLng);
- addedCount = 1;
+ _recalculateBounds: function () {
+ var markers = this._markers,
+ childClusters = this._childClusters,
+ latSum = 0,
+ lngSum = 0,
+ totalCount = this._childCount,
+ i, child, childLatLng, childCount;
+
+ this._bounds = new L.LatLngBounds();
+
+ // Case where all markers are removed from the map and we are left with just an empty _topClusterLevel.
+ if (totalCount === 0) {
+ return;
}
- if (!this._cLatLng) {
- // when clustering, take position of the first point as the cluster center
- this._cLatLng = marker._cLatLng || addedLatLng;
+ // Child markers.
+ for (i = 0; i < markers.length; i++) {
+ childLatLng = markers[i]._latlng;
+
+ this._bounds.extend(childLatLng);
+
+ latSum += childLatLng.lat;
+ lngSum += childLatLng.lng;
}
- // when showing clusters, take weighted average of all points as cluster center
- var totalCount = this._childCount + addedCount;
+ // Child clusters.
+ for (i = 0; i < childClusters.length; i++) {
+ child = childClusters[i];
- //Calculate weighted latlng for display
- if (!this._wLatLng) {
- this._latlng = this._wLatLng = new L.LatLng(addedLatLng.lat, addedLatLng.lng);
- } else {
- this._wLatLng.lat = (addedLatLng.lat * addedCount + this._wLatLng.lat * this._childCount) / totalCount;
- this._wLatLng.lng = (addedLatLng.lng * addedCount + this._wLatLng.lng * this._childCount) / totalCount;
+ // Re-compute child bounds and weighted position first if necessary.
+ if (child._boundsNeedUpdate) {
+ child._recalculateBounds();
+ }
+
+ this._bounds.extend(child._bounds);
+
+ childLatLng = child._wLatLng;
+ childCount = child._childCount;
+
+ latSum += childLatLng.lat * childCount;
+ lngSum += childLatLng.lng * childCount;
}
+
+ this._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount);
+
+ // Reset dirty flag.
+ this._boundsNeedUpdate = false;
},
//Set our markers position as given and add it to the map
@@ -344,20 +378,20 @@ L.MarkerCluster = L.Marker.extend({
}
},
- _recalculateBounds: function () {
- var markers = this._markers,
- childClusters = this._childClusters,
- i;
-
- this._bounds = new L.LatLngBounds();
- delete this._wLatLng;
+ /**
+ * Runs a function recursively on every child cluster, then on THIS cluster.
+ * @param runAtEveryLevel function to be called on each cluster. Takes as single argument the cluster to be processed.
+ * @private
+ */
+ _recursivelySimple: function (runAtEveryLevel) {
+ var childClusters = this._childClusters,
+ i = 0;
- for (i = markers.length - 1; i >= 0; i--) {
- this._expandBounds(markers[i]);
- }
- for (i = childClusters.length - 1; i >= 0; i--) {
- this._expandBounds(childClusters[i]);
+ for (; i < childClusters.length; i++) {
+ childClusters[i]._recursivelySimple(runAtEveryLevel);
}
+
+ return runAtEveryLevel(this);
},
diff --git a/src/MarkerClusterGroup.js b/src/MarkerClusterGroup.js
index f801547..492736e 100644
--- a/src/MarkerClusterGroup.js
+++ b/src/MarkerClusterGroup.js
@@ -105,6 +105,9 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
this._addLayer(layer, this._maxZoom);
+ // Re-calculate bounds must be done manually now.
+ this._topClusterLevel._recalculateBounds();
+
//Work out what is visible
var visibleLayer = layer,
currentZoom = this._map.getZoom();
@@ -160,6 +163,9 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
//Remove the marker from clusters
this._removeLayer(layer, true);
+ // Bounds and weighted position must be done manually now.
+ this._topClusterLevel._recalculateBounds();
+
if (this._featureGroup.hasLayer(layer)) {
this._featureGroup.removeLayer(layer);
if (layer.clusterShow) {
@@ -222,7 +228,12 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
chunkProgress(offset, layersArray.length, (new Date()).getTime() - started);
}
+ // Completed processing all markers.
if (offset === layersArray.length) {
+
+ // Refresh bounds and weighted positions.
+ this._topClusterLevel._recalculateBounds();
+
//Update the icons of all those visible clusters that were affected
this._featureGroup.eachLayer(function (c) {
if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) {
@@ -303,6 +314,9 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
}
}
+ // Re-compute bounds and weighted positions.
+ this._topClusterLevel._recalculateBounds();
+
//Fix up the clusters and markers on the map
this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);
@@ -512,6 +526,9 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
l = this._needsClustering;
this._needsClustering = [];
this.addLayers(l);
+
+ // Re-compute bounds and weighted positions.
+ this._topClusterLevel._recalculateBounds();
},
//Overrides FeatureGroup.onRemove
@@ -558,6 +575,23 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
}
},
+ /**
+ * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom.
+ * @param marker to be removed from _gridUnclustered.
+ * @param z integer bottom start zoom level (included)
+ * @private
+ */
+ _removeFromGridUnclustered: function (marker, z) {
+ var map = this._map,
+ gridUnclustered = this._gridUnclustered;
+
+ for (; z >= 0; z--) {
+ if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) {
+ break;
+ }
+ }
+ },
+
//Internal function for removing a marker from everything.
//dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions)
_removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) {
@@ -568,11 +602,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
//Remove the marker from distance clusters it might be in
if (removeFromDistanceGrid) {
- for (var z = this._maxZoom; z >= 0; z--) {
- if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) {
- break;
- }
- }
+ this._removeFromGridUnclustered(marker, this._maxZoom);
}
//Work our way up the clusters removing them as we go if required
@@ -585,6 +615,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
while (cluster) {
cluster._childCount--;
+ cluster._boundsNeedUpdate = true;
if (cluster._zoom < 0) {
//Top level, do nothing
@@ -610,7 +641,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
}
}
} else {
- cluster._recalculateBounds();
+ //cluster._recalculateBounds();
if (!dontUpdateMap || !cluster._icon) {
cluster._updateIcon();
}
@@ -842,11 +873,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
parent._addChild(lastParent);
//Remove closest from this zoom level and any above that it is in, replace with newCluster
- for (z = zoom; z >= 0; z--) {
- if (!gridUnclustered[z].removeObject(closest, this._map.project(closest.getLatLng(), z))) {
- break;
- }
- }
+ this._removeFromGridUnclustered(closest, zoom);
return;
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/leaflet-markercluster.git
More information about the Pkg-javascript-commits
mailing list