The intersection points of two circles Google Maps

Is there an easy way to get the lat / lng intersection points (if available) of two circles in the Google Maps API V3 ? Or should I go in a tough way?

EDIT: In my problem, circles always have the same radius, in case this makes the solution easier.

+7
javascript algorithm geometry google-maps google-maps-api-3
source share
3 answers

Yes, for equal circles a fairly simple solution can be developed:
Let the first center of the circle be A, the second center of the circle F, the midpoint C, and the intersection points B, D. ABC is a right-angled spherical triangle with a right angle C.

enter image description here

We want to find the angle A - this is the angle of deviation from the direction AF. Spherical trigonometry (Napier rules for right spherical triangles) gives the formula:

cos(A)= tg(AC) * ctg(AB) where one symbol denotes a spherical angle, double symbols indicate angles of a large circle (AB, AC). We can see that AB = the radius of the circle (in radians, of course), AC = the half-distance between A and F on the arc of a large circle. To find AC (and other values), I will use the code from this excellent page

 var R = 6371; // km var dLat = (lat2-lat1).toRad(); var dLon = (lon2-lon1).toRad(); var lat1 = lat1.toRad(); var lat2 = lat2.toRad(); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 

and ours

 AC = c/2 

If the radius of the circle Rd is given - kilometers, then

 AB = Rd / R = Rd / 6371 

Now we can find the angle

 A = arccos(tg(AC) * ctg(AB)) 

Starting bearing (AF direction):

 var y = Math.sin(dLon) * Math.cos(lat2); var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); var brng = Math.atan2(y, x); 

Cross Point Bearings:

 B_bearing = brng - A D_bearing = brng + A 

Coordinates of intersection points:

 var latB = Math.asin( Math.sin(lat1)*Math.cos(Rd/R) + Math.cos(lat1)*Math.sin(Rd/R)*Math.cos(B_bearing) ); var lonB = lon1.toRad() + Math.atan2(Math.sin(B_bearing)*Math.sin(Rd/R)*Math.cos(lat1), Math.cos(Rd/R)-Math.sin(lat1)*Math.sin(lat2)); 

and the same for d_bearing

latB, lonB are in radians

+11
source share

the calculation of the β€œhard” method can be simplified for the case r1 = r2 =: r. First, we need to transform the district centers P1, P2 from (lat, lng) into Cartesian coordinates (x, y, z).

 var DEG2RAD = Math.PI/180; function LatLng2Cartesian(lat_deg,lng_deg) { var lat_rad = lat_deg*DEG2RAD; var lng_rad = lng_deg*DEG2RAD; var cos_lat = Math.cos(lat_rad); return {x: Math.cos(lng_rad)*cos_lat, y: Math.sin(lng_rad)*cos_lat, z: Math.sin(lat_rad)}; } var P1 = LatLng2Cartesian(lat1, lng1); var P2 = LatLng2Cartesian(lat2, lng2); 

But the line of intersection of the planes holding the circles can be easily calculated. Let d be the distance to the actual center of the circle (in the plane) to the corresponding point P1 or P2 on the surface. A simple conclusion shows (with R the radius of the Earth):

 var R = 6371; // earth radius in km var r = 100; // the direct distance (in km) of the given points to the intersections points // if the value rs for the distance along the surface is known, it has to be converted: // var r = 2*R*Math.sin(rs/(2*R*Math.PI)); var d = r*r/(2*R); 

Now let S1 and S2 be the intersection points, and S their midpoint. With s = |OS| and t = |SS1| = |SS2| t = |SS1| = |SS2| (where O = (0,0,0) is the center of the earth), we get from simple differentiations:

 var a = Math.acos(P1.x*P2.x + P1.y*P2.y + P1.z*P2.z); // the angle P1OP2 var s = (Rd)/Math.cos(a/2); var t = Math.sqrt(R*R - s*s); 

Now, since r1 = r2 points S, S1, S2 are in the middle plane between P1 and P2. For v_s = OS we get:

 function vecLen(v) { return Math.sqrt(vx*vx + vy*vy + vz*vz); } function vecScale(scale,v) { return {x: scale*vx, y: scale*vy, z: scale*vz}; } var v = {x: P1.x+P2.x, y: P1.y+P2.y, z:P1.z+P2.z}; // P1+P2 is in the middle of OP1 and OP2 var S = vecScale(s/vecLen(v), v); function crossProd(v1,v2) { return {x: v1.y*v2.z - v1.z*v2.y, y: v1.z*v2.x - v1.x*v2.z, z: v1.x*v2.y - v1.y*v2.x}; } var n = crossProd(P1,P2); // normal vector to plane OP1P2 = vector along S1S2 var SS1 = vecScale(t/vecLen(n),n); var S1 = {x: S.x+SS1.x, y: S.y+SS1.y, z: S.z+SS1.z}; // S + SS1 var S2 = {x: Sx-SS1.x, y: Sy-SS2.y, z: Sz-SS1.z}; // S - SS1 

Finally, we need to convert back (lat, lng):

 function Cartesian2LatLng(P) { var P_xy = {x: Px, y:Py, z:0} return {lat: Math.atan2(Py,Px)/DEG2RAD, lng: Math.atan2(Pz,vecLen(P_xy))/DEG2RAD}; } var S1_latlng = Cartesian2LatLng(S1); var S2_latlng = Cartesian2LatLng(S2); 
+4
source share

Yazanpro, sorry for the late reply to this.

You may be interested in a brief version of the MBo approach, which is simplified in two ways:

  • firstly, using some of the built-in google.maps API functions to avoid much of the hard math.
  • secondly, using the 2D model to calculate the included angle instead of the spherical MBo model. At first, I was not sure of the validity of this simplification, but I was convinced in the MBo script plug tests that the errors are insignificant, but the largest circles are the size of the Earth (for example, at low zoom levels).

Here's the function:

 function getIntersections(circleA, circleB) { /* * Find the points of intersection of two google maps circles or equal radius * circleA: a google.maps.Circle object * circleB: a google.maps.Circle object * returns: null if * the two radii are not equal * the two circles are coincident * the two circles don't intersect * otherwise returns: array containing the two points of intersection of circleA and circleB */ var R, centerA, centerB, D, h, h_; try { R = circleA.getRadius(); centerA = circleA.getCenter(); centerB = circleB.getCenter(); if(R !== circleB.getRadius()) { throw( new Error("Radii are not equal.") ); } if(centerA.equals(centerB)) { throw( new Error("Circle centres are coincident.") ); } D = google.maps.geometry.spherical.computeDistanceBetween(centerA, centerB); //Distance between the two centres (in meters) // Check that the two circles intersect if(D > (2 * R)) { throw( new Error("Circles do not intersect.") ); } h = google.maps.geometry.spherical.computeHeading(centerA, centerB); //Heading from centre of circle A to centre of circle B. (in degrees) h_ = Math.acos(D / 2 / R) * 180 / Math.PI; //Included angle between the intersections (for either of the two circles) (in degrees). This is trivial only because the two radii are equal. //Return an array containing the two points of intersection as google.maps.latLng objects return [ google.maps.geometry.spherical.computeOffset(centerA, R, h + h_), google.maps.geometry.spherical.computeOffset(centerA, R, h - h_) ]; } catch(e) { console.error("getIntersections() :: " + e.message); return null; } } 

No disrespect for MBo by the way is a great answer.

+4
source share

All Articles