Google Maps API v.3 convert polyline into polygon with given width - google-maps

I'm looking for the way for converting polyline (created from i.e. 2 coordinates) to polygon containing at least 4 coordinates. Simple usage case is airway on the aviation map, it has start at point A, end at point B and width of x nautical miles. Dummy code is:
var someLine = new google.maps.Polyline({
path: [
{lat: 51.15, lng: 15},
{lat: 51.15, lng: 18}
],
geodesic: true,
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 5
});
someLine.setMap(map);
// how to convert above someLine into?:
var airway = new google.maps.Polygon({
paths: [
{lat: 51, lng: 15},
{lat: 51, lng: 18},
{lat: 51.3, lng: 18},
{lat: 51.3, lng: 15}
],
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35,
geodesic: true
});
airway.setMap(map);
Which looks like:
where black line is common polyline and red polygon is desired effect.
Is that any API/plugin available for such task or I need to calculate the corners of polygon(s) manually?

One option would be to use the Google Maps Javascript API v3 geometry library to compute your polygon based on the width of the air lane and the center line. If you specify the width of the air lane using meters (rather than nautical miles, which is just a conversion):
var lineWidth = 10000; // (meters)
var lineHeading = google.maps.geometry.spherical.computeHeading(someLine.getPath().getAt(0), someLine.getPath().getAt(1));
var p0a = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(0), lineWidth, lineHeading+90);
var p0b = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(0), lineWidth, lineHeading-90);
var p1a = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(1), lineWidth, lineHeading+90);
var p1b = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(1), lineWidth, lineHeading-90);
var airway = new google.maps.Polygon({
paths: [p0a, p0b, p1b, p1a],
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35,
geodesic: true
});
code snippet:
var geocoder;
var 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
});
var someLine = new google.maps.Polyline({
path: [{
lat: 51.15,
lng: 15
}, {
lat: 49.15,
lng: 18
}],
geodesic: true,
strokeColor: '#000000',
strokeOpacity: 1.0,
strokeWeight: 5
});
someLine.setMap(map);
var lineWidth = 10000; // (meters)
var lineHeading = google.maps.geometry.spherical.computeHeading(someLine.getPath().getAt(0), someLine.getPath().getAt(1));
var p0a = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(0), lineWidth, lineHeading + 90);
var p0b = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(0), lineWidth, lineHeading - 90);
var p1a = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(1), lineWidth, lineHeading + 90);
var p1b = google.maps.geometry.spherical.computeOffset(someLine.getPath().getAt(1), lineWidth, lineHeading - 90);
// how to convert above someLine into?:
var airway = new google.maps.Polygon({
paths: [p0a, p0b, p1b, p1a],
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35,
geodesic: true
});
airway.setMap(map);
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < airway.getPath().getLength(); i++) {
bounds.extend(airway.getPath().getAt(i));
}
map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, "load", initialize);
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>

Related

Google Maps - Animated Polyline -- Stop / Remove Animation

