function fitcircle($X, $Y) { $points = sizeof($X); if ($points < 3) { return array("cx" => 0, "cy" => 0, "r" => 0, "err" => 100); } // Mean of points $meanX = 0; $meanY = 0; for ($i = 0; $i < sizeof($X); $i++) { $meanX += $X[$i]; $meanY += $Y[$i]; } $meanX /= $points; $meanY /= $points; // Auxiliary means $mXx = 0; $mXy = 0; $mYy = 0; $mRx = 0; $mRy = 0; for ($i = 0; $i < sizeof($X); $i++) { $x = $X[$i]; $y = $Y[$i]; $r = $x * $x + $y * $y; $mXx += $x * ($x - $meanX); $mXy += $x * ($y - $meanY); $mYy += $y * ($y - $meanY); $mRx += $r * ($x - $meanX); $mRy += $r * ($y - $meanY); } $mXx /= $points; $mXy /= $points; $mYy /= $points; $mRx /= $points; $mRy /= $points; // Assemble matrix $A[0][0] = $mXx; $A[0][1] = 2.0 * $mXy; $A[1][0] = 0.0; $A[1][1] = $mYy; $matrixA = new Matrix($A); // A=A+transpose(A) $matrixA = $matrixA->plus($matrixA->transpose()); // Assemble B vector $b[0][0] = $mRx; $b[1][0] = $mRy; $matrixB = new Matrix($b); // Calculate center Solve A*x=b for x,then center=x $LU = new LUDecomposition($matrixA); if ($LU->isNonsingular()) { $C = $matrixA->solve($matrixB); $cx = $C->get(0, 0); $cy = $C->get(1, 0); // Calculate radius $meanR2 = 0; $maxR2 = 0; $minR2 = 10000; for ($i = 0; $i < sizeof($X); $i++) { $x = $X[$i]; $y = $Y[$i]; $r2 = ($x - $cx) * ($x - $cx) + ($y - $cy) * ($y - $cy); if ($r2 > $maxR2) { $maxR2 = $r2; } if ($r2 < $minR2) { $minR2 = $r2; } $meanR2 += $r2; } $meanR2 /= $points; $radius = sqrt($meanR2); // Calculate error $err = sqrt($maxR2) / sqrt($minR2); // Return return array("cx" => $cx, "cy" => $cy, "r" => $radius, "err" => $err); } else { return array("cx" => 0, "cy" => 0, "r" => 0, "err" => 100); } }