google.maps.Circle snap to nearest mile - javascript

Created some functionality in google v3 api where users can drop a pin. Once they drop a pin an editable circle is created with the pin as the center. They can expand the circle and see the distance which pops up in an infowindow. The issue is that it is difficult to get to the nearest mile or half mile. I will try to get it to the nearest mile by dragging the circle and it gets to like 10.23 miles...
Does anyone have recommendation about this?
http://jsfiddle.net/wa8s0dya/
//create circle
function createCircle() {
if ((circle != null) && circle.setMap) {
circle.setMap(null);
circle = null;
}
var options = {
strokeColor: '#0099FF',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#0099FF',
fillOpacity: 0.35,
map: map,
center: marker.getPosition(),
editable: true,
radius: 500
};
// Add the circle for this city to the map.
circle = new google.maps.Circle(options);
google.maps.event.addListener(circle, 'radius_changed', function () {
removeInfoWindow();
popUpPinInfo(marker, circle.radius, map);
});
google.maps.event.addListener(circle, 'circlecomplete', function () {
removeInfoWindow();
popUpPinInfo(marker, circle.radius, map);
});
}

One mile is 1609.34 meters (the circle's radius is defined in meters).
To make the circle size in increments of 1 mile, you need to make the radius (the +8m causes it to not get rounded down to .99 miles):
circle.setRadius(circle.getRadius() - (circle.getRadius() % 1609.34)+8);
Whenever the radius changes:
google.maps.event.addListener(circle, 'radius_changed', function () {
if ((circle.getRadius() % 1609.34) > 160) {
circle.setRadius(circle.getRadius() - (circle.getRadius() % 1609.34)+8) // meters per mile
}
removeInfoWindow();
popUpPinInfo(marker, circle.radius, map);
});
google.maps.event.addListener(circle, 'circlecomplete', function () {
circle.setRadius(circle.getRadius() - (circle.getRadius() % 1609.34)+8) // meters per mile
removeInfoWindow();
popUpPinInfo(marker, circle.radius, map);
});
updated fiddle

Related

Google Maps Api draw my polygon (rectangle) as parallelogram

I can't manage with drawing rectangle between two cities. I've searched everywhere on the Internet and can't find out why my polygon is drawn on Google Maps as parallelogram even so on 2d plane (not earth plane) this rectangle is drawn properly.
What I noticed is that the curvature sides of parallelogram depends on where cities are placed on map. If two cities are placed vis-a-vis then my function draw rectangle successfully. But If they are placed diagonally then my function draw parallelogram. The result should be rotated rectangle with height as distance between two cities and width as kilometers that user chooses.
Here is my function that should draw rectangle between two cities. As args we need to give position of first city ($x1 is lat, $y1 is lng), position of second city and as third arg a radius in kilometers ($l1) from center point of rectangle.
function getPolygon($x1,$y1,$x2,$y2,$l1){
var $l1 = $l1*0.010526; //approx kilometers
var $distanceV = [($x2 - $x1), ($y2 - $y1)];
var $vlen = Math.sqrt(Math.pow($distanceV[0], 2) +
Math.pow($distanceV[1],2));
if($vlen == 0)
return [[0,0],[0,0],[0,0],[0,0]];
var $l2 = $vlen;
var $normalized = [($distanceV[0] / $vlen), ($distanceV[1] / $vlen)];
var $rotated = [(-1 * $normalized[1]), ($normalized[0])];
var $p1 = [($x1 - $rotated[0] * $l1 / 2), ($y1 - $rotated[1] * $l1 / 2)];
var $p2 = [($p1[0] + $rotated[0] * $l1), ($p1[1] + $rotated[1] * $l1)];
var $p3 = [($p1[0] + $normalized[0] * $l2), ($p1[1] + $normalized[1] * $l2)];
var $p4 = [($p3[0] + $rotated[0] * $l1), ($p3[1] + $rotated[1] * $l1)];
var $points = [
{lat: $p1[0], lng: $p1[1]},
{lat: $p3[0], lng: $p3[1]},
{lat: $p4[0], lng: $p4[1]},
{lat: $p2[0], lng: $p2[1]},
{lat: $p1[0], lng: $p1[1]}
];
return $points;
}
Then I draw it on Google Maps like this:
new google.maps.Polygon({
paths: getPolygon(first_city_lat, first_city_lng, second_city_lat, second_city_lng, 30),
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.05
});
Here is an example should be rectangle between Birmingham and Oxford: JSFiddle
Additionally I'm sure that kilometers converter is not exact and it again depends how cities are placed.
The earth is curved. To get a polygon that appears rectangular on the curved sphere, you need to use calculations that take the projection of the map into account.
The Google Maps Javascript API v3 has a spherical geometry library that can be used to compute the desired points.
function getPolygon($x1,$y1,$x2,$y2,$l1){
var points = [];
var city1 = new google.maps.LatLng($x1, $y1);
var city2 = new google.maps.LatLng($x2, $y2);
var heading = google.maps.geometry.spherical.computeHeading(city1, city2);
points.push(google.maps.geometry.spherical.computeOffset(city1, $l1/2*1000, heading+90));
points.push(google.maps.geometry.spherical.computeOffset(city1, $l1/2*1000, heading-90));
points.push(google.maps.geometry.spherical.computeOffset(city2, $l1/2*1000, heading-90));
points.push(google.maps.geometry.spherical.computeOffset(city2, $l1/2*1000, heading+90));
points.push(points[0]);
return points;
}
proof of concept fiddle
code snippet:
var map;
google.maps.event.addDomListener(window, "load", function() {
var map = new google.maps.Map(document.getElementById("map_div"), {
center: new google.maps.LatLng(52.489471, -1.898575),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var trace = new google.maps.Polygon({
paths: getPolygon(52.489471, -1.898575, 51.752022, -1.257677, 30),
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.05,
map: map
});
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < trace.getPath().getLength(); i++) {
bounds.extend(trace.getPath().getAt(i));
}
map.fitBounds(bounds);
function getPolygon($x1, $y1, $x2, $y2, $l1) {
var points = [];
var city1 = new google.maps.LatLng($x1, $y1);
var city2 = new google.maps.LatLng($x2, $y2);
var heading = google.maps.geometry.spherical.computeHeading(city1, city2);
points.push(google.maps.geometry.spherical.computeOffset(city1, $l1 / 2 * 1000, heading + 90));
points.push(google.maps.geometry.spherical.computeOffset(city1, $l1 / 2 * 1000, heading - 90));
points.push(google.maps.geometry.spherical.computeOffset(city2, $l1 / 2 * 1000, heading - 90));
points.push(google.maps.geometry.spherical.computeOffset(city2, $l1 / 2 * 1000, heading + 90));
points.push(points[0]);
return points;
}
});
html,
body {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
#map_div {
height: 95%;
}
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map_div"></div>

How can i calculate rectangle area in google map?

I am studying C# , google map api. and i want to draw click rectangle and calculate rectangle area.
this is my code:
function mode() {
google.maps.event.addListener(map, 'click', function (event) {
var bounds = makeBounds(event.latLng, 200, 100);
placeRec(bounds);
});
}
function placeRec(bounds) {
var rectangle = new google.maps.Rectangle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
editable: true,
bounds: bounds,
draggable:true
});
}
function makeBounds(nw, metersEast, metersSouth) {
ne = google.maps.geometry.spherical.computeOffset(nw, metersEast, 90);
sw = google.maps.geometry.spherical.computeOffset(nw, metersSouth, 180);
return new google.maps.LatLngBounds(sw, ne);
sowe = bounds.getSouthWest();
noea = bounds.getNorthEast();
}
I succeed draw click Rectangle in google map,
I want to know calculate Rectangle Area.
How do i have to do?
Thank you

