如何在直线的一侧显示弯曲的折线? [英] How to display curved polyline on one side of a straight line?

查看:105
本文介绍了如何在直线的一侧显示弯曲的折线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



这是我的代码。我有两个样本多段线从北到南。

  var map; 

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

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

var pos3 =新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,
图标:[{
图标:{
路径:'M 0,-1 0,1',
strokeOpacity:1,
比例:4
},
偏移量:'0 ',
repeat:'20px'
}],
map:map
});

var line = new google.maps.Polyline({
path:[pos3,pos4],
strokeOpacity:0,
图标:[{
图标:{
路径:'M 0,-1 0,1',
strokeOpacity:1,
比例:4
},
偏移量:'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 = []; (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,
图标:[{
图标:{
路径:'M 0,-1 0,1',
strokeOpacity:1,
比例:4
} ,
offset:'0',
repeat:'20px'
}],
strokeColor:'gray'
});

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:函数(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 );
返回pos;
}
};


解决方案

绘制您正在寻找的贝塞尔曲线的一般例程因为会是:
$ b $ pre $ 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);

$ / code>

改变角度和距离来计算控制点( pA pB )将会改变曲率的大小。

测试小提琴



程式码片段:



  //绘制一条锚定在P1的虚曲线,P2function 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);}函数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}); //对于(var angle = 0; angle <360; angle + = 10),每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); //原始Belzier曲线代码来自nicoabie在StackOverflow上的这个问题的答案// http://stackoverflow.com/questions/5347984/letting- (latlong1,latlong2,latlong3,latlong4,分辨率,地图){var lat1 = latlong1.lat();用户绘制曲线在谷歌地图上的变量GmapsCubicBezier = 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 = []; (it = 0; it <= 1; it + =分辨率){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},偏移量:'0',重复:'20px'}],strokeColor:'gray'}); Line.setMap(地图); 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);返回pos; }};  

<,c $ c> html,body,#map_canvas {height: 100%;宽度:100%; margin:0px; < script src =https://


This question is related to this SO question and answered by @geocodezip.

A problem I have is drawing a line from either north-to-south or south-to-north. The curved line is now bent like number 8 or a S. How do I control the curved line to display on one side of the straight line. Sometimes the curved line is expanded beyond the starting point and contracted at the ending point. Thanks.

Here are my codes. I have two sample polylines north-to-south.

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

解决方案

A general routine to draw the Bezier curve you are looking for would be:

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

Changing the angles and distance to compute the control points (pA, pB) will change the amount of curvature.

test fiddle

code snippet:

// 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"></script>
<div id="map_canvas"></div>

这篇关于如何在直线的一侧显示弯曲的折线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