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

Stellarium / stellarium / 3996069357

pending completion
3996069357

push

github

Ruslan Kabatsayev
Shorten some lines

5 of 5 new or added lines in 1 file covered. (100.0%)

14663 of 124076 relevant lines covered (11.82%)

22035.13 hits per line

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

0.0
/src/core/StelHips.cpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2017 Guillaume Chereau
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 */
19

20
#include "StelHips.hpp"
21
#include "StelApp.hpp"
22
#include "StelCore.hpp"
23
#include "Planet.hpp"
24
#include "StelPainter.hpp"
25
#include "StelTextureMgr.hpp"
26
#include "StelUtils.hpp"
27
#include "StelProgressController.hpp"
28

29
#include <QNetworkReply>
30
#include <QTimeLine>
31

32
// Declare healpix functions (at bottom of file)
33
void healpix_pix2vec(int nside, int pix, double out[3]);
34
void healpix_get_mat3(int nside, int pix, double out[3][3]);
35
void healpix_xy2vec(const double xy[2], double out[3]);
36

37
class HipsTile
38
{
39
public:
40
        int order;
41
        int pix;
42
        StelTextureSP texture = StelTextureSP(Q_NULLPTR);
43
        StelTextureSP allsky = StelTextureSP(Q_NULLPTR); // allsky low res version of the texture.
44

45
        // Used for smooth fade in
46
        QTimeLine texFader;
47
};
48

49
static QString getExt(const QString& format)
×
50
{
51
        for (auto &ext : format.split(' '))
×
52
        {
53
                if (ext == "jpeg") return "jpg";
×
54
                if (ext == "png") return "png";
×
55
        }
×
56
        return QString();
×
57
}
58

59
QUrl HipsSurvey::getUrlFor(const QString& path) const
×
60
{
61
        QUrl base = url;
×
62
        QString args = "";
×
63
        if (base.scheme().isEmpty()) base.setScheme("file");
×
64
        if (base.scheme() != "file")
×
65
                args += QString("?v=%1").arg(static_cast<int>(releaseDate));
×
66
        return QString("%1/%2%3").arg(base.url(), path, args);
×
67
}
×
68

69
HipsSurvey::HipsSurvey(const QString& url_, double releaseDate_):
×
70
        url(url_),
×
71
        releaseDate(releaseDate_),
×
72
        planetarySurvey(false),
×
73
        tiles(1000 * 512 * 512), // Cache max cost in pixels (enough for 1000 512x512 tiles).
×
74
        nbVisibleTiles(0),
×
75
        nbLoadedTiles(0)
×
76
{
77
        // Immediately download the properties.
78
        QNetworkRequest req = QNetworkRequest(getUrlFor("properties"));
×
79
        req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
×
80
        req.setRawHeader("User-Agent", StelUtils::getUserAgentString().toLatin1());
×
81
        QNetworkReply* networkReply = StelApp::getInstance().getNetworkAccessManager()->get(req);
×
82
        connect(networkReply, &QNetworkReply::finished, this, [&, networkReply] {
×
83
                QByteArray data = networkReply->readAll();
×
84
                for (const QByteArray &line : data.split('\n'))
×
85
                {
86
                        if (line.startsWith("#")) continue;
×
87
                        QStringList list=QString(line).split("=");
×
88
                        if (list.length()!=2) continue;
×
89
                        QString key = list.at(0).trimmed();
×
90
                        if (key.isEmpty()) continue;
×
91
                        QString value = list.at(1).trimmed();
×
92
                        properties[key] = value;
×
93
                }
×
94
                if (properties.contains("hips_release_date"))
×
95
                {
96
                        // XXX: StelUtils::getJulianDayFromISO8601String does not work
97
                        // without the seconds!
98
                        QDateTime date = QDateTime::fromString(properties["hips_release_date"].toString(), Qt::ISODate);
×
99
                        date.setTimeSpec(Qt::UTC);
×
100
                        releaseDate = StelUtils::qDateTimeToJd(date);
×
101
                }
×
102
                if (properties.contains("hips_frame"))
×
103
                        hipsFrame = properties["hips_frame"].toString().toLower();
×
104

105
                QStringList DSSSurveys;
×
106
                DSSSurveys << "equatorial" << "galactic" << "ecliptic"; // HiPS frames for DSS surveys
×
107
                if (DSSSurveys.contains(hipsFrame, Qt::CaseInsensitive) && !(properties["creator_did"].toString().contains("moon", Qt::CaseInsensitive)) && !(properties["client_category"].toString().contains("solar system", Qt::CaseInsensitive)))
×
108
                        planetarySurvey = false;
×
109
                else
110
                        planetarySurvey = true;
×
111

112
                emit propertiesChanged();
×
113
                emit statusChanged();
×
114
                networkReply->deleteLater();
×
115
        });
×
116
}
×
117

