在谷歌地图中围绕折线绘制多边形

时间:2012-09-24 11:52:09

标签: google-maps-api-3 polygon

我正在尝试围绕现有折线创建一个多边形。我想到绘制与现有折线平行的折线,然后将它们连接起来创建一个多边形。我尝试用数学绘制平行线是不成功的。我发现这个链接用于在两边创建折线。

http://wtp2.appspot.com/ParallelLines.htm

这似乎正是我想要的。我开始从v2转换到v3。我试图保持最小的代码并删除其余的。我还删除了原始代码中存在的缩放级别更改的侦听器。

当我使用小的固定折线时,它工作得很好。然而,当我增加折线的尺寸时,平行折线开始变得混乱。

我的代码是:

    var points = null;
    var map;
    var line1;
    var line2;
    var prj = null;
    var idlelistener;
    var gapPx = 2;
    var weight = 4; 

    function BDCCParallelLines(maps, point, bounds) {   

        map = maps;
        points = point;
        //map.fitBounds(bounds);
        MyOverlay.prototype = new google.maps.OverlayView();
    MyOverlay.prototype.onAdd = function() { }
    MyOverlay.prototype.onRemove = function() { }
    MyOverlay.prototype.draw = function() { }
    function MyOverlay(map) { this.setMap(map); }

    var overlay = new MyOverlay(map);
    // Wait for idle map
    idlelistener = google.maps.event.addListener(map, 'idle', function() {
       // Get projection
       prj = overlay.getProjection();
       recalc();    
    })
    }

    function recalc() {
        google.maps.event.removeListener(idlelistener);
       var zoom = this.map.getZoom();

       //left and right swapped throughout!

       var pts1 = new google.maps.MVCArray();//left side of center 
       var pts2 = new google.maps.MVCArray();//right side of center

       //shift the pts array away from the centre-line by half the gap + half the line width
       var o = (this.gapPx + this.weight)/2;

       var p2l,p2r;

       for (var i=1; i<this.points.length; i+=2){


          var p1lm1;
          var p1rm1;
          var p2lm1;
          var p2rm1;
          var thetam1;

          var p1 = this.prj.fromLatLngToContainerPixel(this.points.getAt(i-1),zoom) //**fromLatLngToPixel
          var p2 = this.prj.fromLatLngToContainerPixel(this.points.getAt(i),zoom) //**fromLatLngToPixel
          var theta = Math.atan2(p1.x-p2.x,p1.y-p2.y) + (Math.PI/2);
          var dl = Math.sqrt(((p1.x-p2.x)*(p1.x-p2.x))+((p1.y-p2.y)*(p1.y-p2.y)));  

          if(theta > Math.PI)
              theta -= Math.PI*2; 
          var dx = Math.round(o * Math.sin(theta));
          var dy = Math.round(o * Math.cos(theta));

          var p1l = new google.maps.Point(p1.x+dx,p1.y+dy); //GPoint
          var p1r = new google.maps.Point(p1.x-dx,p1.y-dy); 
          p2l = new google.maps.Point(p2.x+dx,p2.y+dy);
          p2r = new google.maps.Point(p2.x-dx,p2.y-dy);

          if(i==1){   //first point
            pts1.push(this.prj.fromContainerPixelToLatLng(p1l),zoom); //**fromPixelToLatLng
            pts2.push(this.prj.fromContainerPixelToLatLng(p1r),zoom); //**fromPixelToLatLng
          }
          else{ // mid points

            if(theta == thetam1){
                // adjacent segments in a straight line 
                pts1.push(this.prj.fromContainerPixelToLatLng(p1l),zoom);
                pts2.push(this.prj.fromContainerPixelToLatLng(p1r),zoom);
            }
            else{
                var pli = this.intersect(p1lm1,p2lm1,p1l,p2l);
                var pri = this.intersect(p1rm1,p2rm1,p1r,p2r);

                var dlxi = (pli.x-p1.x);
                var dlyi = (pli.y-p1.y);
                var drxi = (pri.x-p1.x);
                var dryi = (pri.y-p1.y);
            var di = Math.sqrt((drxi*drxi)+(dryi*dryi));  
                var s = o / di;

                var dTheta = theta - thetam1;
                if(dTheta < (Math.PI*2))
                    dTheta += Math.PI*2;
                if(dTheta > (Math.PI*2))
                    dTheta -= Math.PI*2;

                if(dTheta < Math.PI){
                   //intersect point on outside bend
                   pts1.push(this.prj.fromContainerPixelToLatLng(p2lm1),zoom);
                   pts1.push(this.prj.fromContainerPixelToLatLng(new google.maps.Point(p1.x+(s*dlxi),p1.y+(s*dlyi))),zoom);
                   pts1.push(this.prj.fromContainerPixelToLatLng(p1l));
                }
            else if (di < dl){
                   pts1.push(this.prj.fromContainerPixelToLatLng(pli),zoom);
            }
                else{
                   pts1.push(this.prj.fromContainerPixelToLatLng(p2lm1),zoom);
                   pts1.push(this.prj.fromContainerPixelToLatLng(p1l),zoom);
            }

                dxi = (pri.x-p1.x)*(pri.x-p1.x);
                dyi = (pri.y-p1.y)*(pri.y-p1.y);
                if(dTheta > Math.PI){
                   //intersect point on outside bend
                   pts2.push(this.prj.fromContainerPixelToLatLng(p2rm1),zoom);
                   pts2.push(this.prj.fromContainerPixelToLatLng(new google.maps.Point(p1.x+(s*drxi),p1.y+(s*dryi))),zoom);
                   pts2.push(this.prj.fromContainerPixelToLatLng(p1r),zoom);
                }
            else if(di<dl)
                   pts2.push(this.prj.fromContainerPixelToLatLng(pri),zoom);
                else{
                   pts2.push(this.prj.fromContainerPixelToLatLng(p2rm1),zoom);
                   pts2.push(this.prj.fromContainerPixelToLatLng(p1r),zoom);
            }
            }
          }

          p1lm1 = p1l;
          p1rm1 = p1r;
          p2lm1 = p2l;
          p2rm1 = p2r;
          thetam1 = theta;
       }

       pts1.push(this.prj.fromContainerPixelToLatLng(p2l),zoom);//final point
       pts2.push(this.prj.fromContainerPixelToLatLng(p2r),zoom);

       this.line1 = new google.maps.Polyline({
              map:           map,
              path:          pts1,
              strokeColor:   "#0000FF",
              strokeWeight:  4,
              strokeOpacity: 1.0
        });


       this.line2 = new google.maps.Polyline({
            map:           map,
                      path:          pts2,
                      strokeColor:   "#0000FF",
                      strokeWeight:  4,
                      strokeOpacity: 1.0
        });*/

       createPolygon(pts1,pts2);
    }

    function intersect(p0,p1,p2,p3)
    {
    // this function computes the intersection of the sent lines p0-p1 and p2-p3
    // and returns the intersection point, 

    var a1,b1,c1, // constants of linear equations
        a2,b2,c2,
        det_inv,  // the inverse of the determinant of the coefficient matrix
        m1,m2;    // the slopes of each line

    var x0 = p0.x;
    var y0 = p0.y;
    var x1 = p1.x;
    var y1 = p1.y;
    var x2 = p2.x;
    var y2 = p2.y;
    var x3 = p3.x;
    var y3 = p3.y;

    // compute slopes, note the cludge for infinity, however, this will
    // be close enough

    if ((x1-x0)!=0)
       m1 = (y1-y0)/(x1-x0);
    else
       m1 = 1e+10;   // close enough to infinity

    if ((x3-x2)!=0)
       m2 = (y3-y2)/(x3-x2);
    else
       m2 = 1e+10;   // close enough to infinity

    // compute constants

    a1 = m1;
    a2 = m2;

    b1 = -1;
    b2 = -1;

    c1 = (y0-m1*x0);
    c2 = (y2-m2*x2);

    // compute the inverse of the determinate

    det_inv = 1/(a1*b2 - a2*b1);

    // use Kramers rule to compute xi and yi

    var xi=((b1*c2 - b2*c1)*det_inv);
    var yi=((a2*c1 - a1*c2)*det_inv);

    return new google.maps.Point(Math.round(xi),Math.round(yi)); // ** CHANGED HERE

    }

    function createPolygon(side1,side2){
        var a = new Array();
        for(var i = 0; i < side1.length;i++){
            a.push(side1.getAt(i))
        }
        for(var i = side1.length-1; i >=0;i--){
            a.push(side2.getAt(i));
        }
        drawPolylinePolygon(a)  
    }

    function drawPolylinePolygon(a){
        a.push(a[0]);
        var color = getColor(false);
          var polygon_options = {
                paths: a,
                strokeColor: color,
                strokeOpacity: 0.7,
                strokeWeight: 2,
                fillColor: color,
                fillOpacity: 0.2
          };
          current_polygon = new google.maps.Polygon(polygon_options);
          current_polygon.setMap(map);
    }

