【问题标题】:How to display curved polyline on one side of a straight line?如何在直线的一侧显示弯曲的折线?
【发布时间】:2016-03-24 02:58:09
【问题描述】:

这个问题与SO question 相关,由@geocodezip 回答。

我遇到的一个问题是从北到南或从南到北画一条线。曲线现在像数字 8 或 S 一样弯曲。如何控制曲线显示在直线的一侧。有时曲线会在起点之外扩展并在终点收缩。谢谢。

这是我的代码。我有两条从北到南的示例折线。

var map;

function init() {
var Map = google.maps.Map,
    LatLng = google.maps.LatLng,
    LatLngBounds = google.maps.LatLngBounds,
    Marker = google.maps.Marker,
    Point = google.maps.Point;

var pos1 = new LatLng(29.703642, -95.152274);
var pos2 = new LatLng(29.702452, -95.152296);

var pos3 = new LatLng(29.703514, -95.151405);
var pos4 = new LatLng(29.702359, -95.152078);

var bounds = new LatLngBounds();
bounds.extend(pos1);
bounds.extend(pos2);
var mapOptions = {
        disableDefaultUI: true,
        mapTypeId: google.maps.MapTypeId.SATELLITE,
        draggableCursor: 'auto',
        panControl: true,
        scaleControl: true,
        smallMapControl: true,
        tilt: 0,
        zoom: 19,           
        zoomControl: true,
        rotateControl:true,
        zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL }
    };
map = new Map(document.getElementById('map-canvas'), mapOptions);
map.fitBounds(bounds);

var markerP1 = new Marker({
    position: pos1,
    draggable: true,
    map: map
});
var markerP2 = new Marker({
    position: pos2,
    draggable: true,
    map: map
});

var markerP2 = new Marker({
    position: pos3,
    draggable: true,
    map: map
});
var markerP3 = new Marker({
    position: pos4,
    draggable: true,
    map: map
});

var curvedLine = new GmapsCubicBezier(pos1, pos2, 0.01, map);
var curvedLine = new GmapsCubicBezier(pos3, pos4, 0.01, map);

var line = new google.maps.Polyline({
  path: [pos1, pos2],
  strokeOpacity: 0,
  icons: [{
    icon: {
      path: 'M 0,-1 0,1',
      strokeOpacity: 1,
      scale: 4
    },
    offset: '0',
    repeat: '20px'
  }],
  map: map
});

var line = new google.maps.Polyline({
    path: [pos3, pos4],
    strokeOpacity: 0,
    icons: [{
      icon: {
        path: 'M 0,-1 0,1',
        strokeOpacity: 1,
        scale: 4
      },
      offset: '0',
      repeat: '20px'
    }],
    map: map
  });
}

google.maps.event.addDomListener(window, 'load', init);

var GmapsCubicBezier = function (latlong1, latlong4, resolution, map) {

var lineLength = google.maps.geometry.spherical.computeDistanceBetween(latlong1, latlong4);
var lineHeading = google.maps.geometry.spherical.computeHeading(latlong1, latlong4);

var positionA = google.maps.geometry.spherical.computeOffset(latlong1, lineLength / 3, lineHeading - 60);
var positionB = google.maps.geometry.spherical.computeOffset(latlong4, lineLength / 3, -lineHeading + 120);

var lat1 = latlong1.lat();
var long1 = latlong1.lng();

var lat2 = positionA.lat();
var long2 = positionA.lng();

var lat3 = positionB.lat();
var long3 = positionB.lng();

var lat4 = latlong4.lat();
var long4 = latlong4.lng();

var points = [];

for (it = 0; it <= 1; it += resolution) {
    points.push(this.getBezier({
        x: lat1,
        y: long1
    }, {
        x: lat2,
        y: long2
    }, {
        x: lat3,
        y: long3
    }, {
        x: lat4,
        y: long4
    }, it));
}
var path = [];
for (var i = 0; i < points.length - 1; i++) {
    path.push(new google.maps.LatLng(points[i].x, points[i].y));
    path.push(new google.maps.LatLng(points[i + 1].x, points[i + 1].y, false));
              }

    var Line = new google.maps.Polyline({
        path: path,
        geodesic: true,
        strokeOpacity: 0.0,
                    icons: [{
                        icon: {
                            path: 'M 0,-1 0,1',
                            strokeOpacity: 1,
                            scale: 4
                        },
                        offset: '0',
                        repeat: '20px'
                    }],
         strokeColor: 'grey'
     });

    Line.setMap(map);

return Line;
};


