• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 17068063291

19 Aug 2025 11:22AM UTC coverage: 11.766%. Remained the same
17068063291

push

github

alex-w
Reformatting

14706 of 124990 relevant lines covered (11.77%)

18303.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/core/StelSkyCultureSkyPartition.cpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2025 Georg Zotti
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18
 */
19

20

21
#include <QJsonObject>
22
#include <QJsonArray>
23

24
#include "StarMgr.hpp"
25
#include "StelLocaleMgr.hpp"
26
#include "StelModuleMgr.hpp"
27
#include "StelObjectMgr.hpp"
28
#include "StelSkyCultureMgr.hpp"
29
#include "StelSkyCultureSkyPartition.hpp"
30
#include "GridLinesMgr.hpp"
31

32
StelSkyCultureSkyPartition::StelSkyCultureSkyPartition(const QJsonObject &json):
×
33
        frameType(StelCore::FrameObservercentricEclipticOfDate),
×
34
        partitions(),
×
35
        extent(90.),
×
36
        centerLine(nullptr),
×
37
        linkStars(),
×
38
        offset(0.0),
×
39
        eclObl(0.0),
×
40
        offsetFromAries(0.0),
×
41
        context()
×
42
{
43
        // Parse defining centerline type
44
        SkyLine::SKY_LINE_TYPE skylineType=SkyLine::ECLIPTIC_CULTURAL;
×
45
        if (json.contains("coordsys"))
×
46
        {
47
                static const QMap<QString, SkyLine::SKY_LINE_TYPE>map={
48
                        {"ecliptical", SkyLine::ECLIPTIC_CULTURAL},
×
49
                        {"equatorial", SkyLine::EQUATORIAL_CULTURAL}};
×
50
                skylineType=map.value(json["coordsys"].toString(), SkyLine::ECLIPTIC_CULTURAL);
×
51
                static const QMap<SkyLine::SKY_LINE_TYPE, StelCore::FrameType>frameMap={
52
                        {SkyLine::ECLIPTIC_CULTURAL   , StelCore::FrameObservercentricEclipticOfDate},
53
                        {SkyLine::EQUATORIAL_CULTURAL , StelCore::FrameEquinoxEqu}};
×
54
                frameType=frameMap.value(skylineType, StelCore::FrameObservercentricEclipticOfDate);
×
55
        }
56
        centerLine=new SkyLine(skylineType);
×
57
        centerLine->setDisplayed(true);
×
58

59
        // Find the context data for localization support
60
        if (json.contains("context"))
×
61
                context = json["context"].toString();
×
62

63
        // Parse extent, create polar caps where needed.
64
        if (json.contains("extent") && json["extent"].isDouble())
×
65
        {
66
                extent=json["extent"].toDouble();
×
67
        }
68
        else
69
                qWarning() << "Bad \"extent\" given in JSON file.";
×
70

71
        if (json.contains("partitions") && json["partitions"].isArray())
×
72
        {
73
                QJsonArray p = json["partitions"].toArray();
×
74
                for (unsigned int i=0; i<p.size(); ++i)
×
75
                        partitions.append(p.at(i).toDouble());
×
76

77
                // From this definition, build the list of sub-tick lists for the central line.
78
                QList<QList<double>>cParts;
×
79
                for (int i=0; i<partitions.length(); ++i)
×
80
                {
81
                        QList<double> partList;
×
82
                        double angle=0;
×
83
                        double partNum=1.;
×
84
                        for (int j=0; j<=i; ++j)
×
85
                        {
86
                                partNum*=partitions[j];
×
87
                        }
88
                        //qDebug() << "partNum" << partNum;
89
                        while (angle <360.)
×
90
                        {
91
                                partList.append(angle);
×
92
                                angle+=360./partNum;
×
93
                                bool take=true;
×
94
                                // build test...
95
                                for (int j=0; j<=i; ++j)
×
96
                                {
97
                                        if (cParts.length() > j && cParts.at(j).contains(angle))
×
98
                                        {
99
                                                take=false;
×
100
                                                //qDebug() << "Angle taken:" << QString::number(angle);
101
                                        }
102
                                }
103
                                if (take)
×
104
                                        partList.append(angle);
×
105
                        }
106
                        cParts.append(partList);
×
107
                }
×
108
                centerLine->setCulturalPartitions(cParts);
×
109
        }
×
110
        else if (json.contains("defining_stars"))
×
111
        {
112
                QJsonArray jStars=json["defining_stars"].toArray();
×
113
                for (unsigned int i=0; i<jStars.size(); ++i)
×
114
                        linkStars.append(jStars.at(i).toInt());
×
115
        }
×
116
        else
117
        {
118
                qWarning() << "Neither \"partitions\" nor \"defining_stars\" array found in JSON data for zodiac or lunarSystem description";
×
119
        }
120

121
        // Parse names
122
        if (json.contains("name"))
×
123
        {
124
                QJsonObject nameObj = json["name"].toObject();
×
125
                name.native = nameObj["native"].toString();
×
126
                name.pronounce = nameObj["pronounce"].toString();
×
127
                name.transliteration = nameObj["transliteration"].toString();
×
128
                name.translated = nameObj["english"].toString();
×
129
        }
×
130
        else
131
        {
132
                qWarning() << "No \"name\" found in JSON data for zodiac or lunarSystem description";
×
133
        }
134
        if (json.contains("names") && json["names"].isArray())
×
135
        {
136
                QJsonArray jNames = json["names"].toArray();
×
137
                for (unsigned int i=0; i<jNames.size(); ++i)
×
138
                {
139
                        const QJsonObject jName = jNames[i].toObject();
×
140
                        StelObject::CulturalName cName;
×
141
                        cName.native=jName["native"].toString();
×
142
                        cName.pronounce=jName["pronounce"].toString();
×
143
                        cName.transliteration=jName["transliteration"].toString();
×
144
                        cName.translated=jName["english"].toString();
×
145
                        names.append(cName);
×
146
                        symbols.append(jName["symbol"].toString());
×
147
                }
×
148
        }
×
149
        else
150
        {
151
                qWarning() << "No \"names\" array found in JSON data for zodiac or lunarSystem description";
×
152
        }
153
        Q_ASSERT(symbols.length() == names.length());
×
154

155
        if (json.contains("link"))
×
156
        {
157
                Q_ASSERT(linkStars.isEmpty());
×
158
                QJsonObject obj=json["link"].toObject();
×
159
                linkStars.append(obj["star"].toInt());
×
160
                offset=obj["offset"].toDouble();
×
161
        }
×
162

163
        // Font size is 14
164
        font.setPixelSize(StelApp::getInstance().getScreenFontSize()+1);
×
165
        updateLabels();
×
166

167
        // Recapitulate what we have loaded:
168
        qDebug() << "Cultural Sky Partition: Loaded partitions:" << partitions << names.length() << "names, " << symbols.length() << "symbols." <<
×
169
                    linkStars.length() << "link stars. " << (linkStars.length()==1 ? QString("Offset %1 at star %2").arg(QString::number(offset), QString::number(linkStars.first())) : QString());
×
170
}
×
171

