user1211577
user1211577

Reputation:

Draw Rectangles in Area on Google Maps

I'm drawing an area on Google Maps using the Geometry API. I want to know if it is possible to draw a repeating element onto an area that is dynamic in size?

For example, if I draw my area to look like this:

enter image description here

Then I want to be able to hit 'Next Step' and see something like this, with the rectangles drawn in the area, but only if they will fit. i.e., they have to be 'full' rectangles, not part rectangles:

enter image description here

The only problem is, I'm not entirely sure how to go about this. I would use HTML5 <canvas> but unfortunately, this needs to be as browser-friendly as possible, but if it has to be <canvas> then so be it!

Upvotes: 5

Views: 7553

Answers (2)

wf9a5m75
wf9a5m75

Reputation: 6158

@Joshua M

Sorry for keeping you wait. Ok, the new code is below. You can specify the small box size at var boxSize = new google.maps.Size(10, 20);


<!DOCTYPE html>
<html>
  <head>
    <script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry"></script>
    <script type='text/javascript'>
      var mapCanvas, boxes = new google.maps.MVCArray();
      function initialize() {
        var mapDiv = document.getElementById("map_canvas");
        mapCanvas = new google.maps.Map(mapDiv, {
          center : new google.maps.LatLng(37.422191,-122.084585),
          mapTypeId : google.maps.MapTypeId.SATELLITE,
          zoom : 19,
          tilt : 0
        });


        //Encoded path
        var encodedPath = "eblcFnuchVv@D@q@P?a@eD]AC~@b@DCz@a@A";
        var points = google.maps.geometry.encoding.decodePath(encodedPath);

        //Draw a polygon
        var polygonOpts = {
          paths : points,
          strokeWeight : 6,
          strokeColor : "#FF0000",
          strokeOpacity : 1,
          //fillColor : "blue",
          fillOpacity : 0,
          map : mapCanvas,
          editable : true
        };
        var poly = new google.maps.Polygon(polygonOpts);


        var proc = function() {
          onPolygonComplete(poly);
        };
        google.maps.event.addListener(mapCanvas, "projection_changed", proc);
        google.maps.event.addListener(poly.getPath(), 'insert_at', proc);
        google.maps.event.addListener(poly.getPath(), 'remove_at', proc);
        google.maps.event.addListener(poly.getPath(), 'set_at', proc);
      }

      function onDrawMgr_complete(polygon) {
        var path = polygon.getPath();
        console.log(google.maps.geometry.encoding.encodePath(path));
      }

      function onPolygonComplete(polygon) {
        var bounds, paths, sw, ne, ystep, xstep, boxH, boxW, posArry, flag, pos, x, y, i, box;

        //Delete old boxes.
        boxes.forEach(function(box, i) {
          box.setMap(null);
          delete box;
        });

        //Calculate the bounds that contains entire polygon.
        bounds = new google.maps.LatLngBounds();
        paths = polygon.getPath();
        paths.forEach(function(latlng, i) {
          bounds.extend(latlng);
        });

        var projection = mapCanvas.getProjection();
        var zoom = mapCanvas.getZoom();
        var powBase = Math.pow(2, zoom);

        //Calculate the small box size.
        sw = bounds.getSouthWest();
        ne = bounds.getNorthEast();
        var swPoint = projection.fromLatLngToPoint(sw);
        var nePoint = projection.fromLatLngToPoint(ne);
        var boxSize = new google.maps.Size(10, 20); //in pixels.
        boxSize.width /= powBase;
        boxSize.height /= powBase;
        var maxX = Math.floor(Math.abs((swPoint.x - nePoint.x)) / boxSize.width);
        var maxY = Math.floor(Math.abs((swPoint.y - nePoint.y)) / boxSize.height);


        for ( y = 0; y < maxY; y++) {
          for (x = 0; x < maxX; x++) {
            //Detect that polygon is able to contain a small box.
            bounds = new google.maps.LatLngBounds();
            posArry = [];
            posArry.push(new google.maps.Point(swPoint.x + boxSize.width * x, swPoint.y - boxSize.height * y));
            posArry.push(new google.maps.Point(swPoint.x + boxSize.width * x, swPoint.y - boxSize.height * (y + 1)));
            posArry.push(new google.maps.Point(swPoint.x + boxSize.width * (x + 1), swPoint.y - boxSize.height * y));
            posArry.push(new google.maps.Point(swPoint.x + boxSize.width * (x + 1), swPoint.y - boxSize.height * (y + 1)));

            var flag = true;
            for (var i = 0; i < posArry.length; i++) {
              pos = projection.fromPointToLatLng(posArry[i]);
              if (flag) {
                flag = google.maps.geometry.poly.containsLocation(pos, polygon);
                bounds.extend(pos);
              }
            }

            if (flag) {
              box = new google.maps.Rectangle({
                bounds : bounds,
                map : mapCanvas,
                strokeColor : 'green',
                strokeOpacity : 1,
                strokeWeight : 1,
                fillColor : 'yellow',
                fillOpacity : 0.5,
                clickable : false
              });
              boxes.push(box);
            }
          }
        }
      }


      google.maps.event.addDomListener(window, "load", initialize);
    </script>
    <style type="text/css">
      window,html,#map_canvas{
        width : 700px;
        height : 500px;
      }
    </style>
  </head>
  <body>

    <div id="map_canvas"/>
  </body>