createPolygon()函数用于合并两条折线以创建多边形。

这是html页面:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">

    <head>
    <title></title>


    <script src="http://maps.google.com/maps/api/js?sensor=true&libraries=drawing,geometry" type="text/javascript"></script>
    <script src="BDCCParallelLines.js" type="text/javascript"></script>

    <script type="text/javascript">
        //<![CDATA[

    var map;

    function linesMap(){

            var latlng1 = new google.maps.LatLng(51.42, -0.95);
            var mapOptions = {zoom: 22, center:latlng1, mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: false};
            var map = new google.maps.Map(document.getElementById('mapLines'),mapOptions);

            var pts = new Array();
            var latlngbounds = new google.maps.LatLngBounds();
            pts.push (new google.maps.LatLng(51.42, -0.97));
            latlngbounds.extend(new google.maps.LatLng(51.42, -0.97));
            pts.push (new google.maps.LatLng(51.43, -0.96));
            latlngbounds.extend(new google.maps.LatLng(51.43, -0.96));
            pts.push (new google.maps.LatLng(51.425, -0.955));
            latlngbounds.extend(new google.maps.LatLng(51.425, -0.955));
            pts.push (new google.maps.LatLng(51.42, -0.95));//straight at zoom = 13
            latlngbounds.extend(new google.maps.LatLng(51.42, -0.95));
            pts.push (new google.maps.LatLng(51.43, -0.94));
            latlngbounds.extend(new google.maps.LatLng(51.43, -0.94));
            pts.push (new google.maps.LatLng(51.43, -0.9375));//horz & straight
            latlngbounds.extend(new google.maps.LatLng(51.43, -0.9375));
            pts.push (new google.maps.LatLng(51.43, -0.935));
            latlngbounds.extend(new google.maps.LatLng(51.43, -0.935));
            pts.push (new google.maps.LatLng(51.425, -0.935));
            latlngbounds.extend(new google.maps.LatLng(51.425, -0.935));
            pts.push (new google.maps.LatLng(51.42, -0.935));//vert & straight
            latlngbounds.extend(new google.maps.LatLng(51.42, -0.935));


            var poly = new BDCCParallelLines(map,pts,latlngbounds);

            var poly2 = new google.maps.Polyline({
                      map:           map,
                      path:          pts,
                      strokeColor:   "#FF0000",
                      strokeWeight:  2,
                      strokeOpacity: 1.0
                });
    }


        //]]>

    </script>
    </head>

    <body     onload="linesMap();"
    style="font-weight: bold; font-size: large; font-family: Arial; background-color: #cccc99">
                    <div id="mapLines" style="width: 800px; height: 600px">
                    </div>
    </body>
    </html>

搜索后,我看到本文似乎有同样的问题。链接上的图像显示了我遇到的完全相同的问题。 Google maps api parallel path lines

我想知道是否有任何方法可以改进平行折线的现有代码,或者如果有任何其他方式,我正在寻找的最终结果是折线周围的多边形。

1 个答案:

答案 0 :(得分:-1)

您应该使用任何空间API或数据库中存在的Buffer函数,例如 sharpmap