118
HipsSurvey::~HipsSurvey()
×
119
{
120
}
×
121

122
bool HipsSurvey::isVisible() const
×
123
{
124
        return static_cast<bool>(fader);
×
125
}
126

127
void HipsSurvey::setVisible(bool value)
×
128
{
129
        if (value == isVisible()) return;
×
130
        fader = value;
×
131
        if (!value && progressBar)
×
132
        {
133
                StelApp::getInstance().removeProgressBar(progressBar);
×
134
                progressBar = Q_NULLPTR;
×
135
        }
136
        emit visibleChanged(value);
×
137
}
138

139
int HipsSurvey::getPropertyInt(const QString& key, int fallback)
×
140
{
141
        if (!properties.contains(key)) return fallback;
×
142
        QJsonValue val = properties[key];
×
143
        if (val.isDouble()) return val.toInt();
×
144
        if (val.isString()) return val.toString().toInt();
×
145
        return 0;
×
146
}
×
147

148
bool HipsSurvey::getAllsky()
×
149
{
150
        if (!allsky.isNull() || noAllsky) return true;
×
151
        if (properties.isEmpty()) return false;
×
152

153
        // Allsky is deprecated after version 1.4.
154
        if (properties.contains("hips_version")) {
×
155
                QStringList version = properties["hips_version"].toString().split(".");
×
156
                if ((version.size() >= 2) && (version[0].toInt() * 100 + version[1].toInt() >= 104)) {
×
157
                        noAllsky = true;
×
158
                        return true;
×
159
                }
160
        }
×
161

162
        if (!networkReply)
×
163
        {
164
                QString ext = getExt(properties["hips_tile_format"].toString());
×
165
                QUrl path = getUrlFor(QString("Norder%1/Allsky.%2").arg(getPropertyInt("hips_order_min", 3)).arg(ext));
×
166
                qDebug() << "Load allsky" << path;
×
167
                QNetworkRequest req = QNetworkRequest(path);
×
168
                req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
×
169
                req.setRawHeader("User-Agent", StelUtils::getUserAgentString().toLatin1());
×
170
                networkReply = StelApp::getInstance().getNetworkAccessManager()->get(req);
×
171
                emit statusChanged();
×
172

173
                updateProgressBar(0, 100);
×
174
                connect(networkReply, &QNetworkReply::downloadProgress, this, [this](qint64 received, qint64 total) {
×
175
                        updateProgressBar(static_cast<int>(received), static_cast<int>(total));
×
176
                });
×
177
        }
×
178
        if (networkReply->isFinished())
×
179
        {
180
                if (networkReply->error() == QNetworkReply::NoError) {
×
181
                        qDebug() << "got allsky";
×
182
                        QByteArray data = networkReply->readAll();
×
183
                        allsky = QImage::fromData(data);
×
184
                } else {
×
185
                        noAllsky = true;
×
186
                }
187
                networkReply->deleteLater();
×
188
                networkReply = Q_NULLPTR;
×
189
                emit statusChanged();
×
190
        }
191
        return !allsky.isNull();
×
192
}
193

