Skip to content

Instantly share code, notes, and snippets.

@jphastings
Created February 26, 2010 19:27
Show Gist options
  • Save jphastings/316058 to your computer and use it in GitHub Desktop.
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
<?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