172
StelSkyCultureSkyPartition::~StelSkyCultureSkyPartition()
×
173
{
174
//        if (centerLine) delete centerLine;
175
}
×
176

177

178
void StelSkyCultureSkyPartition::draw(StelPainter& sPainter, const Vec3d &obsVelocity)
×
179
{
180
        static StelSkyCultureMgr *scMgr=GETSTELMODULE(StelSkyCultureMgr);
×
181
        static StarMgr *starMgr=GETSTELMODULE(StarMgr);
×
182
        static StelCore *core=StelApp::getInstance().getCore();
×
183
        eclObl = GETSTELMODULE(SolarSystem)->getEarth()->getRotObliquity(core->getJDE());
×
184
        StelProjectorP prj = core->getProjection(frameType, (frameType!=StelCore::FrameAltAz && frameType!=StelCore::FrameFixedEquatorial) ? StelCore::RefractionAuto : StelCore::RefractionOff);
×
185
        sPainter.setProjector(prj);
×
186
        const bool lrFlipped=core->getFlipHorz();
×
187
        const bool vertFlipped=core->getFlipVert();
×
188
        const double txtOffset=lrFlipped ? 0.1 : -0.1; // coordinate offset for projecting text
×
189
        const float yShift = vertFlipped ? -font.pixelSize() : 0.f;
×
190

191
        // If defined, find the necessary shift from single linkStar and offset
192
        if (linkStars.length()==1)
×
193
        {
194
                const StelObjectP star=starMgr->searchHP(linkStars.first());
×
195
                Vec3d pos=star->getEquinoxEquatorialPosAuto(core);
×
196
                double ra, dec;
197
                StelUtils::rectToSphe(&ra, &dec, pos);
×
198
                if (frameType==StelCore::FrameObservercentricEclipticOfDate)
×
199
                {
200
                        double lambda, beta;
201
                        Vec3d eclPos;
×
202
                        StelUtils::equToEcl(ra, dec, eclObl, &lambda, &beta);
×
203
                        offsetFromAries=lambda*M_180_PI-offset;
×
204
                }
205
                else
206
                        offsetFromAries=ra*M_180_PI-offset;
×
207
        }
×
208

209

210
        if (linkStars.length()>1)
×
211
        {
212
                // Chinese systems: Unequal partitions defined by stars.
213
                foreach(const int starId, linkStars)
×
214
                {
215
                        //qDebug() << "drawing line for HIP"  << starId;
216
                        StelObjectP star=starMgr->searchHP(starId);
×
217
                        //const double lng=(360./partitions[0]*p +offsetFromAries)*M_PI_180;
218
                        Vec3d posDate=star->getEquinoxEquatorialPos(core);
×
219
                        double ra, dec;
220
                        StelUtils::rectToSphe(&ra, &dec, posDate);
×
221
                        Vec3d eqPt, nPt, sPt;
×
222
                        StelUtils::spheToRect(ra, 0., eqPt);
×
223
                        StelUtils::spheToRect(ra, extent*M_PI_180, nPt);
×
224
                        StelUtils::spheToRect(ra, -extent*M_PI_180, sPt);
×
225
                        sPainter.drawGreatCircleArc(eqPt, nPt);
×
226
                        sPainter.drawGreatCircleArc(eqPt, sPt);
×
227
                        //qDebug() << "done line for HIP"  << starId;
228

229
                        // Mark the defining star with a circlet.
230
                        SphericalCap scCircle(posDate, cos(0.25*M_PI_180));
×
231
                        sPainter.drawSphericalRegion(&scCircle, StelPainter::SphericalPolygonDrawModeBoundary);
×
232
                }
×
233
        }
234
        else
235
        {
236
                // Draw the equal-sized major partitions
237
                for (int p=0; p<partitions[0]; ++p)
×
238
                {
239
                        const double lng=(360./partitions[0]*p +offsetFromAries)*M_PI_180;
×
240
                        Vec3d eqPt, nPt, sPt;
×
241
                        StelUtils::spheToRect(lng, 0., eqPt);
×
242
                        StelUtils::spheToRect(lng, extent*M_PI_180, nPt);
×
243
                        StelUtils::spheToRect(lng, -extent*M_PI_180, sPt);
×
244
                        sPainter.drawGreatCircleArc(eqPt, nPt);
×
245
                        sPainter.drawGreatCircleArc(eqPt, sPt);
×
246
                }
247
        }
248

249
        // Draw top/bottom lines where applicable
250
        if (extent<90.)
×
251
        {
252
                // Get the bounding halfspace
253
                const SphericalCap& viewPortSphericalCap = sPainter.getProjector()->getBoundingCap();
×
254
                drawCap(sPainter, viewPortSphericalCap, extent);
×
255
                drawCap(sPainter, viewPortSphericalCap, -extent);
×
256
        }
257

258
        centerLine->setCulturalOffset(offsetFromAries);
×
259
        centerLine->draw(sPainter, 1.f); // The second arg. is irrelevant, will be restored again in the caller...
×
260

261
        // Symbols: At the beginning of the respective zone.
262
        if (symbols.length() && linkStars.length()<2)
×
263
        {
264
                for (int i=0; i<partitions[0]; ++i)
×
265
                {
266
                        // To have tilted labels, we project a point 0.1deg from the actual label point and derive screen-based angle.
267
                        double lng  = (360./partitions[0]*i + 2.+offsetFromAries)*M_PI_180;
×
268
                        double lng1 = (360./partitions[0]*i + 2.+offsetFromAries + txtOffset)*M_PI_180;
×
269
                        double lat  = (extent<50. ? -extent+0.2 : -10.) *M_PI_180;
×
270
                        Vec3d pos, pos1, scr, scr1;
×
271
                        StelUtils::spheToRect(lng, lat, pos);
×
272
                        StelUtils::spheToRect(lng1, lat, pos1);
×
273
                        prj->project(pos, scr);
×
274
                        prj->project(pos1, scr1);
×
275
                        double angle=atan2(scr1[1]-scr[1], scr1[0]-scr[0])*M_180_PI;
×
276
                        sPainter.drawText(pos, symbols.at(i), angle, 0.f, yShift);
×
277
                }
278
        }
279
        else if (symbols.length()==linkStars.length()  && linkStars.length()>1)
×
280
        {
281
                // Chinese Symbols
282
                for (int i=0; i<linkStars.length(); ++i)
×
283
                {
284
                        QString label=symbols.at(i);
×
285
                        StelObjectP starBegin = starMgr->searchHP(linkStars.at(i));
×
286

287
                        Vec3d eq=starBegin->getEquinoxEquatorialPos(core);
×
288
                        double ra, dec;
289
                        StelUtils::rectToSphe(&ra, &dec, eq);
×
290

291
                        ra += 2.*M_PI_180; // push a bit into the mansion area. Problem: the narrow mansions...
×
292
                        double ra1 = ra+txtOffset*M_PI_180;
×
293
                        double dec1  = (extent<50. ? -extent+0.2 : -10.) *M_PI_180;
×
294
                        Vec3d pos, pos1, scr, scr1;
×
295
                        StelUtils::spheToRect(ra, dec1, pos);
×
296
                        StelUtils::spheToRect(ra1, dec1, pos1);
×
297
                        prj->project(pos, scr);
×
298
                        prj->project(pos1, scr1);
×
299
                        float angle=atan2(scr1[1]-scr[1], scr1[0]-scr[0])*M_180_PIf;
×
300
                        QFontMetrics metrics(font);
×
301
                        float xShift= -0.5 * metrics.boundingRect(label).width();
×
302

303
                        sPainter.drawText(pos, label, angle, xShift, yShift);
×
304
                }
×
305
        }
306

307
        // Labels:
308
        if (names.length()  && linkStars.length()<2)
×
309
        {
310
                for (int i=0; i<partitions[0]; ++i)
×
311
                {
312
                        QString label=scMgr->createCulturalLabel(names.at(i), scMgr->getScreenLabelStyle(), QString());
×
313
                        // To have tilted labels, we project a point 0.1deg from the actual label point and derive screen-based angle.
314
                        double lng  = (360./partitions[0]*(double(i)+0.5) + 2.+offsetFromAries)*M_PI_180;
×
315
                        double lng1 = (360./partitions[0]*(double(i)+0.5) + 2.+offsetFromAries+txtOffset)*M_PI_180;
×
316
                        double lat  = (extent<50. ? -extent+0.2 : -10.) *M_PI_180;
×
317
                        Vec3d pos, pos1, scr, scr1;
×
318
                        StelUtils::spheToRect(lng, lat, pos);
×
319
                        StelUtils::spheToRect(lng1, lat, pos1);
×
320
                        prj->project(pos, scr);
×
321
                        prj->project(pos1, scr1);
×
322
                        float angle=atan2(scr1[1]-scr[1], scr1[0]-scr[0])*M_180_PIf;
×
323
                        QFontMetrics metrics(font);
×
324
                        float xShift= -0.5 * metrics.boundingRect(label).width();
×
325

326
                        sPainter.drawText(pos, label, angle, xShift, yShift);
×
327
                }
×
328
        }
329
        else if (names.length()==linkStars.length()  && linkStars.length()>1)
×
330
        {
331
                for (int i=0; i<linkStars.length(); ++i)
×
332
                {
333
                        QString label=scMgr->createCulturalLabel(names.at(i), scMgr->getScreenLabelStyle(),names.at(i).pronounceI18n);
×
334
                        StelObjectP starBegin = starMgr->searchHP(linkStars.at(i));
×
335
                        StelObjectP starEnd   = starMgr->searchHP(linkStars.at((i==linkStars.length()-1? 0 : i+1)));
×
336

337
                        Vec3d mid=starBegin->getEquinoxEquatorialPos(core)+starEnd->getEquinoxEquatorialPos(core); // no need to normalize!
×
338
                        double ra, dec;
339
                        StelUtils::rectToSphe(&ra, &dec, mid);
×
340

341
                        double ra1 = ra+txtOffset*M_PI_180;
×
342
                        double dec1  = (extent<50. ? -extent+0.2 : -10.) *M_PI_180;
×
343
                        Vec3d pos, pos1, scr, scr1;
×
344
                        StelUtils::spheToRect(ra, dec1, pos);
×
345
                        StelUtils::spheToRect(ra1, dec1, pos1);
×
346
                        prj->project(pos, scr);
×
347
                        prj->project(pos1, scr1);
×
348
                        float angle=atan2(scr1[1]-scr[1], scr1[0]-scr[0])*M_180_PIf;
×
349
                        QFontMetrics metrics(font);
×
350
                        float xShift= -0.5 * metrics.boundingRect(label).width();
×
351

352
                        sPainter.drawText(pos, label, angle, xShift, yShift);
×
353
                }
×
354
        }
355
}
×
356

