Ajaxmap grouping function

This forum deals with any kind of web based client technology, whether it is the well known java script based Ajax servlet or the upcoming approaches such as Leaflet, OpenLayers and so on.

Ajaxmap grouping function

Postby jmamy » Mon Apr 13, 2015 8:13 am

Hello community,

I'd like to know, if one of you already developed an ajaxmap function which can group various items on the map, depending on the zoom level.
Something like "Client-side drawing of Points of Interest (Leaflet)" on the PTV code sample browser.

Thanks in advance.
User avatar
jmamy
 
Posts: 29
Joined: Wed Jul 02, 2014 7:21 am

Re: Ajaxmap grouping function

Postby AndreasJunghans » Fri Apr 17, 2015 1:10 pm

Hi there,

here's a clustering example with 1000 randomly-generated elements.

Regards,

Andreas


javascript code
<!DOCTYPE html>
<html>
<head>
<!--[if IE]><script type="text/javascript" src="webcomponent/script/excanvas.js"></script><![endif]-->
<script type="text/javascript" src="webcomponent/script/qooxdoo/script/qx-transport.js"></script>
<script type="text/javascript" src=".qxrpc"></script>
<script type="text/javascript" src="webcomponent/script/map.js"></script>

<script type="text/javascript">
var map;
var elements;

function init() {
var container =
document.getElementById("mapContainer");
map =
new com.ptvag.webcomponent.map.Map(container);
map.addEventListener("historyChanged", performClustering);
window.onresize = function() {
map.updateSize();
};

var minX = 4300000;
var maxX = 4500000;
var minY = 5400000;
var maxY = 5700000;
elements = [];
for (var i = 0; i < 1000; ++i) {
var x = minX + (maxX - minX)*Math.random();
var y = minY + (maxY - minY)*Math.random();
elements.push({x:x, y:y});
}
}

function performClustering() {
var vector = com.ptvag.webcomponent.map.vector;
var CoordUtil = com.ptvag.webcomponent.map.CoordUtil;
var VectorLayerClass = com.ptvag.webcomponent.map.layer.VectorLayer;
var vectorLayer = map.getLayer("vector");
vectorLayer.startBulkMode();
vectorLayer.removeElement("markers");
var markers = new vector.AggregateElement("markers");
vectorLayer.addElement(markers);

var zoom = map.getZoom();
var gridWidthPix = 64;
var clusterMarkerWidthPix = 24;
var clusterMarkerHeightPix = 24;
var suPerPixel = CoordUtil.getSmartUnitsPerPixel(zoom);
var gridWidthSU = suPerPixel*gridWidthPix;
var clusterMarkerWidthSU = suPerPixel*clusterMarkerWidthPix;
var clusterMarkerHeightSU = suPerPixel*clusterMarkerHeightPix;
var clusters = {};
var elementCount = elements.length;
for (var i = 0; i < elementCount; ++i) {
var element = elements[i];
var x = element.x;
var y = element.y;
var gridX = Math.floor(x/gridWidthSU);
var gridY = Math.floor(y/gridWidthSU);
var clusterKey = gridX + "_" + gridY;
var cluster = clusters[clusterKey];
if (cluster == null) {
cluster = {
members: [element],
x: x, y: y,
gridX: gridX, gridY: gridY
};
clusters[clusterKey] = cluster;
} else {
var oldMemberCount = cluster.members.length;
var newMemberCount = oldMemberCount + 1;
cluster.x = (cluster.x*oldMemberCount + x)/newMemberCount;
cluster.y = (cluster.y*oldMemberCount + y)/newMemberCount;
cluster.members.push(element);
}
}

for (var i = 0; i < 2; ++i) {
for (var key in clusters) {
if (clusters.hasOwnProperty(key)) {
var cluster = clusters[key];
var memberCount = cluster.members.length;
if (memberCount == 0) {
continue;
}
var x = cluster.x;
var y = cluster.y;
var gridX = cluster.gridX;
var gridY = cluster.gridY;
var neighborKeys = [
(gridX - 1) + "_" + (gridY - 1),
(gridX - 1) + "_" + gridY,
(gridX - 1) + "_" + (gridY + 1),
gridX + "_" + (gridY - 1),
gridX + "_" + (gridY + 1),
(gridX + 1) + "_" + (gridY - 1),
(gridX + 1) + "_" + gridY,
(gridX + 1) + "_" + (gridY + 1)
];
var neighborKeyCount = neighborKeys.length;
for (var j = 0; j < neighborKeyCount; ++j) {
var neighborKey = neighborKeys[j];
var neighbor = clusters[neighborKey];
if (neighbor == null) {
continue;
}
var neighborMemberCount = neighbor.members.length;
if (neighborMemberCount == 0) {
continue;
}
var nx = neighbor.x;
var dx = nx - x;
if (Math.abs(dx) < clusterMarkerWidthSU) {
var ny = neighbor.y;
var dy = ny - y;
if (Math.abs(dy) < clusterMarkerHeightSU) {
if (memberCount >= neighborMemberCount) {
var newCount = memberCount + neighborMemberCount;
cluster.x = (cluster.x*memberCount +
neighbor.x*neighborMemberCount)/newCount;
cluster.y = (cluster.y*memberCount +
neighbor.y*neighborMemberCount)/newCount;
cluster.members = cluster.members.concat(
neighbor.members);
neighbor.members = [];
}
}
}
}
}
}
}

for (var key in clusters) {
if (clusters.hasOwnProperty(key)) {
var cluster = clusters[key];
var memberCount = cluster.members.length;
if (memberCount == 0) {
continue;
}
if (memberCount == 1) {
var marker = new vector.ImageMarker(cluster.x, cluster.y);
markers.addElement(marker);
} else {
var circle = new vector.Circle(cluster.x, cluster.y,
"#FF0000", 24);
markers.addElement(circle);
var text = new vector.Text(cluster.x, cluster.y,
"#FFFFFF", 9,
VectorLayerClass.ALIGN_MID_HORIZ +
VectorLayerClass.ALIGN_MID_VERT,
"" + memberCount);
markers.addElement(text);
}
}
}

vectorLayer.endBulkMode();
}

qxp.dev.log.Logger.ROOT_LOGGER.setMinLevel(qxp.dev.log.Logger.LEVEL_INFO);
qxp.dev.log.Logger.getClassLogger(qxp.core.Init).setMinLevel(qxp.dev.log.Logger.LEVEL_ERROR);
</script>
</head>

<body onload="init()">
<div id="mapContainer"
style="position:absolute;left:0;top:0;right:0;bottom:0">
</div>
</body>
</html>
AndreasJunghans
 
Posts: 11
Joined: Tue May 13, 2014 3:28 pm

Re: Ajaxmap grouping function

Postby jmamy » Fri Apr 17, 2015 1:34 pm

Exactly what I was looking for!
Thanks you very much.
User avatar
jmamy
 
Posts: 29
Joined: Wed Jul 02, 2014 7:21 am


Return to PTV Webclients (Ajax, Leaflet, OpenLayers, WMS, ...) (Admin=LNM)