File indexing completed on 2025-01-19 09:46:00
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 }