Ejemplo n.º 1
0
    bool
    operator()(Point a, Point b) {
        // not remove this check or std::sort could crash
        if (a == b) return false;
        Point da = a - o;
        Point db = b - o;
        if (da == -db) return false;

#if 1
        double aa = da[0];
        double ab = db[0];
        if((da[1] == 0) && (db[1] == 0))
            return da[0] < db[0];
        if(da[1] == 0)
            return true; // infinite tangent
        if(db[1] == 0)
            return false; // infinite tangent
        aa = da[0] / da[1];
        ab = db[0] / db[1];
        if(aa > ab)
            return true;
#else
        //assert((ata > atb) == (aa < ab));
        double aa = atan2(da);
        double ab = atan2(db);
        if(aa < ab)
            return true;
#endif
        if(aa == ab)
            return L2sq(da) < L2sq(db);
        return false;
    }
Ejemplo n.º 2
0
 bool operator() (Point const& a, Point const&  b)
 {
     // not remove this check or std::sort could generate
     // a segmentation fault because it needs a strict '<'
     // but due to round errors a == b doesn't mean dxy == dyx
     if (a == b) return false;
     Point da = a - o;
     Point db = b - o;
     if (da == -db) return false;
     double dxy = da[X] * db[Y];
     double dyx = da[Y] * db[X];
     if (dxy > dyx) return true;
     else if (dxy < dyx) return false;
     return L2sq(da) < L2sq(db);
 }
Ejemplo n.º 3
0
/*
 * NOTE: this implementation follows Standard SVG 1.1 implementation guidelines
 * for elliptical arc curves. See Appendix F.6.
 */