357
// shamelessly copied from SkyLine::draw (small circles part)
358
void StelSkyCultureSkyPartition::drawCap(StelPainter &sPainter, const SphericalCap& viewPortSphericalCap, double latDeg) const
×
359
{
360
        double lat=latDeg*M_PI_180;
×
361
        SphericalCap declinationCap(Vec3d(0.,0.,1.), std::sin(lat));
×
362
        const Vec3d rotCenter(0,0,declinationCap.d);
×
363

364
        Vec3d p1, p2;
×
365
        if (!SphericalCap::intersectionPoints(viewPortSphericalCap, declinationCap, p1, p2))
×
366
        {
367
                if ((viewPortSphericalCap.d<declinationCap.d && viewPortSphericalCap.contains(declinationCap.n))
×
368
                                || (viewPortSphericalCap.d<-declinationCap.d && viewPortSphericalCap.contains(-declinationCap.n)))
×
369
                {
370
                        // The line is fully included in the viewport, draw it in 3 sub-arcs to avoid length > 180.
371
                        Vec3d pt1, pt2, pt3;
×
372
                        const double lon1=0.0;
×
373
                        const double lon2=120.0*M_PI_180;
×
374
                        const double lon3=240.0*M_PI_180;
×
375
                        StelUtils::spheToRect(lon1, lat, pt1); //pt1.normalize();
×
376
                        StelUtils::spheToRect(lon2, lat, pt2); //pt2.normalize();
×
377
                        StelUtils::spheToRect(lon3, lat, pt3); //pt3.normalize();
×
378

379
                        sPainter.drawSmallCircleArc(pt1, pt2, rotCenter, nullptr, nullptr);
×
380
                        sPainter.drawSmallCircleArc(pt2, pt3, rotCenter, nullptr, nullptr);
×
381
                        sPainter.drawSmallCircleArc(pt3, pt1, rotCenter, nullptr, nullptr);
×
382
                }
383
        }
384
        else
385
        {
386
                // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg
387
                Vec3d middlePoint = p1-rotCenter+p2-rotCenter;
×
388
                middlePoint.normalize();
×
389
                middlePoint*=(p1-rotCenter).norm();
×
390
                middlePoint+=rotCenter;
×
391
                if (!viewPortSphericalCap.contains(middlePoint))
×
392
                {
393
                        middlePoint-=rotCenter;
×
394
                        middlePoint*=-1.;
×
395
                        middlePoint+=rotCenter;
×
396
                }
397

398
                sPainter.drawSmallCircleArc(p1, middlePoint, rotCenter, nullptr, nullptr);
×
399
                sPainter.drawSmallCircleArc(p2, middlePoint, rotCenter, nullptr, nullptr);
×
400
        }
401
}
×
402

