I am trying to draw multiple polygons using google shapes API. I need to get the intersection of two polygons.
Here I can draw the background polygon(in black) by giving the array of path of each polygon.
Below is my code, here I am giving MVC Array as paths for polygon.
I just want the intersection area to be in separate color. Please check the screen shot link attached after the code.
var bgAreaCoordinates = [];
var bgbounds = map.getBounds(); // Boundary coordinates of the visible area of map
var NE = bgbounds.getNorthEast();
var SW = bgbounds.getSouthWest();
var bgPathCoordinates = [NE, new google.maps.LatLng(NE.lat(),SW.lng()),
SW, new google.maps.LatLng(SW.lat(),NE.lng())];
// Array of boundary coordinates of the visible part of the map
bgAreaCoordinates.push(bgPathCoordinates);
for (var key in flightPlanCoordinates) {
for (var k in flightPlanCoordinates[key]) {
bgAreaCoordinates.push(flightPlanCoordinates[key][k]);// Getting array of coordinates of each polygon
}
}
if (bgPath['bg']) {
bgPath['bg'].setMap(null); // remove the previous bg
}
console.info(bgAreaCoordinates);
bgPath['bg'] = new google.maps.Polygon({
// paths: [bgPathCoordinates, bgAreaCoordinates],
paths:bgAreaCoordinates,
geodesic: true,
strokeColor: '',
strokeOpacity: 0,
strokeWeight: 0,
fillColor: '#687472',
fillOpacity: 0.7
});
bgPath['bg'].setMap(map); // Draw the bg polygon : Google shapes Api
http://i.stack.imgur.com/VjTZe.png
Thanks in advance!
Here is an example that does what I think you want to do (make a hole in a polygon that covers the earth and cover that hole with a polygon with a different color). The example polygon happens to be a circle.
code snippet
// This example creates circles on the map, representing
// populations in the United States.
// First, create an object containing LatLng and population for each city.
var citymap = {};
citymap['chicago'] = {
center: new google.maps.LatLng(41.878113, -87.629798),
population: 2842518
};
citymap['newyork'] = {
center: new google.maps.LatLng(40.714352, -74.005973),
population: 8143197
};
citymap['losangeles'] = {
center: new google.maps.LatLng(34.052234, -118.243684),
population: 3844829
};
var cityCircle;
var bounds = new google.maps.LatLngBounds();
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 3963; // 3963 is the radius of the earth in miles
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point.lat() * d2r);
var extp = new Array();
if (dir == 1) {
var start = 0;
var end = points + 1
} // one extra here makes sure we connect the ends
else {
var start = points + 1;
var end = 0
}
for (var i = start;
(dir == 1 ? i < end : i > end); i = i + dir) {
var theta = Math.PI * (i / (points / 2));
ey = point.lng() + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point.lat() + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push(new google.maps.LatLng(ex, ey));
bounds.extend(extp[extp.length - 1]);
}
return extp;
}
function initialize() {
// Create the map.
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(37.09024, -95.712891),
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var outerbounds = [
new google.maps.LatLng(85, 180),
new google.maps.LatLng(85, 90),
new google.maps.LatLng(85, 0),
new google.maps.LatLng(85, -90),
new google.maps.LatLng(85, -180),
new google.maps.LatLng(0, -180),
new google.maps.LatLng(-85, -180),
new google.maps.LatLng(-85, -90),
new google.maps.LatLng(-85, 0),
new google.maps.LatLng(-85, 90),
new google.maps.LatLng(-85, 180),
new google.maps.LatLng(0, 180),
new google.maps.LatLng(85, 180)
];
var populationOptions = {
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
paths: [outerbounds, drawCircle(citymap['newyork'].center, 10, -1)]
};
// Add the circle for this city to the map.
cityCircle = new google.maps.Polygon(populationOptions);
map.fitBounds(bounds);
var coverHole = new google.maps.Polygon({
strokeColor: '#FFFF00',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#0000FF',
fillOpacity: 0.35,
map: map,
paths: [drawCircle(citymap['newyork'].center, 10, -1)]
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map-canvas"></div>
Related
I want to draw Hexagon polygon on google map based on zip code (single lat, long). How can I get other lat long so I can pass it to polygon array based on single lat long, It would be also based on any radius e.g. 15 miles or 15 km.
Here is sample google map image.
One option is to use code from Mike Williams' eshapes ported to v3.
proof of concept fiddle
from his documentation for a RegularPoly:
Plots a regular polygon (e.g. pentagon, square, octagon) with a specified centre, radius, number of vertices, and rotation.
Parameters
latlng Centre of the shape
radius Length of radius in metres
vertexCount Number of vertices, e.g. 5 for a pentagon
rotation Degrees of rotation.
When zero or omitted the southern edge of the shape is horizontal
color Color parameter for polyline
weight Weight parameter for polyline
opacity Opacity parameter for polyline
opts Options parameter for polyline
code snippet:
var geocoder = new google.maps.Geocoder();
var map;
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
codeAddress("Atlanta, GA");
}
function codeAddress(address) {
geocoder.geocode({
'address': address
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
// === Hexagon ===
var point = results[0].geometry.location;
var hex1 = google.maps.Polygon.RegularPoly(point, 25000, 6, 60, "#000000", 1, 1, "#ff0000", 0.5);
hex1.setMap(map);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
google.maps.event.addDomListener(window, "load", initialize);
// original code from Mike Williams' eshapes.js
// http://econym.org.uk/gmap/eshapes.htm
// ported to the Google Maps Javascript API v3
google.maps.Polygon.RegularPoly = function(point, radius, vertexCount, rotation, strokeColour, strokeWeight, Strokepacity, fillColour, fillOpacity, opts) {
rotation = rotation || 0;
var tilt = !(vertexCount & 1);
return google.maps.Polygon.Shape(point, radius, radius, radius, radius, rotation, vertexCount, strokeColour, strokeWeight, Strokepacity, fillColour, fillOpacity, opts, tilt)
}
google.maps.Polygon.Shape = function(point, r1, r2, r3, r4, rotation, vertexCount, strokeColour, strokeWeight, Strokepacity, fillColour, fillOpacity, opts, tilt) {
var rot = -rotation * Math.PI / 180;
var points = [];
var latConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat() + 0.1, point.lng())) * 10;
var lngConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat(), point.lng() + 0.1)) * 10;
var step = (360 / vertexCount) || 10;
var flop = -1;
if (tilt) {
var I1 = 180 / vertexCount;
} else {
var I1 = 0;
}
for (var i = I1; i <= 360.001 + I1; i += step) {
var r1a = flop ? r1 : r3;
var r2a = flop ? r2 : r4;
flop = -1 - flop;
var y = r1a * Math.cos(i * Math.PI / 180);
var x = r2a * Math.sin(i * Math.PI / 180);
var lng = (x * Math.cos(rot) - y * Math.sin(rot)) / lngConv;
var lat = (y * Math.cos(rot) + x * Math.sin(rot)) / latConv;
points.push(new google.maps.LatLng(point.lat() + lat, point.lng() + lng));
}
return (new google.maps.Polygon({
paths: points,
strokeColor: strokeColour,
strokeWeight: strokeWeight,
strokeOpacity: Strokepacity,
fillColor: fillColour,
fillOpacity: fillOpacity
}))
}
function EOffset(point, easting, northing) {
var latConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat() + 0.1, point.lng())) * 10;
var lngConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat(), point.lng() + 0.1)) * 10;
return new google.maps.LatLng(point.lat() + northing / latConv, point.lng() + easting / lngConv)
}
function EOffsetBearing(point, dist, bearing) {
var latConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat() + 0.1, point.lng())) * 10;
var lngConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat(), point.lng() + 0.1)) * 10;
var lat = dist * Math.cos(bearing * Math.PI / 180) / latConv;
var lng = dist * Math.sin(bearing * Math.PI / 180) / lngConv;
return new google.maps.LatLng(point.lat() + lat, point.lng() + lng)
}
html,
body,
#map_canvas {
height: 500px;
width: 500px;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>
You could calculate and draw hexagon area based on lat/lng using the following approach:
function drawHexagon(map,position,radius){
var coordinates = [];
for(var angle= -90;angle < 270; angle+=60) {
coordinates.push(google.maps.geometry.spherical.computeOffset(position, radius, angle));
}
// Construct the polygon.
var polygon = new google.maps.Polygon({
paths: coordinates,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
polygon.setMap(map);
map.setCenter(position);
}
Complete example
function initialize() {
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
var position = new google.maps.LatLng(33.748589, -84.390392); //Atlanta, GA, USA
var radius = 50 * 1000; //radius in meters
drawHexagon(map,position,radius);
}
function drawHexagon(map,position,radius){
var coordinates = [];
for(var angle= -90;angle < 270; angle+=60) {
coordinates.push(google.maps.geometry.spherical.computeOffset(position, radius, angle));
}
// Construct the polygon.
var polygon = new google.maps.Polygon({
paths: coordinates,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
polygon.setMap(map);
map.setCenter(position);
}
google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=geometry"></script>
<div id="map-canvas"></div>
I use Google maps, I mark areas on the maps like that:
var areaCoords2 = [
new google.maps.LatLng(32.819649, 35.073102),
new google.maps.LatLng(32.819604, 35.073026),
new google.maps.LatLng(32.817169, 35.071321),
new google.maps.LatLng(32.817097, 35.071353),
new google.maps.LatLng(32.816042, 35.073391),
new google.maps.LatLng(32.818513, 35.075119),
new google.maps.LatLng(32.818612, 35.075054)
];
I want to achieve: place the label and the marker in the middle(approximately) of the marked red area.
instead of place it with static Latitude and Longitude(I have a lot of areas)
There is a way of doing so programmatically?
The following code constructs a google.maps.Polygon and places a MapLabel at the center of its bounds.
// Construct the polygon.
var mypolygon2 = new google.maps.Polygon({
paths: polyCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35
});
mypolygon2.setMap(map);
//Define position of label
var bounds = new google.maps.LatLngBounds();
for (var i=0; i< polyCoords.length; i++) {
bounds.extend(polyCoords[i]);
}
var myLatlng = bounds.getCenter();
var mapLabel2 = new MapLabel({
text: '2',
position: myLatlng,
map: map,
fontSize: 20,
align: 'left'
});
mapLabel2.set('position', myLatlng);
var obj = {};
obj.poly = mypolygon2;
obj.label = mapLabel2;
working fiddle
code snippet:
var map;
var gpolygons = [];
var infoWindow;
function initialize() {
var mapOptions = {
zoom: 17,
center: new google.maps.LatLng(50.71392, -1.983551),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Define the LatLng coordinates for the polygon.
var triangleCoords = [
new google.maps.LatLng(50.71433, -1.98392),
new google.maps.LatLng(50.71393, -1.98239),
new google.maps.LatLng(50.71388, -1.98226),
new google.maps.LatLng(50.71377, -1.98246),
new google.maps.LatLng(50.71332, -1.98296),
new google.maps.LatLng(50.71334, -1.98324),
new google.maps.LatLng(50.71374, -1.9845),
new google.maps.LatLng(50.71436, -1.98389)
];
// Construct the polygon.
var mypolygon = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35
});
mypolygon.setMap(map);
//Define position of label
var myLatlng = new google.maps.LatLng(50.71392, -1.983551);
var mapLabel = new MapLabel({
text: '1',
position: myLatlng,
map: map,
fontSize: 20,
align: 'left'
});
mapLabel.set('position', myLatlng);
var obj = {};
obj.poly = mypolygon;
obj.label = mapLabel;
gpolygons.push(obj);
var polyCoords = [
new google.maps.LatLng(50.713689004418, -1.9845771789550781),
new google.maps.LatLng(50.71316590540595, -1.9829249382019043),
new google.maps.LatLng(50.71296209901576, -1.983107328414917),
new google.maps.LatLng(50.71296889257639, -1.9837510585784912),
new google.maps.LatLng(50.713186285996215, -1.9845235347747803),
new google.maps.LatLng(50.71293492476347, -1.9847595691680908),
new google.maps.LatLng(50.71311155712187, -1.9853174686431885),
new google.maps.LatLng(50.71335612390394, -1.9853603839874268),
new google.maps.LatLng(50.713396884910225, -1.9850599765777588),
new google.maps.LatLng(50.71348520030224, -1.9848453998565674),
new google.maps.LatLng(50.71357351552787, -1.9846951961517334)
]
// Construct the polygon.
var mypolygon2 = new google.maps.Polygon({
paths: polyCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 3,
fillColor: '#FF0000',
fillOpacity: 0.35
});
mypolygon2.setMap(map);
//Define position of label
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < polyCoords.length; i++) {
bounds.extend(polyCoords[i]);
}
var myLatlng = bounds.getCenter();
var mapLabel2 = new MapLabel({
text: '2',
position: myLatlng,
map: map,
fontSize: 20,
align: 'left'
});
mapLabel2.set('position', myLatlng);
var obj = {};
obj.poly = mypolygon2;
obj.label = mapLabel2;
gpolygons.push(obj);
// Add a listener for the click event. You can expand this to change the color of the polygon
google.maps.event.addListener(mypolygon, 'click', showArrays);
google.maps.event.addListener(mypolygon2, 'click', showArrays);
infoWindow = new google.maps.InfoWindow();
}
/** #this {google.maps.Polygon} */
function showArrays(event) {
//Change the color here
// toggle it
if (this.get("fillColor") != '#0000ff') {
this.setOptions({
fillColor: '#0000ff'
});
} else {
this.setOptions({
fillColor: '#ff0000'
});
}
// Since this polygon has only one path, we can call getPath()
// to return the MVCArray of LatLngs.
var vertices = this.getPath();
var contentString = '<b>My polygon</b><br>' +
'Clicked location: <br>' + event.latLng.lat() + ',' + event.latLng.lng() +
'<br>';
// Iterate over the vertices.
for (var i = 0; i < vertices.getLength(); i++) {
var xy = vertices.getAt(i);
contentString += '<br>' + 'Coordinate ' + i + ':<br>' + xy.lat() + ',' + xy.lng();
}
// Replace the info window's content and position.
infoWindow.setContent(contentString);
infoWindow.setPosition(event.latLng);
infoWindow.open(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<script src="https://cdn.rawgit.com/googlemaps/js-map-label/gh-pages/src/maplabel.js"></script>
<title>Polygon Arrays</title>
<div id="map-canvas">
</div>
Here is a method that does what you ask for Android/Java. You can try to adjust it for use in the web:
public Location GetCentrePointFromListOfLocations(List<Location> coordList)
{
int total = coordList.size();
double X = 0;
double Y = 0;
double Z = 0;
for(Location location : coordList)
{
double lat = location.getLatitude() * Math.PI / 180;
double lon = location.getLongitude() * Math.PI / 180;
double x = Math.cos(lat) * Math.cos(lon);
double y = Math.cos(lat) * Math.sin(lon);
double z = Math.sin(lat);
X += x;
Y += y;
Z += z;
}
X = X / total;
Y = Y / total;
Z = Z / total;
double Lon = Math.atan2(Y, X);
double Hyp = Math.sqrt(X * X + Y * Y);
double Lat = Math.atan2(Z, Hyp);
Location tempLocation = new Location("");
tempLocation.setLatitude(Lat * 180 / Math.PI);
tempLocation.setLongitude(Lon * 180 / Math.PI);
return tempLocation;
}
Did you add
zoom: 10,
center: myLatlng,
for you Marker Object
(or)
// map: an instance of GMap3
// latlng: an array of instances of GLatLng
var latlngbounds = new google.maps.LatLngBounds();
latlng.each(function(n){
latlngbounds.extend(n);
});
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);
This one works for me with the dynamic polygon values.
<script type="text/javascript" src="https://cdn.rawgit.com/googlemaps/js-map-label/gh-pages/src/maplabel.js"></script>
<script>
// This example creates a simple polygon representing the Bermuda Triangle.
var gpolygons = [];
function initStaticMap() {
var bounds = new google.maps.LatLngBounds();
var latlng = new google.maps.LatLng(-22.5747697,-43.857650); //-22.820554842103107--43.184738187119365
var map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 10,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
// Define the LatLng coordinates for the polygon's path.
<?php if($store_delivery_zone){ foreach($store_delivery_zone as $point){ ?>
var coord<?php echo $point['delivery_zone_id']; ?> = <?php echo $point['polygon_points']; ?>;
// Construct the polygon.
var poly<?php echo $point['delivery_zone_id']; ?> = new google.maps.Polygon({
paths: coord<?php echo $point['delivery_zone_id']; ?>,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
poly<?php echo $point['delivery_zone_id']; ?>.setMap(map);
//var center = poly<?php echo $point['delivery_zone_id']; ?>.getBounds().getCenter();
//map.fitBounds(poly<?php echo $point['delivery_zone_id']; ?>.getBounds());
//Define position of label
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < coord<?php echo $point['delivery_zone_id']; ?>.length; i++) {
bounds.extend(coord<?php echo $point['delivery_zone_id']; ?>[i]);
}
var myLatlng<?php echo $point['delivery_zone_id']; ?> = bounds.getCenter();
var mapLabel<?php echo $point['delivery_zone_id']; ?> = new MapLabel({
text: '<?php echo $point['delivery_cost']; ?>',
position: myLatlng<?php echo $point['delivery_zone_id']; ?>,
map: map,
fontSize: 20,
align: 'left'
});
mapLabel<?php echo $point['delivery_zone_id']; ?>.set('position', myLatlng<?php echo $point['delivery_zone_id']; ?>);
var obj = {};
obj.poly = poly<?php echo $point['delivery_zone_id']; ?>;
obj.label = mapLabel<?php echo $point['delivery_zone_id']; ?>;
gpolygons.push(obj);
<?php } } ?>
google.maps.event.addListener(map, "idle", function()
{
google.maps.event.trigger(map, 'resize');
});
}
</script>
For Android/Java there is no need to start inventing an algorithm yourself, JTS is the package for such functionality.
// use jts to get suitable coordinate for label inside polygon
// convert google maps latlong to jts coordinates
List<Coordinate> jtsCoordinateList = new ArrayList<>();
for (LatLng gMapLatLng : polygon.getPoints())
jtsCoordinateList.add(new Coordinate(gMapLatLng.latitude, gMapLatLng.longitude));
Coordinate[] jtsCoordinateArray = jtsCoordinateList.toArray(new Coordinate[0]);
// create jts polygon
Geometry jtsGeometry = new GeometryFactory().createPolygon(jtsCoordinateArray);
// initiate InteriorPointArea
InteriorPointArea interiorPointArea = new InteriorPointArea(jtsGeometry);
// use InteriorPointArea to get the coordinate
Coordinate jtsInteriorPoint = interiorPointArea.getInteriorPoint();
// convert jts coordinate to google maps coordinate
LatLng polygonPoint = new LatLng(jtsInteriorPoint.getX(), jtsInteriorPoint.getY());
// use the calculated coordinate to place a marker
marker = createViewMarker(context, map, polygonPoint, legend);
After drawing a Polygon shape on the map. I would like to change what direction the polygon is pointing when the map is refreshed by rotating around one of the points of the polygon. For example point the polygon in the direction of 90 degrees rotating around my first polygon point (code shown below). Can anyone provide any code examples of this working?
I have seen some similar posts however examples given appear over complicated.
poly = new google.maps.Polygon({
strokeWeight: 3,
fillColor: '#5555FF'
});
poly.setMap(map);
poly.setPaths(new google.maps.MVCArray([path]));
var triangleCoords = [
new google.maps.LatLng(51.5087, -0.1277),
new google.maps.LatLng(51.5387, -0.1077),
new google.maps.LatLng(51.5387, -0.1477),
new google.maps.LatLng(51.5087, -0.1277)
];
// Construct the polygon
triangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.8
});
triangle.setMap(map);
google.maps.event.addListener(map, 'click', triangle);
}
The following example demonstrates how to rotate a polygon
Note: the rotation is performed around the first point
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: {lat: 24.886, lng: -70.268},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
// Define the LatLng coordinates for the polygon's path.
var triangleCoords = [
{lat: 25.774, lng: -80.190},
{lat: 18.466, lng: -66.118},
{lat: 32.321, lng: -64.757},
{lat: 25.774, lng: -80.190}
];
// Construct the polygon.
var bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
bermudaTriangle.setMap(map);
//rotate a polygon
document.getElementById('btnRotate').onclick = function() {
rotatePolygon(bermudaTriangle, 90);
};
}
function rotatePolygon(polygon,angle) {
var map = polygon.getMap();
var prj = map.getProjection();
var origin = prj.fromLatLngToPoint(polygon.getPath().getAt(0)); //rotate around first point
var coords = polygon.getPath().getArray().map(function(latLng){
var point = prj.fromLatLngToPoint(latLng);
var rotatedLatLng = prj.fromPointToLatLng(rotatePoint(point,origin,angle));
return {lat: rotatedLatLng.lat(), lng: rotatedLatLng.lng()};
});
polygon.setPath(coords);
}
function rotatePoint(point, origin, angle) {
var angleRad = angle * Math.PI / 180.0;
return {
x: Math.cos(angleRad) * (point.x - origin.x) - Math.sin(angleRad) * (point.y - origin.y) + origin.x,
y: Math.sin(angleRad) * (point.x - origin.x) + Math.cos(angleRad) * (point.y - origin.y) + origin.y
};
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: 'Roboto','sans-serif';
line-height: 30px;
padding-left: 10px;
}
<div id="floating-panel">
<input type="button" id="btnRotate" value="Rotate 90"></div>
<div id="map"></div>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
JSFiddle
You might want to look at something like Mike Williams' eshapes library. It was written originally for the Google Maps API v2, but this page demonstrates the version that I ported to the Google Maps API v3.
example
proof of concept fiddle
code snippet;
var map = null;
var triangle, angle, point;
function initMap() {
point = new google.maps.LatLng(44, -80);
var myOptions = {
zoom: 8,
center: point,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map"),
myOptions);
angle = 0;
// === Triangle ===
triangle = google.maps.Polyline.RegularPoly(point, 30000, 3, angle, "#ff0000", 8, 1);
triangle.setMap(map);
google.maps.event.addListener(triangle, "click", rotateTriangle);
}
google.maps.event.addDomListener(window, 'load', initMap);
function rotateTriangle() {
triangle.setMap(null);
angle += 90;
if (angle >= 360) angle -= 360;
triangle = google.maps.Polyline.RegularPoly(point, 30000, 3, angle, "#ff0000", 8, 1);
triangle.setMap(map);
google.maps.event.addListener(triangle, "click", rotateTriangle);
}
// This Javascript is based on code provided by the
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/
// http://econym.org.uk/gmap/
// From v3_eshapes.js:
// EShapes.js
//
// Based on an idea, and some lines of code, by "thetoy"
//
// This Javascript is provided by Mike Williams
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/
// http://econym.org.uk/gmap/
//
// This work is licenced under a Creative Commons Licence
// http://creativecommons.org/licenses/by/2.0/uk/
//
// Version 0.0 04/Apr/2008 Not quite finished yet
// Version 1.0 10/Apr/2008 Initial release
// Version 3.0 12/Oct/2011 Ported to v3 by Lawrence Ross
google.maps.Polyline.RegularPoly = function(point, radius, vertexCount, rotation, colour, weight, opacity, opts) {
rotation = rotation || 0;
var tilt = !(vertexCount & 1);
return google.maps.Polyline.Shape(point, radius, radius, radius, radius, rotation, vertexCount, colour, weight, opacity, opts, tilt)
}
google.maps.Polyline.Shape = function(point, r1, r2, r3, r4, rotation, vertexCount, colour, weight, opacity, opts, tilt) {
if (!colour) {
colour = "#0000FF";
}
if (!weight) {
weight = 4;
}
if (!opacity) {
opacity = 0.45;
}
var rot = -rotation * Math.PI / 180;
var points = [];
var latConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat() + 0.1, point.lng())) * 10;
var lngConv = google.maps.geometry.spherical.computeDistanceBetween(point, new google.maps.LatLng(point.lat(), point.lng() + 0.1)) * 10;
var step = (360 / vertexCount) || 10;
var flop = -1;
if (tilt) {
var I1 = 180 / vertexCount;
} else {
var I1 = 0;
}
for (var i = I1; i <= 360.001 + I1; i += step) {
var r1a = flop ? r1 : r3;
var r2a = flop ? r2 : r4;
flop = -1 - flop;
var y = r1a * Math.cos(i * Math.PI / 180);
var x = r2a * Math.sin(i * Math.PI / 180);
var lng = (x * Math.cos(rot) - y * Math.sin(rot)) / lngConv;
var lat = (y * Math.cos(rot) + x * Math.sin(rot)) / latConv;
points.push(new google.maps.LatLng(point.lat() + lat, point.lng() + lng));
}
return (new google.maps.Polyline({
path: points,
strokeColor: colour,
strokeWeight: weight,
strokeOpacity: opacity
}))
}
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<b>Click triangle's border to rotate it.</b>
<div id="map"></div>
I had the same issue, i wanted to rotate a symbol or polygon. The rotation attribute defines the rotation of the object and thats all.
Try it.
The path defines the shape of the polygon and uses SVG notation like (x,y) coordinates.
function init_nuevo_mapa(){
var mapOptions = {
zoom: 13
center: new google.maps.LatLng(-33.5351136,-70.5876618)
};
var new_map = new google.maps.Map(document.getElementById('new-map'), mapOptions);
var myLatLng = new google.maps.LatLng(-33.5351136,-70.5876618)
var image = {
path: 'M 0,0 -10,-30 10,-30 z',
rotation: 10, //10ยบ clockwise
fillColor: "red",
fillOpacity: 0.5,
scale: 1,
strokeColor: "red",
strokeWeight: 4
};
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
zIndex: zIndex,
title: location[2]
});
You can easily do it with the new Google Maps symbol object. Just take a look at https://developers.google.com/maps/documentation/javascript/reference#Symbol.
Warning: This works really bad with IE 9 when you have a lot of markers.
Good luck!
I'm drawing two polygons on the map. The second polygon makes a hole in the first one. I want the first polygon to cover as much as possible of the earth. So lets focus on that and drop the hole for the time.
Since max/min lat = 90,-90 and max/min lng = 180, -180.
If I draw the following the seems to "eat each other up"
nw = new google.maps.LatLng(90, -180, true);
ne = new google.maps.LatLng(90, 180, true);
se = new google.maps.LatLng(-90, 180, true);
sw = new google.maps.LatLng(-90, -180, true);
points = [nw, ne, se, sw];
If I tweak the values a little I can get them to not eat up each other but I'm always left with quite a big miss.
Thanks in advance.
I got it to work, here is the code:
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script type="text/javascript">
function drawCircle(point, radius, dir) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var earthsradius = 3963; // 3963 is the radius of the earth in miles
var points = 1000;
// find the raidus in lat/lon
var rlat = (radius / earthsradius) * r2d;
var rlng = rlat / Math.cos(point.lat() * d2r);
var extp = new Array();
if (dir==1) {var start=0;var end=points+1} // one extra here makes sure we connect the
else {var start=points+1;var end=0}
for (var i=start; (dir==1 ? i < end : i > end); i=i+dir)
{
var theta = Math.PI * (i / (points/2));
ey = point.lng() + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point.lat() + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push(new google.maps.LatLng(ex, ey));
bounds.extend(extp[extp.length-1]);
}
// alert(extp.length);
return extp;
}
var map = null;
var bounds = null;
function initialize() {
var myOptions = {
zoom: 10,
center: new google.maps.LatLng(42,-80),
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.TERRAIN
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
bounds = new google.maps.LatLngBounds();
var donut = new google.maps.Polygon({
paths: [triangleCoords = [
new google.maps.LatLng(-87, 120),
new google.maps.LatLng(-87, -87),
new google.maps.LatLng(-87, 0)],
drawCircle(new google.maps.LatLng(42,-80), 1000, -1)],
strokeColor: "#000000",
strokeOpacity: 0.6,
strokeWeight: 2,
fillColor: "#999999",
fillOpacity: 0.6
});
donut.setMap(map);
map.fitBounds(bounds);
}
</script>
There doesn't seem to be a length funciton for the Polyline in Google Maps anymore in V3.
Has anyone found a workaround for this functionality gap?
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?libraries=geometry&sensor=true"></script>
... var path = poly.getPath(); // or:
var path = polygon.getPath();
... = google.maps.geometry.spherical.computeLength(path.getArray())
... = google.maps.geometry.spherical.computeArea(path.getArray())
--> distance for polyline, area for polygon
and between two points:
computeDistanceBetween()
Don't forget to specify the geometry library (libraries=geometry)
http://code.google.com/apis/maps/documentation/javascript/geometry.html
here's the prototypes for the required function - hope this helps any further:
google.maps.Polygon.prototype.Distance = function() {
var dist = 0;
for (var i=1; i < this.getPath().getLength(); i++) {
dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1));
}
return dist;
}
google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
//var R = 6371; // km (change this constant to get miles)
var R = 6378100; // meters
var lat1 = this.lat();
var lon1 = this.lng();
var lat2 = newLatLng.lat();
var lon2 = newLatLng.lng();
var dLat = (lat2-lat1) * Math.PI / 180;
var dLon = (lon2-lon1) * Math.PI / 180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
source
There is now a method in the Google Maps Javascript API v3 geometry library to compute the distance between two google.maps.LatLng objects in meters google.maps.geometry.spherical.computeDistanceBetween.
And a method in the Google Maps Javascript API v3 geometry library to compute the length of a polyline google.maps.geometry.poly.computeLength.
Concept from the Google Maps JavaScript API v3 groups post referenced in Hamish's answer, but using the Google Maps Javascript API v3 geometry library method computeDistanceBetween:
google.maps.Polyline.prototype.inKm = function(n) {
var a = this.getPath(n),
len = a.getLength(),
dist = 0;
for (var i = 0; i < len - 1; i++) {
dist += google.maps.geometry.spherical.computeDistanceBetween(a.getAt(i), a.getAt(i + 1));
}
return dist / 1000;
}
The result is the length of the polyline in kilometers. The optional
parameter is the path index of multi path polylines.
proof of concept fiddle
Using computeLength:
google.maps.geometry.spherical.computeLength(poly.getPath())/1000
proof of concept fiddle
code snippet:
var map;
var poly;
var gmarkers = [];
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'click', addLatLng);
var polyCoord = [
new google.maps.LatLng(41.86, 8.73),
new google.maps.LatLng(41.88, 8.75)
];
var bounds = new google.maps.LatLngBounds();
bounds.extend(polyCoord[0]);
bounds.extend(polyCoord[1]);
map.fitBounds(bounds);
google.maps.event.addListenerOnce(map, 'bounds_changed', function() {
map.setZoom(map.getZoom() - 2);
});
// Polyline
poly = new google.maps.Polyline({
path: polyCoord
});
poly.binder = new MVCArrayBinder(poly.getPath());
var marker0 = new google.maps.Marker({
position: event.latLng,
title: '#0',
map: map,
icon: {
path: 'M256,320c-70.688,0-128-57.312-128-128c0-70.687,57.313-128,128-128c70.688,0,128,57.313,128,128C384,262.688,326.688,320,256,320z',
fillColor: 'white',
fillOpacity: 1,
scale: 0.025,
strokeColor: 'black',
strokeWeight: 1,
strokeOpacity: 1,
anchor: new google.maps.Point(200, 200)
},
draggable: true
});
marker0.bindTo('position', poly.binder, (0).toString());
google.maps.event.addListener(marker0, 'dragend', updateLength);
gmarkers.push(marker0);
var marker1 = new google.maps.Marker({
position: event.latLng,
title: '#1',
map: map,
icon: {
path: 'M256,320c-70.688,0-128-57.312-128-128c0-70.687,57.313-128,128-128c70.688,0,128,57.313,128,128C384,262.688,326.688,320,256,320z',
fillColor: 'white',
fillOpacity: 1,
scale: 0.025,
strokeColor: 'black',
strokeWeight: 1,
strokeOpacity: 1,
anchor: new google.maps.Point(200, 200)
},
draggable: true
});
marker1.bindTo('position', poly.binder, (1).toString());
google.maps.event.addListener(marker1, 'dragend', updateLength);
gmarkers.push(marker1);
poly.setMap(map);
updateLength();
}
function updateLength() {
document.getElementById('length').value = (google.maps.geometry.spherical.computeLength(poly.getPath()) / 1000).toFixed(2);
};
google.maps.event.addDomListener(window, "load", initialize);
/**
* Handles click events on a map, and adds a new point to the Polyline.
* #param {MouseEvent} mouseEvent
*/
function addLatLng(event) {
var path = poly.getPath();
path.push(event.latLng);
var len = path.getLength();
var marker = new google.maps.Marker({
position: event.latLng,
title: '#' + len,
map: map,
icon: {
path: 'M256,320c-70.688,0-128-57.312-128-128c0-70.687,57.313-128,128-128c70.688,0,128,57.313,128,128C384,262.688,326.688,320,256,320z',
fillColor: 'white',
fillOpacity: 1,
scale: 0.025,
strokeColor: 'black',
strokeWeight: 1,
strokeOpacity: 1,
anchor: new google.maps.Point(200, 200)
},
draggable: true
});
gmarkers.push(marker);
marker.bindTo('position', poly.binder, (len - 1).toString());
google.maps.event.addListener(marker, 'dragend', updateLength);
document.getElementById('length').value = poly.inKm().toFixed(2);
}
/*
* Use bindTo to allow dynamic drag of markers to refresh poly.
*/
function MVCArrayBinder(mvcArray) {
this.array_ = mvcArray;
}
MVCArrayBinder.prototype = new google.maps.MVCObject();
MVCArrayBinder.prototype.get = function(key) {
if (!isNaN(parseInt(key))) {
return this.array_.getAt(parseInt(key));
} else {
this.array_.get(key);
}
}
MVCArrayBinder.prototype.set = function(key, val) {
if (!isNaN(parseInt(key))) {
this.array_.setAt(parseInt(key), val);
} else {
this.array_.set(key, val);
}
}
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>
<label>polyline length (km):</label>
<input id="length" type="text" />
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>
It has to be done segment by segment.
See this Google Maps JavaScript API v3 groups post for a suggested solution.
I went looking for the same information and found that the api call you're looking for is in the geometry.spherical namespace.
Here's the code I'm using:
//Path is the mvc array of lat/lng that makes up the polyline
var path = $scope.courseLine.getPath();
$scope.totalDistance = google.maps.geometry.spherical.computeLength(path);
$scope.totalMiles = ($scope.totalDistance * 0.00062137).toFixed(2) + " mi";
});
If you got the polyline from DirectionsService, check distance and duration in DirectionsLeg.
https://developers.google.com/maps/documentation/javascript/reference#DirectionsLeg
Get the distance between the 2 LatLngs it connects using the haversine formula