194
bool HipsSurvey::isLoading(void) const
×
195
{
196
        return (networkReply != Q_NULLPTR);
×
197
}
198

199
void HipsSurvey::draw(StelPainter* sPainter, double angle, HipsSurvey::DrawCallback callback)
×
200
{
201
        // We don't draw anything until we get the properties file and the
202
        // allsky texture (if available).
203
        const bool outside = qFuzzyCompare(angle, 2.0 * M_PI);
×
204
        if (properties.isEmpty()) return;
×
205
        if (!getAllsky()) return;
×
206
        if (fader.getInterstate() == 0.0f) return;
×
207
        sPainter->setColor(1, 1, 1, fader.getInterstate());
×
208

209
        // Set the projection.
210
        StelCore* core = StelApp::getInstance().getCore();
×
211
        StelCore::FrameType frame = StelCore::FrameUninitialized;
×
212
        if (hipsFrame == "galactic")
×
213
                frame = StelCore::FrameGalactic;
×
214
        else if (hipsFrame == "equatorial")
×
215
                frame = StelCore::FrameJ2000;
×
216
        if (frame)
×
217
                sPainter->setProjector(core->getProjection(frame));
×
218

219
        Vec3d obsVelocity(0.);
×
220
        // Aberration: retrieve observer velocity to apply, and transform it to frametype-dependent orientation
221
        if (core->getUseAberration())
×
222
        {
223
                static const Mat4d matVsop87ToGalactic=StelCore::matJ2000ToGalactic*StelCore::matVsop87ToJ2000;
×
224
                obsVelocity=core->getCurrentPlanet()->getHeliocentricEclipticVelocity(); // in VSOP87 frame...
×
225
                switch (frame){
×
226
                        case StelCore::FrameJ2000:
×
227
                                StelCore::matVsop87ToJ2000.transfo(obsVelocity);
×
228
                                break;
×
229
                        case StelCore::FrameGalactic:
×
230
                                matVsop87ToGalactic.transfo(obsVelocity);
×
231
                                break;
×
232
                        case StelCore::FrameHeliocentricEclipticJ2000:
×
233
                                // do nothing. Assume this frame is equal to VSOP87 (which is slightly incorrect!)
234
                                break;
×
235
                        default:
×
236
                                if (!planetarySurvey)
×
237
                                        qDebug() << "HiPS: Unexpected Frame: " << hipsFrame;
×
238
                }
239
                obsVelocity *= core->getAberrationFactor() * (AU/(86400.0*SPEED_OF_LIGHT));
×
240
        }
241

242
        // Compute the maximum visible level for the tiles according to the view resolution.
243
        // We know that each tile at level L represents an angle of 90 / 2^L
244
        // The maximum angle we want to see is the size of a tile in pixels time the angle for one visible pixel.
245
        double px = static_cast<double>(sPainter->getProjector()->getPixelPerRadAtCenter()) * angle;
×
246
        int tileWidth = getPropertyInt("hips_tile_width");
×
247

248
        int orderMin = getPropertyInt("hips_order_min", 3);
×
249
        int order = getPropertyInt("hips_order");
×
250
        int drawOrder = qRound(ceil(log2(px / (4.0 * std::sqrt(2.0) * tileWidth))));
×
251
        drawOrder = qBound(orderMin, drawOrder, order);
×
252
        int splitOrder = qMax(drawOrder, 4);
×
253

254
        nbVisibleTiles = 0;
×
255
        nbLoadedTiles = 0;
×
256

257
        // Draw the 12 root tiles and their children.
258
        const SphericalCap& viewportRegion = sPainter->getProjector()->getBoundingCap();
×
259
        for (int i = 0; i < 12; i++)
×
260
        {
261
                drawTile(0, i, drawOrder, splitOrder, outside, viewportRegion, sPainter, obsVelocity, callback);
×
262
        }
263

264
        updateProgressBar(nbLoadedTiles, nbVisibleTiles);
×
265
}
266