403
void StelSkyCultureSkyPartition::setFontSize(int newFontSize)
×
404
{
405
        font.setPixelSize(newFontSize);
×
406
}
×
407

408
void StelSkyCultureSkyPartition::updateLabels()
×
409
{
410
        // TODO: Extract short cultural labels and apply here.
411
}
×
412

413
void StelSkyCultureSkyPartition::updateI18n()
×
414
{
415
        const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
×
416

417
        // The name of the system
418
        name.translatedI18n = trans.tryQtranslate(name.translated, context);
×
419
        if (name.translatedI18n.isEmpty())
×
420
        {
421
                if (context.isEmpty())
×
422
                        name.translatedI18n = q_(name.translated);
×
423
                else
424
                        name.translatedI18n = qc_(name.translated, context);
×
425
        }
426
        name.pronounceI18n = trans.tryQtranslate(name.pronounce, context);
×
427
        if (name.pronounceI18n.isEmpty())
×
428
        {
429
                if (context.isEmpty())
×
430
                        name.pronounceI18n = q_(name.pronounce);
×
431
                else
432
                        name.pronounceI18n = qc_(name.pronounce, context);
×
433
        }
434

435
        // names array
436
        for (auto &name : names)
×
437
        {
438
                name.translatedI18n = trans.tryQtranslate(name.translated, context);
×
439
                if (name.translatedI18n.isEmpty())
×
440
                {
441
                        if (context.isEmpty())
×
442
                                name.translatedI18n = q_(name.translated);
×
443
                        else
444
                                name.translatedI18n = qc_(name.translated, context);
×
445
                }
446
                name.pronounceI18n = trans.tryQtranslate(name.pronounce, context);
×
447
                if (name.pronounceI18n.isEmpty())
×
448
                {
449
                        if (context.isEmpty())
×
450
                                name.pronounceI18n = q_(name.pronounce);
×
451
                        else
452
                                name.pronounceI18n = qc_(name.pronounce, context);
×
453
                }
454
        }
455
}
×
456