GmapsCubicBezier.prototype = {

B1: function (t) {
    return t * t * t;
},
B2: function (t) {
    return 3 * t * t * (1 - t);
},
B3: function (t) {
    return 3 * t * (1 - t) * (1 - t);
},
B4: function (t) {
    return (1 - t) * (1 - t) * (1 - t);
},
getBezier: function (C1, C2, C3, C4, percent) {
    var pos = {};
    pos.x = C1.x * this.B1(percent) + C2.x * this.B2(percent) + C3.x * this.B3(percent) + C4.x * this.B4(percent);
    pos.y = C1.y * this.B1(percent) + C2.y * this.B2(percent) + C3.y * this.B3(percent) + C4.y * this.B4(percent);
    return pos;
}
};

【问题讨论】:

    标签: google-maps-api-3 polyline bezier


    【解决方案1】:

    绘制您正在寻找的贝塞尔曲线的一般程序是:

    function drawDashedCurve(P1, P2, map) {
      var lineLength = google.maps.geometry.spherical.computeDistanceBetween(P1, P2);
      var lineHeading = google.maps.geometry.spherical.computeHeading(P1, P2);
      if (lineHeading < 0) {
        var lineHeading1 = lineHeading + 45;
        var lineHeading2 = lineHeading + 135;
      } else {
        var lineHeading1 = lineHeading + -45;
        var lineHeading2 = lineHeading + -135;
      }
      var pA = google.maps.geometry.spherical.computeOffset(P1, lineLength / 2.2, lineHeading1);
      var pB = google.maps.geometry.spherical.computeOffset(P2, lineLength / 2.2, lineHeading2);
    
      var curvedLine = new GmapsCubicBezier(P1, pA, pB, P2, 0.01, map);
    }
    

    更改计算控制点的角度和距离(pApB)将改变曲率。

    test fiddle

    代码 sn-p:

    // draw a dashed curve anchored at P1, P2
    function drawDashedCurve(P1, P2, map) {
      var lineLength = google.maps.geometry.spherical.computeDistanceBetween(P1, P2);
      var lineHeading = google.maps.geometry.spherical.computeHeading(P1, P2);
      if (lineHeading < 0) {
        var lineHeading1 = lineHeading + 45;
        var lineHeading2 = lineHeading + 135;
      } else {
        var lineHeading1 = lineHeading + -45;
        var lineHeading2 = lineHeading + -135;
      }
      var pA = google.maps.geometry.spherical.computeOffset(P1, lineLength / 2.2, lineHeading1);
      var pB = google.maps.geometry.spherical.computeOffset(P2, lineLength / 2.2, lineHeading2);
    
      var curvedLine = new GmapsCubicBezier(P1, pA, pB, P2, 0.01, map);
    }
    
    function initialize() {
      var map = new google.maps.Map(
        document.getElementById("map_canvas"), {
          center: new google.maps.LatLng(37.4419, -122.1419),
          zoom: 13,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });
      // generate test points every 10 degrees
      for (var angle = 0; angle < 360; angle += 10) {
        var p1 = google.maps.geometry.spherical.computeOffset(map.getCenter(), 1000, angle);
        var p2 = google.maps.geometry.spherical.computeOffset(map.getCenter(), 2000, angle);
        drawDashedCurve(p1, p2, map);
        var straightPoly = new google.maps.Polyline({
          map: map,
          path: [p1, p2],
          strokeOpacity: 0.2,
          strokeColor: "blue"
        });
        var markerP1 = new google.maps.Marker({
          position: p1,
          map: map,
          icon: {
            path: google.maps.SymbolPath.CIRCLE,
            scale: 4,
            fillColor: "black",
            fillOpacity: 1.0
          }
        });
        var markerP2 = new google.maps.Marker({
          position: p2,
          map: map,
          icon: {
            path: google.maps.SymbolPath.CIRCLE,
            scale: 4,
            fillColor: "black",
            fillOpacity: 1.0
          }
        });
      }
    }
    google.maps.event.addDomListener(window, "load", initialize);
    
    // original Belzier Curve code from nicoabie's answer to this question on StackOverflow:
    // http://stackoverflow.com/questions/5347984/letting-users-draw-curved-lines-on-a-google-map
    var GmapsCubicBezier = function(latlong1, latlong2, latlong3, latlong4, resolution, map) {
      var lat1 = latlong1.lat();
      var long1 = latlong1.lng();
      var lat2 = latlong2.lat();
      var long2 = latlong2.lng();
      var lat3 = latlong3.lat();
      var long3 = latlong3.lng();
      var lat4 = latlong4.lat();
      var long4 = latlong4.lng();
    
      var points = [];
    
      for (it = 0; it <= 1; it += resolution) {
        points.push(this.getBezier({
          x: lat1,
          y: long1
        }, {
          x: lat2,
          y: long2
        }, {
          x: lat3,
          y: long3
        }, {
          x: lat4,
          y: long4
        }, it));
      }
      var path = [];
      for (var i = 0; i < points.length - 1; i++) {
        path.push(new google.maps.LatLng(points[i].x, points[i].y));
        path.push(new google.maps.LatLng(points[i + 1].x, points[i + 1].y, false));
      }
    
      var Line = new google.maps.Polyline({
        path: path,
        geodesic: true,
        strokeOpacity: 0.0,
        icons: [{
          icon: {
            path: 'M 0,-1 0,1',
            strokeOpacity: 1,
            scale: 4
          },
          offset: '0',
          repeat: '20px'
        }],
        strokeColor: 'grey'
      });
    
      Line.setMap(map);
    
      return Line;
    };
    
    
    GmapsCubicBezier.prototype = {
    
      B1: function(t) {
        return t * t * t;
      },
      B2: function(t) {
        return 3 * t * t * (1 - t);
      },
      B3: function(t) {
        return 3 * t * (1 - t) * (1 - t);
      },
      B4: function(t) {
        return (1 - t) * (1 - t) * (1 - t);
      },
      getBezier: function(C1, C2, C3, C4, percent) {
        var pos = {};
        pos.x = C1.x * this.B1(percent) + C2.x * this.B2(percent) + C3.x * this.B3(percent) + C4.x * this.B4(percent);
        pos.y = C1.y * this.B1(percent) + C2.y * this.B2(percent) + C3.y * this.B3(percent) + C4.y * this.B4(percent);
        return pos;
      }
    };
    html,
    body,
    #map_canvas {
      height: 100%;
      width: 100%;
      margin: 0px;
      padding: 0px
    }
    <script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
    <div id="map_canvas"></div>

    【讨论】:

    • 好的,所以当你进入世界规模时,线条会失去控制(我将点偏移量增加到 1000000、5000000:i.imgur.com/wsbHTsm.jpeg,这看起来类似于这里发生的事情:stackoverflow.com/questions/47950659/… 任何想法为什么会发生以及如何解决?
    • 这是一个新的/不同的问题。如果您提出要求(并提供minimal reproducible example),可能会更容易提供帮助。
    • 查看the picture,看起来像是国际日期变更线问题。
    • 你的意思是格林威治和世界另一端的坐标应该归零?
    • 这取决于你想做什么。
    猜你喜欢
    • 2018-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2017-02-23
    • 1970-01-01
    相关资源
    最近更新 更多