267
void HipsSurvey::updateProgressBar(int nb, int total)
×
268
{
269
        if (nb == total && progressBar) {
×
270
                StelApp::getInstance().removeProgressBar(progressBar);
×
271
                progressBar = Q_NULLPTR;
×
272
        }
273
        if (nb == total) return;
×
274

275
        if (!progressBar)
×
276
        {
277
                progressBar = StelApp::getInstance().addProgressBar();
×
278
                progressBar->setFormat(getTitle());
×
279
                progressBar->setRange(0, 100);
×
280
        }
281
        progressBar->setValue(100 * nb / total);
×
282
}
283

284
HipsTile* HipsSurvey::getTile(int order, int pix)
×
285
{
286
        int nside = 1 << order;
×
287
        long int uid = pix + 4L * nside * nside;
×
288
        int orderMin = getPropertyInt("hips_order_min", 3);
×
289
        HipsTile* tile = tiles[uid];
×
290
        if (!tile)
×
291
        {
292
                StelTextureMgr& texMgr = StelApp::getInstance().getTextureManager();
×
293
                tile = new HipsTile();
×
294
                tile->order = order;
×
295
                tile->pix = pix;
×
296
                QString ext = getExt(properties["hips_tile_format"].toString());
×
297
                QUrl path = getUrlFor(QString("Norder%1/Dir%2/Npix%3.%4").arg(order).arg((pix / 10000) * 10000).arg(pix).arg(ext));
×
298
                tile->texture = texMgr.createTextureThread(path.url(), StelTexture::StelTextureParams(true), false);
×
299

300
                // Use the allsky image until we load the full texture.
301
                if (order == orderMin && !allsky.isNull())
×
302
                {
303
                        int nbw = static_cast<int>(std::sqrt(12 * (1 << (2 * order))));
×
304
                        int x = (pix % nbw) * allsky.width() / nbw;
×
305
                        int y = (pix / nbw) * allsky.width() / nbw;
×
306
                        int s = allsky.width() / nbw;
×
307
                        QImage image = allsky.copy(x, y, s, s);
×
308
                        tile->allsky = texMgr.createTexture(image, StelTexture::StelTextureParams(true));
×
309
                }
×
310
                int tileWidth = getPropertyInt("hips_tile_width", 512);
×
311
                tiles.insert(uid, tile, tileWidth * tileWidth);
×
312
        }
×
313
        return tile;
×
314
}
315

316
// Test if a shape in clipping coordinate is clipped or not.
317
static bool isClipped(int n, double (*pos)[4])
×
318
{
319
    // The six planes equations:
320
    const int P[6][4] = {
×
321
        {-1, 0, 0, -1}, {1, 0, 0, -1},
322
        {0, -1, 0, -1}, {0, 1, 0, -1},
323
        {0, 0, -1, -1}, {0, 0, 1, -1}
324
    };
325
    int i, p;
326
    for (p = 0; p < 6; p++) {
×
327
        for (i = 0; i < n; i++) {
×
328
            if (    P[p][0] * pos[i][0] +
×
329
                    P[p][1] * pos[i][1] +
×
330
                    P[p][2] * pos[i][2] +
×
331
                    P[p][3] * pos[i][3] <= 0) {
×
332
                break;
×
333
            }
334
        }
335
        if (i == n) // All the points are outside a clipping plane.
×
336
            return true;
×
337
    }
338
    return false;
×
339
}
340

341

342
void HipsSurvey::drawTile(int order, int pix, int drawOrder, int splitOrder, bool outside,
×
343
                                                  const SphericalCap& viewportShape, StelPainter* sPainter, Vec3d observerVelocity, DrawCallback callback)
