File indexing completed on 2024-05-19 05:41:05

0001 /***************************************************************************
0002  *  Copyright (C) 2019 by Renaud Guezennec                                 *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "mindmap/geometry/linknode.h"
0021 
0022 #define PenWidth 4
0023 
0024 #include <QDebug>
0025 #include <QLineF>
0026 namespace mindmap
0027 {
0028 LinkNode::LinkNode() : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 0)
0029 {
0030     setGeometry(&m_geometry);
0031     m_geometry.setDrawingMode(QSGGeometry::DrawLineStrip);
0032     m_geometry.allocate(6);
0033     setMaterial(&m_material);
0034 }
0035 void LinkNode::setColor(const QColor& color)
0036 {
0037     m_material.setColor(color);
0038     markDirty(QSGNode::DirtyMaterial);
0039 }
0040 void LinkNode::update(const QRectF& rect, LinkController::Orientation orient, const QRectF& startBox,
0041                       const QRectF& endBox)
0042 {
0043     qreal arrowLenght= 10.0;
0044     qreal arrowWidth= 8.0;
0045     qreal radius= 0.;
0046     qreal diameter= 0.;
0047     m_geometry.setLineWidth(PenWidth);
0048 
0049     QPointF p1, p2;
0050     QRectF rect1= startBox;
0051     rect1.moveTo(-startBox.width() / 2, -startBox.height() / 2);
0052     QRectF rect2= endBox;
0053     rect2.moveTo(-endBox.width() / 2, -endBox.height() / 2);
0054 
0055     switch(orient)
0056     {
0057     case LinkController::RightBottom:
0058     {
0059         p1= rect.topLeft();
0060         p2= rect.bottomRight();
0061         rect2= rect2.translated(p2.x(), p2.y());
0062     }
0063     break;
0064     case LinkController::LeftBottom:
0065     {
0066         p1= rect.topRight();
0067         p2= rect.bottomLeft();
0068         rect2= rect2.translated(p2.x(), p2.y());
0069         rect1= rect1.translated(p1.x(), p1.y());
0070     }
0071     break;
0072     case LinkController::RightTop:
0073     {
0074         p1= rect.bottomLeft();
0075         p2= rect.topRight();
0076         rect2= rect2.translated(p2.x(), p2.y());
0077         rect1= rect1.translated(p1.x(), p1.y());
0078     }
0079     break;
0080     case LinkController::LeftTop:
0081     {
0082         p1= rect.bottomRight();
0083         p2= rect.topLeft();
0084         rect1= rect1.translated(p1.x(), p1.y());
0085     }
0086     break;
0087     }
0088 
0089     QLineF line(p1, p2);
0090     // qDebug() << "center:" << line.center();
0091 
0092     QLineF rect1Bottom(rect1.bottomLeft(), rect1.bottomRight());
0093     QLineF rect1Top(rect1.topLeft(), rect1.topRight());
0094     QLineF rect1Left(rect1.topLeft(), rect1.bottomLeft());
0095     QLineF rect1Right(rect1.topRight(), rect1.bottomRight());
0096 
0097     QVector<QLineF> lines({rect1Bottom, rect1Top, rect1Left, rect1Right});
0098 
0099     QPointF intersection1;
0100     for(auto const& rectSide : qAsConst(lines))
0101     {
0102         QPointF point;
0103         if(line.intersects(rectSide, &point) == QLineF::BoundedIntersection)
0104             intersection1= point;
0105     }
0106 
0107     QLineF rect2Bottom(rect2.bottomLeft(), rect2.bottomRight());
0108     QLineF rect2Top(rect2.topLeft(), rect2.topRight());
0109     QLineF rect2Left(rect2.topLeft(), rect2.bottomLeft());
0110     QLineF rect2Right(rect2.topRight(), rect2.bottomRight());
0111 
0112     QVector<QLineF> lines2({rect2Bottom, rect2Top, rect2Left, rect2Right});
0113 
0114     QPointF intersection2;
0115     for(auto const& rectSide : qAsConst(lines2))
0116     {
0117         QPointF point;
0118         if(line.intersects(rectSide, &point) == QLineF::BoundedIntersection)
0119             intersection2= point;
0120     }
0121 
0122     line= QLineF(intersection1, intersection2);
0123 
0124     auto pArrow= line.pointAt(1 - radius / line.length());
0125     auto startArrow= line.pointAt(1 - radius / line.length() - arrowLenght / line.length());
0126 
0127     QLineF arrowLine(startArrow, pArrow);
0128     QLineF arrowBase= arrowLine.normalVector();
0129 
0130     auto pointArrow= arrowBase.pointAt(arrowWidth / arrowBase.length());
0131     auto pointArrow2= arrowBase.pointAt(-arrowWidth / arrowBase.length());
0132     auto vertices= m_geometry.vertexDataAsPoint2D();
0133     {
0134         vertices[0].set(static_cast<float>(intersection1.x() + diameter),
0135                         static_cast<float>(intersection1.y() + diameter));
0136         vertices[1].set(static_cast<float>(startArrow.x() + diameter), static_cast<float>(startArrow.y() + diameter));
0137         vertices[2].set(static_cast<float>(pointArrow.x() + diameter), static_cast<float>(pointArrow.y() + diameter));
0138         vertices[3].set(static_cast<float>(pArrow.x() + diameter), static_cast<float>(pArrow.y() + diameter));
0139         vertices[4].set(static_cast<float>(pointArrow2.x() + diameter), static_cast<float>(pointArrow2.y() + diameter));
0140         vertices[5].set(static_cast<float>(startArrow.x() + diameter), static_cast<float>(startArrow.y() + diameter));
0141     }
0142     markDirty(QSGNode::DirtyGeometry);
0143 }
0144 } // namespace mindmap