void mgnear::getRectHandle(const Box2d& rect, int index, Point2d& pt) { switch (index) { case 0: pt = rect.leftTop(); break; case 1: pt = rect.rightTop(); break; case 2: pt = rect.rightBottom(); break; case 3: pt = rect.leftBottom(); break; case 4: pt = Point2d(rect.center().x, rect.ymax); break; case 5: pt = Point2d(rect.xmax, rect.center().y); break; case 6: pt = Point2d(rect.center().x, rect.ymin); break; case 7: pt = Point2d(rect.xmin, rect.center().y); break; default: pt = rect.center(); break; } }
void mgcurv::roundRectToBeziers( Point2d points[16], const Box2d& rect, float rx, float ry) { if (2 * rx > rect.width()) rx = rect.width() / 2; if (2 * ry > rect.height()) ry = rect.height() / 2; int i, j; float dx = rect.width() / 2 - rx; float dy = rect.height() / 2 - ry; mgcurv::ellipseToBezier(points, rect.center(), rx, ry); for (i = 3; i >= 1; i--) { for (j = 3; j >= 0; j--) points[4 * i + j] = points[3 * i + j]; } for (i = 0; i < 4; i++) { float dx1 = (0 == i || 3 == i) ? dx : -dx; float dy1 = (0 == i || 1 == i) ? dy : -dy; for (j = 0; j < 4; j++) points[4 * i + j].offset(dx1, dy1); } }
static void AdjustCenterW(Point2d &ptW, float halfw, float halfh, const Box2d& rectW) { if (ptW.x - halfw < rectW.xmin) ptW.x += rectW.xmin - (ptW.x - halfw); if (ptW.x + halfw > rectW.xmax) ptW.x += rectW.xmax - (ptW.x + halfw); if (2 * halfw >= rectW.width()) ptW.x = rectW.center().x; if (ptW.y - halfh < rectW.ymin) ptW.y += rectW.ymin - (ptW.y - halfh); if (ptW.y + halfh > rectW.ymax) ptW.y += rectW.ymax - (ptW.y + halfh); if (2 * halfh >= rectW.height()) ptW.y = rectW.center().y; }
bool GiTransformImpl::zoomPanAdjust(Point2d &ptW, float dxPixel, float dyPixel) const { bool bAdjusted = false; float halfw = cxWnd / w2dx * 0.5f; float halfh = cyWnd / w2dy * 0.5f; if (dxPixel > 0 && ptW.x - halfw < rectLimitsW.xmin) { bAdjusted = true; ptW.x += rectLimitsW.xmin - (ptW.x - halfw); } if (dxPixel < 0 && ptW.x + halfw > rectLimitsW.xmax) { bAdjusted = true; ptW.x += rectLimitsW.xmax - (ptW.x + halfw); } if (fabs(dxPixel) > 0 && 2 * halfw >= rectLimitsW.width()) { bAdjusted = true; ptW.x = rectLimitsW.center().x; } if (dyPixel < 0 && ptW.y - halfh < rectLimitsW.ymin) { bAdjusted = true; ptW.y += rectLimitsW.ymin - (ptW.y - halfh); } if (dyPixel > 0 && ptW.y + halfh > rectLimitsW.ymax) { bAdjusted = true; ptW.y += rectLimitsW.ymax - (ptW.y + halfh); } if (fabs(dyPixel) > 0 && 2 * halfh >= rectLimitsW.height()) { bAdjusted = true; ptW.y = rectLimitsW.center().y; } return bAdjusted; }
void MgBaseRect::setRect(const Box2d& rect, float angle) { _points[0] = rect.leftTop(); _points[1] = rect.rightTop(); _points[2] = rect.rightBottom(); _points[3] = rect.leftBottom(); if (!mgIsZero(angle)) { Matrix2d mat(Matrix2d::rotation(angle, rect.center())); for (int i = 0; i < 4; i++) _points[i] *= mat; } }
static void _RoundRectHit( const Box2d& rect, float rx, float ry, const Point2d& pt, float tol, const Box2d &rectTol, Point2d* pts, float& distMin, Point2d& nearpt, int& segment) { Point2d ptsBezier[13], ptTemp; Vector2d vec; float dx = rect.width() * 0.5f - rx; float dy = rect.height() * 0.5f - ry; // 按逆时针方向从第一象限到第四象限连接的四段 mgcurv::ellipseToBezier(ptsBezier, rect.center(), rx, ry); pts[3] = ptsBezier[0]; for (int i = 0; i < 4; i++) { pts[0] = pts[3]; pts[1] = ptsBezier[3 * i]; pts[2] = ptsBezier[3 * i + 1]; pts[3] = ptsBezier[3 * i + 2]; switch (i) { case 0: vec.set(dx, dy); break; case 1: vec.set(-dx, dy); break; case 2: vec.set(-dx, -dy); break; case 3: vec.set(dx, -dy); break; } for (int j = 0; j < 4; j++) pts[j] += vec; if (rectTol.isIntersect(Box2d(4, pts))) { mgnear::nearestOnBezier(pt, pts, ptTemp); float dist = pt.distanceTo(ptTemp); if (dist <= tol && dist < distMin) { distMin = dist; nearpt = ptTemp; segment = (5 - i) % 4; } } pts[3] -= vec; } }
Box2d calcButtonPosition(mgvector<float>& pos, int n, const Box2d& selbox) { Box2d rect; for (int i = 0; i < n; i++) { switch (i) { case 0: if (n == 1) { pos.set(2 * i, selbox.center().x, selbox.ymin); // MT } else { pos.set(2 * i, selbox.xmin, selbox.ymin); // LT } break; case 1: if (n == 3) { pos.set(2 * i, selbox.center().x, selbox.ymin); // MT } else { pos.set(2 * i, selbox.xmax, selbox.ymin); // RT } break; case 2: if (n == 3) { pos.set(2 * i, selbox.xmax, selbox.ymin); // RT } else { pos.set(2 * i, selbox.xmax, selbox.ymax); // RB } break; case 3: pos.set(2 * i, selbox.xmin, selbox.ymax); // LB break; case 4: pos.set(2 * i, selbox.center().x, selbox.ymin); // MT break; case 5: pos.set(2 * i, selbox.center().x, selbox.ymax); // MB break; case 6: pos.set(2 * i, selbox.xmax, selbox.center().y); // RM break; case 7: pos.set(2 * i, selbox.xmin, selbox.center().y); // LM break; default: return rect; } rect.unionWith(Box2d(Point2d(pos.get(2 * i), pos.get(2 * i + 1)), 32, 32)); } return rect; }
bool GiCanvasIos::drawImage(CGImageRef image, const Box2d& rectM) { CGContextRef context = m_draw->getContext(); bool ret = false; if (context && image) { Point2d ptD = rectM.center() * m_draw->xf().modelToDisplay(); Box2d rect = rectM * m_draw->xf().modelToDisplay(); CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height()); af = CGAffineTransformTranslate(af, ptD.x - rect.width() * 0.5f, m_draw->height() - (ptD.y + rect.height() * 0.5f)); CGContextConcatCTM(context, af); CGContextDrawImage(context, CGRectMake(0, 0, rect.width(), rect.height()), image); CGContextConcatCTM(context, CGAffineTransformInvert(af)); ret = true; } return ret; }
bool MgPath::crossWithPath(const MgPath& p, const Box2d& box, Point2d& ptCross) const { MgPathCrossCallback cc(box, ptCross); if (isLine() && p.isLine()) { return (mglnrel::cross2Line(getPoint(0), getPoint(1), p.getPoint(0), p.getPoint(1), ptCross) && box.contains(ptCross)); } if (isLines() && p.isLines()) { for (int m = getCount() - (isClosed() ? 0 : 1), i = 0; i < m; i++) { Point2d a(getPoint(i)), b(getPoint(i + 1)); for (int n = p.getCount() - (p.isClosed() ? 0 : 1), j = 0; j < n; j++) { Point2d c(p.getPoint(j)), d(p.getPoint(j + 1)); if (mglnrel::cross2Line(a, b, c, d, cc.tmpcross) && box.contains(cc.tmpcross)) { float dist = cc.tmpcross.distanceTo(box.center()); if (cc.mindist > dist) { cc.mindist = dist; ptCross = cc.tmpcross; } } } } } else if (isLine() && p.getSubPathCount() == 1) { cc.a = getPoint(0); cc.b = getPoint(1); p.scanSegments(cc); } else if (p.isLine() && getSubPathCount() == 1) { cc.a = p.getPoint(0); cc.b = p.getPoint(1); scanSegments(cc); } return cc.mindist < box.width(); }
bool GiTransform::zoomTo(const Box2d& rectWorld, const RECT_2D* rcTo, bool adjust) { // 如果图形范围的宽或高接近于零,就返回 if (rectWorld.isEmpty()) return false; // 计算像素到毫米的比例 const float d2mmX = m_impl->viewScale / m_impl->w2dx; const float d2mmY = m_impl->viewScale / m_impl->w2dy; // 计算目标窗口区域(毫米) float w = 0, h = 0; Point2d ptCen; if (rcTo != NULL) { w = fabsf(static_cast<float>(rcTo->right - rcTo->left)); h = fabsf(static_cast<float>(rcTo->bottom - rcTo->top)); ptCen.x = (rcTo->left + rcTo->right) * 0.5f; ptCen.y = (rcTo->top + rcTo->bottom) * 0.5f; } if (w < 4 || h < 4) { w = (float)m_impl->cxWnd; h = (float)m_impl->cyWnd; ptCen.set(w * 0.5f, h * 0.5f); w -= 8; h -= 8; } if (w < 4 || h < 4) return false; w *= d2mmX; h *= d2mmY; ptCen.scaleBy(d2mmX, d2mmY); // 计算新显示比例 (中心不变,缩小窗口区域使得宽高比例和图形范围相同) float scale; if (h * rectWorld.width() > w * rectWorld.height()) { //h = w * rectWorld.height() / rectWorld.width(); scale = w / rectWorld.width(); } else { //w = h * rectWorld.width() / rectWorld.height(); scale = h / rectWorld.height(); } // 检查显示比例 if (!adjust && ScaleOutRange(scale, m_impl)) return false; scale = mgMax(scale, m_impl->minViewScale); scale = mgMin(scale, m_impl->maxViewScale); // 计算在新显示比例下显示窗口中心的世界坐标 Point2d ptW; ptW.x = rectWorld.center().x + (m_impl->cxWnd * d2mmX * 0.5f - ptCen.x) / scale; ptW.y = rectWorld.center().y - (m_impl->cyWnd * d2mmY * 0.5f - ptCen.y) / scale; // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内 float halfw = m_impl->cxWnd * d2mmX / scale * 0.5f; float halfh = m_impl->cyWnd * d2mmY / scale * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); if (!AdjustCenterIn(adjust, box, m_impl->rectLimitsW, ptW, halfw, halfh)) { return false; } return m_impl->zoomNoAdjust(ptW, scale); }
bool GiGraphics::drawEllipse(const GiContext* ctx, const Box2d& rect, bool modelUnit) { return drawEllipse(ctx, rect.center(), rect.width() / 2, rect.height() / 2, modelUnit); }