Beispiel #1
0
static int _crossTwoCircles(point_t& pt1, point_t& pt2,
                            const point_t& c1, double r1,
                            const point_t& c2, double r2)
{
    double d, a, b, c, p, q, r;
    double cos_value[2], sin_value[2];
    
    if (mgEquals(c1.x, c2.x) && mgEquals(c1.y, c2.y) && mgEquals(r1, r2)) {
        return -1;
    }
    
    d = c1.distanceTo(c2);
    if (d > r1 + r2 || d < fabs(r1 - r2)) {
        return 0;
    }
    
    a = 2.0 * r1 * (c1.x - c2.x);
    b = 2.0 * r1 * (c1.y - c2.y);
    c = r2 * r2 - r1 * r1 - c1.distanceSquare(c2);
    p = a * a + b * b;
    q = -2.0 * a * c;
    if (mgEquals(d, r1 + r2) || mgEquals(d, fabs(r1 - r2))) {
        cos_value[0] = -q / p / 2.0;
        sin_value[0] = sqrt(1 - cos_value[0] * cos_value[0]);
        
        pt1.x = r1 * cos_value[0] + c1.x;
        pt1.y = r1 * sin_value[0] + c1.y;
        
        if (!mgEquals(pt1.distanceSquare(c2), r2 * r2)) {
            pt1.y = c1.y - r1 * sin_value[0];
        }
        return 1;
    }
    
    r = c * c - b * b;
    cos_value[0] = (sqrt(q * q - 4.0 * p * r) - q) / p / 2.0;
    cos_value[1] = (-sqrt(q * q - 4.0 * p * r) - q) / p / 2.0;
    sin_value[0] = sqrt(1 - cos_value[0] * cos_value[0]);
    sin_value[1] = sqrt(1 - cos_value[1] * cos_value[1]);
    
    pt1.x = r1 * cos_value[0] + c1.x;
    pt2.x = r1 * cos_value[1] + c1.x;
    pt1.y = r1 * sin_value[0] + c1.y;
    pt2.y = r1 * sin_value[1] + c1.y;
    
    if (!mgEquals(pt1.distanceSquare(c2), r2 * r2)) {
        pt1.y = c1.y - r1 * sin_value[0];
    }
    if (!mgEquals(pt2.distanceSquare(c2), r2 * r2)) {
        pt2.y = c1.y - r1 * sin_value[1];
    }
    if (mgEquals(pt1.y, pt2.y) && mgEquals(pt1.x, pt2.x)) {
        if (pt1.y > 0) {
            pt2.y = -pt2.y;
        } else {
            pt1.y = -pt1.y;
        }
    }
    return 2;
}
Beispiel #2
0
float mglnrel::ptToBeeline2(
    const Point2d& a, const Point2d& b, const Point2d& pt, Point2d& ptPerp)
{
    // 两点重合
    if (a == b)
    {
        ptPerp = a;
        return a.distanceTo(pt);
    }
    // 竖直线
    else if (mgEquals(a.x, b.x))
    {
        ptPerp.set(a.x, pt.y);
        return fabsf(a.x - pt.x);
    }
    // 水平线
    else if (mgEquals(a.y, b.y))
    {
        ptPerp.set(pt.x, a.y);
        return fabsf(a.y - pt.y);
    }
    else
    {
        float t1 = ( b.y - a.y ) / ( b.x - a.x );
        float t2 = -1.f / t1;
        ptPerp.x = ( pt.y - a.y + a.x * t1 - pt.x * t2 ) / ( t1 - t2 );
        ptPerp.y = a.y + (ptPerp.x - a.x) * t1;
        return pt.distanceTo(ptPerp);
    }
}
Beispiel #3
0
float MgArc::getSweepAngle() const
{
    if (!mgIsZero(_sweepAngle)) {
        return _sweepAngle;
    }
    
    const float midAngle = (getMidPoint() - getCenter()).angle2();
    const float startAngle = getStartAngle();
    const float endAngle = getEndAngle();

    if (mgEquals(midAngle, startAngle) && mgEquals(startAngle, endAngle)) {
        return endAngle - startAngle;
    }
    
    Tol tol(getRadius() * 1e-3f, 1e-4f);
    if (getStartPoint().isEqualTo(getEndPoint(), tol)
        && (getMidPoint() + (getStartPoint() + getEndPoint()) / 2).isEqualTo(2 * getCenter(), tol)) {
        return _M_2PI;
    }

    float startAngle2 = startAngle;
    float midAngle2 = midAngle;
    float endAngle2 = endAngle;

    // 先尝试看是否为逆时针方向:endAngle2 > midAngle2 > startAngle2 >= 0
    if (startAngle2 < 0)
        startAngle2 += _M_2PI;
    while (midAngle2 < startAngle2)
        midAngle2 += _M_2PI;
    while (endAngle2 < midAngle2)
        endAngle2 += _M_2PI;

    if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6
        && endAngle2 - startAngle2 < _M_2PI) {
        return endAngle2 - startAngle2;
    }

    // 再尝试看是否为顺时针方向:endAngle2 < midAngle2 < startAngle2 <= 0
    startAngle2 = startAngle;
    midAngle2 = midAngle;
    endAngle2 = endAngle;
    if (startAngle2 > 0)
        startAngle2 -= _M_2PI;
    while (midAngle2 > startAngle2)
        midAngle2 -= _M_2PI;
    while (endAngle2 > midAngle2)
        endAngle2 -= _M_2PI;

    if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6) {
        if (endAngle2 - startAngle2 > -_M_2PI)
            return endAngle2 - startAngle2;
        return mgbase::toRange(endAngle2 - startAngle2, -_M_2PI, 0);
    }

    return endAngle - startAngle;   // error
}
Beispiel #4
0
static bool PtInArea_Edge(int &odd, const Point2d& pt, const Point2d& p1, 
                          const Point2d& p2, const Point2d& p0)
{
    // 如果从X方向上P不在边[P1,P2)上,则没有交点. 竖直边也没有
    if (!((p2.x > p1.x) && (pt.x >= p1.x) && (pt.x < p2.x)) &&
        !((p1.x > p2.x) && (pt.x <= p1.x) && (pt.x > p2.x)) )
    {
        return false;
    }
    
    // 求从Y负无穷大向上到P的射线和该边的交点(pt.x, yy)
    float yy = p1.y + (pt.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
    if (pt.y > yy)      // 相交
    {
        if (mgEquals(pt.x, p1.x))   // 交点是顶点, 则比较P[i+1]和P[i-1]是否在pt.x同侧
        {
            if (((p0.x > pt.x) && (p2.x > pt.x)) ||
                ((p0.x < pt.x) && (p2.x < pt.x)) )      // 同侧
            {
                return false;
            }
        }
        odd = 1 - odd;      // 增加一个交点, 奇偶切换
    }
    
    return true;
}
Beispiel #5
0
bool GiGraphics::setPen(const GiContext* ctx)
{
    bool changed = !(m_impl->ctxused & 1);
    
    if (m_impl->canvas) {
        if (ctx && (!mgEquals(ctx->getLineWidth(), m_impl->ctx.getLineWidth())
                    || ctx->isAutoScale() != m_impl->ctx.isAutoScale())) {
            m_impl->ctx.setLineWidth(ctx->getLineWidth(), ctx->isAutoScale());
            changed = true;
        }
        if (ctx && ctx->getLineColor() != m_impl->ctx.getLineColor()) {
            m_impl->ctx.setLineColor(ctx->getLineColor());
            changed = true;
        }
        if (ctx && ctx->getLineStyle() != m_impl->ctx.getLineStyle()) {
            m_impl->ctx.setLineStyle(ctx->getLineStyle());
            changed = true;
        }
    }
    
    ctx = &(m_impl->ctx);
    if (m_impl->canvas && changed) {
        m_impl->ctxused &= 1;
        m_impl->canvas->setPen(calcPenColor(ctx->getLineColor()).getARGB(),
                               calcPenWidth(ctx->getLineWidth(), ctx->isAutoScale()),
                               ctx->getLineStyle(), 0);
    }
    
    return !ctx->isNullLine();
}
Beispiel #6
0
bool mgcurv::cubicSplines(
    int n, const Point2d* knots, Vector2d* knotvs,
    int flag, float tension)
{
    bool ret = false;
    
    if (!knots || !knotvs || n < 2)
        return false;
    
    if ((flag & cubicLoop) && n <= 512) {
        float* a = new float[n * n];
        ret = a && CalcCubicClosed(n, a, knotvs, knots);
        delete[] a;
    }
    else {
        float* a = new float[n * 3];
        ret = a && CalcCubicUnclosed(flag, n, knots, 
            a, a+n, a+2*n, knotvs);
        delete[] a;
    }
    
    if (!mgEquals(tension, 1.f)) {
        for (int i = 0; i < n; i++) {
            knotvs[i].x *= tension;
            knotvs[i].y *= tension;
        }
    }

    return ret;
}
Beispiel #7
0
float MgArc::getSweepAngle() const
{
    const float midAngle = (getMidPoint() - getCenter()).angle2();
    const float startAngle = getStartAngle();
    const float endAngle = getEndAngle();

    if (mgEquals(midAngle, startAngle) && mgEquals(startAngle, endAngle)) {
        return endAngle - startAngle;
    }

    float startAngle2 = startAngle;
    float midAngle2 = midAngle;
    float endAngle2 = endAngle;

    // 先尝试看是否为逆时针方向:endAngle2 > midAngle2 > startAngle2 >= 0
    if (startAngle2 < 0)
        startAngle2 += _M_2PI;
    while (midAngle2 < startAngle2)
        midAngle2 += _M_2PI;
    while (endAngle2 < midAngle2)
        endAngle2 += _M_2PI;

    if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6
        && endAngle2 - startAngle2 < _M_2PI) {
        return endAngle2 - startAngle2;
    }

    // 再尝试看是否为顺时针方向:endAngle2 < midAngle2 < startAngle2 <= 0
    startAngle2 = startAngle;
    midAngle2 = midAngle;
    endAngle2 = endAngle;
    if (startAngle2 > 0)
        startAngle2 -= _M_2PI;
    while (midAngle2 > startAngle2)
        midAngle2 -= _M_2PI;
    while (endAngle2 > midAngle2)
        endAngle2 -= _M_2PI;

    if (fabsf(startAngle2 + endAngle2 - 2 * midAngle2) < _M_PI_6) {
        if (endAngle2 - startAngle2 > -_M_2PI)
            return endAngle2 - startAngle2;
        return mgToRange(endAngle2 - startAngle2, -_M_2PI, 0);
    }

    return endAngle - startAngle;   // error
}
Beispiel #8
0
bool GiGraphics::_drawPolygon(const GiContext* ctx, int count, const Point2d* points,
                              bool m2d, bool fill, bool edge, bool modelUnit)
{
    GiContext context (ctx ? *ctx : m_impl->ctx);
    if (!edge)
        context.setNullLine();
    if (!fill)
        context.setNoFillColor();
    
    if (context.isNullLine() && !context.hasFillColor())
        return false;

    vector<Point2d> pxpoints;
    Point2d pt1, pt2;
    Matrix2d matD(S2D(xf(), modelUnit));

    pxpoints.resize(count);
    Point2d *pxs = &pxpoints.front();
    int n = 0;
    for (int i = 0; i < count; i++) {
        pt2 = points[i];
        if (m2d)
            pt2 *= matD;
        if (i == 0 || count <= 4
            || fabsf(pt1.x - pt2.x) > 2
            || fabsf(pt1.y - pt2.y) > 2) {
            pt1 = pt2;
            pxs[n++] = pt1;
        }
    }

    if (n == 4 && m2d
        && mgEquals(pxs[0].x, pxs[3].x) && mgEquals(pxs[1].x, pxs[2].x)
        && mgEquals(pxs[0].y, pxs[1].y) && mgEquals(pxs[2].y, pxs[3].y))
    {
        Box2d rc(pxs[0].x, pxs[0].y, pxs[2].x, pxs[2].y, true);
        return rawRect(&context, rc.xmin, rc.ymin, rc.width(), rc.height());
    }

    return rawPolygon(&context, pxs, n);
}
Beispiel #9
0
bool GiGraphics::setPen(const GiContext* ctx)
{
    bool changed = !(m_impl->ctxused & 1);
    
    if (m_impl->canvas) {
        if (ctx && (!mgEquals(ctx->getLineWidth(), m_impl->ctx.getLineWidth())
                    || ctx->isAutoScale() != m_impl->ctx.isAutoScale())) {
            m_impl->ctx.setLineWidth(ctx->getLineWidth(), ctx->isAutoScale());
            changed = true;
        }
        if (ctx && !mgEquals(ctx->getExtraWidth(), m_impl->ctx.getExtraWidth())) {
            m_impl->ctx.setExtraWidth(ctx->getExtraWidth());
            changed = true;
        }
        if (ctx && ctx->getLineColor() != m_impl->ctx.getLineColor()) {
            m_impl->ctx.setLineColor(ctx->getLineColor());
            changed = true;
        }
        if (ctx && ctx->getLineStyleEx() != m_impl->ctx.getLineStyleEx()) {
            m_impl->ctx.setLineStyle(ctx->getLineStyleEx(), true);
            changed = true;
        }
    }
    
    ctx = &(m_impl->ctx);
    if (m_impl->canvas && changed) {
        m_impl->ctxused &= 1;
        float w = calcPenWidth(ctx->getLineWidth(), ctx->isAutoScale());
        float orgw = ctx->getLineWidth();
        orgw = (orgw < -0.1f && ctx->isAutoScale()) ? orgw - 1e4f : orgw;
        m_impl->canvas->setPen(calcPenColor(ctx->getLineColor()).getARGB(),
                               w + ctx->getExtraWidth(),
                               ctx->getLineStyleEx(),
                               mgMax(m_impl->phase, 0.f), orgw);
    }
    
    return !ctx->isNullLine();
}
Beispiel #10
0
bool GiTransform::zoomByFactor(float factor, const Point2d* pxAt, bool adjust)
{
    float scale = m_impl->viewScale;
    if (factor > 0)
        scale *= (1.f + fabsf(factor));
    else
        scale /= (1.f + fabsf(factor));

    if (adjust) {
        scale = mgMax(scale, m_impl->minViewScale);
        scale = mgMin(scale, m_impl->maxViewScale);
    }
    if (mgEquals(scale, m_impl->viewScale))
        return false;
    return zoomScale(scale, pxAt, adjust);
}
Beispiel #11
0
    bool zoomNoAdjust(const Point2d& pnt, float scale, bool* changed = NULL)
    {
        bool bChanged = false;

        if (pnt != centerW || !mgEquals(scale, viewScale))
        {
            tmpCenterW = pnt;
            tmpViewScale = scale;
            bChanged = true;
            if (zoomEnabled) {
                centerW = pnt;
                viewScale = scale;
                updateTransforms();
                zoomChanged();
            }
        }
        if (changed != NULL)
            *changed = bChanged;

        return bChanged;
    }
Beispiel #12
0
bool Matrix2d::isIdentity() const
{
    return mgEquals(m11, 1.f) && mgIsZero(m12)
        && mgEquals(m22, 1.f) && mgIsZero(m21)
        && mgIsZero(dx) && mgIsZero(dy);
}
Beispiel #13
0
bool MgBaseRect::isOrtho() const
{
    return mgEquals(_points[1].y, _points[0].y);
}
Beispiel #14
0
bool MgRoundRect::_equals(const MgRoundRect& src) const
{
    return mgEquals(_rx, src._rx)
        && mgEquals(_ry, src._ry)
        && __super::_equals(src);
}