IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Nov 28, 2006, 4:33:08 PM (19 years ago)
Author:
magnier
Message:

added axis-ratio limits to psEllipse functions, fixed math for psEllipse functions

File:
1 edited

Legend:

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

    r9774 r10254  
    11#include <stdio.h>
     2#include <assert.h>
    23#include "psConstants.h"
    34#include "psEllipse.h"
    45
    5 psEllipseAxes psEllipseMomentsToAxes(psEllipseMoments moments)
     6// ellipse rotation (major, minor, theta) -> (x2, y2, xy)
     7psEllipseMoments psEllipseAxesToMoments(psEllipseAxes axes)
     8{
     9    psEllipseMoments moments;
     10
     11    double f1 = PS_SQR(axes.major) + PS_SQR(axes.minor);
     12    double f2 = PS_SQR(axes.major) - PS_SQR(axes.minor);
     13
     14    moments.x2 = +0.5*f1 + 0.5*f2*cos(2*axes.theta);
     15    moments.y2 = +0.5*f1 - 0.5*f2*cos(2*axes.theta);
     16    moments.xy = -0.5*f2*sin(2*axes.theta);
     17
     18    assert (isfinite(moments.x2));
     19    assert (isfinite(moments.y2));
     20    assert (isfinite(moments.xy));
     21
     22    return moments;
     23}
     24
     25// ellipse rotation (x2, y2, xy) -> (major, minor, theta)
     26psEllipseAxes psEllipseMomentsToAxes(psEllipseMoments moments, double maxAR)
    627{
    728    psEllipseAxes axes;
    829
    9     double f = sqrt (0.25*PS_SQR(moments.x2 - moments.y2) + PS_SQR(moments.xy));
    10     if (f > (moments.x2 + moments.y2) / 2.0) {
    11         f = 0.98*(moments.x2 + moments.y2) / 2.0;
     30    double g1 = moments.x2 + moments.y2;
     31    double g2 = moments.x2 - moments.y2;
     32    double g3 = sqrt(PS_SQR(g2) + 4*PS_SQR(moments.xy));
     33
     34    axes.major = sqrt (0.5*(g1 + g3));
     35    axes.theta = 0.5 * atan2 (-2.0*moments.xy, g2); // theta in radians
     36
     37    // long, thin objects are likely to have a poorly measured minor axis
     38    // the angle and major axis are likely to be ok.
     39    // restrict the axis ratio
     40    double rAR2 = (g1 - g3) / (g1 + g3);
     41    if (rAR2 < 1.0/PS_SQR(maxAR)) {
     42        axes.minor = axes.major / maxAR;
     43    } else {
     44        axes.minor = sqrt (0.5*(g1 - g3));
    1245    }
    1346
    14     axes.major = sqrt (0.5*(moments.x2 + moments.y2) + f);
    15     axes.minor = sqrt (0.5*(moments.x2 + moments.y2) - f);
    16     axes.theta = atan2 (2*moments.xy, moments.x2 - moments.y2) / 2;
    17     // theta in radians
     47    assert (isfinite(axes.major));
     48    assert (isfinite(axes.minor));
     49    assert (isfinite(axes.theta));
    1850
    1951    return axes;
     
    2557    psEllipseShape shape;
    2658
    27     double f1 = 1.0 / PS_SQR(axes.major) + 1.0 / PS_SQR(axes.minor);
    28     double f2 = 1.0 / PS_SQR(axes.major) - 1.0 / PS_SQR(axes.minor);
     59    double f1 = 1.0 / PS_SQR(axes.minor) + 1.0 / PS_SQR(axes.major);
     60    double f2 = 1.0 / PS_SQR(axes.minor) - 1.0 / PS_SQR(axes.major);
    2961
    30     double sxr = 0.5*f1 + 0.5*f2*cos(2*axes.theta);
    31     double syr = 0.5*f1 - 0.5*f2*cos(2*axes.theta);
     62    double sxr = 0.5*f1 - 0.5*f2*cos(2*axes.theta);
     63    double syr = 0.5*f1 + 0.5*f2*cos(2*axes.theta);
    3264
    33     shape.sx = 1.0 / sqrt(sxr);
    34     shape.sy = 1.0 / sqrt(syr);
    35     shape.sxy = 0.5*f2*sin(2*axes.theta);
     65    shape.sx  = +1.0 / sqrt(sxr);
     66    shape.sy  = +1.0 / sqrt(syr);
     67    shape.sxy = -0.5*f2*sin(2*axes.theta);
     68
     69    assert (isfinite(shape.sx));
     70    assert (isfinite(shape.sy));
     71    assert (isfinite(shape.sxy));
    3672
    3773    return shape;
     
    3975
    4076// ellipse derotation (sx, sy, sxy) -> (major, minor, theta)
    41 psEllipseAxes psEllipseShapeToAxes(psEllipseShape shape)
     77psEllipseAxes psEllipseShapeToAxes(psEllipseShape shape, double maxAR)
    4278{
    4379    psEllipseAxes axes;
    4480
    45     double f1 = 1.0 / PS_SQR(shape.sx) + 1.0 / PS_SQR(shape.sy);
    46     double f2 = 1.0 / PS_SQR(shape.sx) - 1.0 / PS_SQR(shape.sy);
     81    double f1 = 1.0 / PS_SQR(shape.sy) + 1.0 / PS_SQR(shape.sx);
     82    double f2 = 1.0 / PS_SQR(shape.sy) - 1.0 / PS_SQR(shape.sx);
    4783    double f3 = sqrt(PS_SQR(f2) + 4*PS_SQR(shape.sxy));
    4884
    49     axes.theta = 0.5 * atan2 (2*shape.sxy, f2);
    50     axes.major = sqrt (2.0 / (f1 - f3));
    5185    axes.minor = sqrt (2.0 / (f1 + f3));
     86    axes.theta = 0.5 * atan2 (-2.0*shape.sxy, f2);
     87
     88    // long, thin objects are likely to have a poorly measured major axis
     89    // the angle and minor axis are likely to be ok.
     90    // restrict the axis ratio
     91    double rAR2 = (f1 - f3) / (f1 + f3);
     92    if (rAR2 < 1.0/PS_SQR(maxAR)) {
     93        axes.major = axes.minor * maxAR;
     94    } else {
     95        axes.major = sqrt (2.0 / (f1 - f3));
     96    }
     97
     98    assert (isfinite(axes.theta));
     99    assert (isfinite(axes.major));
     100    assert (isfinite(axes.minor));
    52101
    53102    return axes;
     
    57106// force the axis ratio to be less than 10
    58107// double r1 = 0.5*0.95*sqrt (PS_SQR(f1) - PS_SQR(f2));
     108
     109//    double f = sqrt (0.25*PS_SQR(moments.x2 - moments.y2) + PS_SQR(moments.xy));
     110//    if (f > (moments.x2 + moments.y2) / 2.0) {
     111//        f = 0.98*(moments.x2 + moments.y2) / 2.0;
Note: See TracChangeset for help on using the changeset viewer.