Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adjust google.maps.Circle radius to be more accurate

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:

enter image description here

enter image description here

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

like image 392
radubogdan Avatar asked May 25 '17 11:05

radubogdan


2 Answers

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;
like image 119
plexer Avatar answered Oct 03 '22 13:10

plexer


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.

like image 29
therobinkim Avatar answered Oct 03 '22 14:10

therobinkim