344
{
345
        Vec3d pos;
×
346
        Mat3d mat3;
×
347
        const Vec2d uv[4] = {Vec2d(0, 0), Vec2d(0, 1), Vec2d(1, 0), Vec2d(1, 1)};
×
348
        HipsTile *tile;
349
        int orderMin = getPropertyInt("hips_order_min", 3);
×
350
        QVector<Vec3d> vertsArray;
×
351
        QVector<Vec2f> texArray;
×
352
        QVector<uint16_t> indicesArray;
×
353
        int nb;
354
        Vec4f color = sPainter->getColor();
×
355
        float alpha;
356

357
        healpix_pix2vec(1 << order, pix, pos.v);
×
358

359
        // Check if the tile is visible.  For outside survey (fullsky), we
360
        // use bounding cap, otherwise we use proper tile clipping test.
361
        if (outside)
×
362
        {
363
                SphericalCap boundingCap;
×
364
                boundingCap.n = pos;
×
365
                boundingCap.d = cos(M_PI / 2.0 / (1 << order));
×
366
                if (!viewportShape.intersects(boundingCap)) return;
×
367
        }
×
368
        else
369
        {
370
                double clip_pos[4][4];
371
                healpix_get_mat3(1 << order, pix, reinterpret_cast<double(*)[3]>(mat3.r));
×
372
                auto proj = sPainter->getProjector();
×
373
                for (int i = 0; i < 4; i++)
×
374
                {
375
                        pos = mat3 * Vec3d(1 - uv[i][1], uv[i][0], 1.0);
×
376
                        healpix_xy2vec(pos.v, pos.v);
×
377
                        proj->projectInPlace(pos);
×
378
                        pos[0] = (pos[0] - proj->getViewportCenter()[0]) / proj->getViewportWidth() * 2.0;
×
379
                        pos[1] = (pos[1] - proj->getViewportCenter()[1]) / proj->getViewportHeight() * 2.0;
×
380
                        clip_pos[i][0] = pos[0];
×
381
                        clip_pos[i][1] = pos[1];
×
382
                        clip_pos[i][2] = 0.0;
×
383
                        clip_pos[i][3] = 1.0;
×
384
                }
385
                if (isClipped(4, clip_pos)) return;
×
386

387
                // Also check the culling.
388
                if (order > 0)
×
389
                {
390
                        Vec2d u(clip_pos[1][0] - clip_pos[0][0], clip_pos[1][1] - clip_pos[0][1]);
×
391
                        Vec2d v(clip_pos[2][0] - clip_pos[0][0], clip_pos[2][1] - clip_pos[0][1]);
×
392
                        u.normalize();
×
393
                        v.normalize();
×
394
                        // XXX: the error (0.5) depends on the order: the higher the order
395
                        // the lower the error should be.
396
                        if (u[0] * v[1] - u[1] * v[0] > 0.5) return;
×
397
                }
398
        }
×
399

400
        if (order < orderMin)
×
401
                goto skip_render;
×
402

403
        nbVisibleTiles++;
×
404
        tile = getTile(order, pix);
×
405
        if (!tile) return;
×
406
        if (!tile->texture->bind() && (!tile->allsky || !tile->allsky->bind()))
×
407
                return;
×
408
        if (tile->texFader.state() == QTimeLine::NotRunning && tile->texFader.currentValue() == 0.0)
×
409
                tile->texFader.start();
×
410
        nbLoadedTiles++;
×
411

412
        if (order < drawOrder)
×
413
        {
414
                // If all the children tiles are loaded, we can skip the parent.
415
                int i;
416
                for (i = 0; i < 4; i++)
×
417
                {
418
                        HipsTile* child = getTile(order + 1, pix * 4 + i);
×
419
                        if (!child || child->texFader.currentValue() < 1.0) break;
×
420
                }
421
                if (i == 4) goto skip_render;
×
422
        }
423

424
        // Actually draw the tile, as a single quad.
425
        alpha = color[3] * static_cast<float>(tile->texFader.currentValue());
×
426
        if (alpha < 1.0f)
×
427
        {
428
                sPainter->setBlending(true);
×
429
                sPainter->setColor(color[0], color[1], color[2], alpha);
×
430
        }
431
        else
432
        {
433
                sPainter->setBlending(false);
×
434
                sPainter->setColor(1, 1, 1, 1);
×
435
        }
436
        sPainter->setCullFace(true);
×
437
        nb = fillArrays(order, pix, drawOrder, splitOrder, outside, sPainter, observerVelocity,
×
438
                                        vertsArray, texArray, indicesArray);
439
        if (!callback) {
×
440
                sPainter->setArrays(vertsArray.constData(), texArray.constData());
×
441
                sPainter->drawFromArray(StelPainter::Triangles, nb, 0, true, indicesArray.constData());
×
442
        } else {
443
                callback(vertsArray, texArray, indicesArray);
×
444
        }
445

446
skip_render:
×
447
        // Draw the children.
448
        if (order < drawOrder)
×
449
        {
450
                for (int i = 0; i < 4; i++)
×
451
                {
452
                        drawTile(order + 1, pix * 4 + i, drawOrder, splitOrder, outside,
×
453
                                         viewportShape, sPainter, observerVelocity, callback);
454
                }
455
        }
456
        // Restore the painter color.
457
        sPainter->setColor(color);
×
458
}
×
459

