123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #include "WindowAppItemIsometricLine.h"
- WindowAppItemIsometricLine::WindowAppItemIsometricLine(const UI_ISOLINE_INFO& lineInfo) :
- m_isoLineInfo(lineInfo)
- {
- }
- /// <summary>
- /// 绘制线条
- /// </summary>
- /// <param name="painter"></param>
- /// <param name="option"></param>
- /// <param name="widget"></param>
- void WindowAppItemIsometricLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget /*= nullptr*/)
- {
- Q_UNUSED(option);
- Q_UNUSED(widget);
- painter->setRenderHint(QPainter::Antialiasing, true);
- painter->save();
- // 绘制等宽线条
- this->drawIsoLines(painter);
- painter->restore();
- }
- /// <summary>
- /// 绘制两个端点
- /// </summary>
- /// <param name="painter"></param>
- void WindowAppItemIsometricLine::drawIsoLines(QPainter* painter)
- {
- // 如果stretchDir参数是None,那么绘制的就是目标控件的等宽线
- // 因为目标控件的等宽线永远都只出现在右侧和下侧
- if (m_isoLineInfo.stretchDir == STRETCH_DIRECTION::DIR_NONE)
- {
- // 右侧的等高线
- if (m_isoLineInfo.sideDir == SIDE_DIRECTION::SIDE_RIGHT)
- {
- QLine rightLine = Utility::getSideLineByID(m_isoLineInfo.pWidget, (short)SIDE_DIRECTION::SIDE_RIGHT);
- this->drawIsoLines(painter, rightLine, SIDE_DIRECTION::SIDE_RIGHT);
- }
- // 下侧的等宽线
- else if (m_isoLineInfo.sideDir == SIDE_DIRECTION::SIDE_BOTTOM)
- {
- QLine bottomLine = Utility::getSideLineByID(m_isoLineInfo.pWidget, (short)SIDE_DIRECTION::SIDE_BOTTOM);
- this->drawIsoLines(painter, bottomLine, SIDE_DIRECTION::SIDE_BOTTOM);
- }
- // 错误,不应该走到这里
- else
- {
- vDebug() << "[Error] Invalid SideDirection:" << (short) m_isoLineInfo.sideDir;
- }
- }
- // 如果stretchDir参数是有值的,那么绘制的就是源控件的等宽线
- // 源控件的等宽线就需要根据拖拽方向来绘制在不同的位置了,需要额外解析一下
- else
- {
- STRETCH_DIRECTION sDir = m_isoLineInfo.stretchDir;
- // 如果是等高线
- if (m_isoLineInfo.sideDir == SIDE_DIRECTION::SIDE_RIGHT)
- {
- // 如果拖拽的是上、下、左上、左下,等高线在右侧
- if (sDir == STRETCH_DIRECTION::DIR_TOP
- || sDir == STRETCH_DIRECTION::DIR_BOTTOM
- || sDir == STRETCH_DIRECTION::DIR_LEFTTOP
- || sDir == STRETCH_DIRECTION::DIR_LEFTBOTTOM
- )
- {
- // 获取右侧的边,然后在右侧边的右侧绘制等高线
- QLine rightLine = Utility::getSideLineByID(m_isoLineInfo.pWidget, (short)SIDE_DIRECTION::SIDE_RIGHT);
- this->drawIsoLines(painter, rightLine, SIDE_DIRECTION::SIDE_RIGHT);
- }
-
- // 如果拖拽的是右上、右下,等高线在左侧
- else if (sDir == STRETCH_DIRECTION::DIR_RIGHTTOP
- || sDir == STRETCH_DIRECTION::DIR_RIGHTBOTTOM
- )
- {
- // 获取左侧的边,然后在左侧边的左侧绘制等高线
- QLine leftLine = Utility::getSideLineByID(m_isoLineInfo.pWidget, (short)SIDE_DIRECTION::SIDE_LEFT);
- this->drawIsoLines(painter, leftLine, SIDE_DIRECTION::SIDE_LEFT);
- }
- }
- // 如果是等宽线
- else if (m_isoLineInfo.sideDir == SIDE_DIRECTION::SIDE_BOTTOM)
- {
- // 如果拖拽的是左、右、左上、右上,等宽线在下侧
- if (sDir == STRETCH_DIRECTION::DIR_LEFT
- || sDir == STRETCH_DIRECTION::DIR_RIGHT
- || sDir == STRETCH_DIRECTION::DIR_LEFTTOP
- || sDir == STRETCH_DIRECTION::DIR_RIGHTTOP
- )
- {
- // 获取底部的边,然后在底部边下侧绘制等宽线
- QLine bottomLine = Utility::getSideLineByID(m_isoLineInfo.pWidget, (short)SIDE_DIRECTION::SIDE_BOTTOM);
- this->drawIsoLines(painter, bottomLine, SIDE_DIRECTION::SIDE_BOTTOM);
- }
- // 如果拖拽的是右下、左下,等宽线在上侧
- else if (sDir == STRETCH_DIRECTION::DIR_LEFTBOTTOM
- || sDir == STRETCH_DIRECTION::DIR_RIGHTBOTTOM
- )
- {
- // 获取顶部的边,然后在顶部边上侧绘制等宽线
- QLine topLine = Utility::getSideLineByID(m_isoLineInfo.pWidget, (short)SIDE_DIRECTION::SIDE_TOP);
- this->drawIsoLines(painter, topLine, SIDE_DIRECTION::SIDE_TOP);
- }
- }
- }
- }
- /// <summary>
- /// 根据指定的位置绘制线条
- /// </summary>
- /// <param name="painter"></param>
- /// <param name="side"></param>
- /// <param name="sideDir"></param>
- void WindowAppItemIsometricLine::drawIsoLines(QPainter* painter, const QLine& side, SIDE_DIRECTION sideDir)
- {
- // 设置颜色风格
- painter->setPen(QPen(COLOR_REFLINE, PEN_LINE_WIDTH, Qt::SolidLine));
- QLine line1, line2;
- // 在右侧绘制
- if (sideDir == SIDE_DIRECTION::SIDE_RIGHT)
- {
- // 上侧标尺
- line1.setLine(
- side.p1().x() + ISOLINE_SPACE,
- side.p1().y() - ISOLINE_FIX,
- side.p1().x() + ISOLINE_SPACE + ISOLINE_MARK_LEN,
- side.p1().y() - ISOLINE_FIX
- );
- // 下侧标尺
- line2.setLine(
- side.p2().x() + ISOLINE_SPACE,
- side.p2().y() + ISOLINE_FIX,
- side.p2().x() + ISOLINE_SPACE + ISOLINE_MARK_LEN,
- side.p2().y() + ISOLINE_FIX
- );
- }
- // 在下侧绘制
- else if (sideDir == SIDE_DIRECTION::SIDE_BOTTOM)
- {
- // 左侧标尺
- line1.setLine(
- side.p1().x() - ISOLINE_FIX,
- side.p1().y() + ISOLINE_SPACE,
- side.p1().x() - ISOLINE_FIX,
- side.p1().y() + ISOLINE_SPACE + ISOLINE_MARK_LEN
- );
- // 右侧标尺
- line2.setLine(
- side.p2().x() + ISOLINE_FIX,
- side.p2().y() + ISOLINE_SPACE,
- side.p2().x() + ISOLINE_FIX,
- side.p2().y() + ISOLINE_SPACE + ISOLINE_MARK_LEN
- );
- }
- // 在左侧绘制
- else if (sideDir == SIDE_DIRECTION::SIDE_LEFT)
- {
- // 上侧标尺
- line1.setLine(
- side.p1().x() - ISOLINE_SPACE - ISOLINE_MARK_LEN,
- side.p1().y() - ISOLINE_FIX,
- side.p1().x() - ISOLINE_SPACE,
- side.p1().y() - ISOLINE_FIX
- );
- // 下侧标尺
- line2.setLine(
- side.p2().x() - ISOLINE_SPACE - ISOLINE_MARK_LEN,
- side.p2().y() + ISOLINE_FIX,
- side.p2().x() - ISOLINE_SPACE,
- side.p2().y() + ISOLINE_FIX
- );
- }
- // 在上侧绘制
- else if (sideDir == SIDE_DIRECTION::SIDE_TOP)
- {
- // 左侧标尺
- line1.setLine(
- side.p1().x() - ISOLINE_FIX,
- side.p1().y() - ISOLINE_SPACE - ISOLINE_MARK_LEN,
- side.p1().x() - ISOLINE_FIX,
- side.p1().y() - ISOLINE_SPACE
- );
- // 右侧标尺
- line2.setLine(
- side.p2().x() + ISOLINE_FIX,
- side.p2().y() - ISOLINE_SPACE - ISOLINE_MARK_LEN,
- side.p2().x() + ISOLINE_FIX,
- side.p2().y() - ISOLINE_SPACE
- );
- }
- // 错误,不应该执行到这里
- else
- {
- vDebug() << "[Error] Invalid side direction: " << (int)sideDir;
- return;
- }
- // 绘制标尺线条
- painter->drawLine(line1);
- painter->drawLine(line2);
- // 绘制箭头
- this->drawIsoArrowLines(painter, line1, line2, sideDir);
- }
- /// <summary>
- /// 绘制箭头线条
- /// </summary>
- /// <param name="painter"></param>
- void WindowAppItemIsometricLine::drawIsoArrowLines(QPainter* painter, QLine line1, QLine line2, SIDE_DIRECTION sideDir)
- {
- QLineF arrowLine;
- // 如果是左侧边或者右侧边,那么就是纵向的等高线
- if (sideDir == SIDE_DIRECTION::SIDE_RIGHT || sideDir == SIDE_DIRECTION::SIDE_LEFT)
- {
- // 线条
- arrowLine.setLine(
- line1.x1() + ISOLINE_MARK_LEN / 2,
- line1.y1() + ISOLINE_ARROW_SIZE + 1,
- line2.x1() + ISOLINE_MARK_LEN / 2,
- line2.y1() - ISOLINE_ARROW_SIZE - 1
- );
- painter->drawLine(arrowLine);
- }
- // 其他情况就是横向的等宽线
- else
- {
- // 线条
- arrowLine.setLine(
- line1.x1() + ISOLINE_ARROW_SIZE + 1,
- line1.y1() + ISOLINE_MARK_LEN / 2,
- line2.x1() - ISOLINE_ARROW_SIZE - 1,
- line2.y1() + ISOLINE_MARK_LEN / 2
- );
- painter->drawLine(arrowLine);
- }
- // 加上箭头
- this->drawIsoArrow(painter, arrowLine);
- // 翻转线条,绘制另一侧箭头
- arrowLine.setPoints(arrowLine.p2(), arrowLine.p1());
- this->drawIsoArrow(painter, arrowLine);
- }
- /// <summary>
- /// 为指定的线条绘制箭头
- /// </summary>
- /// <param name="isoLine"></param>
- void WindowAppItemIsometricLine::drawIsoArrow(QPainter* painter, QLineF isoLine)
- {
- // 获取单位向量
- QLineF v = isoLine.unitVector();
- // 设置箭头长度
- v.setLength(ISOLINE_ARROW_SIZE);
- v.translate(QPointF(isoLine.dx(), isoLine.dy()));
- // 计算法向量
- QLineF n = v.normalVector();
- // 设置箭头宽度
- n.setLength(n.length() * 0.5);
- // 计算两次法向量获取反向的法向量
- QLineF n2 = n.normalVector().normalVector();
- // 三个向量的终点即是三角形的三个顶点
- const QPointF points[3] = { v.p2(), n.p2(), n2.p2() };
-
- // 按照三个顶点绘制多边形,然后填充
- painter->setBrush(QBrush(COLOR_REFLINE, Qt::SolidPattern));
- painter->drawPolygon(points, 3);
- }
|