void EllipticalArc::_updateCenterAndAngles(bool svg)
{
    Point d = initialPoint() - finalPoint();

    // TODO move this to SVGElipticalArc?
    if (svg)
    {
        if ( initialPoint() == finalPoint() )
        {
            _rot_angle = _start_angle = _end_angle = 0;
            _center = initialPoint();
            _rays = Geom::Point(0,0);
            _large_arc = _sweep = false;
            return;
        }

        _rays[X] = std::fabs(_rays[X]);
        _rays[Y] = std::fabs(_rays[Y]);

        if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
        {
            _rays[X] = L2(d) / 2;
            _rays[Y] = 0;
            _rot_angle = std::atan2(d[Y], d[X]);
            _start_angle = 0;
            _end_angle = M_PI;
            _center = middle_point(initialPoint(), finalPoint());
            _large_arc = false;
            _sweep = false;
            return;
        }
    }
    else
    {
        if ( are_near(initialPoint(), finalPoint()) )
        {
            if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
            {
                _start_angle = _end_angle = 0;
                _center = initialPoint();
                return;
            }
            else
            {
                THROW_RANGEERROR("initial and final point are the same");
            }
        }
        if ( are_near(ray(X), 0) && are_near(ray(Y), 0) )
        { // but initialPoint != finalPoint
            THROW_RANGEERROR(
                "there is no ellipse that satisfies the given constraints: "
                "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint"
            );
        }
        if ( are_near(ray(Y), 0) )
        {
            Point v = initialPoint() - finalPoint();
            if ( are_near(L2sq(v), 4*ray(X)*ray(X)) )
            {
                Angle angle(v);
                if ( are_near( angle, _rot_angle ) )
                {
                    _start_angle = 0;
                    _end_angle = M_PI;
                    _center = v/2 + finalPoint();
                    return;
                }
                angle -= M_PI;
                if ( are_near( angle, _rot_angle ) )
                {
                    _start_angle = M_PI;
                    _end_angle = 0;
                    _center = v/2 + finalPoint();
                    return;
                }
                THROW_RANGEERROR(
                    "there is no ellipse that satisfies the given constraints: "
                    "ray(Y) == 0 "
                    "and slope(initialPoint - finalPoint) != rotation_angle "
                    "and != rotation_angle + PI"
                );
            }
            if ( L2sq(v) > 4*ray(X)*ray(X) )
            {
                THROW_RANGEERROR(
                    "there is no ellipse that satisfies the given constraints: "
                    "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)"
                );
            }
            else
            {
                THROW_RANGEERROR(
                    "there is infinite ellipses that satisfy the given constraints: "
                    "ray(Y) == 0  and distance(initialPoint, finalPoint) < 2*ray(X)"
                );
            }

        }

        if ( are_near(ray(X), 0) )
        {
            Point v = initialPoint() - finalPoint();
            if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) )
            {
                double angle = std::atan2(v[Y], v[X]);
                if (angle < 0) angle += 2*M_PI;
                double rot_angle = _rot_angle.radians() + M_PI/2;
                if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI;
                if ( are_near( angle, rot_angle ) )
                {
                    _start_angle = M_PI/2;
                    _end_angle = 3*M_PI/2;
                    _center = v/2 + finalPoint();
                    return;
                }
                angle -= M_PI;
                if ( angle < 0 ) angle += 2*M_PI;
                if ( are_near( angle, rot_angle ) )
                {
                    _start_angle = 3*M_PI/2;
                    _end_angle = M_PI/2;
                    _center = v/2 + finalPoint();
                    return;
                }
                THROW_RANGEERROR(
                    "there is no ellipse that satisfies the given constraints: "
                    "ray(X) == 0 "
                    "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 "
                    "and != rotation_angle + (3/2)*PI"
                );
            }
            if ( L2sq(v) > 4*ray(Y)*ray(Y) )
            {
                THROW_RANGEERROR(
                    "there is no ellipse that satisfies the given constraints: "
                    "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)"
                );
            }
            else
            {
                THROW_RANGEERROR(
                    "there is infinite ellipses that satisfy the given constraints: "
                    "ray(X) == 0  and distance(initialPoint, finalPoint) < 2*ray(Y)"
                );
            }

        }

    }

    Rotate rm(_rot_angle);
    Affine m(rm);
    m[1] = -m[1];
    m[2] = -m[2];

    Point p = (d / 2) * m;
    double rx2 = _rays[X] * _rays[X];
    double ry2 = _rays[Y] * _rays[Y];
    double rxpy = _rays[X] * p[Y];
    double rypx = _rays[Y] * p[X];
    double rx2py2 = rxpy * rxpy;
    double ry2px2 = rypx * rypx;
    double num = rx2 * ry2;
    double den = rx2py2 + ry2px2;
    assert(den != 0);
    double rad = num / den;
    Point c(0,0);
    if (rad > 1)
    {
        rad -= 1;
        rad = std::sqrt(rad);

        if (_large_arc == _sweep) rad = -rad;
        c = rad * Point(rxpy / ray(Y), -rypx / ray(X));

        _center = c * rm + middle_point(initialPoint(), finalPoint());
    }
    else if (rad == 1 || svg)
    {
        double lamda = std::sqrt(1 / rad);
        _rays[X] *= lamda;
        _rays[Y] *= lamda;
        _center = middle_point(initialPoint(), finalPoint());
    }
    else
    {
        THROW_RANGEERROR(
            "there is no ellipse that satisfies the given constraints"
        );
    }

    Point sp((p[X] - c[X]) / ray(X), (p[Y] - c[Y]) / ray(Y));
    Point ep((-p[X] - c[X]) / ray(X), (-p[Y] - c[Y]) / ray(Y));
    Point v(1, 0);
    _start_angle = angle_between(v, sp);
    double sweep_angle = angle_between(sp, ep);
    if (!_sweep && sweep_angle > 0) sweep_angle -= 2*M_PI;
    if (_sweep && sweep_angle < 0) sweep_angle += 2*M_PI;

    _end_angle = _start_angle;
    _end_angle += sweep_angle;
}