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; }
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); } }
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 }
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; }
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(); }
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; }
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 }
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); }
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(); }
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); }
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; }
bool Matrix2d::isIdentity() const { return mgEquals(m11, 1.f) && mgIsZero(m12) && mgEquals(m22, 1.f) && mgIsZero(m21) && mgIsZero(dx) && mgIsZero(dy); }
bool MgBaseRect::isOrtho() const { return mgEquals(_points[1].y, _points[0].y); }
bool MgRoundRect::_equals(const MgRoundRect& src) const { return mgEquals(_rx, src._rx) && mgEquals(_ry, src._ry) && __super::_equals(src); }