google maps resize symbol on zoom not working

I'm resizing the symbol this way:
google.maps.event.addListener(map_object, 'zoom_changed', (function(arrow) { return function() {
var zoom = map_object.getZoom();
var scale = 2.48676567E-2 * Math.exp(0.143700035 * zoom);
arrow.icons[0].icon.scale = scale;
}})(arrow));
When I inspect the arrow object, the scale property changes properly on zoom_changed, but it's not changing its size in the map.
Is there something I'm forgetting to do?
UPDATE
The arrow object is defined as follow:
var sym = {
path: "M0 15 L30 0 L60 15",
rotation: angle,
scale: 0.25,
strokeWeight: 3,
};
var arrow = new google.maps.Polyline({
path: [{lat: lat, lng: lng},{lat: lat2, lng: lng}],
geodesic: true,
strokeColor: color,
strokeOpacity: 0.9,
icons: [{
icon: sym,
offset: '100%'
}]
});
Just for future references.
I solved my problem using the setOptions method from Polyline class, instead of setting the scale property.
My code becomes to this:
google.maps.event.addListener(map_object, 'zoom_changed', (function(arrow) { return function() {
var zoom = map_object.getZoom();
var scale = 2.48676567E-2 * Math.exp(0.143700035 * zoom);
var icon = arrow.icons[0].icon;
icon.scale = scale;
arrow.setOptions({icons: [{icon: icon, offset: '100%'}]});
}})(arrow));
Now, the arrow size is changing on map zoom in the right way.

