IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Aug 29, 2014, 8:45:13 AM (12 years ago)
Author:
bills
Message:

Add psEllipsShapeToAxesWithErrors which propaaates the
errors in the shape parameters to the ellipse parameters.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/math/psEllipse.c

    r36375 r37327  
    134134    assert (isfinite(axes.major));
    135135    assert (isfinite(axes.minor));
     136
     137    return axes;
     138}
     139// ellipse derotation (sx, sy, sxy) -> (major, minor, theta)
     140psEllipseAxes psEllipseShapeToAxesWithErrors(psEllipseShape shape, psEllipseShape shapeErrors, double maxAR, psEllipseAxes *pShapeErrors)
     141{
     142    psEllipseAxes axes;
     143    psEllipseAxes errors;
     144
     145    double f1 = 1.0 / PS_SQR(shape.sy) + 1.0 / PS_SQR(shape.sx);
     146    double f2 = 1.0 / PS_SQR(shape.sy) - 1.0 / PS_SQR(shape.sx);
     147
     148    double f32 = PS_SQR(f2) + 4*PS_SQR(shape.sxy);
     149    double f3 = sqrt(f32);
     150
     151    double df1 = - 2.0 * shapeErrors.sy / (PS_SQR(shape.sy) * shape.sy)
     152                 - 2.0 * shapeErrors.sx / (PS_SQR(shape.sx) * shape.sx);
     153    double df2 = - 2.0 * shapeErrors.sy / (PS_SQR(shape.sy) * shape.sy)
     154                 + 2.0 * shapeErrors.sx / (PS_SQR(shape.sx) * shape.sx);
     155
     156    // df3 = 0.5 * df32 / sqrt(f32) = 0.5 * df32 / f3
     157    double df3 = 0.5 * (2.0*f2*df2 + 2 * 4 * shape.sxy * shapeErrors.sxy) / f3;
     158
     159    double f13 = f1 + f3;
     160    axes.minor = sqrt (2.0 / f13);
     161
     162    // dminor = -0.5 * sqrt (2) * df13 * f13**-3/2  = - 0.5 * df13 * minor / f13
     163    errors.minor = - 0.5 * (df1 + df3) * axes.minor / f13;
     164
     165    axes.theta = -0.5 * atan2 (+2.0*shape.sxy, f2);
     166
     167    // according to wikipedia the derivitive of atan2(y, x) is
     168    //
     169    //  dAtan2(y, x) = - y * dx / (x**2 + y**2)) + x * dy / (x**2 + y**2) (for x > 0 and y!=0)
     170    //  where
     171    //  y = 2 * sxy  dy = 2 * dsxy   x = f2 so dx = df2
     172
     173    // dtheta = -0.5 * dAtan2(y, x)
     174
     175    errors.theta = -0.5 * ( -2.0 * shape.sxy * df2  +  f2 * 2 *shapeErrors.sxy ) /
     176                            (PS_SQR(f2) + 4 * PS_SQR(shape.sxy)) ;
     177
     178    // long, thin objects are likely to have a poorly measured major axis
     179    // the angle and minor axis are likely to be ok.
     180    // restrict the axis ratio
     181    double rAR2 = (f1 - f3) / (f1 + f3);
     182    if (rAR2 < 1.0/PS_SQR(maxAR)) {
     183        axes.major = axes.minor * maxAR;
     184        errors.major = errors.minor * maxAR;
     185    } else {
     186        axes.major = sqrt (2.0 / (f1 - f3));
     187
     188        // dmajor = -0.5 * (df1 - df3) * sqrt(2) * (f1 - f3)**-3/2
     189        //        = -0.5 * (df2 - df3) * major / (f1 - f3)
     190        errors.major = -0.5 * axes.major * (df1 - df3) / (f1 - f3);
     191    }
     192
     193    assert (isfinite(axes.theta));
     194    assert (isfinite(axes.major));
     195    assert (isfinite(axes.minor));
     196
     197    *pShapeErrors = errors;
    136198
    137199    return axes;
Note: See TracChangeset for help on using the changeset viewer.