460
int HipsSurvey::fillArrays(int order, int pix, int drawOrder, int splitOrder,
×
461
                                                   bool outside, StelPainter* sPainter, Vec3d observerVelocity,
462
                                                   QVector<Vec3d>& verts, QVector<Vec2f>& tex, QVector<uint16_t>& indices)
463
{
464
        Q_UNUSED(sPainter)
465
        Mat3d mat3;
×
466
        Vec3d pos;
×
467
        Vec2f texPos;
×
468
        uint16_t gridSize = static_cast<uint16_t>(1 << (splitOrder - drawOrder));
×
469
        uint16_t n = gridSize + 1;
×
470
        const uint16_t INDICES[2][6][2] = {
×
471
                {{0, 0}, {0, 1}, {1, 0}, {1, 1}, {1, 0}, {0, 1}},
472
                {{0, 0}, {1, 0}, {1, 1}, {1, 1}, {0, 1}, {0, 0}},
473
        };
474

475
        healpix_get_mat3(1 << order, pix, reinterpret_cast<double(*)[3]>(mat3.r));
×
476

477
        for (int i = 0; i < n; i++)
×
478
        {
479
                for (int j = 0; j < n; j++)
×
480
                {
481
                        texPos = Vec2f(static_cast<float>(i) / gridSize, static_cast<float>(j) / gridSize);
×
482
                        pos = mat3 * Vec3d(1.0 - static_cast<double>(j) / gridSize, static_cast<double>(i) / gridSize, 1.0);
×
483
                        healpix_xy2vec(pos.v, pos.v);
×
484

485
                        // Aberration: Assume pos=normalized vertex position on the sphere in HiPS frame equatorial/ecliptical/galactic. Velocity is already transformed to frame
486
                        if (!planetarySurvey)
×
487
                        {
488
                                pos+=observerVelocity;
×
489
                                pos.normalize();
×
490
                        }
491

492
                        verts << pos;
×
493
                        tex << texPos;
×
494
                }
495
        }
496
        for (uint16_t i = 0; i < gridSize; i++)
×
497
        {
498
                for (uint16_t j = 0; j < gridSize; j++)
×
499
                {
500
                        for (uint16_t k = 0; k < 6; k++)
×
501
                        {
502
                                indices << (INDICES[outside ? 1 : 0][k][1] + i) * n +
×
503
                                                INDICES[outside ? 1 : 0][k][0] + j;
×
504
                        }
505
                }
506
        }
507
        return gridSize * gridSize * 6;
×
508
}
509