Google Maps API v3 Hiding and showing a circle bound to a marker

I have successfully bound a circle to my marker using google map api v3. I know this because if I make the marker dragable the circle moves as well.
How can I refer to the circle if the marker is clicked. I need to show the circle if not visible or vice-versa.
Here is the code to create the marker and circle
var markerOptions = {
title: title,
icon: markerImage,
shadow: markerShadow,
position: latlng,
map: map
}
var marker = new google.maps.Marker(markerOptions);
// Add a Circle overlay to the map.
var circle = new google.maps.Circle({
map: map,
radius: 50*1609.34,// 50 MI
visible: false
});
//circle.bindTo('map', marker);
circle.bindTo('center', marker, 'position');
I found an answer on stackoverflow that led me to think I needed to do the rem'd out map binding as well the center binding, but that did not work.
Here is my click event for the marker.
google.maps.event.addListener(marker, "click", function() {
var infowindowOptions = {
content: html
}
var infowindow = new google.maps.InfoWindow(infowindowOptions);
cm_setInfowindow(infowindow);
infowindow.open(map, marker);
marker.setIcon(markerImageOut);
marker.circle({visible: true});
Any ideas. I need to interact with the bound circle of the marker that was just clicked or moused over.
One option is to make the circle a property of the marker (like ._myCircle), reference it in the click handler as marker._myCircle.
Add the circle as the _myCircle property of marker:
var circle = new google.maps.Circle({
map: map,
radius: 50*1609.34,// 50 MI
visible: false
});
circle.bindTo('center', marker, 'position');
marker._myCircle = circle;
To toggle it use something like (not tested):
if(marker._myCircle.getMap() != null) marker._myCircle.setMap(null);
else marker._myCircle.setMap(map);
var rad =".$this->conf['radius'] * 1000 ."; //convert km to meter
var populationOptions = {
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 1,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,//map object
center: new google.maps.LatLng($corr_match[0], $corr_match[1]),//center of circle
radius: rad
};
var cityCircle = new google.maps.Circle(populationOptions);

Work out LatLng distance from LatLng (or point in circle) - Google Maps v3

I need to find out if certain LatLngs are inside a Google Maps Circle (one of these: http://code.google.com/apis/maps/documentation/javascript/overlays.html#Circles). How would I get around doing this? My markup for making the circle is:
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
circlemarker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
THEradius = parseFloat(THEradius);
var populationOptions = {
strokeColor: "#BDAEBB",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#BDAEBB",
fillOpacity: 0.5,
map: map,
center: results[0].geometry.location,
radius: THEradius
};
cityCircle = new google.maps.Circle(populationOptions);
map.fitBounds(cityCircle.getBounds());
}
});
Could I just use the radius?
var distance = google.maps.geometry.spherical.computeDistanceBetween(
results[0].geometry.location, otherLatLng);
if (distance <= THEradius) {...} else {...}
I hope that works for you. See http://code.google.com/apis/maps/documentation/javascript/reference.html#spherical
What you need to do is to convert either your lat-lon list into google coordinate space, or the circle into lat-lon coordinate space.
How you do the conversion depends on the language you are using, but there are websites that will do the conversion for you if it is a one off.
Once you've got the lat-lon locations in the same co-ordinate space as your circle, you can use simple pythagoras math to work out if the location is less than the radius of the circle (as you suggest).
HYP = (OPP^2 * ADJ^2)^0.5
Where:
OPP is the difference in x direction from the centre of the circle
ADJ is the difference in y direction from the centre of the circle.
HYP is the distance in a straight line from the centre of the circle
In terms of mathematics, to find the distance from one point to another in 2D, use Pythagoras:
X = X1 - X2
Y = Y1 - Y2
(The above effectively calculates a vector from one point to another)
Distance from 1 to 2 = sqrt(X^2 + Y^2)
Then you can compare that to your radius. If the distance is less than your radius, the point is within the circle.
You need to first acquire the point corresponding to the centre of the circle and the point you are trying to compare. These must be in the same co-ordinate space.

Categories

Resources