Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing irregular concentric circles using Google Maps

I have a bit of a problem. I am trying to do the following using Javascript & the Google Maps API v2:

myhurricane.net - Wind Radii Profile

I can draw individual circles just fine using formulas found all over the Internet. The problem I am facing is that the circles must:

A. Be concentric, and B. Must have different radius for each "quadrant", i.e., NE, NW, SE & SW

I've searched almost everywhere I can think of on the Internet, and have come up with no way on how to do this. Clearly someone has done this before, and thus why I'm asking in a forum of programmers. :)

Thanks!

UPDATE: I have drawn out, using the following code, what I think the coordinates for each of the points would be. for the drawing below:

snapshot-1252125257.781397

This was obtained using the following JS:

http://gist.github.com/181290

NOTE: This javascript is from (slightly modified) the following site, which may hold more answers in terms of what the algorithm may end up being: http://www.movable-type.co.uk/scripts/latlong.html

UPDATE 2: I was able to get this in Google Maps:

Concentric Circles Progress

Created using the following code:

var NEQ = [0, 90];
var SEQ = [90, 180];
var SWQ = [180, 270];
var NWQ = [270, 0];

// var centrePoint = new LatLon(25.0, -83.1);
// pointsForWindQuadrant(NEQ, centrePoint, 50);
function pointsForWindQuadrant(quadrantDegrees, centrePoint, radius){
  var points = [];

  // Points must be pushed into the array in order
  points.push(new google.maps.LatLng(centrePoint.lat, centrePoint.lon));

  for(i = quadrantDegrees[0]; i <= quadrantDegrees[1]; i++){
    var point = centrePoint.destPoint(i, radius * 1.85);
    points.push(new google.maps.LatLng(point.lat, point.lon)); // Radius should be in nautical miles from NHC
  }

  points.push(new google.maps.LatLng(centrePoint.lat, centrePoint.lon));

  return points;
}

UPDATE 3: I should probably also point out that this is for a geographic coordinate system (as this whole thing is for tropical cyclone wind radii), not the Cartesian coordinate system. Thanks!

like image 256
Josh Delsman Avatar asked Sep 05 '09 03:09

Josh Delsman


2 Answers

Basically, calculate the circle as the x,y = (cos(a), sin(a)), and then multiple this (both terms) by a radius that's the appropriate function of the angle. I don't know Javascript well, or Google maps, so I'll do this in Python, hopefully it's clear enough from this.

from pylab import *

def Rscale(a):
    if a>3*pi/2:  # lower right, and then work CW around the circle
        return 1.
    elif a>pi:  # lower left
        return .9
    elif a>pi/2:   # upper left
        return .8
    else:       # upper right
        return 1.

def step_circle(R):
    return array([(R*Rscale(a))*array([cos(a), sin(a)]) for a in arange(0, 2*pi, .001)])

for R in (.5, .7, .9):  # make three concentric circles
    c = step_circle(R)
    plot(c[:,0], c[:,1])

show()

Which gives alt text

I couldn't really follow your sketch, so I just guessed at the numbers. Also, I made the two rightmost quadrants to be the same since that's what your plot looked like, but that is, of course, optional.

like image 165
tom10 Avatar answered Sep 21 '22 14:09

tom10


I figured it out. Here is the final code. Maybe it can be refactored a bit?

// Returns points for a wind field for a cyclone. Requires
// a LatLon centre point, and an array of wind radii, starting
// from the northeast quadrant (NEQ), i.e., [200, 200, 150, 175]
//
// Returns points to be used in a GPolyline object.
function pointsForWindQuadrant(centrePoint, radii){
  if(radii.length != 4){ return false; }

  var points = [];
  var angles = [0, 90, 180, 270];

  // For each angle 0, 90, 180, 270...
  for(a = 0; a < angles.length; a++){
    // For each individual angle within the range, create a point...
    for(i = angles[a]; i <= angles[a] + 90; i++){
      var point = centrePoint.destPoint(i, radii[a] * 1.85); // Radius should be in nautical miles from NHC
      points.push(new google.maps.LatLng(point.lat, point.lon));
    }
  }

  // Add the first point again, to be able to close the GPolyline
  var point = centrePoint.destPoint(0, radii[0] * 1.85);
  points.push(new google.maps.LatLng(point.lat, point.lon));

  return points;
}

This results in the following:

New myhurricane.net - Wind Radii (Map View) New myhurricane.net - Wind Radii (Satellite View)

like image 40
Josh Delsman Avatar answered Sep 19 '22 14:09

Josh Delsman