Arhn - архитектура программирования

Рисование многоугольника вокруг полилинии в картах Google

Я пытаюсь создать многоугольник вокруг существующей полилинии. Я подумал о том, чтобы нарисовать полилинии параллельно существующей полилинии, а затем соединить их, чтобы создать многоугольник. Я безуспешно пытался вычислить параллельные линии. Я нашел эту ссылку, которую я использовал для создания полилиний с обеих сторон.

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 отображает линии параллельного пути API

Я хотел бы знать, есть ли способ улучшить существующий код для параллельных полилиний или есть ли какой-либо другой способ, которым я ищу конечный результат, - это многоугольник вокруг полилинии.


  • Каково назначение многоугольника? Что-то вроде того, что RouteBoxer работает? 24.09.2012
  • @user1694185 user1694185 Пожалуйста, обрежьте примеры кода, чтобы они охватывали только рассматриваемую тему, чтобы их было легче читать и находить общий ответ. 25.09.2012
  • @geocodezip - я проверил RouteBoxer, но он мне не подходит. Я позволяю пользователю рисовать полилинию на карте, и после этого я хочу создать многоугольник, поскольку я хочу проверить, входит ли пользователь с GPS в многоугольник или выходит из него. У меня уже есть код javascript для проверки входа и выхода. 25.09.2012
  • @MikulasDite - Спасибо, что указали на это. Я новичок здесь, поэтому я подумал, что размещение всего кода поможет другим понять поток, а также позволит им протестировать его. 25.09.2012

Ответы:


1

Вы должны использовать функцию Buffer, которая существует в любом пространственном API или базе данных, одним из примеров является sharpmap. .

24.09.2012
  • Спасибо за ссылку. Я искал функцию в javascript, так как хотел выполнять вычисления на стороне клиента, а не на сервере, чтобы минимизировать нагрузку. Однако я проверю NTS и дам вам знать. 25.09.2012
  • Хорошо, я читал быстро, здесь связанный вопрос 25.09.2012
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..