</html>

enter image description here

Upvotes: 7

wf9a5m75
wf9a5m75

Reputation: 6158

Although I didn't use canvas, how about this code?

function onPolygonComplete(polygon) {
  var bounds, paths, sw, ne, ystep, xstep,
      boxH, boxW, posArry, flag, pos,
      x, y, i, box, maxBoxCnt;

  //Delete old boxes.
  boxes.forEach(function(box, i) {
    box.setMap(null);
    delete box;
  });

  //Calculate the bounds that contains entire polygon.
  bounds = new google.maps.LatLngBounds();
  paths = polygon.getPath();
  paths.forEach(function(latlng, i){
    bounds.extend(latlng);
  });


  //Calculate the small box size.
  maxBoxCnt = 8;
  sw = bounds.getSouthWest();
  ne = bounds.getNorthEast();
  ystep = Math.abs(sw.lat() - ne.lat()) / maxBoxCnt;
  boxH = Math.abs(sw.lat() - ne.lat()) / (maxBoxCnt + 1);
  xstep = Math.abs(sw.lng() - ne.lng()) / maxBoxCnt;
  boxW = Math.abs(sw.lng() - ne.lng()) / (maxBoxCnt + 1);

  for (y = 0; y < maxBoxCnt; y++) {
    for (x = 0; x < maxBoxCnt; x++) {
      //Detect that polygon is able to contain a small box.
      bounds = new google.maps.LatLngBounds();
      posArry = [];
      posArry.push(new google.maps.LatLng(sw.lat() + ystep * y, sw.lng() + xstep * x));
      posArry.push(new google.maps.LatLng(sw.lat() + ystep * y, sw.lng() + xstep * x + boxW));
      posArry.push(new google.maps.LatLng(sw.lat() + ystep * y + boxH, sw.lng() + xstep * x));
      posArry.push(new google.maps.LatLng(sw.lat() + ystep * y + boxH, sw.lng() + xstep * x + boxW));
      flag = true;
      for (i = 0; i < posArry.length; i++) {
        pos = posArry[i];
        if (flag) {
          flag = google.maps.geometry.poly.containsLocation(pos, polygon);
          bounds.extend(pos);
        }
      }

      //Draw a small box.
      if (flag) {
        box = new google.maps.Rectangle({
          bounds : bounds,
          map : mapCanvas,
          strokeColor: '#00ffff',
          strokeOpacity: 0.5,
          strokeWeight: 1,
          fillColor: '#00ffff',
          fillOpacity : 0.5,
          clickable: false
        });
        boxes.push(box);
      }
    }
  }
}

This code works like this image. enter image description here

I wrote a page that explains the code. http://googlemaps.googlermania.com/google_maps_api_v3/en/poly_containsLocation.html

Upvotes: 14

Related Questions