There are many Solutions out there which provides info on how to draw a curved polyline using Google Maps JS Api. All of them provides a solution for shorter distances. Is there a way to make the curved polyline adapts to the longer distances too ?
If I try to plot for longer distances as below it draws the curve differently .
I am trying to find a solution which can draw a standard beizer curve for all geo polylines(Shorter&Longer).
Any ideas ?
function drawCurve(P1, P2, map) {
var lineLength = google.maps.geometry.spherical.computeDistanceBetween(P1, P2);
//console.log(lineLength);
var distance = (50/100) * lineLength;
//console.log(distance);
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.1, map);
}
function setMarkers(data) {
console.log('setMarkers');
var pos;
var marker;
var allMarkers = [];
//console.log(markerJson.length);
pos = new google.maps.LatLng(data.lat(), data.lng());
marker = new google.maps.Marker({
position: pos,
map: map,
title: 'Title',
icon: 'https://www.google.com/support/enterprise/static/geo/cdate/art/dots/red_dot.png'
});
/// LABEL ///
var label = new Label({
map: map,
text: marker.getPosition().toUrlValue(6)
});
label.bindTo('position', marker, 'position');
/// LABEL ///
allMarkers.push(marker);
}
function Label(opt_options) {
// Initialization
this.setValues(opt_options);
// Label specific
var span = this.span_ = document.createElement('span');
span.classList.add('icon-right');
span.classList.add('icon-right-text');
var div = this.div_ = document.createElement('div');
div.appendChild(span);
//div.style.cssText = 'position: absolute; display: none;'
div.classList.add("icon-right");
}
var x=new google.maps.LatLng(14.560774500000008,121.02631410000006);
var london = new google.maps.LatLng(51.5073509, -0.12775829999998223);
var rcbc=new google.maps.LatLng(14.560648, 121.016781);
var powerplant=new google.maps.LatLng(14.565066, 121.036184);
var trafalgar=new google.maps.LatLng(14.560774500000008,121.02631410000006);
var mapua=new google.maps.LatLng(14.562883, 121.022039);
var map;
function initialize()
{
var mapProp = {
center:x,
zoom:2,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
map=new google.maps.Map(document.getElementById("googleMap"),mapProp);
var myTrip=[trafalgar,rcbc];
var myTrip2=[rcbc,powerplant];
drawCurve(trafalgar,rcbc, map);
drawCurve(rcbc,powerplant, map);
drawCurve(london,rcbc,map);
var marker=new google.maps.Marker({
position:x,
});
var marker2=new google.maps.Marker({
position:london,
});
var marker3=new google.maps.Marker({
position:rcbc,
});
var marker4=new google.maps.Marker({
position:powerplant,
});
marker4.setMap(map);
marker3.setMap(map);
marker2.setMap(map);
marker.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
Label.prototype = new google.maps.OverlayView();
// Implement onAdd
Label.prototype.onAdd = function() {
var pane = this.getPanes().overlayLayer;
pane.appendChild(this.div_);
};
// Implement draw
Label.prototype.draw = function() {
var projection = this.getProjection();
var position = projection.fromLatLngToDivPixel(this.get('position'));
var div = this.div_;
div.style.left = parseFloat(position.x)-18 'px';
div.style.top = parseFloat(position.y)-20 'px';
//div.sytle.borderRadius = '50%';
this.span_.innerHTML = "12";
};
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));
}
console.log(path[path.length/2].lat(), path[path.length/2].lng());
/* var linesymbol = {
path:google.maps.SymbolPath.FORWARD_CLOSED_ARROW
} */
var Line = new google.maps.Polyline({
path: path,
// icons:[{
/* icon:linesymbol,
offset:"50%"
}], */
geodesic: true,
strokeColor:"##35495e",
strokeOpacity:0.8,
strokeWeight:3,
});
Line.setMap(map);
setMarkers(new google.maps.LatLng(path[path.length/2].lat(), path[path.length/2].lng()));
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,
#googleMap {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
.icon-left {
position: absolute;
border-radius:50%;
box-sizing: border-box;
display: inline-block;
height: 30px;
line-height: 30px;
overflow: hidden;
width: 30px;
text-align: center;
background: black;
color: white;
rotate: -45deg;
z-index:200;
}
.icon-left-text {
position: relative;
text-align: center;
rotate: 45deg;
}
.icon-right {
position: absolute;
box-sizing: border-box;
display: inline-block;
height: 30px;
line-height: 30px;
overflow: hidden;
width: 30px;
border-radius:50%;
text-align: center;
background: black;
color: white;
rotate: 135deg;
z-index:200;
}
.icon-right-text {
position: relative;
text-align: center;
rotate: -135deg;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="googleMap"></div>
CodePudding user response:
One option would be to change the calculation of the
function drawCurve(P1, P2, map) {
var lineLength = google.maps.geometry.spherical.computeDistanceBetween(P1, P2);
var distance = (50 / 100) * lineLength;
var lineHeading = google.maps.geometry.spherical.computeHeading(P1, P2);
// makes the curve above the direct line
if (lineHeading < 0) {
var lineHeadingMult = 1;
} else {
var lineHeadingMult = -1;
}
// calculate the midpoint of the line
var midpoint = google.maps.geometry.spherical.computeOffset(
P1,
google.maps.geometry.spherical.computeDistanceBetween(P1, P2) / 2,
google.maps.geometry.spherical.computeHeading(P1, P2));
// calculate the new control points, the 1/8 is one option, smaller makes a shallower curve
var modMidpoint = google.maps.geometry.spherical.computeOffset(
midpoint,
google.maps.geometry.spherical.computeDistanceBetween(P1, P2) / 8,
google.maps.geometry.spherical.computeHeading(P1, P2) lineHeadingMult * 90);
var curvedLine = new GmapsCubicBezier(P1, modMidpoint, modMidpoint, P2, 0.1, map);
}
function setMarkers(data) {
console.log('setMarkers');
var pos;
var marker;
var allMarkers = [];
//console.log(markerJson.length);
pos = new google.maps.LatLng(data.lat(), data.lng());
marker = new google.maps.Marker({
position: pos,
map: map,
title: 'Title',
icon: 'https://www.google.com/support/enterprise/static/geo/cdate/art/dots/red_dot.png'
});
/// LABEL ///
var label = new Label({
map: map,
text: marker.getPosition().toUrlValue(6)
});
label.bindTo('position', marker, 'position');
/// LABEL ///
allMarkers.push(marker);
}
function Label(opt_options) {
// Initialization
this.setValues(opt_options);
// Label specific
var span = this.span_ = document.createElement('span');
span.classList.add('icon-right');
span.classList.add('icon-right-text');
var div = this.div_ = document.createElement('div');
div.appendChild(span);
//div.style.cssText = 'position: absolute; display: none;'
div.classList.add("icon-right");
}
var x = new google.maps.LatLng(14.560774500000008, 121.02631410000006);
var london = new google.maps.LatLng(51.5073509, -0.12775829999998223);
var rcbc = new google.maps.LatLng(14.560648, 121.016781);
var powerplant = new google.maps.LatLng(14.565066, 121.036184);
var trafalgar = new google.maps.LatLng(14.560774500000008, 121.02631410000006);
var mapua = new google.maps.LatLng(14.562883, 121.022039);
var map;
function initialize() {
var mapProp = {
center: x,
zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
var myTrip = [trafalgar, rcbc];
var myTrip2 = [rcbc, powerplant];
drawCurve(trafalgar, rcbc, map);
drawCurve(rcbc, powerplant, map);
drawCurve(london, rcbc, map);
var marker = new google.maps.Marker({
position: x,
});
var marker2 = new google.maps.Marker({
position: london,
});
var marker3 = new google.maps.Marker({
position: rcbc,
});
var marker4 = new google.maps.Marker({
position: powerplant,
});
marker4.setMap(map);
marker3.setMap(map);
marker2.setMap(map);
marker.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
Label.prototype = new google.maps.OverlayView();
// Implement onAdd
Label.prototype.onAdd = function() {
var pane = this.getPanes().overlayLayer;
pane.appendChild(this.div_);
};
// Implement draw
Label.prototype.draw = function() {
var projection = this.getProjection();
var position = projection.fromLatLngToDivPixel(this.get('position'));
var div = this.div_;
div.style.left = parseFloat(position.x) - 18 'px';
div.style.top = parseFloat(position.y) - 20 'px';
//div.sytle.borderRadius = '50%';
this.span_.innerHTML = "12";
};
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));
}
console.log(path[path.length / 2].lat(), path[path.length / 2].lng());
/* var linesymbol = {
path:google.maps.SymbolPath.FORWARD_CLOSED_ARROW
} */
var Line = new google.maps.Polyline({
path: path,
// icons:[{
/* icon:linesymbol,
offset:"50%"
}], */
geodesic: true,
strokeColor: "##35495e",
strokeOpacity: 0.8,
strokeWeight: 3,
});
Line.setMap(map);
setMarkers(new google.maps.LatLng(path[path.length / 2].lat(), path[path.length / 2].lng()));
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,
#googleMap {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
.icon-left {
position: absolute;
border-radius: 50%;
box-sizing: border-box;
display: inline-block;
height: 30px;
line-height: 30px;
overflow: hidden;
width: 30px;
text-align: center;
background: black;
color: white;
rotate: -45deg;
z-index: 200;
}
.icon-left-text {
position: relative;
text-align: center;
rotate: 45deg;
}
.icon-right {
position: absolute;
box-sizing: border-box;
display: inline-block;
height: 30px;
line-height: 30px;
overflow: hidden;
width: 30px;
border-radius: 50%;
text-align: center;
background: black;
color: white;
rotate: 135deg;
z-index: 200;
}
.icon-right-text {
position: relative;
text-align: center;
rotate: -135deg;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="googleMap"></div>
CodePudding user response:
As I was trying all the possible ways ...I see that the below logic works fine for my requirement.
But, It is using addListeners and trying to update the latest polyline by removing the previous one.
var map;
var curvature = 0.5; // how curvy to make the arc
function init() {
var Map = google.maps.Map,
LatLng = google.maps.LatLng,
LatLngBounds = google.maps.LatLngBounds,
Marker = google.maps.Marker,
Point = google.maps.Point;
// This is the initial location of the points
// (you can drag the markers around after the map loads)
var pos1 = new LatLng(38.60971599083999, -105.42822913560047);
var pos2 = new LatLng(31.549917555822212, -99.49938531446615);
var bounds = new LatLngBounds();
bounds.extend(pos1);
bounds.extend(pos2);
map = new Map(document.getElementById('map-canvas'), {
center: bounds.getCenter(),
zoom: 12
});
map.fitBounds(bounds);
var markerP1 = new Marker({
position: pos1,
// draggable: true,
map: map
});
var markerP2 = new Marker({
position: pos2,
// draggable: true,
map: map
});
var curveMarker;
function updateCurveMarker() {
var pos1 = markerP1.getPosition(), // latlng
pos2 = markerP2.getPosition(),
projection = map.getProjection(),
p1 = projection.fromLatLngToPoint(pos1), // xy
p2 = projection.fromLatLngToPoint(pos2);
// Calculate the arc.
// To simplify the math, these points
// are all relative to p1:
var e = new Point(p2.x - p1.x, p2.y - p1.y), // endpoint (p2 relative to p1)
m = new Point(e.x / 2, e.y / 2), // midpoint
o = new Point(e.y, -e.x), // orthogonal
c = new Point( // curve control point
m.x curvature * o.x,
m.y curvature * o.y);
var pathDef = 'M 0,0 '
'q ' c.x ',' c.y ' ' e.x ',' e.y;
var zoom = map.getZoom(),
scale = 1 / (Math.pow(2, -zoom));
var symbol = {
path: pathDef,
scale: scale,
strokeWeight: 1,
fillColor: 'none'
};
if (!curveMarker) {
curveMarker = new Marker({
position: pos1,
clickable: false,
icon: symbol,
zIndex: 0, // behind the other markers
map: map
});
} else {
curveMarker.setOptions({
position: pos1,
icon: symbol,
});
}
}
google.maps.event.addListener(map, 'projection_changed', updateCurveMarker);
google.maps.event.addListener(map, 'zoom_changed', updateCurveMarker);
}
google.maps.event.addDomListener(window, 'load', init);
html, body, #map-canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry,places&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map-canvas" style="border: 2px solid #3872ac;"></div>
But how can we add multiple polylines at the same time by adapting to the curve logic?