Ejemplo n.º 1
0
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);
    }
}