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.
Post Reply
User avatar
jmamy
Posts: 31
Joined: Wed Jul 02, 2014 7:21 am

Ajaxmap grouping function

Post by jmamy »

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.
AndreasJunghans
Posts: 13
Joined: Tue May 13, 2014 3:28 pm

Re: Ajaxmap grouping function

Post by AndreasJunghans »

Hi there,

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

Regards,

Andreas

Code: Select all

<!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>
User avatar
jmamy
Posts: 31
Joined: Wed Jul 02, 2014 7:21 am

Re: Ajaxmap grouping function

Post by jmamy »

Exactly what I was looking for!
Thanks you very much.
Post Reply