I have two points represented by (lat, lng) and a circle represented center = point(lat, lng) and radius.
[2] pry(main)> points
=> [#<struct Geography::Point x=8.6836, y=56.7619>, #<struct Geography::Point x=8.7501, y=56.8298>]
[3] pry(main)> circle
=> #<struct Geography::Circle center=#<struct Geography::Point x=8.71685, y=56.79585>, radius=5253.053885917054>
I have a method that calculates the distance using Haversine formula so if I do it from the center of the circle towards both points, I'll get:
[4] pry(main)> Geography::Utils.distance_between(circle.center, points.first)
=> 5253.053885917054
[5] pry(main)> Geography::Utils.distance_between(circle.center, points.second)
=> 5252.8180384905045
Please note that the distance between the first point and the center of the circle is the actual radius of the circle. All the distances are in meters. What I mean by this is that one point is on the arc and the one should be super close.
Expected result:
If I represent that in google maps, the arc of the circle will pass through one point and be super close to second.
Actual result:
Question
How does google maps projection works in my case and how can I have an ouput that satisfies the reality?
Map code:
:coffeescript
window.createPostcodeMarker = (postcode) ->
marker = new google.maps.Marker
draggable: false
raiseOnDrag: false
position: postcode.position
map: map
tooltip: postcode.name
icon:
path: google.maps.SymbolPath.CIRCLE
fillOpacity: 1
strokeOpacity: 1
strokeColor: postcode.stroke_color
strokeWeight: 1
scale: 3
fillColor: postcode.stroke_color
circle = new google.maps.Circle
map: map
radius: postcode.radius
fillColor: postcode.fill_color
strokeColor: postcode.stroke_color
strokeWeight: 1
strokeOpacity: 0.8
circle.bindTo('center', marker, 'position')
marker
window.createAreaMarker = (area) ->
marker = new google.maps.Marker
draggable: false
raiseOnDrag: false
position: area.position
map: map
tooltip: area.name
icon:
path: google.maps.SymbolPath.CIRCLE
fillOpacity: 0.3
strokeOpacity: 0.3
strokeColor: area.stroke_color
strokeWeight: 1
scale: 0
fillColor: area.stroke_color
circle = new google.maps.Circle
map: map
radius: area.radius
fillColor: area.fill_color
strokeColor: area.stroke_color
strokeWeight: 1
strokeOpacity: 0.3
circle.bindTo('center', marker, 'position')
marker
window.googleMapsInitializePostcodesMap = ->
if PageData?.postcodesData?
window.bounds = new google.maps.LatLngBounds()
window.markers = []
mapOptions =
mapTypeId: google.maps.MapTypeId.ROADMAP
maxZoom: 13
window.map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions)
# Create markers & extend bounds
for postcode in PageData.postcodesData
marker = createPostcodeMarker(postcode)
markers.push(marker)
bounds.extend(marker.position)
for area in PageData.areasData
marker = createAreaMarker(area)
markers.push(marker)
window.map.fitBounds(bounds)
= json_data_tag(#postcodes_map_data, 'postcodesData')
= json_data_tag(#areas_map_data, 'areasData')
#map-canvas{style: "width: 100%; height: 600px;"}
- content_for :footer_javascripts do
= google_maps_api_js("googleMapsInitializePostcodesMap")
Codepen: https://codepen.io/radubogdan/pen/gWEvZP
You should use the Spherical Geometry library that can be loaded as part of the Javascript Maps API by appending &libraries=geometry when loading the API - for example:
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">
The advantage of this method is that it abstracts away the implementation details of the default projection in the Maps API. This makes your life easy, and more importantly, will not break if that default projection ever changes.
Pass the lat/lng coordinates down to the browser and compute the distance between them (in meters) as follows:
var location1 = new google.maps.LatLng(lat1, lng1);
var location2 = new google.maps.LatLng(lat2, lng2);
var distance = google.maps.geometry.spherical.computeDistanceBetween(location1, location2);
or in Coffeescript:
location1 = new google.maps.LatLng lat1, lng1;
location2 = new google.maps.LatLng lat2, lng2;
distance = google.maps.geometry.spherical.computeDistanceBetween location1, location2;
The radius for the circle needs to be the distance between the center of the circle and CoordinateA in meters.
Once you convert to meters, the following site shows that 4288 should be the radius of the circle https://www.daftlogic.com/projects-google-maps-distance-calculator.htm?route=56.79585,8.716850000000022|56.7619,8.68360000000007
Basically, your Haversine formula isn't giving you exactly what you need yet.
Related
I want to build a polygon area as pictures using google MAP, you can know how to get the array of coordinates for the area?
picture of desired polygon
You can build a Polygon using an array of lat, lng couples of at least 3 elements.
If the array isn't close, Google Maps will close it by default.
While for the most of DBMS, you must save an array of coordinates that is closed. What does close mean? Essentially, the first and the last points of the array are equal. DBMS like MongoDB will throw an error for bad formatted geospatial data. MongoDB Documentation on $polygon.Another thing to mention is that, MongoDB accepts ONLY lng, lat formatted coordinates.
As you can see from Official Google Maps Documentation on Polygons you can draw a Polygon starting from an array of coordinates:
// Define the LatLng coordinates for the polygon.
var triangleCoords = [
{lat: 25.774, lng: -80.190},
{lat: 18.466, lng: -66.118},
{lat: 32.321, lng: -64.757}
];
Then you can construct it and set it on the map:
// Construct the polygon.
var bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords, //Array of Coordinates
strokeColor: '#FF0000', //Color of the line
strokeOpacity: 0.8, //Color opacity
strokeWeight: 3, //Line weight
fillColor: '#FF0000', //Inner Color
fillOpacity: 0.35 //Inner color opacity
});
//Set it on the map
bermudaTriangle.setMap(map);
Then, you can add information to your polygon using clickListener and infoWindows
// Add a listener for the click event and opens infoWindow
bermudaTriangle.addListener('click', showArrays);
infoWindow = new google.maps.InfoWindow;
You can read more about infoWindows here.
Finally, here you can find a Plunker I made up using Google Maps Docs and AngularJS. Of course you can do it with pure Javascript.
Last but not least, make sure of having points on the boundaries and with reasonable lat, lng coordinates.
I hope I've been helpful.
The following draws a curve:
var curvedLine = {
path: 'M 50,-150 A 100,100 0 0 100 -3,0',
fillColor: 'transparent',
fillOpacity: 0.5,
scale: 1,
strokeColor: 'gold',
strokeOpacity: 0.6,
strokeWeight: 7
};
var marker = new google.maps.Marker({
position: newLoc,
icon: curvedLine,
map: map
});
In the curvedLine, after A, can I give a location coordinates on the map?
Because when the map is zoomed out, curvedLine size remains same. I want it to scale along with the map zoom.
I have written a function. Please review it.
function drawCurvedLine(startLatLng, endLatLng, offset, right, left, lineColor) {
var midLoc = getMidPoint(startLatLng, endLatLng);// Get the mid point of the start and end LatLngs
var midLoc1 = getMidPoint(startLatLng, midLoc);// Get the mid point of the start LatLng and mid LatLng
var midLoc2 = getMidPoint(midLoc, endLatLng);// Get the mid point of the mid LatLng and end LatLng
var heading = google.maps.geometry.spherical.computeHeading(startLatLng, endLatLng);// Compute the heading of the start and end LatLngs
// Change the heading based on right or left value
var headingOffset;
if (right == 1 && left == 0) {
headingOffset = 90;
}
else if (right == 0 && left == 1) {
headingOffset = -90;
}
var offsetLoc = google.maps.geometry.spherical.computeOffset(midLoc, offset / 1.5, heading + headingOffset);// Get the offset location of the mid point of start and end LatLngs
var offsetLoc1 = google.maps.geometry.spherical.computeOffset(midLoc1, offset / 2, heading + headingOffset);// Get the offset location of the mid point of midLoc and start LatLng
var offsetLoc2 = google.maps.geometry.spherical.computeOffset(midLoc2, offset / 2, heading + headingOffset);// Get the offset location of the mid point of midLoc and start LatLng
// Draw poly line along above computed locations
var curve = new google.maps.Polyline({
path: [startLatLng, offsetLoc1, offsetLoc, offsetLoc2, endLatLng],
geodesic: true,
strokeColor: lineColor,
strokeOpacity: 0.6,
strokeWeight: 7
});
curve.setMap(map);
// Add an arrow to the end of the curved line
var arrow = new google.maps.Marker({
position: newLoc,
map: map,
icon: {
path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
scale: 4,
strokeColor: lineColor,
strokeOpacity: 1,
strokeWeight: 5.0,
fillColor: 'transparent',
fillOpacity: 0.6,
rotation: google.maps.geometry.spherical.computeHeading(offsetLoc2, endLatLng)
},
});
}
I have following issue with drawing a polygon with google maps api. It looks like that there is to much fillColor. The center of the following polygon is not supposed to have fillColor.
Is it google maps API or is it me who has a bug?
Example: http://jsfiddle.net/zCA2u/
$(function(){
var shape;
var mapDiv = document.getElementById('map-canvas');
var map = new google.maps.Map(mapDiv, {
center: new google.maps.LatLng(24.886436490787712, -70.2685546875),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var coords = [
new google.maps.LatLng(31.50362, -70.0488),
new google.maps.LatLng(29.91685, -62.4023),
new google.maps.LatLng(22.91792, -56.42578),
new google.maps.LatLng(22.67484, -69.6972),
new google.maps.LatLng(27.29368, -74.8828),
new google.maps.LatLng(33.06392, -73.3007),
new google.maps.LatLng(34.23451, -66.0058),
new google.maps.LatLng(32.32427, -58.2714),
new google.maps.LatLng(26.35249, -56.4257),
new google.maps.LatLng(18.81271, -60.64453),
new google.maps.LatLng(20.13847, -69.4335)
];
shape = new google.maps.Polygon({
paths: coords,
strokeColor: '#ff0000',
strokeOpacity: 0.8,
strokeWeight: 2,
draggable: true,
fillColor: '#ff0000',
fillOpacity: 0.35
});
shape.setMap(map);
});
I have now tried the above in IE8 and it renders correct in IE8
If you want to make "holes" in polygons
they aren't supported by the drawing manager directly
you need to have separate paths (the polygon "paths" property takes an array)
the inner paths (the "holes") need to wind in the opposite direction from the inner path
simple example of a polygon with a hole (a donut)
fiddle with self intersection removed and hole
var coords = [
[ new google.maps.LatLng(27.29368, -74.8828),
new google.maps.LatLng(33.06392, -73.3007),
new google.maps.LatLng(34.23451, -66.0058),
new google.maps.LatLng(32.32427, -58.2714),
new google.maps.LatLng(26.35249, -56.4257),
new google.maps.LatLng(18.81271, -60.64453),
new google.maps.LatLng(20.13847, -69.4335)
],
[
new google.maps.LatLng(21.534847,-63.28125),
new google.maps.LatLng(30.221102,-59.677734),
new google.maps.LatLng(30.600094,-71.279297)
]
];
I have drawn circle using
circle = new google.maps.Circle({
map: map,
radius: r, // 1 miles in metres = 1609.3 m
strokeWeight:1,
strokeOpacity:0.5,
fillOpacity:0.2,
fillColor: '#AA0000'
});
circle.bindTo('center', marker, 'position');
How to remove circle from the map ?
circle.setMap(null);
will remove the circle
I am using google map api version 3 . Now i want to link markers with line, so that a path can be created between the markers.
Any solution ?
To create line between two markers
use this
var Polyline_Coordinates = [
new google.maps.LatLng(42.357778,-71.061667), // your location lattitude and longitude
new google.maps.LatLng(40.716667,-74),
new google.maps.LatLng(41.836944,-87.684444),
new google.maps.LatLng(34.05,-118.25)
];
var Polyline_Path = new google.maps.Polyline({
path: Polyline_Coordinates,
strokeColor: "#000000",
// color of the outline of the polyline
strokeOpacity: 1.0,
// between 0.0 and 1.0
strokeWeight: 5
// The stroke width in pixels
});
Polyline_Path.setMap(map);