I'm plotting a polyline on Google Maps API V3, from a GPX file.
On mouseover of that polyline, I have an animated dot, moving along the polyline, using function animateRoute();
Currently however, I don't have a way to remove the animated dot on mouseout, and as a result, if you mouseover, mouseout, mouseover etc, you end up with multiple animated dots moving along the same line.
Code snippet: (see full working URL below too)
var gmarkers = [];
function loadGPXFileIntoGoogleMap(map, filename,recordNum, name, hex_code) {
$.ajax({
type: "GET",
url: filename,
dataType: "xml",
success: function(xml) {
var points = [];
var bounds = new google.maps.LatLngBounds ();
$(xml).find("trkpt").each(function() {
var lat = $(this).attr("lat");
var lon = $(this).attr("lon");
if((lat != 0) && (lon != 0))
{
var p = new google.maps.LatLng(lat, lon);
points.push(p);
bounds.extend(p);
}
});
var strokeColor = "#ff0000";
var poly = new google.maps.Polyline({
path: points,
strokeColor: strokeColor,
strokeOpacity: 1,
strokeWeight: 4,
recordNum: recordNum,
});
poly.setMap(map);
google.maps.event.addListener(poly, 'mouseover', function() {
var start = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#00ff00',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var end = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var markerStart = new google.maps.Marker({
position: poly.getPath().getAt(0),
icon: start,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerStart);
var markerEnd = new google.maps.Marker({
position: poly.getPath().getAt(poly.getPath().getLength() - 1),
icon: end,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerEnd);
var icons = this.setOptions({
icons: [{
icon: {
path: google.maps.SymbolPath.CIRCLE,
strokeOpacity: 1,
strokeColor: "#000000",
strokeWeight: 2,
scale: 4
},
}]});
animateRoute(poly);
});
function animateRoute(line) {
var count = 0;
window.setInterval(function() {
count = (count + 1) % 200;
var icons = poly.get('icons');
icons[0].offset = (count / 2) + '%';
poly.set('icons', icons);
}, 60);
}
google.maps.event.addListener(poly, 'mouseout', function() {
removeMarkers();
});
// fit bounds to track
map.fitBounds(bounds);
}
});
}
function removeMarkers(){
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
$(document).ready(function() {
var mapOptions = {
zoom: 17,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById("map"),
mapOptions);
loadGPXFileIntoGoogleMap(map, "cmsAdmin/uploads/blue_and_green_not_comfortable_.gpx","724","Example A","FFFF00");
loadGPXFileIntoGoogleMap(map, "cmsAdmin/uploads/taraweratrailrouterecce.gpx","431","Example B","4F4CBE");
});
Full working example:
https://www.wildthings.club/mapStack.php
Hover over the blue line and you'll see the animated dot.
Mouse off, and then after a few seconds hover again - a second dot will appear, and the first dot is still going.
Repeat and you'll soon have a bunch of jittery dots.
Ideally I'd like to remove all animated dots on mouseout.
Second option would be to not add a subsequent animated dot icon if there is already one on that polyLine (note there are multiple polyLines on the map).
Third option failing that would be to have the animated dot stop and remove once it reaches the end (position markerEnd) so at least it doesn't loop.
I have tried placing the icons into an array and then removing from there (like I have done with the gmarkers array and removeMarkers(), but no luck.
I also had a play with Animate google maps polyline but this just works with straight line point to point, rather than following a series of points from a GPX file.
Any help, most appreciated
Cheers
You should use the window.clearInterval() function to remove the interval you are using to animate the icon on the polyline. You should save the id when call window.setInterval() in animateRoute(). Here is a simple JSBin proof of concept adapted from the code on that website. In my code, I'm just simply using a global id variable, and updating that variable in animateRoute():
<!DOCTYPE html>
<html>
<head>
<title>Polyline path</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map {
height: 100%;
width: 100%;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var map;
var id;
var gmarkers = [];
var gmarkersicons = [];
function initMap() {
var mapOptions = {
zoom: 3,
mapTypeId: google.maps.MapTypeId.TERRAIN,
center: {lat: 9.291, lng: -157.821}
};
map = new google.maps.Map(document.getElementById("map"),
mapOptions);
var points = [
{lat: 37.772, lng: -122.214},
{lat: 21.291, lng: -157.821},
{lat: -18.142, lng: 178.431},
{lat: -27.467, lng: 153.027}
];
var poly = new google.maps.Polyline({
path: points,
strokeColor: "red",
strokeOpacity: 1,
strokeWeight: 4,
recordNum: "test"
});
poly.setMap(map);
google.maps.event.addListener(poly, 'mouseover', function() {
var start = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#00ff00',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var end = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 1,
strokeColor:'#000000',
strokeWeight: 4,
scale: 0.5
}
var go = {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#000000',
fillOpacity: 1,
strokeColor:'#fff',
strokeWeight: 4,
scale: 0.5
}
var markerStart = new google.maps.Marker({
position: poly.getPath().getAt(0),
icon: start,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerStart);
var markerEnd = new google.maps.Marker({
position: poly.getPath().getAt(poly.getPath().getLength() - 1),
icon: end,
map: map,
zIndex: 200,
scale: 1
});
gmarkers.push(markerEnd);
var icons = this.setOptions({
icons: [{
icon: {
path: google.maps.SymbolPath.CIRCLE,
strokeOpacity: 1,
strokeColor: "#000000",
strokeWeight: 2,
scale: 4
},
}]});
this.setOptions({
strokeColor: "red",
scale: 1,
strokeWeight:15,
strokeOpacity:.6
});
var contentString = "Testing";
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, markerStart);
id = animateRoute(poly);
});
function animateRoute(line) {
var count = 0;
var id = window.setInterval(function() {
count = (count + 1) % 200;
var icons = poly.get('icons');
icons[0].offset = (count / 2) + '%';
poly.set('icons', icons);
}, 60);
return id;
}
google.maps.event.addListener(poly, 'mouseout', function() {
removeMarkers();
this.setOptions({strokeColor:"red",strokeWeight:4,strokeOpacity:1});
this.setOptions( { suppressMarkers: true } );
this.setOptions({
icons: [{}]});
window.clearInterval(id);
});
function removeMarkers(){
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
}
$(document).ready(function() {
initMap();
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>

Draw Circles Inside Polygon in Google Maps

I'm using react.js and I currently know how to put a hole in a polygon via the following:
drawShape(google){
var entireMap = [
new google.maps.LatLng(-85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, -180),
new google.maps.LatLng(85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 180),
new google.maps.LatLng(-85.1054596961173, 0)];
var innerCoords = [
{lat: 28.745, lng: -70.579},
{lat: 29.570, lng: -67.514},
{lat: 27.339, lng: -66.668}
];
const poly = new google.maps.Polygon({
paths: [entireMap, innerCoords],
strokeColor: '#000000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#000000',
fillOpacity: 0.35
});
poly.setMap(google.map);
}
Right now, I have a list of properties that contain lng and lat. Instead of having polygon as holes I want to have circles as holes, using the lng and lat.
So far, I see that the documentation allows you to create circles separately:
var cityCircle = new google.maps.Circle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
center: citymap[city].center,
radius: Math.sqrt(citymap[city].population) * 100
});
However, I would like the circles to be "holes" within the entireMap polygon. Is it possible to combine the entireMap shape and circle shape or would I need to create a function that creates circles from the polygon shape?

Color variations Polyline property in Google maps API

I have requirement such that I need to draw a line between Sydney, Melbourne and Adelaide and the line between Sydney and Adelaide should be dark in color and the line between Melbourne and Adelaide should be lighter.
Is it possible in current API to provide this functionality in a single object:
new google.maps.Polyline({
});
To achieve the functionality?
One option would be to create google.maps.Polyline object per every line, below is provided the modified example from Simple Polylines page:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: {lat: -32.9340105, lng: 128.2698231},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
var flightPlanCoordinates = [
{lat: -33.877024, lng: 151.227963},
{lat: -37.816567, lng: 144.961489},
{lat: -34.930054, lng: 138.593065}
];
var flightPath = new google.maps.Polyline({
path: flightPlanCoordinates.slice(0,2),
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2,
map: map
});
var flightPath2 = new google.maps.Polyline({
path: flightPlanCoordinates.slice(1,3),
geodesic: true,
strokeColor: '#FFCC00',
strokeOpacity: 1.0,
strokeWeight: 2,
map: map
});
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
<div id="map"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
A single polyline has a single set of properties. You can do it with a single google.maps.Polyline for each unique set of properties, so in your example, two polylines.

Google Map circles are seems like hand drawn image

Google Maps circle looks like hand drawn.
Circle script is:
var circle = new google.maps.Circle({
center: myLatLng,
radius:1000,
strokeColor: "#000000",
strokeOpacity:1,
fillOpacity:0.4,
strokeWeight: 2,
fillColor: "#000000",
map:map
});
Can we make the circle more fine tuned.
My requirement is to show circle around marker with fine tuned circle border.
You could try using a symbol. I don't believe there's an option to change those circles from using the "hand-drawn" style. It's odd because their rectangles don't seem to be using that look.
Here is an example :
https://developers.google.com/maps/documentation/javascript/examples/marker-symbol-predefined
function initialize() {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(-25.363882, 131.044922)
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var myCircle = {
path: google.maps.SymbolPath.CIRCLE,
fillColor: 'red',
fillOpacity: 0.8,
scale: 20,
strokeColor: 'black',
strokeWeight: 3
};
var marker = new google.maps.Marker({
position: map.getCenter(),
icon: myCircle,
map: map
});
}
Here is an example of a circle around a marker :
function initialize() {
var myLatlng = new google.maps.LatLng(16.5083,80.64);var mapOptions = {zoom: 12,center: myLatlng};
var map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
var marker = new google.maps.Marker({map: map,position: myLatlng});
var circle = new google.maps.Circle({
map: map,
radius: 2000,
fillColor: '#000000',
fillOpacity: 0.4,
strokeColor: '#000000',
strokeWeight: 2
});
circle.bindTo('center', marker, 'position');
}
google.maps.event.addDomListener(window, 'load', initialize);

how to display same polygon on 2 maps present in different divs in the same page

I am using Google maps api V3.
I have a polygonpoints array as like in this Link's variable 'triangleCoords'.
I am generating maps dynamically using a button click..
I want to place the same polygon to be included in all maps.
As i am trying, the Polygon only displayed on the latest Map that is generated.
I want the Polygons to be like as in the Image Link
You can only add a google.maps.Polygon to one map. If you have multiple maps, you need to make one for each.
function initialize() {
var myLatLng = new google.maps.LatLng(24.886436490787712, -70.2685546875);
var mapOptions = {
zoom: 4,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var bermudaTriangle;
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var map2 = new google.maps.Map(document.getElementById('map-canvas2'),
mapOptions);
var map3 = new google.maps.Map(document.getElementById('map-canvas3'),
mapOptions);
var triangleCoords = [
new google.maps.LatLng(25.774252, -80.190262),
new google.maps.LatLng(18.466465, -66.118292),
new google.maps.LatLng(32.321384, -64.75737),
new google.maps.LatLng(25.774252, -80.190262)
];
// Construct the polygon
var bermudaTriangle1 = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
var bermudaTriangle2 = new google.maps.Polygon({
map: map2,
paths: triangleCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
var bermudaTriangle3 = new google.maps.Polygon({
map: map3,
paths: triangleCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
bermudaTriangle1.setMap(map);
}
example