~ubuntu-branches/ubuntu/saucy/merkaartor/saucy

« back to all changes in this revision

Viewing changes to src/Maps/Projection.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Zeimetz
  • Date: 2009-09-13 00:52:12 UTC
  • mto: (1.2.7 upstream) (0.1.3 upstream) (3.1.7 sid)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20090913005212-pjecal8zxm07x0fj
ImportĀ upstreamĀ versionĀ 0.14+svnfixes~20090912

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "Maps/Projection.h"
 
2
#include "Maps/TrackPoint.h"
 
3
 
 
4
#include <QRect>
 
5
#include <QRectF>
 
6
 
 
7
#include <math.h>
 
8
 
 
9
#include <ggl/projections/parameters.hpp>
 
10
#include <ggl/projections/factory.hpp>
 
11
 
 
12
// from wikipedia
 
13
#define EQUATORIALRADIUS 6378137.0
 
14
#define POLARRADIUS      6356752.0
 
15
//#define PROJ_RATIO ((double(INT_MAX)/M_PI) / EQUATORIALRADIUS)
 
16
 
 
17
using namespace ggl;
 
18
 
 
19
// ProjectionPrivate
 
20
 
 
21
class ProjectionPrivate
 
22
{
 
23
public:
 
24
        ProjProjection *theWGS84Proj;
 
25
        QRectF ProjectedViewport;
 
26
        int ProjectionRevision;
 
27
 
 
28
public:
 
29
        ProjectionPrivate()
 
30
                : ProjectionRevision(0)
 
31
        {
 
32
        }
 
33
};
 
34
 
 
35
//Projection
 
36
 
 
37
Projection::Projection(void)
 
38
: theProj(0), p(new ProjectionPrivate)
 
39
{
 
40
#ifndef _MOBILE
 
41
        p->theWGS84Proj = Projection::getProjection("+proj=longlat +ellps=WGS84 +datum=WGS84");
 
42
        setProjectionType(M_PREFS->getProjectionType());
 
43
#endif
 
44
}
 
45
 
 
46
Projection::~Projection(void)
 
47
{
 
48
        delete p;
 
49
}
 
50
 
 
51
 
 
52
#ifndef _MOBILE
 
53
 
 
54
#include "ggl/projections/impl/pj_transform.hpp"
 
55
void Projection::projTransform(ProjProjection *srcdefn, 
 
56
                                                   ProjProjection *dstdefn, 
 
57
                                                   long point_count, int point_offset, double *x, double *y, double *z )
 
58
{
 
59
        ggl::projection::detail::pj_transform(srcdefn, dstdefn, point_count, point_offset, x, y, z);
 
60
}
 
61
 
 
62
void Projection::projTransformFromWGS84(long point_count, int point_offset, double *x, double *y, double *z )
 
63
{
 
64
        ggl::projection::detail::pj_transform(p->theWGS84Proj, theProj, point_count, point_offset, x, y, z);
 
65
}
 
66
 
 
67
void Projection::projTransformToWGS84(long point_count, int point_offset, double *x, double *y, double *z )
 
68
{
 
69
        ggl::projection::detail::pj_transform(theProj, p->theWGS84Proj, point_count, point_offset, x, y, z);
 
70
}
 
71
 
 
72
QPointF Projection::projProject(const Coord & Map) const
 
73
{
 
74
        try {
 
75
                point_ll_deg in(longitude<>(intToAng(Map.lon())), latitude<>(intToAng(Map.lat())));
 
76
                point_2d out;
 
77
 
 
78
                theProj->forward(in, out);
 
79
 
 
80
                return QPointF(out.x(), out.y());
 
81
        } catch (...) {
 
82
                return QPointF(0., 0.);
 
83
        }
 
84
}
 
85
 
 
86
Coord Projection::projInverse(const QPointF & pProj) const
 
87
{
 
88
        try {
 
89
                point_2d in(pProj.x(), pProj.y());
 
90
                point_ll_deg out;
 
91
 
 
92
                theProj->inverse(in, out);
 
93
 
 
94
                return Coord(angToInt(out.lat()), angToInt(out.lon()));
 
95
        } catch (...) {
 
96
                return Coord(0, 0);
 
97
        }
 
98
}
 
99
 
 
100
bool Projection::projIsLatLong()
 
101
{
 
102
        return (theProj->params().is_latlong > 0);
 
103
}
 
104
 
 
105
QRectF Projection::getProjectedViewport(CoordBox& Viewport, QRect& screen)
 