510
//! Parse a hipslist file into a list of surveys.
511
QList<HipsSurveyP> HipsSurvey::parseHipslist(const QString& data)
×
512
{
513
        QList<HipsSurveyP> ret;
×
514
        QString url;
×
515
        double releaseDate = 0;
×
516
        for (auto &line : data.split('\n'))
×
517
        {
518
                if (line.startsWith('#')) continue;
×
519
                QString key = line.section("=", 0, 0).trimmed();
×
520
                QString value = line.section("=", 1, -1).trimmed();
×
521
                if (key == "hips_service_url") url = value;
×
522
                // special case: https://github.com/Stellarium/stellarium/issues/1276
523
                if (url.contains("data.stellarium.org/surveys/dss")) continue;
×
524
                if (key == "hips_release_date")
×
525
                {
526
                        // XXX: StelUtils::getJulianDayFromISO8601String does not work
527
                        // without the seconds!
528
                        QDateTime date = QDateTime::fromString(value, Qt::ISODate);
×
529
                        date.setTimeSpec(Qt::UTC);
×
530
                        releaseDate = StelUtils::qDateTimeToJd(date);
×
531
                }
×
532
                if (key == "hips_status" && value.split(' ').contains("public")) {
×
533
                        ret.append(HipsSurveyP(new HipsSurvey(url, releaseDate)));
×
534
                        url = "";
×
535
                        releaseDate = 0;
×
536
                }
537
        }
×
538
        return ret;
×
539
}
×
540

541
QString HipsSurvey::getTitle(void) const
×
542
{
543
        // Todo: add a fallback if the properties don't have a title.
544
        return properties["obs_title"].toString();
×
545
}
546

547
/* This used to be in healpix.c. Moved here to allow PCH */
548

549

550
/* utab[m] = (short)(
551
      (m&0x1 )       | ((m&0x2 ) << 1) | ((m&0x4 ) << 2) | ((m&0x8 ) << 3)
552
    | ((m&0x10) << 4) | ((m&0x20) << 5) | ((m&0x40) << 6) | ((m&0x80) << 7)); */
553
static const short utab[]={
554
#define Z(a) 0x##a##0, 0x##a##1, 0x##a##4, 0x##a##5
555
#define Y(a) Z(a##0), Z(a##1), Z(a##4), Z(a##5)
556
#define X(a) Y(a##0), Y(a##1), Y(a##4), Y(a##5)
557
X(0),X(1),X(4),X(5)
558
#undef X
559
#undef Y
560
#undef Z
561
};
562

563
/* ctab[m] = (short)(
564
       (m&0x1 )       | ((m&0x2 ) << 7) | ((m&0x4 ) >> 1) | ((m&0x8 ) << 6)
565
    | ((m&0x10) >> 2) | ((m&0x20) << 5) | ((m&0x40) >> 3) | ((m&0x80) << 4)); */
566
static const short ctab[]={
567
#define Z(a) a,a+1,a+256,a+257
568
#define Y(a) Z(a),Z(a+2),Z(a+512),Z(a+514)
569
#define X(a) Y(a),Y(a+4),Y(a+1024),Y(a+1028)
570
X(0),X(8),X(2048),X(2056)
571
#undef X
572
#undef Y
573
#undef Z
574
};
575

576
// Position of the healpix faces.
577
static const int FACES[12][2] = {{1,  0}, {3,  0}, {5,  0}, {7,  0},
578
                                 {0, -1}, {2, -1}, {4, -1}, {6, -1},
579
                                 {1, -2}, {3, -2}, {5, -2}, {7, -2}};
580

581
int healpix_xyf2nest(int nside, int ix, int iy, int face_num)
×
582
{
583
  return (face_num*nside*nside) +
×
584
      (utab[ix&0xff] | (utab[ix>>8]<<16)
×
585
    | (utab[iy&0xff]<<1) | (utab[iy>>8]<<17));
×
586
}
587

