在Google地图上划定区域内的矩形

5

我正在使用Geometry API在Google Maps上绘制区域。 我想知道是否有可能在大小动态的区域上绘制重复元素?

例如,如果我将我的区域绘制成这样:

enter image description here

然后,我想能够点击“下一步”并看到像这样的内容,其中矩形被绘制在该区域中,但仅当它们适合该区域时。 也就是说,它们必须是“完整”的矩形,而不是部分矩形:

enter image description here

唯一的问题是,我不太确定如何实现这一点。 我会使用HTML5的<canvas>,但不幸的是,这需要尽可能适用于各种浏览器,但如果必须使用<canvas>,那么就使用它吧!


这与回答你的问题无关,但出于好奇,如果可以的话,你为什么想要那样做呢? - Andrei Cristian Prodan
@AndreiCristianProdan 根据客户要求.. - user1211577
哈哈,是啊,但他想要实现什么目标,为了什么目的。如果你知道目的,也许可以找到一个解决方法。 - Andrei Cristian Prodan
@AndreiCristianProdan,很不幸,这正是目的8-),我需要能够在所选区域内绘制最大数量的矩形,作为我们正在构建的在线应用程序中流程的视觉辅助。 - user1211577
这些包含的矩形是固定大小的吗? - david strachan
@davidstrachan - 是的,它们是。 - user1211577
2个回答

14

虽然我没有使用画布,但这段代码怎么样?

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);
      }
    }
  }
}

这段代码的作用类似于这张图片。 enter image description here

我编写了一个页面来解释这段代码。 http://googlemaps.googlermania.com/google_maps_api_v3/en/poly_containsLocation.html


1
太棒了,这太神奇了!但是我有一个更改无法自己解决。我需要矩形具有有限的宽度 - 我假设要更改此内容,应该在这里吧?boxH = Math.abs(sw.lat() - ne.lat()) / maxBoxCnt;例如;我需要盒子像10高,5宽,然后尽可能多地放置,而不是无论区域大小都放置有限数量的盒子。希望我表达清楚,再次感谢,这将使事情继续进行(除非以上内容不可行,那么我会让他们知道!) - user1211577
以上示例中,这是将13放入小区域这是将14放入巨大区域;我想要的是,如果它将13放入较小的区域,在所有指定的其他尺寸中保持该尺寸永久不变。 - user1211577
1
盒子的最大数量总是15吗?而且你不介意盒子的大小吗? - wf9a5m75
@wf9a5m75,不行。我需要有一个固定的盒子尺寸,并且盒子的最大数量取决于这些固定盒子能够放入该区域的数量。 - user1211577
他可能试图展示在某个区域内“适合”的内容。您需要检测当前的缩放级别并相应地调整基本框大小。 - Sinetheta
哦,谢谢你的建议。我正在感恩节假期中。抱歉让你等待了。我稍后会创建。 - wf9a5m75

7

@Joshua M

非常抱歉让您等待了。以下是新代码。 您可以在 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


1
非常感谢您的帮助,但我有一个问题: 我们不能根据当前缩放级别以像素为单位声明框的高度和宽度吗?比如说,我想要绘制一个1英尺* 1英尺或1米* 1米的框,而不是使用var boxSize = new google.maps.Size(10, 20); //以像素为单位.吗? 提前致谢。 - rohan dani
我需要知道缩放比例。我们如何将25平方米的正方形转换为像素?它应该适用于所有缩放级别。 - Umar Niazi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接