106
{
 
107
        QPointF br, tl;
 
108
 
 
109
        double x = intToRad(Viewport.topLeft().lon());
 
110
        double y = intToRad(Viewport.topLeft().lat());
 
111
        projTransformFromWGS84(1, 0, &x, &y, NULL);
 
112
        if (theProj->params().is_latlong)
 
113
                tl = QPointF(radToAng(x), radToAng(y));
 
114
        else
 
115
                tl = QPointF(x, y);
 
116
 
 
117
        x = intToRad(Viewport.bottomRight().lon());
 
118
        y = intToRad(Viewport.bottomRight().lat());
 
119
        projTransformFromWGS84(1, 0, &x, &y, NULL);
 
120
        if (theProj->params().is_latlong)
 
121
                br = QPointF(radToAng(x), radToAng(y));
 
122
        else
 
123
                br = QPointF(x, y);
 
124
 
 
125
        QRectF pViewport = QRectF(tl, br);
 
126
 
 
127
        QPointF pCenter(pViewport.center());
 
128
 
 
129
        double wv, hv;
 
130
        //wv = (pViewport.width() / Viewport.londiff()) * ((double)screen.width() / Viewport.londiff());
 
131
        //hv = (pViewport.height() / Viewport.latdiff()) * ((double)screen.height() / Viewport.latdiff());
 
132
 
 
133
        double Aspect = (double)screen.width() / screen.height();
 
134
        double pAspect = fabs(pViewport.width() / pViewport.height());
 
135
 
 
136
        if (pAspect > Aspect) {
 
137
                wv = fabs(pViewport.width());
 
138
                hv = fabs(pViewport.height() * pAspect / Aspect);
 
139
        } else {
 
140
                wv = fabs(pViewport.width() * Aspect / pAspect);
 
141
                hv = fabs(pViewport.height());
 
142
        }
 
143
 
 
144
        pViewport = QRectF((pCenter.x() - wv/2), (pCenter.y() + hv/2), wv, -hv);
 
145
 
 
146
        return pViewport;
 
147
}
 
148
 
 
149
#endif
 
150
 
 
151
#ifndef _MOBILE
 
152
 
 
153
ProjProjection * Projection::getProjection(QString projString)
 
154
{
 
155
        ggl::projection::factory<ggl::point_ll_deg, ggl::point_2d> fac;
 
156
        ggl::projection::parameters par;
 
157
        ggl::projection::projection<ggl::point_ll_deg, ggl::point_2d> *theProj;
 
158
 
 
159
        try {
 
160
                par = ggl::projection::init(std::string(QString("%1 +over").arg(projString).toLatin1().data()));
 
161
                theProj = fac.create_new(par);
 
162
                if (!theProj) {
 
163
                        par = ggl::projection::init(std::string(QString("%1 +over").arg(M_PREFS->getProjection("mercator").projection).toLatin1().data()));
 
164
                        theProj = fac.create_new(par);
 
165
                        if (!theProj) {
 
166
                                qDebug() << "Unable to set projection : " << projString;
 
167
                                return NULL;
 
168
                        }
 
169
                }
 
170
        } catch (...) {
 
171
                par = ggl::projection::init(std::string(QString("%1 +over").arg(M_PREFS->getProjection("mercator").projection).toLatin1().data()));
 
172
                theProj = fac.create_new(par);
 
173
        }
 
174
        return theProj;
 
175
}
 
176
 
 
177
bool Projection::setProjectionType(ProjectionType aProjectionType)
 
178
{
 
179
        delete theProj;
 
180
        p->ProjectionRevision++;
 
181
        try {
 
182
                theProj = getProjection(M_PREFS->getProjection(aProjectionType).projection);
 
183
        } catch (...) {
 
184
                return false;
 
185
        }
 
186
        return (theProj != NULL);
 
187
}
 
188
#endif
 
189
 
 
190
// Common routines
 
191
 
 
192
double Projection::latAnglePerM() const
 
193
{
 
194
        double LengthOfOneDegreeLat = EQUATORIALRADIUS * M_PI / 180;
 
195
        return 1 / LengthOfOneDegreeLat;
 
196
}
 
197
 
 
198
double Projection::lonAnglePerM(double Lat) const
 
199
{
 
200
        double LengthOfOneDegreeLat = EQUATORIALRADIUS * M_PI / 180;
 
201
        double LengthOfOneDegreeLon = LengthOfOneDegreeLat * fabs(cos(Lat));
 
202
        return 1 / LengthOfOneDegreeLon;
 
203
}
 
204
 
 
205
QPointF Projection::project(const Coord & Map) const
 
206
{
 
207
#ifndef _MOBILE
 
208
        return projProject(Map);
 
209
#else
 
210
        return QPoint(qRound(Map.lon()), qRound(Map.lat()));
 
211
#endif
 
212
}
 
213
 
 
214
QPointF Projection::project(TrackPoint* aNode) const
 
215
{
 
216
#ifndef _MOBILE
 
217
        if (aNode && aNode->projectionRevision() == p->ProjectionRevision)
 
218
                return aNode->projection();
 
219
 
 
220
        QPointF pt = projProject(aNode->position());
 
221
 
 
222
        aNode->setProjectionRevision(p->ProjectionRevision);
 
223
        aNode->setProjection(pt);
 
224
 
 
225
        return pt;
 
226
#else
 
227
        return project(aNode->position());
 
228
#endif
 
229
}
 
230
 
 
231
Coord Projection::inverse(const QPointF & Screen) const
 
232
{
 
233
#ifndef _MOBILE
 
234
        return projInverse(QPointF(Screen.x(), Screen.y()));
 
235
#else
 
236
        return Coord(qRound(Screen.y()),
 
237
                                 qRound(Screen.x()));
 
238
#endif
 
239
}
 
240
 
 
241
int Projection::projectionRevision() const
 
242
{
 
243
        return p->ProjectionRevision;
 
244
}
 
245