588
static void nest2xyf(int nside, int pix, int *ix, int *iy, int *face_num)
×
589
{
590
    int npface_ = nside * nside, raw;
×
591
    *face_num = pix / npface_;
×
592
    pix &= (npface_ - 1);
×
593
    raw = (pix & 0x5555) | ((pix & 0x55550000) >> 15);
×
594
    *ix = ctab[raw & 0xff] | (ctab[raw >> 8] << 4);
×
595
    pix >>= 1;
×
596
    raw = (pix & 0x5555) | ((pix & 0x55550000) >> 15);
×
597
    *iy = ctab[raw & 0xff] | (ctab[raw >> 8] << 4);
×
598
}
×
599

600
// Create a 3x3 mat that transforms uv texture position to healpix xy
601
// coordinates.
602
void healpix_get_mat3(int nside, int pix, double out[3][3])
×
603
{
604
    int ix, iy, face;
605
    nest2xyf(nside, pix, &ix, &iy, &face);
×
606
    out[0][0] = +M_PI / 4 / nside;
×
607
    out[0][1] = +M_PI / 4 / nside;
×
608
    out[0][2] = 0;
×
609
    out[1][0] = -M_PI / 4 / nside;
×
610
    out[1][1] = +M_PI / 4 / nside;
×
611
    out[1][2] = 0;
×
612
    out[2][0] = (FACES[face][0] + (ix - iy + 0.0) / nside) * M_PI / 4;
×
613
    out[2][1] = (FACES[face][1] + (ix + iy + 0.0) / nside) * M_PI / 4;
×
614
    out[2][2] = 1;
×
615
}
×
616

617
static void healpix_xy2_z_phi(const double xy[2], double *z, double *phi)
×
618
{
619
    double x = xy[0], y = xy[1];
×
620
    double sigma, xc;
621

622
    if (fabs(y) > M_PI / 4) {
×
623
        // Polar
624
        sigma = 2 - fabs(y * 4) / M_PI;
×
625
        *z = (y > 0 ? 1 : -1) * (1 - sigma * sigma / 3);
×
626
        xc = -M_PI + (2 * floor((x + M_PI) * 4 / (2 * M_PI)) + 1) * M_PI / 4;
×
627
        *phi = sigma ? (xc + (x - xc) / sigma) : x;
×
628
    } else {
629
        // Equatorial
630
        *phi = x;
×
631
        *z = y * 8 / (M_PI * 3);
×
632
    }
633
}
×
634

635
void healpix_xy2ang(const double xy[2], double *theta, double *phi)
×
636
{
637
    double z;
638
    healpix_xy2_z_phi(xy, &z, phi);
×
639
    *theta = acos(z);
×
640
}
×
641

642
void healpix_xy2vec(const double xy[2], double out[3])
×
643
{
644
    double z, phi, stheta;
645
    healpix_xy2_z_phi(xy, &z, &phi);
×
646
    stheta = sqrt((1 - z) * (1 + z));
×
647
    out[0] = stheta * cos(phi);
×
648
    out[1] = stheta * sin(phi);
×
649
    out[2] = z;
×
650
}
×
651

652
void healpix_pix2vec(int nside, int pix, double out[3])
×
653
{
654
    int ix, iy, face;
655
    double xy[2];
656
    nest2xyf(nside, pix, &ix, &iy, &face);
×
657
    xy[0] = (FACES[face][0] + (ix - iy + 0.0) / nside) * M_PI / 4;
×
658
    xy[1] = (FACES[face][1] + (ix + iy + 1.0) / nside) * M_PI / 4;
×
659
    healpix_xy2vec(xy, out);
×
660
}
×
661

662
void healpix_pix2ang(int nside, int pix, double *theta, double *phi)
×
663
{
664
    int ix, iy, face;
665
    double xy[2];
666
    nest2xyf(nside, pix, &ix, &iy, &face);
×
667
    xy[0] = (FACES[face][0] + (ix - iy + 0.0) / nside) * M_PI / 4;
×
668
    xy[1] = (FACES[face][1] + (ix + iy + 1.0) / nside) * M_PI / 4;
×
669
    healpix_xy2ang(xy, theta, phi);
×
670
}
×
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