File indexing completed on 2024-05-12 03:45:46

0001 /*
0002     SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "linenode.h"
0007 
0008 #include "skymaplite.h"
0009 #include "projections/projector.h"
0010 #include "skycomponents/skiphashlist.h"
0011 
0012 #include <QLinkedList>
0013 #include <QSGFlatColorMaterial>
0014 
0015 LineNode::LineNode(LineList *lineList, SkipHashList *skipList, QColor color, int width, Qt::PenStyle drawStyle)
0016     : m_geometryNode(new QSGGeometryNode), m_lineList(lineList), m_skipList(skipList),
0017       m_material(new QSGFlatColorMaterial), m_drawStyle(drawStyle)
0018 {
0019     m_geometryNode->setOpaqueMaterial(m_material);
0020     //m_geometryNode->setFlag(QSGNode::OwnsMaterial);
0021     m_material->setColor(color);
0022 
0023     m_geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
0024     m_geometryNode->setGeometry(m_geometry);
0025     //m_geometryNode->setFlag(QSGNode::OwnsGeometry);
0026     setWidth(width);
0027 
0028     appendChildNode(m_geometryNode);
0029 }
0030 
0031 LineNode::~LineNode()
0032 {
0033     delete m_geometry;
0034     delete m_material;
0035 }
0036 
0037 void LineNode::setColor(QColor color)
0038 {
0039     if (m_material->color() != color)
0040     {
0041         m_material->setColor(color);
0042         m_color = color;
0043         m_geometryNode->markDirty(QSGNode::DirtyMaterial);
0044     }
0045 }
0046 
0047 void LineNode::setWidth(int width)
0048 {
0049     m_geometry->setLineWidth(width);
0050     m_geometryNode->markDirty(QSGNode::DirtyGeometry);
0051 }
0052 
0053 void LineNode::setDrawStyle(Qt::PenStyle style)
0054 {
0055     m_drawStyle = style;
0056 }
0057 
0058 void LineNode::setStyle(QColor color, int width, Qt::PenStyle drawStyle)
0059 {
0060     setColor(color);
0061     setWidth(width);
0062     setDrawStyle(drawStyle);
0063 }
0064 
0065 void LineNode::updateGeometry()
0066 {
0067     SkyList *points = m_lineList->points();
0068 
0069     m_geometry->setDrawingMode(GL_LINES);
0070 
0071     const Projector *m_proj = SkyMapLite::Instance()->projector();
0072 
0073     bool isVisible, isVisibleLast;
0074 
0075     QPointF oLast = m_proj->toScreen(points->first().get(), true, &isVisibleLast);
0076 
0077     // & with the result of checkVisibility to clip away things below horizon
0078     isVisibleLast &= m_proj->checkVisibility(points->first().get());
0079     QPointF oThis;
0080 
0081     QLinkedList<QPointF> newPoints;
0082 
0083     for (int j = 1; j < points->size(); j++)
0084     {
0085         SkyPoint *pThis = points->at(j).get();
0086 
0087         /*In regular KStars we first call checkVisibility and then toScreen
0088         Here we minimize the number of calls to toScreen by proceeding only if
0089         checkVisibility is true*/
0090         oThis = m_proj->toScreen(pThis, true, &isVisible);
0091         // & with the result of checkVisibility to clip away things below horizon
0092         isVisible &= m_proj->checkVisibility(pThis);
0093         bool doSkip = false;
0094         if (m_skipList)
0095         {
0096             doSkip = m_skipList->skip(j);
0097         }
0098 
0099         bool pointsVisible = false;
0100         //Temporary solution to avoid random lines in Gnomonic projection and draw lines up to horizon
0101         if (SkyMapLite::Instance()->projector()->type() == Projector::Gnomonic)
0102         {
0103             if (isVisible && isVisibleLast)
0104                 pointsVisible = true;
0105         }
0106         else
0107         {
0108             if (isVisible || isVisibleLast)
0109                 pointsVisible = true;
0110         }
0111 
0112         if (!doSkip)
0113         {
0114             if (pointsVisible)
0115             {
0116                 newPoints.append(oLast);
0117                 newPoints.append(oThis);
0118             }
0119         }
0120         oLast         = oThis;
0121         isVisibleLast = isVisible;
0122     }
0123 
0124     int size = newPoints.size();
0125     m_geometry->allocate(size);
0126 
0127     QSGGeometry::Point2D *vertex = m_geometry->vertexDataAsPoint2D();
0128 
0129     QLinkedList<QPointF>::const_iterator i = newPoints.constBegin();
0130     int c                                  = 0;
0131 
0132     while (i != newPoints.constEnd())
0133     {
0134         vertex[c].x = (*i).x();
0135         vertex[c].y = (*i).y();
0136         ++c;
0137         ++i;
0138     }
0139     m_geometryNode->markDirty(QSGNode::DirtyGeometry);
0140 }