Created
February 26, 2010 19:27
-
-
Save jphastings/316058 to your computer and use it in GitHub Desktop.
Calculating the percentage area overlap between circles in PHP. Built for Jon Hazan @ Bam UK
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Returns the percentage area overlap between two circles | |
* NB. Doesn't validate input. | |
* | |
* Built for Jon Hazan of Bam UK student marketing | |
* | |
* @author JP Hastings-Spital | |
* @param float distance between the two circles' origins | |
* @param array The two radii (floats) | |
* @return float percentage_overlap | |
**/ | |
function circle_overlap($d,$rs){ | |
// Make sure the larger circle is left-most (for convenience) | |
$r1 = max($rs); | |
$r2 = min($rs); | |
// Are the circles non-overlapping? | |
if ($d >= $r1 + $r2) { | |
return 0; // 0% coverage | |
} | |
// Is one circle entirely within the other? | |
elseif (max($rs) >= $d + min($rs)) { | |
return 1; // 100% Coverage | |
} | |
// Partial overlap | |
else { | |
// Distance of cross-point from origin of left circle | |
$x1 = ($d*$d - $r2*$r2 + $r1*$r1 )/(2*$d); | |
// Distance of cross-point from origin of right circle | |
// (symmetry means we can shortcut with absolute value) | |
$x2 = abs($d - $x1); | |
$y = sqrt($r1*$r1 - ($x1*$x1)); | |
// Area of left lens | |
$a1 = ($r1*$r1) * acos($x1 / $r1) - $x1 * $y; | |
// Area of right lens | |
$a2 = ($r2*$r2) * acos($x2 / $r2) - $x2 * $y; | |
// Special case, if the cross-point is further away from the origin of | |
// the first circle than the second circle is, then a2 needs to be the | |
// large side of the circle, not the small one: | |
if ($x1 > $d) | |
$a2 = (pi() * $r2*$r2) - $a2; | |
$overlap_area = $a1 + $a2; | |
// The total area of the union is: | |
// area of circle 1 + area of circle 2 - overlap_area | |
// (as the overlap area only needs to be counted once) | |
$total_area = pi() * ($r1*$r1 + $r2*$r2) - $overlap_area; | |
return $overlap_area / $total_area; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment