1

I have three markers in Google Maps, and I'd like to create a circle that touches all three in its circumference. I have the following function that receives the three markers as parameters (I borrowed the algorithm from What is the algorithm for finding the center of a circle from three points?).

The problem is that it does create a circle, but it doesn't touch the markers. Is there any way to improve this code? I need it as precise as possible.

Thanks in advance.

function drawCircleDel(a, b, c) {
    a_x = a.getPosition().lng();
    a_y = a.getPosition().lat();
    b_x = b.getPosition().lng();
    b_y = b.getPosition().lat();
    c_x = c.getPosition().lng();
    c_y = c.getPosition().lat();
    var yDelta_a = b_y - a_y;
    var xDelta_a = b_x - a_x;
    var yDelta_b = c_y - b_y;
    var xDelta_b = c_x - b_x;
    var aSlope = ((yDelta_a)/(xDelta_a));
    var bSlope = ((yDelta_b)/(xDelta_b));
    var center_x = (aSlope*bSlope*(a_y - c_y) + bSlope*(a_x + b_x) - aSlope*(b_x + c_x))/(2*(bSlope - aSlope));
    var center_y = -1*(center_x - (a_x + b_x) / 2) / aSlope + (a_y + b_y)/2;
    var distanceA = google.maps.geometry.spherical.computeDistanceBetween(new google.maps.LatLng(center_y, center_x), a.getPosition());
    var distanceB = google.maps.geometry.spherical.computeDistanceBetween(new google.maps.LatLng(center_y, center_x), b.getPosition());
    var distanceC = google.maps.geometry.spherical.computeDistanceBetween(new google.maps.LatLng(center_y, center_x), c.getPosition());
    var circleOptions = {
        strokeColor: '#FFFFFF',
        strokeOpacity: 0.5,
        strokeWeight: 2,
        fillColor: '#FFFFFF',
        fillOpacity: 0.25,
        map: map,
        center: new google.maps.LatLng(center_y, center_x),
        radius: (distanceA + distanceB + distanceC)/3,
        clickable: false,
        zIndex: 1
    };
    window.circlesRNG.push(new google.maps.Circle(circleOptions));
}
Community
  • 1
  • 1
  • Your function assumes the world is two dimensional, that only works over short distances. You need a version that accounts for the curvature of the earth. – geocodezip Feb 03 '15 at 15:32
  • Thanks! I thought it was a problem with the decimal places of the variables, but you're right. I managed to find the answer. – disjunctive Feb 03 '15 at 16:50
  • Can you please post the answer you found as an answer? – geocodezip Feb 03 '15 at 16:51
  • 1
    I see you updated your question. It would be better to revert that change and put the updated code as an answer, and [accept that answer](http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work) – geocodezip Feb 04 '15 at 01:24
  • [and with draggable markers](http://jsfiddle.net/cw34pkvy/2/) – geocodezip Feb 04 '15 at 02:49
  • @geocodezip , I did as you said. This was my first question on this site, and for some reason I have to wait 23 hours to accept my own answer. Anyway, thanks for everything. – disjunctive Feb 04 '15 at 15:48

1 Answers1

1

The math was OK, but the problem was that i wasn't taking into account the curvature of the earth. So I transformed the LatLng coordinates to points, found the center, and did the inverse. Here's the updated function:

function drawCircleDel(a, b, c) {
var pixelA = map.getProjection().fromLatLngToPoint(a.getPosition());
var pixelB = map.getProjection().fromLatLngToPoint(b.getPosition());
var pixelC = map.getProjection().fromLatLngToPoint(c.getPosition());
var a_x = pixelA.x;
var a_y = pixelA.y;
var b_x = pixelB.x;
var b_y = pixelB.y;
var c_x = pixelC.x;
var c_y = pixelC.y;
var aSlope = (b_y - a_y)/(b_x - a_x);
var bSlope = (c_y - b_y)/(c_x - b_x);
var center_x = (aSlope*bSlope*(a_y - c_y) + bSlope*(a_x + b_x) - aSlope*(b_x + c_x))/(2*(bSlope - aSlope));
var center_y = -1*(center_x - (a_x + b_x)/2)/aSlope + (a_y + b_y)/2;
var center = map.getProjection().fromPointToLatLng(new google.maps.Point(center_x, center_y));
var distance = google.maps.geometry.spherical.computeDistanceBetween(center, a.getPosition());
var circleOptions = {
    strokeColor: '#FFFFFF',
    strokeOpacity: 0.5,
    strokeWeight: 2,
    fillColor: '#FFFFFF',
    fillOpacity: 0.25,
    map: map,
    center: center,
    radius: distance,
    clickable: false,
    zIndex: 1
};
window.circlesRNG.push(new google.maps.Circle(circleOptions));
}

Also, user geocodezip created an example that implements the function with draggable markers and put it in this JSFiddle link. Thanks geocodezip!

Community
  • 1
  • 1