457
QString StelSkyCultureSkyPartition::getCulturalName() const
×
458
{
459
        static StelSkyCultureMgr *scMgr=GETSTELMODULE(StelSkyCultureMgr);
×
460
        return scMgr->createCulturalLabel(name, scMgr->getScreenLabelStyle(), QString());
×
461
}
462

463
QString StelSkyCultureSkyPartition::getLongitudeCoordinate(Vec3d &eqPos) const
×
464
{
465
        static StelSkyCultureMgr *scMgr=GETSTELMODULE(StelSkyCultureMgr);
×
466
        double ra, dec;
467
        StelUtils::rectToSphe(&ra, &dec, eqPos);
×
468
        if (frameType==StelCore::FrameObservercentricEclipticOfDate)
×
469
        {
470
                // We can for now assume this is a Zodiac or Indian Lunar system. However, e.g. both Indian are shifted by offsetFromAries.
471
                double lambda, beta;
472
                StelUtils::equToEcl(ra, dec, eclObl, &lambda, &beta);
×
473
                double cultureLambda=StelUtils::fmodpos((lambda*M_180_PI-offsetFromAries), 360.); // Degrees from zero point of cultural scale
×
474
                const double widthOfSign=(360./partitions.at(0));
×
475
                int sign=int(floor(cultureLambda/widthOfSign));
×
476
                double startOfSign=sign*widthOfSign;
×
477
                double degreeInSign=cultureLambda-startOfSign;
×
478

479
                if (partitions.at(0)==12)
×
480
                {
481
                        double minuteInSign=(degreeInSign-floor(degreeInSign))*60.;
×
482
                        return QString("%1 %2°%3'").arg(symbols.at(sign), QString::number(int(floor(degreeInSign))), QString::number(int(floor(minuteInSign))));
×
483
                }
484
                else if (partitions.at(0)==27)
×
485
                {
486
                        // Indian Nakshatras
487
                        int padaInSign=int(floor((degreeInSign/widthOfSign)*4.));
×
488
                        return QString("%1: %2").arg(symbols.at(sign), QString::number(int(floor(padaInSign+1))));
×
489
                }
490
                else if (partitions.at(0)==28)
×
491
                {
492
                        // Arab LM: Presumably a pragmatic three-partition is in use, like "not quite here yet", "central", "slightly past".
493
                        static StelSkyCultureMgr *scMgr=GETSTELMODULE(StelSkyCultureMgr);
×
494

495
                        int thirdInSign=int(floor((degreeInSign/widthOfSign)*3.));
×
496
                        return QString("%1: %2").arg(scMgr->createCulturalLabel(names.at(sign), scMgr->getScreenLabelStyle(), QString()), QString::number(int(floor(thirdInSign+1))));
×
497
                }
498
                else
499
                {
500
                        static bool reported=false;
501
                        if (!reported)
×
502
                        {
503
                                qInfo() << "Unknown ecliptical partition scheme for " << name.translated;
×
504
                                reported=true;
×
505
                        }
506
                        return QString();
×
507
                }
508
        }
509
        else
510
        {
511
                // We only know Chinese mansions here. Provide Mansion symbol+name. So far I don't know any further subdivision.
512
                static StarMgr *starMgr=GETSTELMODULE(StarMgr);
×
513
                static StelCore *core=StelApp::getInstance().getCore();
×
514

515
                const double raDeg=StelUtils::fmodpos(ra*M_180_PI, 360.); // object RA of date, degrees
×
516
                const Vec3d starPos0=starMgr->searchHP(linkStars.at(0))->getEquinoxEquatorialPos(core);
×
517
                double raStar0, decStar0;
518
                StelUtils::rectToSphe(&raStar0, &decStar0, starPos0); // start of mansion 0.
×
519
                const double raDeg0=StelUtils::fmodpos(raStar0*M_180_PI, 360.); // start RA of mansion 0, date, degrees
×
520
                const double lngInMansions=StelUtils::fmodpos(raDeg-raDeg0, 360.); // object's 'longitude' counted from the start of mansion 0 along the equator, degrees.
×
521

522
                int mansion=0;
×
523
                while (mansion<linkStars.length()-1)
×
524
                {
525
                        int nextStarIdx=StelUtils::imod(mansion+1, 28);
×
526
                        Vec3d starPos=starMgr->searchHP(linkStars.at(nextStarIdx))->getEquinoxEquatorialPos(core);
×
527
                        double raStar, decStar;
528
                        StelUtils::rectToSphe(&raStar, &decStar, starPos); // start of next mansion.
×
529
                        double lngNxtMansion=StelUtils::fmodpos(raStar*M_180_PI-raDeg0, 360.);
×
530
                        if (lngNxtMansion>lngInMansions)
×
531
                                break;
×
532
                        ++mansion;
×
533
                }
534
                QString mnName=scMgr->createCulturalLabel(names.at(mansion), scMgr->getScreenLabelStyle(), names.at(mansion).pronounceI18n);
×
535

536

537
                return QString("%1 - %2").arg(symbols.at(mansion), mnName);
×
538
        }
×
539
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc