diff --git a/supercluster.min.js b/libraries/supercluster.min.js
similarity index 100%
rename from supercluster.min.js
rename to libraries/supercluster.min.js
diff --git a/MarkerCluster.js b/src/MarkerCluster.js
similarity index 52%
rename from MarkerCluster.js
rename to src/MarkerCluster.js
index 1674d00..2f87812 100644
--- a/MarkerCluster.js
+++ b/src/MarkerCluster.js
@@ -1,23 +1,21 @@
-requirejs.config({
- baseUrl: '.',
- paths: {
- supercluster: '../supercluster.min',
- }
-});
+define(['../libraries/supercluster.min', '../libraries/WorldWind/WorldWind'], function (supercluster, wwe) {
-define(['supercluster'], function (supercluster) {
-
- var MarkerCluster = function (wwd, markers, options) {
+ var MarkerCluster = function (globe, markers, options) {
if (!options) {
options = {
- levels: 23
+ levels: 9,
+ smooth: true
}
}
+
+ this.options = options;
this.placemarks = [];
this.layer = new WorldWind.RenderableLayer("MarkerCluster");
- if (wwd) {
- wwd.addLayer(this.layer);
+ if (globe) {
+ globe.addLayer(this.layer);
}
+ this.globe = globe;
+ this.zoomLevel = 0;
this.zoomLevels = options.levels;
this.levels = [];
this.maxReached = this.zoomLevels;
@@ -37,7 +35,7 @@ define(['supercluster'], function (supercluster) {
MarkerCluster.prototype.bindNavigator = function () {
- var navigator = wwd.navigator;
+ var navigator = this.globe.navigator;
var LookAtNavigator = WorldWind.LookAtNavigator;
var self = this;
@@ -57,80 +55,169 @@ define(['supercluster'], function (supercluster) {
navigator.handleWheelEvent = function (event) {
LookAtNavigator.prototype.handleWheelEvent.apply(this, arguments);
- var range = this.range;
+ if (self.options.smooth) {
+ self.globe.goToAnimator.travelTime = 600;
+ if (!this.busy) {
+ var normalizedDelta;
+ if (event.deltaMode == WheelEvent.DOM_DELTA_PIXEL) {
+ normalizedDelta = event.deltaY;
+ } else if (event.deltaMode == WheelEvent.DOM_DELTA_LINE) {
+ normalizedDelta = event.deltaY * 40;
+ } else if (event.deltaMode == WheelEvent.DOM_DELTA_PAGE) {
+ normalizedDelta = event.deltaY * 400;
+ }
+ normalizedDelta *= 5;
+ var scale = 1 + (normalizedDelta / 1000);
+ var nav = this;
+
+ var lat = this.lookAtLocation.latitude;
+ var lng = this.lookAtLocation.longitude;
+ var alt = this.range * scale;
+ var newPosition = new WorldWind.Position(lat, lng, alt);
+ nav.busy = true;
+ this.worldWindow.goTo(newPosition, function () {
+ nav.busy = false;
+ });
+ this.applyLimits();
+ this.worldWindow.redraw();
+ }
+ }
+ var range = this.range;
var res;
- if (range > 10000) {
- res = convertToRange(range, [10000, 6165728], [0, 16]);
- res = Math.round(16 - res);
+
+
+ var ranges = [100000000,5294648, 4099739, 2032591, 1650505, 800762, 500000, 100000, 7000];
+
+ console.log(range);
+ if (range >= ranges[0]) {
+ res = 1;
+ } else if (range <= ranges[ranges.length - 1]) {
+ res = ranges.length;
} else {
- res = convertToRange(range, [500, 10000], [16, 23]);
- res = Math.round(23 + 16 - res);
+ for (var x = 0; x < ranges.length; x++) {
+ if (range <= ranges[x] && range >= ranges[x + 1]) {
+ res = x + 1;
+ break;
+ }
+ }
}
+ /*
+
+ if (range > 10000) {
+ res = convertToRange(range, [10000, 5000000], [0, 11]);//0-16
+ res = Math.round(16 - res);
+ } else {
+ res = convertToRange(range, [500, 10000], [11, 16]);//16-23
+ res = Math.round(16 - 11 + res);//23+16
+ }
+ */
+ //res = Math.round(convertToRange(res, [0, 16], [0, self.zoomLevels]));//23
- res = Math.round(convertToRange(res, [0, 23], [0, self.zoomLevels]));
+ self.oldZoom = self.zoomLevel || 0;
+ self.zoomLevel = res;
console.log(res);
- self.hideAll();
+
if (res < self.minReached) {
+ self.hideAll();
self.showZoomLevel(self.minReached);//possible overhead
- }else if (res > self.maxReached) {
- self.showZoomLevel(self.maxReached);
- }else{
- self.showZoomLevel(res);
+ } else if (res > self.maxReached) {
+ self.hideAll();
+ self.showInRange(self.maxReached);
+ //self.showZoomLevel(self.maxReached);
+ } else {
+ if (self.levels[res].length != self.levels[self.oldZoom].length) {
+ // self.showZoomLevel(res);
+ self.hideAll();
+ self.showInRange(res);
+ self.globe.redraw();//dynamic
+ }
+
+ //self.hideOutside(res);
+
+
}
};
};
-
+ MarkerCluster.prototype.showInRange = function (level) {
+ var h = $("#canvasOne").height();
+ var v = [];
+ if (wwd.pickTerrain(new WorldWind.Vec2(h / 2, h / 2)).objects && wwd.pickTerrain(new WorldWind.Vec3(0, 0, 0)).objects [0]) {
+
+ var center = wwd.pickTerrain(new WorldWind.Vec2(h / 2, h / 2));
+
+ center = center.objects[0].position;
+
+ var l = this.globe.navigator.range / Math.cos(Math.PI / 8);
+ var base = Math.sqrt(Math.pow(l, 2) - Math.pow(this.globe.navigator.range, 2));
+
+ base = base / 100000;
+ var minLat = center.latitude - base;
+ var maxLat = center.latitude + base;
+ var minLng = center.longitude - base;
+ var maxLng = center.longitude + base;
+
+ var bb = {
+ ix: minLat,
+ iy: minLng,
+ ax: maxLat,
+ ay: maxLng
+ };
+ for (var x = 0; x < this.levels[level].length; x++) {
+ var point = this.placemarks[this.levels[level][x]];
+ var p = point.position;
+
+ if (bb.ix <= p.latitude && p.latitude <= bb.ax && bb.iy <= p.longitude && p.longitude <= bb.ay) {
+ this.show(point);
+ }
+ }
+ } else {
+ this.showZoomLevel(level);
+ }
+ };
MarkerCluster.prototype.generateCluster = function () {
- var myJSON = {
- "type": "FeatureCollection",
- "features": []
- };
+ var myJSON = '{"type": "FeatureCollection","features":[';
newFeature = function (position) {
- return {
- "type": "Feature",
- "properties": {},
- "geometry": {
- "type": "Point",
- "coordinates": [
- position.longitude,
- position.latitude
- ]
- }
- }
+ return '{"type": "Feature","properties": {},"geometry": {"type": "Point","coordinates": [' +
+ +position.longitude + ',' +
+ +position.latitude + ']}}';
};
- this.placemarks.forEach(function (p) {
- myJSON.features.push(newFeature(p.position))
+ this.placemarks.forEach(function (p, i) {
+ myJSON += newFeature(p.position) + ",";
});
+ myJSON = myJSON.slice(0, -1);
+ myJSON += ']}';
- this.generateJSONCluster(myJSON);
+ this.generateJSONCluster(JSON.parse(myJSON));
+ this.showZoomLevel(this.zoomLevel);
};
MarkerCluster.prototype.generateJSONCluster = function (geojson) {
-
+ var self = this;
cluster = supercluster({
log: true,
- radius: 10060,//should be dynamic
- extent: 256,
- maxZoom: 23
+ radius: 60,//should be dynamic
+ extent: 128,
+ maxZoom: self.zoomLevels
}).load(geojson.features);
var end = this.zoomLevels;
for (var y = 0; y <= end; y++) {
- var res = cluster.getClusters([-180, -90, 180, 90], y);
+ var res = cluster.getClusters([-180, -90, 180, 90], y + 1);
var self = this;
if (this.minReached == 0 && res.length > 0) {
this.minReached = y;
}
- if (y > 0 && res.length > 0 && res.length == this.levels[y - 1].length) {
+ //if (y > 0 && res.length > 0 && res.length == this.levels[y - 1].length) {
+ if (res.length == geojson.features.length && y > 0 && res.length > 0 && res.length == this.levels[y - 1].length) {
this.maxReached = y - 1;
break;
} else {
@@ -148,6 +235,9 @@ define(['supercluster'], function (supercluster) {
});
}
}
+ if (!this.maxReached) {
+ this.maxReached = end;
+ }
};
MarkerCluster.prototype.createZoomClusters = function (n) {
@@ -182,14 +272,17 @@ define(['supercluster'], function (supercluster) {
MarkerCluster.prototype.generatePlacemarks = function (coordinates, placemarkAttributes, options) {
var lat, lng, alt;
- if (coordinates[0] && coordinates[1]) {
+ if (typeof(coordinates[0]) !== "undefined" && typeof(coordinates[1]) !== "undefined") {
lat = coordinates[0];
lng = coordinates[1];
- } else if (coordinates.lat && coordinates.lng) {
+ } else if (typeof(coordinates.lat) !== "undefined" && typeof(coordinates.lng) !== "undefined") {
lat = coordinates.lat;
lng = coordinates.lng;
+ } else {
+ throw ("Error in coordinates");
}
+
if (!options) {
options = {};
}
@@ -202,7 +295,7 @@ define(['supercluster'], function (supercluster) {
if (!placemarkAttributes) {
placemarkAttributes = new WorldWind.PlacemarkAttributes(null);
- placemarkAttributes.imageScale = 5;
+ placemarkAttributes.imageScale = 2;
placemarkAttributes.imageOffset = new WorldWind.Offset(
WorldWind.OFFSET_FRACTION, 0.3,
WorldWind.OFFSET_FRACTION, 0.0);
@@ -211,7 +304,7 @@ define(['supercluster'], function (supercluster) {
WorldWind.OFFSET_FRACTION, 0.5,
WorldWind.OFFSET_FRACTION, 1.0);
placemarkAttributes.labelAttributes.color = WorldWind.Color.YELLOW;
- placemarkAttributes.labelAttributes.font.size = 100;
+ placemarkAttributes.labelAttributes.font.size = 40;
}
@@ -219,8 +312,9 @@ define(['supercluster'], function (supercluster) {
placemark.label = options.label ? options.label : "MyMarker " + lat + " - " + lng;
placemark.altitudeMode = options.altitudeMode ? options.altitudeMode : WorldWind.RELATIVE_TO_GROUND;
placemarkAttributes = new WorldWind.PlacemarkAttributes(placemarkAttributes);
- placemarkAttributes.imageSource = options.imageSource ? options.imageSource : WorldWind.configuration.baseUrl + "images/pushpins/plain-blue.png";
+ placemarkAttributes.imageSource = options.imageSource ? options.imageSource : WorldWind.configuration.baseUrl + "images/pushpins/push-pin-red.png";
placemark.attributes = placemarkAttributes;
+ placemark.eyeDistanceScaling = true;
placemark.eyeDistanceScalingLabelThreshold = 1e20;
if (options.enabled == false) {
@@ -260,7 +354,7 @@ define(['supercluster'], function (supercluster) {
MarkerCluster.prototype.hideAll = function () {
- for (var x = 0; x <= this.zoomLevels && x < this.maxReached; x++) {
+ for (var x = 0; x <= this.zoomLevels && x <= this.maxReached; x++) {
this.hideZoomLevel(x);
}
};
@@ -281,6 +375,21 @@ define(['supercluster'], function (supercluster) {
}
};
+ MarkerCluster.prototype.hideOutside = function (zoomLevel) {
+ var count = 0;
+ if (this.levels[zoomLevel]) {
+ for (var x = 0; x < this.levels[zoomLevel].length; x++) {
+ if (this.placemarks[this.levels[zoomLevel][x]].imageBounds) {
+ if (!this.placemarks[this.levels[zoomLevel][x]].isVisible(wwd.drawContext)) {
+ this.placemarks[this.levels[zoomLevel][x]].enabled = false;
+ count++;
+ }
+ }
+ }
+ }
+ console.log(count);
+ };
+
MarkerCluster.prototype.removePlacemark = function (placemark) {
this.layer.removeRenderable(placemark);
this.placemarks.splice(this.placemarks.indexOf(placemark));
diff --git a/test/MarkerCluster.test.js b/test/MarkerCluster.test.js
index 40f299a..b964cce 100644
--- a/test/MarkerCluster.test.js
+++ b/test/MarkerCluster.test.js
@@ -1,11 +1,15 @@
-define(['MarkerCluster','libraries/WorldWind/WorldWind'], function (MarkerCluster,WorldWind) {
-
+define(['src/MarkerCluster', 'libraries/WorldWind/WorldWind'], function (MarkerCluster, WorldWind) {
describe('MarkerCluster test', function () {
it('Example test', function () {
-
- var m = new MarkerCluster();
- var l=1;
+ var wwd = {
+ addLayer: function () {
+ },
+ navigator: function () {
+ }
+ };
+ var m = new MarkerCluster(wwd);
+ var l = 1;
m.setLayer(l);
expect(m.layer).toBe(1);
});
diff --git a/karma.conf.js b/test/karma.conf.js
similarity index 79%
rename from karma.conf.js
rename to test/karma.conf.js
index fdf43b4..8eaa499 100644
--- a/karma.conf.js
+++ b/test/karma.conf.js
@@ -1,14 +1,15 @@
module.exports = function (config) {
config.set({
- basePath: '',
+ basePath: '../',
frameworks: ['jasmine', 'requirejs'],
files: [
'test/test-main.js',
{pattern: 'test/*.js', included: false},
- {pattern: 'MarkerCluster.js', included: false},
+ {pattern: 'src/MarkerCluster.js', included: false},
+ {pattern: 'libraries/supercluster.min.js', included: false},
{pattern: 'libraries/WorldWind/*.js', included: false},
{pattern: 'libraries/WorldWind/**/*.js', included: false},
],