StelSphereGeometry.cpp   StelSphereGeometry.cpp 
skipping to change at line 29 skipping to change at line 29
#include <QDebug> #include <QDebug>
#include <QBuffer> #include <QBuffer>
#include <stdexcept> #include <stdexcept>
#include "StelSphereGeometry.hpp" #include "StelSphereGeometry.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
#include "StelJsonParser.hpp" #include "StelJsonParser.hpp"
// Definition of static constants. // Definition of static constants.
const QVariant::Type SphericalRegionP::qVariantType = (QVariant::Type)(QVar iant::UserType+1);
int SphericalRegionP::metaTypeId = SphericalRegionP::initialize(); int SphericalRegionP::metaTypeId = SphericalRegionP::initialize();
int SphericalRegionP::initialize() int SphericalRegionP::initialize()
{ {
int id = qRegisterMetaType<SphericalRegionP>(); int id = qRegisterMetaType<SphericalRegionP>("SphericalRegionP");
qRegisterMetaTypeStreamOperators<SphericalRegionP>("SphericalRegionP "); qRegisterMetaTypeStreamOperators<SphericalRegionP>("SphericalRegionP ");
return id; return id;
} }
QDataStream& operator<<(QDataStream& out, const SphericalRegionP& region) QDataStream& operator<<(QDataStream& out, const SphericalRegionP& region)
{ {
out << (quint8)region->getType(); out << (quint8)region->getType();
region->serialize(out); region->serialize(out);
return out; return out;
} }
skipping to change at line 568 skipping to change at line 566
double SphericalCap::relativeDiameterOverlap(const SphericalCap& c1, const SphericalCap& c2) double SphericalCap::relativeDiameterOverlap(const SphericalCap& c1, const SphericalCap& c2)
{ {
if (!c1.intersects(c2)) if (!c1.intersects(c2))
return 0.; return 0.;
if (c1.contains(c2)) if (c1.contains(c2))
return c2.getRadius()/c1.getRadius(); return c2.getRadius()/c1.getRadius();
if (c2.contains(c1)) if (c2.contains(c1))
return c1.getRadius()/c2.getRadius(); return c1.getRadius()/c2.getRadius();
const double r1 = c1.getRadius(); const double r1 = c1.getRadius();
const double r2 = c2.getRadius(); const double r2 = c2.getRadius();
const double a = c1.n.angle(c2.n); const double a = c1.n.angleNormalized(c2.n);
const double overlapDist = (a-r1-r2)/(std::fabs(r1-r2)-r1-r2); const double overlapDist = (a-r1-r2)/(std::fabs(r1-r2)-r1-r2);
Q_ASSERT(overlapDist>=0); Q_ASSERT(overlapDist>=0);
return overlapDist*qMin(r1/r2, r2/r1); return overlapDist*qMin(r1/r2, r2/r1);
} }
QVector<Vec3d> SphericalCap::getClosedOutlineContour() const QVector<Vec3d> SphericalCap::getClosedOutlineContour() const
{ {
static const int nbStep = 40; static const int nbStep = 40;
QVector<Vec3d> contour; QVector<Vec3d> contour;
Vec3d p(n); Vec3d p(n);
skipping to change at line 594 skipping to change at line 592
for (int i=0;i<nbStep;++i) for (int i=0;i<nbStep;++i)
{ {
contour.append(p); contour.append(p);
p.transfo4d(rot); p.transfo4d(rot);
} }
return contour; return contour;
} }
OctahedronPolygon SphericalCap::getOctahedronPolygon() const OctahedronPolygon SphericalCap::getOctahedronPolygon() const
{ {
return OctahedronPolygon(getClosedOutlineContour()); if (d>=0)
return OctahedronPolygon(getClosedOutlineContour());
else
{
SphericalCap cap(-n, -d);
AllSkySphericalRegion allSky;
OctahedronPolygon poly = allSky.getOctahedronPolygon();
poly.inPlaceSubtraction(cap.getOctahedronPolygon());
return poly;
}
} }
QVariantMap SphericalCap::toQVariant() const QVariantList SphericalCap::toQVariant() const
{ {
QVariantMap res; QVariantList res;
res.insert("type", "CAP"); res << "CAP";
double ra, dec; double ra, dec;
StelUtils::rectToSphe(&ra, &dec, n); StelUtils::rectToSphe(&ra, &dec, n);
QVariantList l; QVariantList l;
l << ra*180./M_PI << dec*180./M_PI; l << ra*180./M_PI << dec*180./M_PI;
res.insert("center", l); res << QVariant(l);
res.insert("radius", std::acos(d)*180./M_PI); res << std::acos(d)*180./M_PI;
return res; return res;
} }
SphericalRegionP SphericalCap::deserialize(QDataStream& in) SphericalRegionP SphericalCap::deserialize(QDataStream& in)
{ {
Vec3d nn; Vec3d nn;
double dd; double dd;
in >> nn >> dd; in >> nn >> dd;
return SphericalRegionP(new SphericalCap(nn, dd)); return SphericalRegionP(new SphericalCap(nn, dd));
} }
skipping to change at line 638 skipping to change at line 645
return r.contains(n); return r.contains(n);
} }
OctahedronPolygon SphericalPoint::getOctahedronPolygon() const OctahedronPolygon SphericalPoint::getOctahedronPolygon() const
{ {
QVector<Vec3d> contour; QVector<Vec3d> contour;
contour << n << n << n; contour << n << n << n;
return OctahedronPolygon(contour); return OctahedronPolygon(contour);
} }
QVariantMap SphericalPoint::toQVariant() const QVariantList SphericalPoint::toQVariant() const
{ {
QVariantMap res; QVariantList res;
res.insert("type", "POINT"); res << "POINT";
double ra, dec; double ra, dec;
StelUtils::rectToSphe(&ra, &dec, n); StelUtils::rectToSphe(&ra, &dec, n);
QVariantList l; QVariantList l;
l << ra*180./M_PI << dec*180./M_PI; l << ra*180./M_PI << dec*180./M_PI;
res.insert("pos", l); res << l;
return res; return res;
} }
SphericalRegionP SphericalPoint::deserialize(QDataStream& in) SphericalRegionP SphericalPoint::deserialize(QDataStream& in)
{ {
Vec3d nn; Vec3d nn;
in >> nn; in >> nn;
return SphericalRegionP(new SphericalPoint(nn)); return SphericalRegionP(new SphericalPoint(nn));
} }
/////////////////////////////////////////////////////////////////////////// / /////////////////////////////////////////////////////////////////////////// /
// Methods for AllSkySphericalRegion // Methods for AllSkySphericalRegion
/////////////////////////////////////////////////////////////////////////// / /////////////////////////////////////////////////////////////////////////// /
const SphericalRegionP AllSkySphericalRegion::staticInstance = SphericalReg ionP(new AllSkySphericalRegion()); const SphericalRegionP AllSkySphericalRegion::staticInstance = SphericalReg ionP(new AllSkySphericalRegion());
QVariantMap AllSkySphericalRegion::toQVariant() const QVariantList AllSkySphericalRegion::toQVariant() const
{ {
QVariantMap res; QVariantList res;
res.insert("type", "ALLSKY"); res << "ALLSKY";
return res; return res;
} }
/////////////////////////////////////////////////////////////////////////// / /////////////////////////////////////////////////////////////////////////// /
// Methods for EmptySphericalRegion // Methods for EmptySphericalRegion
/////////////////////////////////////////////////////////////////////////// / /////////////////////////////////////////////////////////////////////////// /
const SphericalRegionP EmptySphericalRegion::staticInstance = SphericalRegi onP(new EmptySphericalRegion()); const SphericalRegionP EmptySphericalRegion::staticInstance = SphericalRegi onP(new EmptySphericalRegion());
QVariantMap EmptySphericalRegion::toQVariant() const QVariantList EmptySphericalRegion::toQVariant() const
{ {
QVariantMap res; QVariantList res;
res.insert("type", "EMPTY"); res << "EMPTY";
return res; return res;
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// Methods for SphericalPolygon // Methods for SphericalPolygon
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
SphericalCap SphericalPolygon::getBoundingCap() const SphericalCap SphericalPolygon::getBoundingCap() const
{ {
SphericalCap res; SphericalCap res;
octahedronPolygon.getBoundingCap(res.n, res.d); octahedronPolygon.getBoundingCap(res.n, res.d);
return res; return res;
} }
QVariantMap SphericalPolygon::toQVariant() const struct TriangleSerializer
{ {
QVariantMap res; TriangleSerializer(const TriangleSerializer& ts) : triangleList(ts.t
// QVariantList worldCoordinates; riangleList) {}
// double ra, dec;
Q_ASSERT(0); TriangleSerializer() {}
// foreach (const QVector<Vec3d>& contour, getFillVertexArray().vertex) inline void operator()(const Vec3d* v1, const Vec3d* v2, const Vec3d
// { * v3,
// QVariantList cv; const Vec2f* , const Vec2
// foreach (const Vec3d& v, contour) f* , const Vec2f* ,
// { unsigned int , unsigned i
// StelUtils::rectToSphe(&ra, &dec, v); nt , unsigned int )
// QVariantList vv; {
// vv << ra*180./M_PI << dec*180./M_PI; QVariantList triangle;
// cv.append((QVariant)vv); double ra, dec;
// } QVariantList l;
// worldCoordinates.append((QVariant)cv); StelUtils::rectToSphe(&ra, &dec, *v1);
// } l << ra*180./M_PI << dec*180./M_PI;
// res.insert("worldCoords", worldCoordinates); triangle << QVariant(l);
return res; l.clear();
StelUtils::rectToSphe(&ra, &dec, *v2);
l << ra*180./M_PI << dec*180./M_PI;
triangle << QVariant(l);
l.clear();
StelUtils::rectToSphe(&ra, &dec, *v3);
l << ra*180./M_PI << dec*180./M_PI;
triangle << QVariant(l);
Q_ASSERT(triangle.size()==3);
triangleList << QVariant(triangle);
}
QVariantList triangleList;
};
QVariantList SphericalPolygon::toQVariant() const
{
TriangleSerializer result = getFillVertexArray().foreachTriangle(Tri
angleSerializer());
return result.triangleList;
} }
void SphericalPolygon::serialize(QDataStream& out) const void SphericalPolygon::serialize(QDataStream& out) const
{ {
out << octahedronPolygon; out << octahedronPolygon;
} }
SphericalRegionP SphericalPolygon::deserialize(QDataStream& in) SphericalRegionP SphericalPolygon::deserialize(QDataStream& in)
{ {
OctahedronPolygon p; OctahedronPolygon p;
in >> p; in >> p;
return SphericalRegionP(new SphericalPolygon(p)); return SphericalRegionP(new SphericalPolygon(p));
} }
bool SphericalPolygon::contains(const SphericalConvexPolygon& r) const {ret urn octahedronPolygon.contains(r.getOctahedronPolygon());} bool SphericalPolygon::contains(const SphericalConvexPolygon& r) const {ret urn octahedronPolygon.contains(r.getOctahedronPolygon());}
bool SphericalPolygon::intersects(const SphericalConvexPolygon& r) const {r eturn r.intersects(*this);} bool SphericalPolygon::intersects(const SphericalConvexPolygon& r) const {r eturn r.intersects(*this);}
SphericalRegionP SphericalPolygon::multiUnion(const QList<SphericalRegionP> & regions) SphericalRegionP SphericalPolygon::multiUnion(const QList<SphericalRegionP> & regions, bool optimizeByPreGrouping)
{ {
QList<OctahedronPolygon> l; if (regions.size()==1)
foreach (const SphericalRegionP& r, regions) return regions.at(0);
l.append(r->getOctahedronPolygon()); if (optimizeByPreGrouping)
return SphericalRegionP(new SphericalPolygon(l)); {
static const double minOverlap = 0.2;
// Try to first split the set of regions into groups of inte
rsecting regions
QList<QList<SphericalRegionP> > res;
QList<SphericalCap> groupReferenceCap;
foreach (const SphericalRegionP& newReg, regions)
{
bool createNewGroup = true;
const SphericalCap& newRegBoundingCap = newReg->getB
oundingCap();
for (int i=0;i<res.size();++i)
{
// Make sure not to group full sky regions b
ecause it is usually not what we want.
if (SphericalCap::relativeDiameterOverlap(ne
wRegBoundingCap, groupReferenceCap.at(i))>minOverlap && newRegBoundingCap.d
>-0.9)
{
// It intersects with the reference
element of the group
res[i].append(newReg);
createNewGroup = false;
break;
}
}
if (createNewGroup)
{
QList<SphericalRegionP> newGroup;
newGroup.append(newReg);
res.append(newGroup);
// The reference element of the group is def
ined as the first element
groupReferenceCap.append(newRegBoundingCap);
}
}
// res now contains n list of regions to union together
QList<SphericalRegionP> mappedRegions;
foreach (const QList<SphericalRegionP>& l, res)
{
mappedRegions.append(SphericalPolygon::multiUnion(l)
);
}
return SphericalPolygon::multiUnion(mappedRegions);
}
else
{
// Just add all contours to one polygon
QList<OctahedronPolygon> l;
foreach (const SphericalRegionP& r, regions)
l.append(r->getOctahedronPolygon());
return SphericalRegionP(new SphericalPolygon(l));
}
}
SphericalRegionP SphericalPolygon::multiIntersection(const QList<SphericalR
egionP>& regions)
{
if (regions.isEmpty())
return EmptySphericalRegion::staticInstance;
SphericalRegionP reg = regions.at(0);
for (int i=1;i<regions.size();++i)
reg = reg->getIntersection(regions.at(i));
return reg;
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// Methods for SphericalTexturedPolygon // Methods for SphericalTexturedPolygon
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// Methods for SphericalConvexPolygon // Methods for SphericalConvexPolygon
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
skipping to change at line 932 skipping to change at line 1007
if (cachedBoundingCap.n*v<cachedBoundingCap.d) if (cachedBoundingCap.n*v<cachedBoundingCap.d)
cachedBoundingCap.d = cachedBoundingCap.n*v; cachedBoundingCap.d = cachedBoundingCap.n*v;
} }
cachedBoundingCap.d*=cachedBoundingCap.d>0 ? 0.9999999 : 1.0000001; cachedBoundingCap.d*=cachedBoundingCap.d>0 ? 0.9999999 : 1.0000001;
#ifndef NDEBUG #ifndef NDEBUG
foreach (const Vec3d& v, contour) foreach (const Vec3d& v, contour)
Q_ASSERT(cachedBoundingCap.contains(v)); Q_ASSERT(cachedBoundingCap.contains(v));
#endif #endif
} }
QVariantMap SphericalConvexPolygon::toQVariant() const QVariantList SphericalConvexPolygon::toQVariant() const
{ {
QVariantMap res; QVariantList res;
res.insert("type", "CVXPOLYGON"); res << "CONVEX_POLYGON";
QVariantList cv; QVariantList cv;
double ra, dec; double ra, dec;
foreach (const Vec3d& v, contour) foreach (const Vec3d& v, contour)
{ {
StelUtils::rectToSphe(&ra, &dec, v); StelUtils::rectToSphe(&ra, &dec, v);
QVariantList vv; QVariantList vv;
vv << ra*180./M_PI << dec*180./M_PI; vv << ra*180./M_PI << dec*180./M_PI;
cv.append((QVariant)vv); cv.append((QVariant)vv);
} }
res.insert("worldCoords", cv); res << cv;
return res; return res;
} }
SphericalRegionP SphericalConvexPolygon::deserialize(QDataStream& in) SphericalRegionP SphericalConvexPolygon::deserialize(QDataStream& in)
{ {
QVector<Vec3d> contour; QVector<Vec3d> contour;
in >> contour; in >> contour;
return SphericalRegionP(new SphericalConvexPolygon(contour)); return SphericalRegionP(new SphericalConvexPolygon(contour));
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// Methods for SphericalTexturedConvexPolygon // Methods for SphericalTexturedConvexPolygon
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
QVariantMap SphericalTexturedConvexPolygon::toQVariant() const QVariantList SphericalTexturedConvexPolygon::toQVariant() const
{ {
QVariantMap res = SphericalConvexPolygon::toQVariant(); QVariantList res = SphericalConvexPolygon::toQVariant();
QVariantList cv; QVariantList cv;
foreach (const Vec2f& v, textureCoords) foreach (const Vec2f& v, textureCoords)
{ {
QVariantList vv; QVariantList vv;
vv << v[0] << v[1]; vv << v[0] << v[1];
cv.append((QVariant)vv); cv.append((QVariant)vv);
} }
res.insert("textureCoords", cv); res << cv;
return res; return res;
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// Methods for SphericalTexturedPolygon // Methods for SphericalTexturedPolygon
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
QVariantMap SphericalTexturedPolygon::toQVariant() const QVariantList SphericalTexturedPolygon::toQVariant() const
{ {
Q_ASSERT(0); Q_ASSERT(0);
// TODO store a tesselated polygon?, including edge flags? // TODO store a tesselated polygon?, including edge flags?
return QVariantMap(); return QVariantList();
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// Utility methods // Utility methods
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
Vec3d greatCircleIntersection(const Vec3d& p1, const Vec3d& p2, const Vec3d & p3, const Vec3d& p4, bool& ok) Vec3d greatCircleIntersection(const Vec3d& p1, const Vec3d& p2, const Vec3d & p3, const Vec3d& p4, bool& ok)
{ {
if (p3*p4>1.-1E-10) if (p3*p4>1.-1E-10)
{ {
skipping to change at line 1060 skipping to change at line 1135
{ {
const QVariantList& vl = vRaDec.toList(); const QVariantList& vl = vRaDec.toList();
bool ok; bool ok;
if (vl.size()!=2) if (vl.size()!=2)
throw std::runtime_error(qPrintable(QString("invalid Ra,Dec pair: \"%1\" (expect 2 double values in degree, got %2)").arg(vRaDec.toStri ng()).arg(vl.size()))); throw std::runtime_error(qPrintable(QString("invalid Ra,Dec pair: \"%1\" (expect 2 double values in degree, got %2)").arg(vRaDec.toStri ng()).arg(vl.size())));
StelUtils::spheToRect(vl.at(0).toDouble(&ok)*M_PI/180., vl.at(1).toD ouble(&ok)*M_PI/180., v); StelUtils::spheToRect(vl.at(0).toDouble(&ok)*M_PI/180., vl.at(1).toD ouble(&ok)*M_PI/180., v);
if (!ok) if (!ok)
throw std::runtime_error(qPrintable(QString("invalid Ra,Dec pair: \"%1\" (expect 2 double values in degree)").arg(vRaDec.toString()))); throw std::runtime_error(qPrintable(QString("invalid Ra,Dec pair: \"%1\" (expect 2 double values in degree)").arg(vRaDec.toString())));
} }
QVector<QVector<Vec3d> > SphericalRegionP::loadContourFromQVariant(const QV ariantList& contoursList) struct TriangleDumper
{ {
QVector<QVector<Vec3d> > contours; TriangleDumper(const TriangleDumper& ts) : triangleList(ts.triangleL
QVector<Vec3d> vertices; ist) {}
bool ok;
for (int i=0;i<contoursList.size();++i) TriangleDumper() {}
inline void operator()(const Vec3d* v1, const Vec3d* v2, const Vec3d
* v3,
const Vec2f* , const Vec2
f* , const Vec2f* ,
unsigned int , unsigned i
nt , unsigned int )
{ {
const QVariantList& contourToList = contoursList.at(i).toLis QVector<Vec3d> triangle;
t(); triangle << *v1 << *v2 << *v3;
if (contourToList.size()<1) triangleList.append(triangle);
throw std::runtime_error(qPrintable(QString("invalid }
contour definition: %1").arg(contoursList.at(i).toString())));
if (contourToList.at(0).toString()=="CAP") QVector<QVector<Vec3d > > triangleList;
};
QVector<QVector<Vec3d > > SphericalRegion::getSimplifiedContours() const
{
TriangleDumper result = getFillVertexArray().foreachTriangle(Triangl
eDumper());
return result.triangleList;
}
SphericalRegionP capFromQVariantList(const QVariantList& l)
{
Q_ASSERT(l.at(0).toString()=="CAP");
// We now parse a cap, the format is "CAP",[ra, dec],aperture
if (l.size()!=3)
throw std::runtime_error(qPrintable(QString("invalid CAP des
cription: %1 (expect \"CAP\",[ra, dec],aperture)").arg(QString::fromUtf8(St
elJsonParser::write(l)))));
Vec3d v;
parseRaDec(l.at(1), v);
bool ok;
double d = l.at(2).toDouble(&ok)*M_PI/180.;
if (!ok)
throw std::runtime_error(qPrintable(QString("invalid apertur
e angle: \"%1\" (expect a double value in degree)").arg(l.at(2).toString())
));
return SphericalRegionP(new SphericalCap(v,std::cos(d)));
}
QVector<Vec3d> pathFromQVariantList(const QVariantList& l)
{
Q_ASSERT(l.at(0).toString()=="PATH");
// We now parse a path single contour, the format is:
// "PATH",[ra, dec],["greatCircleTo", [ra, dec]], ["smallCircle", [r
aAxis, decAxis], angle], [etc..]
QVector<Vec3d> vertices;
Vec3d v;
parseRaDec(l.at(1), v);
vertices.append(v); // Starting point
for (int k=2;k<l.size();++k)
{
const QVariantList& elemList = l.at(k).toList();
if (elemList.size()<1)
throw std::runtime_error(qPrintable(QString("invalid
PATH description: \"%1\" (expect a list of greatCircleTo or smallCircle").
arg(l.at(2).toString())));
if (elemList.at(0)=="greatCircleTo")
{ {
// We now parse a cap, the format is "CAP",[ra, dec] parseRaDec(elemList.at(1), v);
,aperture vertices.append(v);
if (contourToList.size()!=3)
throw std::runtime_error(qPrintable(QString(
"invalid CAP description: %1 (expect \"CAP\",[ra, dec],aperture)").arg(cont
oursList.at(i).toString())));
Vec3d v;
parseRaDec(contourToList.at(1), v);
double d = contourToList.at(2).toDouble(&ok)*M_PI/18
0.;
if (!ok)
throw std::runtime_error(qPrintable(QString(
"invalid aperture angle: \"%1\" (expect a double value in degree)").arg(con
tourToList.at(2).toString())));
SphericalCap cap(v,std::cos(d));
contours.append(cap.getClosedOutlineContour());
continue; continue;
} }
if (contourToList.at(0).toString()=="PATH") if (elemList.at(0)=="smallCircle")
{ {
// We now parse a path, the format is Vec3d axis;
// "PATH",[ra, dec],[["greatCircleTo", [ra, dec]], [ parseRaDec(elemList.at(1), axis);
"smallCircle", [raAxis, decAxis], angle], [etc..]] bool ok;
Q_ASSERT(vertices.isEmpty()); double angle = elemList.at(2).toDouble(&ok)*M_PI/180
.;
if (!ok || std::fabs(angle)>2.*M_PI)
throw std::runtime_error(qPrintable(QString(
"invalid small circle rotation angle: \"%1\" (expect a double value in degr
ee betwwen -2pi and 2pi)").arg(elemList.at(2).toString())));
int nbStep = 1+(int)(std::fabs(angle)/(2.*M_PI)*75);
Q_ASSERT(nbStep>0);
v = vertices.last();
const Mat4d& rotMat = Mat4d::rotation(axis, angle/nb
Step);
for (int step=0; step<nbStep;++step)
{
v.transfo4d(rotMat);
vertices.append(v);
}
continue;
}
throw std::runtime_error(qPrintable(QString("invalid PATH de
scription: \"%1\" (expect a list of greatCircleTo or smallCircle").arg(l.at
(2).toString())));
}
Q_ASSERT(vertices.size()>2);
return vertices;
}
QVector<Vec3d> singleContourFromQVariantList(const QVariantList& l)
{
if (l.size()<3)
throw std::runtime_error("a polygon contour must have at lea
st 3 vertices");
QVector<Vec3d> vertices;
Vec3d v;
foreach (const QVariant& vRaDec, l)
{
parseRaDec(vRaDec, v);
vertices.append(v);
}
Q_ASSERT(vertices.size()>2);
return vertices;
}
SphericalRegionP SphericalRegionP::loadFromQVariant(const QVariantList& l)
{
if (l.isEmpty())
return EmptySphericalRegion::staticInstance;
if (l.at(0).type()==QVariant::List)
{
// The region is composed of either:
// - a list of regions, which are assumed to be combined usi
ng the positive winding rule.
// - or a single contour
QVector<QVector<Vec3d> > contours;
try {
Vec3d v; Vec3d v;
parseRaDec(contourToList.at(1), v); parseRaDec(l.at(0), v);
vertices.append(v); // Starting point // No exception was thrown, we are parsing a single
foreach (const QVariant& elem, contourToList.at(2).t contour
oList()) contours.append(singleContourFromQVariantList(l));
}
catch (std::runtime_error&)
{
// We are parsing a list of regions.
for (int i=0;i<l.size();++i)
{ {
const QVariantList& elemList = elem.toList() const QVariantList& subL = l.at(i).toList();
; if (subL.isEmpty())
if (elemList.size()<1) throw std::runtime_error(qPrintable(
throw std::runtime_error(qPrintable( QString("invalid region definition: %1").arg(l.at(i).toString())));
QString("invalid PATH description: \"%1\" (expect a list of greatCircleTo o if (subL.at(0).type()==QVariant::List)
r smallCircle").arg(contourToList.at(2).toString())));
if (elemList.at(0)=="greatCircleTo")
{ {
parseRaDec(elemList.at(1), v); // Special optimization for basic co
vertices.append(v); ntours (if no type is provided, assume a polygon)
contours.append(singleContourFromQVa
riantList(subL));
continue; continue;
} }
if (elemList.at(0)=="smallCircle") Q_ASSERT(subL.at(0).type()==QVariant::String
{ || subL.at(0).type()==QVariant::ByteArray);
Vec3d axis; const SphericalRegionP& reg = loadFromQVaria
parseRaDec(elemList.at(1), axis); nt(subL);
double angle = elemList.at(2).toDoub if (!reg->isEmpty())
le(&ok)*M_PI/180.; contours << reg->getSimplifiedContou
if (!ok || std::fabs(angle)>2.*M_PI) rs();
throw std::runtime_error(qPr
intable(QString("invalid small circle rotation angle: \"%1\" (expect a doub
le value in degree betwwen -2pi and 2pi)").arg(elemList.at(2).toString())))
;
int nbStep = 1+(int)(std::fabs(angle
)/(2.*M_PI)*50);
Q_ASSERT(nbStep>0);
v = vertices.last();
const Mat4d& rotMat = Mat4d::rotatio
n(axis, angle/nbStep);
for (int step=0; step<nbStep;++step)
{
v.transfo4d(rotMat);
vertices.append(v);
}
continue;
}
throw std::runtime_error(qPrintable(QString(
"invalid PATH description: \"%1\" (expect a list of greatCircleTo or smallC
ircle").arg(contourToList.at(2).toString())));
} }
Q_ASSERT(vertices.size()>2);
contours.append(vertices);
vertices.clear();
continue;
} }
// If no type is provided, assume a polygon return SphericalRegionP(new SphericalPolygon(contours));
if (contourToList.size()<3) }
throw std::runtime_error("a polygon contour must hav
e at least 3 vertices"); Q_ASSERT(l.at(0).type()==QVariant::String || l.at(0).type()==QVarian
Q_ASSERT(vertices.isEmpty()); t::ByteArray);
Vec3d v; const QString& code=l.at(0).toString();
foreach (const QVariant& vRaDec, contourToList) if (code=="CAP")
return capFromQVariantList(l);
else if (code=="INTERSECTION")
{
Q_ASSERT(l.size()>2);
SphericalRegionP reg1 = loadFromQVariant(l.at(1).toList());
for (int n=2;n<l.size();++n)
{ {
parseRaDec(vRaDec, v); SphericalRegionP reg2 = loadFromQVariant(l.at(n).toL
vertices.append(v); ist());
reg1 = reg1->getIntersection(reg2.data());
} }
Q_ASSERT(vertices.size()>2); return reg1;
contours.append(vertices);
vertices.clear();
} }
return contours; else if (code=="SUBTRACTION")
} {
Q_ASSERT(l.size()==3);
SphericalRegionP SphericalRegionP::loadFromQVariant(const QVariantList& con SphericalRegionP reg1 = loadFromQVariant(l.at(1).toList());
toursList) SphericalRegionP reg2 = loadFromQVariant(l.at(2).toList());
{ SphericalRegionP regIntersection = reg1->getIntersection(reg
// It can only be a pure shape definition, without texture coords 2.data());
const QVector<QVector<Vec3d> >& contours = loadContourFromQVariant(c reg1 = reg1->getSubtraction(regIntersection.data());
ontoursList); return reg1;
return SphericalRegionP(new SphericalPolygon(contours)); }
else if (code=="PATH")
{
return SphericalRegionP(new SphericalPolygon(pathFromQVarian
tList(l)));
}
Q_ASSERT(0);
return EmptySphericalRegion::staticInstance;
} }
SphericalRegionP SphericalRegionP::loadFromQVariant(const QVariantMap& map) SphericalRegionP SphericalRegionP::loadFromQVariant(const QVariantMap& map)
{ {
QVariantList contoursList = map.value("skyConvexPolygons").toList(); QVariantList contoursList = map.value("skyConvexPolygons").toList();
if (contoursList.empty()) if (contoursList.empty())
contoursList = map.value("worldCoords").toList(); contoursList = map.value("worldCoords").toList();
else else
qWarning() << "skyConvexPolygons in preview JSON files is de precated. Replace with worldCoords."; qWarning() << "skyConvexPolygons in preview JSON files is de precated. Replace with worldCoords.";
skipping to change at line 1172 skipping to change at line 1324
// Load the matching textures positions (if any) // Load the matching textures positions (if any)
QVariantList texCoordList = map.value("textureCoords").toList(); QVariantList texCoordList = map.value("textureCoords").toList();
if (!texCoordList.isEmpty() && contoursList.size()!=texCoordList.siz e()) if (!texCoordList.isEmpty() && contoursList.size()!=texCoordList.siz e())
throw std::runtime_error(qPrintable(QString("the number of s ky contours (%1) does not match the number of texture space contours (%2)") .arg( contoursList.size()).arg(texCoordList.size()))); throw std::runtime_error(qPrintable(QString("the number of s ky contours (%1) does not match the number of texture space contours (%2)") .arg( contoursList.size()).arg(texCoordList.size())));
bool ok; bool ok;
if (texCoordList.isEmpty()) if (texCoordList.isEmpty())
{ {
// No texture coordinates // No texture coordinates
const QVector<QVector<Vec3d> >& contours = loadContourFromQV return loadFromQVariant(contoursList);
ariant(contoursList);
return SphericalRegionP(new SphericalPolygon(contours));
} }
else else
{ {
// With texture coordinates // With texture coordinates
QVector<QVector<SphericalTexturedPolygon::TextureVertex> > c ontours; QVector<QVector<SphericalTexturedPolygon::TextureVertex> > c ontours;
QVector<SphericalTexturedPolygon::TextureVertex> vertices; QVector<SphericalTexturedPolygon::TextureVertex> vertices;
for (int i=0;i<contoursList.size();++i) for (int i=0;i<contoursList.size();++i)
{ {
// Load vertices // Load vertices
const QVariantList& polyRaDecToList = contoursList.a t(i).toList(); const QVariantList& polyRaDecToList = contoursList.a t(i).toList();
skipping to change at line 1215 skipping to change at line 1366
throw std::runtime_error("invalid te xture coordinate pair (expect 2 double values in degree)"); throw std::runtime_error("invalid te xture coordinate pair (expect 2 double values in degree)");
} }
contours.append(vertices); contours.append(vertices);
vertices.clear(); vertices.clear();
} }
return SphericalRegionP(new SphericalTexturedPolygon(contour s)); return SphericalRegionP(new SphericalTexturedPolygon(contour s));
} }
Q_ASSERT(0); Q_ASSERT(0);
return SphericalRegionP(new SphericalCap()); return SphericalRegionP(new SphericalCap());
} }
void SphericalRegionP::serializeToJson(const QVariant& jsonObject, QIODevic
e* output, int indentLevel)
{
const SphericalRegionP& reg = jsonObject.value<SphericalRegionP>();
StelJsonParser::write(reg->toQVariant(), output, indentLevel);
}
 End of changes. 44 change blocks. 
154 lines changed or deleted 325 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/