bool GiGraphics::drawBeziers(const GiContext* ctx, int count, const Point2d* points, bool closed, bool modelUnit) { if (count < 4 || !points || isStopping()) return false; if (count > 0x2000) count = 0x2000; count = 1 + (count - 1) / 3 * 3; bool ret = false; vector<Point2d> pxpoints; vector<Point2d> pointBuf; int i, j, n, si, ei; Point2d * pxs; Matrix2d matD(S2D(xf(), modelUnit)); const Box2d extent (count, points); // 模型坐标范围 if (!DRAW_RECT(m_impl, modelUnit).isIntersect(extent)) // 全部在显示区域外 return false; if (closed) { pxpoints.resize(count); pxs = &pxpoints.front(); for (i = 0; i < count; i++) pxs[i] = points[i] * matD; ret = rawBeziers(ctx, pxs, count, closed); } else if (DRAW_MAXR(m_impl, modelUnit).contains(extent)) { // 全部在显示区域内 pxpoints.resize(count); pxs = &pxpoints.front(); for (i = 0; i < count; i++) pxs[i] = points[i] * matD; ret = rawBeziers(ctx, pxs, count); } else { pointBuf.resize(count); for (i = 0; i < count; i++) // 转换到像素坐标 pointBuf[i] = points[i] * matD; Point2d* pts = &pointBuf.front(); for (i = 0; i + 3 < count;) { for (; i + 3 < count && !m_impl->rectDraw.isIntersect(Box2d(4, &pts[i])); i += 3) ; si = ei = i; for (; i + 3 < count && m_impl->rectDraw.isIntersect(Box2d(4, &pts[i])); i += 3) ei = i + 3; if (ei > si) { n = ei - si + 1; pxpoints.resize(n); pxs = &pxpoints.front(); for (j=0; j<n; j++) pxs[j] = pts[si + j]; ret = rawBeziers(ctx, pxs, n); } } } return ret; }
bool GiGraphics::drawBeziers(const GiContext* ctx, int count, const Point2d* points, bool modelUnit) { if (m_impl->drawRefcnt == 0 || count < 4 || points == NULL) return false; GiLock lock (&m_impl->drawRefcnt); if (count > 0x2000) count = 0x2000; count = 1 + (count - 1) / 3 * 3; bool ret = false; vector<Point2d> pxpoints; vector<Point2d> pointBuf; int i, j, n, si, ei; Point2d * pxs; Matrix2d matD(S2D(xf(), modelUnit)); const Box2d extent (count, points); // 模型坐标范围 if (!DRAW_RECT(m_impl, modelUnit).isIntersect(extent)) // 全部在显示区域外 return false; if (DRAW_MAXR(m_impl, modelUnit).contains(extent)) // 全部在显示区域内 { pxpoints.resize(count); pxs = &pxpoints.front(); for (i = 0; i < count; i++) pxs[i] = points[i] * matD; ret = rawBeziers(ctx, pxs, count); } else { pointBuf.resize(count); for (i = 0; i < count; i++) // 转换到像素坐标 pointBuf[i] = points[i] * matD; Point2d* pts = &pointBuf.front(); si = ei = 0; for (i = 3; i < count; i += 3) { for ( ; i < count && m_impl->rectDraw.isIntersect(Box2d(4, &pts[ei])); i += 3) ei = i; n = ei - si + 1; if (n > 1) { pxpoints.resize(n); pxs = &pxpoints.front(); for (j=0; j<n; j++) pxs[j] = pts[si + j]; ret = rawBeziers(ctx, pxs, n); } si = ei = i; } } return ret; }
bool GiGraphics::drawSplines(const GiContext* ctx, int count, const Point2d* knots, const Vector2d* knotvs, bool modelUnit) { if (m_impl->drawRefcnt == 0 || count < 2 || knots == NULL || knotvs == NULL) return false; GiLock lock (&m_impl->drawRefcnt); count = mgMin(count, static_cast<int>(1 + (0x2000 - 1) / 3)); int i; Point2d pt; Vector2d vec; vector<Point2d> pxpoints; Matrix2d matD(S2D(xf(), modelUnit)); // 开辟整形像素坐标数组 pxpoints.resize(1 + (count - 1) * 3); Point2d *pxs = &pxpoints.front(); pt = knots[0] * matD; // 第一个Bezier段的起点 vec = knotvs[0] * matD / 3.f; // 第一个Bezier段的起始矢量 *pxs++ = pt; // 产生Bezier段的起点 for (i = 1; i < count; i++) // 计算每一个Bezier段 { *pxs++ = (pt += vec); // 产生Bezier段的第二点 pt = knots[i] * matD; // Bezier段的终点 vec = knotvs[i] * matD / 3.f; // Bezier段的终止矢量 *pxs++ = pt - vec; // 产生Bezier段的第三点 *pxs++ = pt; // 产生Bezier段的终点 } // 绘图 return rawBeziers(ctx, &pxpoints.front(), getSize(pxpoints)); }
bool GiGraphics::drawHermiteSplines(const GiContext* ctx, int count, const Point2d* knots, const Vector2d* knotvs, bool closed, bool modelUnit) { if (count < 2 || !knots || !knotvs || isStopping()) return false; count = mgMin(count, 0x1000); int i; Point2d pt; Vector2d vec; vector<Point2d> pxpoints; Matrix2d matD(S2D(xf(), modelUnit)); Matrix2d mat2(matD / 3.f); pxpoints.resize(1 + (closed ? count : count - 1) * 3); Point2d *pxs = &pxpoints.front(); pt = knots[0] * matD; // 第一个Bezier段的起点 vec = knotvs[0] * mat2; // 第一个Bezier段的起始矢量 *pxs++ = pt; // 产生Bezier段的起点 for (i = 1; i < count; i++) { // 计算每一个Bezier段 *pxs++ = (pt += vec); // 产生Bezier段的第二点 pt = knots[i] * matD; // Bezier段的终点 vec = knotvs[i] * mat2; // Bezier段的终止矢量 *pxs++ = pt - vec; // 产生Bezier段的第三点 *pxs++ = pt; // 产生Bezier段的终点 } if (closed) { *pxs++ = (pt += vec); // 产生Bezier段的第二点 *pxs++ = 2 * pxpoints[0] - pxpoints[1].asVector(); // 产生Bezier段的第三点 *pxs++ = pxpoints[0]; // 产生Bezier段的终点 } return rawBeziers(ctx, &pxpoints.front(), getSize(pxpoints), closed); }
bool GiGraphics::drawEllipse(const GiContext* ctx, const Point2d& center, float rx, float ry, bool modelUnit) { if (rx < _MGZERO || isStopping()) return false; bool ret = false; Matrix2d matD(S2D(xf(), modelUnit)); if (ry < _MGZERO) { ry = (Vector2d(rx, rx) * matD).x; ry = fabsf((Vector2d(ry, ry) * matD.inverse()).y); } const Box2d extent (center, rx*2.f, ry*2.f); // 模型坐标范围 if (!DRAW_RECT(m_impl, modelUnit).isIntersect(extent)) // 全部在显示区域外 return false; if (mgIsZero(matD.m12) && mgIsZero(matD.m21)) { Point2d cen (center * matD); rx *= fabsf(matD.m11); ry *= fabsf(matD.m22); ret = rawEllipse(ctx, cen.x - rx, cen.y - ry, 2 * rx, 2 * ry); } else { Point2d pxs[13]; mgcurv::ellipseToBezier(pxs, center, rx, ry); matD.transformPoints(13, pxs); ret = rawBeziers(ctx, pxs, 13, true); } return ret; }
bool GiGraphics::drawBSplines(const GiContext* ctx, int count, const Point2d* ctlpts, bool closed, bool modelUnit) { if (closed) { if (count < 3 || !ctlpts || isStopping()) return false; count = mgMin(count, static_cast<int>((0x2000 - 1) / 3)); } else { if (count < 4 || !ctlpts || isStopping()) return false; count = mgMin(count, static_cast<int>(3 + (0x2000 - 1) / 3)); } const Box2d extent (count, ctlpts); // 模型坐标范围 if (!DRAW_RECT(m_impl, modelUnit).isIntersect(extent)) // 全部在显示区域外 return false; int i; Point2d pt1, pt2, pt3, pt4; float d6 = 1.f / 6.f; vector<Point2d> pxpoints; Matrix2d matD(S2D(xf(), modelUnit)); // 开辟像素坐标数组 pxpoints.resize(1 + (closed ? count : (count - 3)) * 3); Point2d *pxs = &pxpoints.front(); // 计算第一个曲线段 pt1 = ctlpts[0] * matD; pt2 = ctlpts[1] * matD; pt3 = ctlpts[2] * matD; pt4 = ctlpts[3 % count] * matD; (*pxs++).set((pt1.x + 4 * pt2.x + pt3.x)*d6, (pt1.y + 4 * pt2.y + pt3.y)*d6); (*pxs++).set((4 * pt2.x + 2 * pt3.x) *d6, (4 * pt2.y + 2 * pt3.y) *d6); (*pxs++).set((2 * pt2.x + 4 * pt3.x) *d6, (2 * pt2.y + 4 * pt3.y) *d6); (*pxs++).set((pt2.x + 4 * pt3.x + pt4.x)*d6, (pt2.y + 4 * pt3.y + pt4.y)*d6); // 计算其余曲线段 for (i = 4; i < (closed ? (count + 3) : count); i++) { pt1 = pt2; pt2 = pt3; pt3 = pt4; pt4 = ctlpts[i % count] * matD; (*pxs++).set((4 * pt2.x + 2 * pt3.x) *d6, (4 * pt2.y + 2 * pt3.y) *d6); (*pxs++).set((2 * pt2.x + 4 * pt3.x) *d6, (2 * pt2.y + 4 * pt3.y) *d6); (*pxs++).set((pt2.x + 4 * pt3.x + pt4.x)*d6,(pt2.y + 4 * pt3.y + pt4.y)*d6); } // 绘图 return rawBeziers(ctx, &pxpoints.front(), getSize(pxpoints), closed); }
bool GiGraphics::drawArc(const GiContext* ctx, const Point2d& center, float rx, float ry, float startAngle, float sweepAngle, bool modelUnit) { if (rx < _MGZERO || fabsf(sweepAngle) < 1e-5f || isStopping()) return false; if (ry < _MGZERO) ry = rx; if (!DRAW_RECT(m_impl, modelUnit).isIntersect(Box2d(center, 2 * rx, 2 * ry))) return false; Point2d points[16]; int count = mgcurv::arcToBezier(points, center, rx, ry, startAngle, sweepAngle); S2D(xf(), modelUnit).transformPoints(count, points); return count > 3 && rawBeziers(ctx, points, count); }
bool GiGraphics::drawArc(const GiContext* ctx, const Point2d& center, float rx, float ry, float startAngle, float sweepAngle, bool modelUnit) { if (m_impl->drawRefcnt == 0 || rx < _MGZERO || fabs(sweepAngle) < 1e-5f) return false; GiLock lock (&m_impl->drawRefcnt); if (ry < _MGZERO) ry = rx; if (!DRAW_RECT(m_impl, modelUnit).isIntersect(Box2d(center, 2 * rx, 2 * ry))) return false; Point2d points[16]; int count = mgAngleArcToBezier(points, center, rx, ry, startAngle, sweepAngle); S2D(xf(), modelUnit).TransformPoints(count, points); return count > 3 && rawBeziers(ctx, points, count); }
bool GiGraphics::drawBeziers(const GiContext* ctx, int count, const Point2d* knot, const Vector2d* knotvs, bool closed, bool modelUnit) { if (count < 2 || !knot || !knotvs || isStopping()) return false; if (count > 0x1000) count = 0x1000; bool ret = false; vector<Point2d> pxpoints; vector<Point2d> pointBuf; int i, j, n, si, ei; Point2d * pxs; Matrix2d matD(S2D(xf(), modelUnit)); const Box2d extent (count, knot); // 模型坐标范围 if (!DRAW_RECT(m_impl, modelUnit).isIntersect(extent)) // 全部在显示区域外 return false; pointBuf.resize(1 + (count - 1) * 3); pxs = &pointBuf.front(); if (closed) { pxs[0] = knot[0] * matD; for (i = 0, j = 1; i + 1 < count; i++) { pxs[j++] = (knot[i] + knotvs[i]) * matD; pxs[j++] = (knot[i+1] - knotvs[i+1]) * matD; pxs[j++] = knot[i+1] * matD; } ret = rawBeziers(ctx, pxs, j, closed); } else if (DRAW_MAXR(m_impl, modelUnit).contains(extent)) { // 全部在显示区域内 pxs[0] = knot[0] * matD; for (i = 0, j = 1; i + 1 < count; i++) { pxs[j++] = (knot[i] + knotvs[i]) * matD; pxs[j++] = (knot[i+1] - knotvs[i+1]) * matD; pxs[j++] = knot[i+1] * matD; } ret = rawBeziers(ctx, pxs, j); } else { pxs[0] = knot[0] * matD; for (i = 0, j = 1; i + 1 < count; i++) { pxs[j++] = (knot[i] + knotvs[i]) * matD; pxs[j++] = (knot[i+1] - knotvs[i+1]) * matD; pxs[j++] = knot[i+1] * matD; } Point2d* pts = pxs; count = 1 + (count - 1) * 3; for (i = 0; i + 3 < count;) { for (; i + 3 < count && !m_impl->rectDraw.isIntersect(Box2d(4, &pts[i])); i += 3) ; si = ei = i; for (; i + 3 < count && m_impl->rectDraw.isIntersect(Box2d(4, &pts[i])); i += 3) ei = i + 3; if (ei > si) { n = ei - si + 1; pxpoints.resize(n); pxs = &pxpoints.front(); for (j=0; j<n; j++) pxs[j] = pts[si + j]; ret = rawBeziers(ctx, pxs, n); } } } return ret; }