File indexing completed on 2024-04-14 14:11:22

0001 /*
0002     SPDX-FileCopyrightText: 2007 James B. Bowlin <bowlin@mindspring.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /****************************************************************************
0008  * The filled polygon code in the innermost loops below in drawFilled*() below
0009  * implements the Sutherland-Hodgman's Polygon clipping algorithm.  Please
0010  * don't mess with it unless you ensure that the Milky Way clipping continues
0011  * to work.  The line clipping uses a similar but slightly less complicated
0012  * algorithm.
0013  *
0014  * Since the clipping code is a bit messy, there are four versions of the
0015  * inner loop for Filled/Outline * Integer/Float.  This moved these two
0016  * decisions out of the inner loops to make them a bit faster and less
0017  * messy.
0018  *
0019  * -- James B. Bowlin
0020  *
0021  ****************************************************************************/
0022 
0023 #include "linelistindex.h"
0024 
0025 #include "Options.h"
0026 #include "kstarsdata.h"
0027 #include "linelist.h"
0028 #ifndef KSTARS_LITE
0029 #include "skymap.h"
0030 #endif
0031 #include "skypainter.h"
0032 #include "htmesh/MeshIterator.h"
0033 
0034 LineListIndex::LineListIndex(SkyComposite *parent, const QString &name) : SkyComponent(parent), m_name(name)
0035 {
0036     m_skyMesh   = SkyMesh::Instance();
0037     m_lineIndex.reset(new LineListHash());
0038     m_polyIndex.reset(new LineListHash());
0039 }
0040 
0041 // This is a callback for the indexLines() function below
0042 const IndexHash &LineListIndex::getIndexHash(LineList *lineList)
0043 {
0044     return skyMesh()->indexLine(lineList->points());
0045 }
0046 
0047 void LineListIndex::removeLine(const std::shared_ptr<LineList> &lineList)
0048 {
0049     const IndexHash &indexHash     = getIndexHash(lineList.get());
0050     IndexHash::const_iterator iter = indexHash.constBegin();
0051 
0052     while (iter != indexHash.constEnd())
0053     {
0054         Trixel trixel = iter.key();
0055         iter++;
0056 
0057         if (m_lineIndex->contains(trixel))
0058             m_lineIndex->value(trixel)->removeOne(lineList);
0059     }
0060     m_listList.removeOne(lineList);
0061 }
0062 
0063 void LineListIndex::appendLine(const std::shared_ptr<LineList> &lineList)
0064 {
0065     const IndexHash &indexHash     = getIndexHash(lineList.get());
0066     IndexHash::const_iterator iter = indexHash.constBegin();
0067 
0068     while (iter != indexHash.constEnd())
0069     {
0070         Trixel trixel = iter.key();
0071 
0072         iter++;
0073         if (!m_lineIndex->contains(trixel))
0074         {
0075             m_lineIndex->insert(trixel, std::shared_ptr<LineListList>(new LineListList()));
0076         }
0077         m_lineIndex->value(trixel)->append(lineList);
0078     }
0079     m_listList.append(lineList);
0080 }
0081 
0082 void LineListIndex::appendPoly(const std::shared_ptr<LineList> &lineList)
0083 {
0084     const IndexHash &indexHash     = skyMesh()->indexPoly(lineList->points());
0085     IndexHash::const_iterator iter = indexHash.constBegin();
0086 
0087     while (iter != indexHash.constEnd())
0088     {
0089         Trixel trixel = iter.key();
0090         iter++;
0091 
0092         if (!m_polyIndex->contains(trixel))
0093         {
0094             m_polyIndex->insert(trixel, std::shared_ptr<LineListList>(new LineListList()));
0095         }
0096         m_polyIndex->value(trixel)->append(lineList);
0097     }
0098 }
0099 
0100 void LineListIndex::appendBoth(const std::shared_ptr<LineList> &lineList)
0101 {
0102     QMutexLocker m1(&mutex);
0103 
0104     appendLine(lineList);
0105     appendPoly(lineList);
0106 }
0107 
0108 void LineListIndex::reindexLines()
0109 {
0110     LineListHash *oldIndex = m_lineIndex.release();
0111     DrawID drawID = skyMesh()->incDrawID();
0112 
0113     m_lineIndex.reset(new LineListHash());
0114     for (auto &listList : *oldIndex)
0115     {
0116         for (auto &item : *listList)
0117         {
0118             if (item->drawID == drawID)
0119                 continue;
0120 
0121             item->drawID = drawID;
0122             appendLine(item);
0123         }
0124         listList.reset();
0125     }
0126     delete oldIndex;
0127 }
0128 
0129 void LineListIndex::JITupdate(LineList *lineList)
0130 {
0131     KStarsData *data   = KStarsData::Instance();
0132     lineList->updateID = data->updateID();
0133     SkyList *points    = lineList->points();
0134 
0135     if (lineList->updateNumID != data->updateNumID())
0136     {
0137         lineList->updateNumID = data->updateNumID();
0138         KSNumbers *num        = data->updateNum();
0139 
0140         for (const auto &point : *points)
0141         {
0142             point->updateCoords(num);
0143         }
0144     }
0145 
0146     for (const auto &point : *points)
0147     {
0148         point->EquatorialToHorizontal(data->lst(), data->geo()->lat());
0149     }
0150 }
0151 
0152 // This is a callback used in draw() below
0153 void LineListIndex::preDraw(SkyPainter *skyp)
0154 {
0155     skyp->setPen(QPen(QBrush(QColor("white")), 1, Qt::SolidLine));
0156 }
0157 
0158 void LineListIndex::draw(SkyPainter *skyp)
0159 {
0160     if (!selected())
0161         return;
0162     preDraw(skyp);
0163     drawLines(skyp);
0164 }
0165 
0166 #ifdef KSTARS_LITE
0167 MeshIterator LineListIndex::visibleTrixels()
0168 {
0169     return MeshIterator(skyMesh(), drawBuffer());
0170 }
0171 #endif
0172 
0173 // This is a callback used int drawLinesInt() and drawLinesFloat()
0174 SkipHashList *LineListIndex::skipList(LineList *lineList)
0175 {
0176     Q_UNUSED(lineList)
0177     return nullptr;
0178 }
0179 
0180 void LineListIndex::drawLines(SkyPainter *skyp)
0181 {
0182     DrawID drawID     = skyMesh()->drawID();
0183     UpdateID updateID = KStarsData::Instance()->updateID();
0184 
0185     for (auto &lineListList : m_lineIndex->values())
0186     {
0187         for (int i = 0; i < lineListList->size(); i++)
0188         {
0189             std::shared_ptr<LineList> lineList = lineListList->at(i);
0190 
0191             if (lineList->drawID == drawID)
0192                 continue;
0193             lineList->drawID = drawID;
0194 
0195             if (lineList->updateID != updateID)
0196                 JITupdate(lineList.get());
0197 
0198             skyp->drawSkyPolyline(lineList.get(), skipList(lineList.get()), label());
0199         }
0200     }
0201 }
0202 
0203 void LineListIndex::drawFilled(SkyPainter *skyp)
0204 {
0205     DrawID drawID     = skyMesh()->drawID();
0206     UpdateID updateID = KStarsData::Instance()->updateID();
0207 
0208     MeshIterator region(skyMesh(), drawBuffer());
0209 
0210     while (region.hasNext())
0211     {
0212         std::shared_ptr<LineListList> lineListList = m_polyIndex->value(region.next());
0213 
0214         if (lineListList == nullptr)
0215             continue;
0216 
0217         for (int i = 0; i < lineListList->size(); i++)
0218         {
0219             std::shared_ptr<LineList> lineList = lineListList->at(i);
0220 
0221             // draw each Linelist at most once
0222             if (lineList->drawID == drawID)
0223                 continue;
0224             lineList->drawID = drawID;
0225 
0226             if (lineList->updateID != updateID)
0227                 JITupdate(lineList.get());
0228 
0229             skyp->drawSkyPolygon(lineList.get());
0230         }
0231     }
0232 }
0233 
0234 void LineListIndex::intro()
0235 {
0236     emitProgressText(i18n("Loading %1", m_name));
0237     if (skyMesh()->debug() >= 1)
0238         qDebug() << Q_FUNC_INFO << QString("Loading %1 ...").arg(m_name);
0239 }
0240 
0241 void LineListIndex::summary()
0242 {
0243     if (skyMesh()->debug() < 2)
0244         return;
0245 
0246     int total    = skyMesh()->size();
0247     int polySize = m_polyIndex->size();
0248     int lineSize = m_lineIndex->size();
0249 
0250     if (lineSize > 0)
0251         printf("%4d out of %4d trixels in line index %3d%%\n", lineSize, total, 100 * lineSize / total);
0252 
0253     if (polySize > 0)
0254         printf("%4d out of %4d trixels in poly index %3d%%\n", polySize, total, 100 * polySize / total);
0255 }