bool GiTransform::zoomWnd(const Point2d& pt1, const Point2d& pt2, bool adjust) { // 计算开窗矩形的中心和宽高 Point2d ptCen ((pt2.x + pt1.x) * 0.5f, (pt2.y + pt1.y) * 0.5f); float w = fabs(static_cast<float>(pt2.x - pt1.x)); float h = fabs(static_cast<float>(pt2.y - pt1.y)); if (w < 4 || h < 4) return false; // 中心不变,扩大开窗矩形使得宽高比例和显示窗口相同 if (h * m_impl->cxWnd > w * m_impl->cyWnd) w = h * m_impl->cxWnd / m_impl->cyWnd; else h = w * m_impl->cyWnd / m_impl->cxWnd; // 计算放缩前矩形中心的世界坐标 Point2d ptW (ptCen * m_impl->matD2W); // 计算新显示比例 float scale = m_impl->viewScale * m_impl->cyWnd / h; if (!adjust && ScaleOutRange(scale, m_impl)) return false; scale = mgMax(scale, m_impl->minViewScale); scale = mgMin(scale, m_impl->maxViewScale); // 计算新显示比例下的显示窗口的世界坐标范围 float halfw = m_impl->cxWnd / (m_impl->w2dx / m_impl->viewScale * scale) * 0.5f; float halfh = m_impl->cyWnd / (m_impl->w2dy / m_impl->viewScale * scale) * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); // 检查显示窗口的新坐标范围是否在极限范围内 if (!m_impl->rectLimitsW.isEmpty() && !m_impl->rectLimitsW.contains(box)) { if (adjust) AdjustCenterW(ptW, halfw, halfh, m_impl->rectLimitsW); else return false; } // 改变显示比例和位置 return m_impl->zoomNoAdjust(ptW, scale); }
bool GiTransform::zoomScale(float viewScale, const Point2d* pxAt, bool adjust) { // 检查显示比例 if (!adjust && ScaleOutRange(viewScale, m_impl)) return false; viewScale = mgMax(viewScale, m_impl->minViewScale); viewScale = mgMin(viewScale, m_impl->maxViewScale); // 得到放缩中心点的客户区坐标 Point2d ptAt (m_impl->cxWnd * 0.5f, m_impl->cyWnd * 0.5f); if (pxAt != NULL) ptAt.set(pxAt->x, pxAt->y); // 得到放缩中心点在放缩前的世界坐标 Point2d ptAtW (ptAt * m_impl->matD2W); // 计算新显示比例下显示窗口中心的世界坐标 Point2d ptW; float w2dx = m_impl->w2dx / m_impl->viewScale * viewScale; float w2dy = m_impl->w2dy / m_impl->viewScale * viewScale; ptW.x = ptAtW.x + (m_impl->cxWnd * 0.5f - ptAt.x) / w2dx; ptW.y = ptAtW.y - (m_impl->cyWnd * 0.5f - ptAt.y) / w2dy; // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内 float halfw = m_impl->cxWnd / w2dx * 0.5f; float halfh = m_impl->cyWnd / w2dy * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); if (!AdjustCenterIn(adjust, box, m_impl->rectLimitsW, ptW, halfw, halfh)) { return false; } if (halfw - 3 > m_impl->rectLimitsW.width() / 2 && halfh - 3 > m_impl->rectLimitsW.height() / 2) // 显示比例太小 { viewScale *= mgMin(2 * (halfw - 3) / m_impl->rectLimitsW.width(), 2 * (halfh - 3) / m_impl->rectLimitsW.height()); viewScale = mgMin(viewScale, m_impl->maxViewScale); } return m_impl->zoomNoAdjust(ptW, viewScale); }
bool GiTransform::zoomScale(float viewScale, const Point2d* pxAt, bool adjust) { // 检查显示比例 if (!adjust && ScaleOutRange(viewScale, m_impl)) return false; viewScale = mgMax(viewScale, m_impl->minViewScale); viewScale = mgMin(viewScale, m_impl->maxViewScale); // 得到放缩中心点的客户区坐标 Point2d ptAt (m_impl->cxWnd * 0.5f, m_impl->cyWnd * 0.5f); if (pxAt != NULL) ptAt.set(pxAt->x, pxAt->y); // 得到放缩中心点在放缩前的世界坐标 Point2d ptAtW (ptAt * m_impl->matD2W); // 计算新显示比例下显示窗口中心的世界坐标 Point2d ptW; float w2dx = m_impl->w2dx / m_impl->viewScale * viewScale; float w2dy = m_impl->w2dy / m_impl->viewScale * viewScale; ptW.x = ptAtW.x + (m_impl->cxWnd * 0.5f - ptAt.x) / w2dx; ptW.y = ptAtW.y - (m_impl->cyWnd * 0.5f - ptAt.y) / w2dy; // 检查新显示比例下显示窗口的世界坐标范围是否在极限范围内 float halfw = m_impl->cxWnd / w2dx * 0.5f; float halfh = m_impl->cyWnd / w2dy * 0.5f; Box2d box (ptW, 2 * halfw, 2 * halfh); if (!m_impl->rectLimitsW.isEmpty() && !m_impl->rectLimitsW.contains(box)) { if (adjust) AdjustCenterW(ptW, halfw, halfh, m_impl->rectLimitsW); else return false; } return m_impl->zoomNoAdjust(ptW, viewScale); }
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); }