geo/merkaartor: update to 0.19.0.

See https://github.com/openstreetmap/merkaartor/releases/tag/0.19.0
This commit is contained in:
landry 2021-09-10 06:45:01 +00:00
parent a4797f50c2
commit a5b68441f5
17 changed files with 13 additions and 793 deletions

View File

@ -1,11 +1,10 @@
# $OpenBSD: Makefile,v 1.46 2021/04/12 10:17:11 landry Exp $
# $OpenBSD: Makefile,v 1.47 2021/09/10 06:45:01 landry Exp $
COMMENT = OpenStreetMap editor
REVISION = 2
GH_ACCOUNT = openstreetmap
GH_PROJECT = merkaartor
GH_TAGNAME = 0.18.4
GH_TAGNAME = 0.19.0
CATEGORIES = geo x11
@ -16,24 +15,21 @@ MAINTAINER = Landry Breuil <landry@openbsd.org>
PERMIT_PACKAGE = Yes
NO_TEST = Yes
MODULES = devel/qmake x11/qt5
MODULES = devel/cmake x11/qt5
RUN_DEPENDS = devel/desktop-file-utils \
x11/gtk+3,-guic
# spatialite is marked as non-working
LIB_DEPENDS = devel/proj \
x11/qt5/qtsvg \
graphics/exiv2 \
geo/gdal
WANTLIB += ${COMPILER_LIBCXX} GL Qt5Concurrent Qt5Core Qt5Gui
WANTLIB += ${COMPILER_LIBCXX} Qt5Concurrent Qt5Core Qt5Gui
WANTLIB += Qt5Network Qt5PrintSupport Qt5Svg Qt5Widgets Qt5Xml
WANTLIB += c gdal m proj z
WANTLIB += c exiv2 gdal m proj
# C++11
COMPILER = base-clang ports-gcc
#generate the .qm files from the .ts files before configure runs
pre-configure:
cd ${WRKSRC} && lrelease-qt5 src/src.pro
.include <bsd.port.mk>

View File

@ -1,2 +1,2 @@
SHA256 (merkaartor-0.18.4.tar.gz) = FueQUHpbtU5LPAnqBj67CVpLAUzoupN7dxcG1MlAl2o=
SIZE (merkaartor-0.18.4.tar.gz) = 6562065
SHA256 (merkaartor-0.19.0.tar.gz) = 9TjR6zgABcvV0EcHCydtpZxYu3/0chjiCggLiT0LpFc=
SIZE (merkaartor-0.19.0.tar.gz) = 5665947

View File

@ -1,14 +0,0 @@
$OpenBSD: patch-interfaces_IProjection_h,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: interfaces/IProjection.h
--- interfaces/IProjection.h.orig
+++ interfaces/IProjection.h
@@ -10,7 +10,7 @@ class IProjection (public)
virtual ~IProjection(void) {};
virtual QPointF project(const QPointF& pt) const = 0;
- virtual QPointF inverse2Point(const QPointF& pt) const = 0;
+ virtual QPointF inverse(const QPointF& pt) const = 0;
virtual QString getProjectionType() const = 0;
};

View File

@ -1,13 +0,0 @@
$OpenBSD: patch-src_Features_Feature_h,v 1.1 2021/01/19 06:44:56 rsadowski Exp $
Index: src/Features/Feature.h
--- src/Features/Feature.h.orig
+++ src/Features/Feature.h
@@ -9,6 +9,7 @@ class Feature;
#include "FeaturePainter.h"
#include <QtCore/QString>
+#include <QPainterPath>
#include <QList>
#define CAST_FEATURE(x) (dynamic_cast<Feature*>(x))

View File

@ -1,15 +0,0 @@
$OpenBSD: patch-src_Features_Node_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/Features/Node.cpp
--- src/Features/Node.cpp.orig
+++ src/Features/Node.cpp
@@ -373,7 +373,8 @@ QString Node::toHtml()
if ((i = findKey("_waypoint_")) != -1)
D += "<p><b>"+QApplication::translate("MapFeature", "Waypoint")+"</b><br/>";
- D += "<i>"+QApplication::translate("MapFeature", "coord")+": </i>" + COORD2STRING(position().y()) + " (" + Coord2Sexa(position().y()) + ") / " + COORD2STRING(position().x()) + " (" + Coord2Sexa(position().x()) + ")";
+ D += "<i>"+QApplication::translate("MapFeature", "WGS84 coordinates")+": </i>" + COORD2STRING(position().y()) + " (" + Coord2Sexa(position().y()) + ") / " + COORD2STRING(position().x()) + " (" + Coord2Sexa(position().x()) + ")<br/>";
+ D += "<i>"+QApplication::translate("MapFeature", "Projected coordinates")+": </i>" + COORD2STRING(projected().y()) + " / " + COORD2STRING(projected().x());
if ((i = findKey("_description_")) != -1)
D += "<br/><i>"+QApplication::translate("MapFeature", "description")+": </i>" + tagValue(i);

View File

@ -1,14 +0,0 @@
$OpenBSD: patch-src_ImportExport_ImportCSVDialog_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/ImportExport/ImportCSVDialog.cpp
--- src/ImportExport/ImportCSVDialog.cpp.orig
+++ src/ImportExport/ImportCSVDialog.cpp
@@ -237,7 +237,7 @@ Feature* ImportCSVDialog::generateOSM(Layer* l, QStrin
if (CSVProjection.projIsLatLong())
N->setPosition(p);
else
- N->setPosition(CSVProjection.inverse2Coord(p));
+ N->setPosition(CSVProjection.inverse(p));
return N;
}

View File

@ -1,38 +0,0 @@
$OpenBSD: patch-src_Layers_ImageMapLayer_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/Layers/ImageMapLayer.cpp
--- src/Layers/ImageMapLayer.cpp.orig
+++ src/Layers/ImageMapLayer.cpp
@@ -97,8 +97,8 @@ CoordBox ImageMapLayer::boundingBox()
p->theProjection.setProjectionType(p->theMapAdapter->projection());
QRectF r = p->theMapAdapter->getBoundingbox();
- Coord tl = p->theProjection.inverse2Coord(r.topLeft());
- Coord br = p->theProjection.inverse2Coord(r.bottomRight());
+ Coord tl = p->theProjection.inverse(r.topLeft());
+ Coord br = p->theProjection.inverse(r.bottomRight());
return CoordBox(tl, br);
}
@@ -691,8 +691,8 @@ QRect ImageMapLayer::drawFull(MapView& theView, QRect&
MapView::transformCalc(p->theTransform, p->theProjection, 0.0, CoordBox(alignedViewport), rect);
- CoordBox cViewport(p->theProjection.inverse2Coord(p->theTransform.inverted().map(fRect.bottomLeft())),
- p->theProjection.inverse2Coord(p->theTransform.inverted().map(fRect.topRight())));
+ CoordBox cViewport(p->theProjection.inverse(p->theTransform.inverted().map(fRect.bottomLeft())),
+ p->theProjection.inverse(p->theTransform.inverted().map(fRect.topRight())));
CoordBox Viewport = CoordBox(p->AlignementTransformList.at(0).mapRect(cViewport));
QPointF bl = theView.toView(Viewport.bottomLeft());
QPointF tr = theView.toView(Viewport.topRight());
@@ -906,8 +906,8 @@ QRect ImageMapLayer::drawTiled(MapView& theView, QRect
QPointF vp0Center = QPointF(projVp.width()/2, -projVp.height()/2);
Coord ulCoord, lrCoord;
- ulCoord = p->theProjection.inverse2Coord(vlm.topLeft());
- lrCoord = p->theProjection.inverse2Coord(vlm.bottomRight());
+ ulCoord = p->theProjection.inverse(vlm.topLeft());
+ lrCoord = p->theProjection.inverse(vlm.bottomRight());
const QPointF tl = theView.transform().map(theView.projection().project(ulCoord));
const QPointF br = theView.transform().map(theView.projection().project(lrCoord));

View File

@ -1,16 +0,0 @@
$OpenBSD: patch-src_Layers_OsmRenderLayer_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/Layers/OsmRenderLayer.cpp
--- src/Layers/OsmRenderLayer.cpp.orig
+++ src/Layers/OsmRenderLayer.cpp
@@ -96,8 +96,8 @@ class RenderTile (public)
projR.setTop(projR.top()+dlat);
projR.setRight(projR.right()+dlon);
- Coord tl = p->theProjection.inverse2Coord(projR.topLeft());
- Coord br = p->theProjection.inverse2Coord(projR.bottomRight());
+ Coord tl = p->theProjection.inverse(projR.topLeft());
+ Coord br = p->theProjection.inverse(projR.bottomRight());
CoordBox invalidRect(tl, br);
QMap<RenderPriority, QSet <Feature*> > theFeatures;

View File

@ -1,29 +0,0 @@
$OpenBSD: patch-src_MainWindow_cpp,v 1.4 2021/04/12 10:17:11 landry Exp $
Index: src/MainWindow.cpp
--- src/MainWindow.cpp.orig
+++ src/MainWindow.cpp
@@ -102,11 +102,7 @@
#include <locale.h>
#include <limits.h>
-//For About
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-#include "proj_api.h"
+#include "proj.h"
#include "gdal_version.h"
#include "Utils/SlippyMapWidget.h"
@@ -2103,8 +2099,8 @@ void MainWindow::on_helpAboutAction_triggered()
dlg.setWindowFlags(dlg.windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
About.Version->setText(About.Version->text().arg(STRINGIFY(REVISION)));
About.QTVersion->setText(About.QTVersion->text().arg(qVersion()).arg(QT_VERSION_STR));
- QString projVer = QString(STRINGIFY(PJ_VERSION));
- About.Proj4Version->setText(About.Proj4Version->text().arg(QString("%1.%2.%3").arg(projVer.left(1)).arg(projVer.mid(1, 1)).arg(projVer.right(1))));
+ PJ_INFO projVer = proj_info();
+ About.ProjVersion->setText(About.ProjVersion->text().arg(QString("%1.%2.%3").arg(projVer.major).arg(projVer.minor).arg(projVer.patch)));
About.GdalVersion->setText(About.GdalVersion->text().arg(GDAL_RELEASE_NAME));
QFile ct(":/Utils/CHANGELOG");

View File

@ -1,28 +0,0 @@
$OpenBSD: patch-src_Main_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/Main.cpp
--- src/Main.cpp.orig
+++ src/Main.cpp
@@ -9,10 +9,7 @@
#include <qtsingleapplication.h>
#include "MainWindow.h"
#include "Preferences/MerkaartorPreferences.h"
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-#include "proj_api.h"
+#include "proj.h"
#include "gdal_version.h"
#include "Global.h"
@@ -140,8 +137,8 @@ int main(int argc, char** argv)
qDebug() << "**** " << QDateTime::currentDateTime().toString(Qt::ISODate) << " -- Starting " << QString("%1 %2").arg(qApp->applicationName()).arg(STRINGIFY(VERSION));
qDebug() << "-------" << QString("using Qt version %1 (built with %2)").arg(qVersion()).arg(QT_VERSION_STR);
- QString projVer = QString(STRINGIFY(PJ_VERSION));
- qDebug() << "-------" << QString("using PROJ4 version %1.%2.%3").arg(projVer.left(1)).arg(projVer.mid(1, 1)).arg(projVer.right(1));
+ PJ_INFO projVer = proj_info();
+ qDebug() << "-------" << QString("using PROJ version %1.%2.%3").arg(projVer.major).arg(projVer.minor).arg(projVer.patch);
qDebug() << "-------" << QString("using GDAL version %1").arg(GDAL_RELEASE_NAME);
qDebug() << "-------" << "with arguments: " << QCoreApplication::arguments();

View File

@ -1,29 +0,0 @@
$OpenBSD: patch-src_common_AboutDialog_ui,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/common/AboutDialog.ui
--- src/common/AboutDialog.ui.orig
+++ src/common/AboutDialog.ui
@@ -31,7 +31,7 @@
<number>-1</number>
</property>
<item row="2" column="1">
- <widget class="QLabel" name="Proj4Version">
+ <widget class="QLabel" name="ProjVersion">
<property name="styleSheet">
<string notr="true">QLabel { font-size:small; font-weight:bold; }</string>
</property>
@@ -91,12 +91,12 @@
</widget>
</item>
<item row="2" column="0">
- <widget class="QLabel" name="Proj4VersionLabel">
+ <widget class="QLabel" name="ProjVersionLabel">
<property name="styleSheet">
<string notr="true">QLabel { font-size: x-small; font-style: italic; }</string>
</property>
<property name="text">
- <string>PROJ.4 version</string>
+ <string>PROJ version</string>
</property>
</widget>
</item>

View File

@ -1,38 +0,0 @@
$OpenBSD: patch-src_common_FeatureManipulations_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/common/FeatureManipulations.cpp
--- src/common/FeatureManipulations.cpp.orig
+++ src/common/FeatureManipulations.cpp
@@ -1658,12 +1658,12 @@ static bool axisAlignPreprocess(/* in */ PropertiesDoc
Node *n1;
Node *n2 = theWay->getNode(0);
QPointF p1;
- QPointF p2 = proj.project(n2);
+ QPointF p2 = proj.project(n2->position());
for (int j = 0; j < theWay->size()-1; ++j, ++i) {
n1 = n2;
n2 = theWay->getNode(j + 1);
p1 = p2;
- p2 = proj.project(n2);
+ p2 = proj.project(n2->position());
if (n1 == n2 || p1 == p2) {
qWarning() << "ERROR: duplicate nodes found during axis align in" << theWay->id().numId;
return false;
@@ -1863,7 +1863,7 @@ AxisAlignResult axisAlignRoads(Document* theDocument,
Node *N = theWay->getNode(i);
if (!dups && node_pos.contains(N) && !(theWay->isClosed() && i == theWay->size()-1))
dups = true;
- node_pos[N] = proj.project(N);
+ node_pos[N] = proj.project(N->position());
}
}
@@ -1983,7 +1983,7 @@ AxisAlignResult axisAlignRoads(Document* theDocument,
foreach (Way *theWay, theWays) {
for (int i = 0; i < theWay->size(); ++i) {
Node *N = theWay->getNode(i);
- theList->add(new MoveNodeCommand(N, proj.inverse2Coord(node_pos[N]), theDocument->getDirtyOrOriginLayer(N->layer())));
+ theList->add(new MoveNodeCommand(N, proj.inverse(node_pos[N]), theDocument->getDirtyOrOriginLayer(N->layer())));
}
}
return AxisAlignSuccess;

View File

@ -1,32 +0,0 @@
$OpenBSD: patch-src_common_MapView_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/common/MapView.cpp
--- src/common/MapView.cpp.orig
+++ src/common/MapView.cpp
@@ -514,7 +514,7 @@ void MapView::drawLatLonGrid(QPainter & P)
continue;
// QPoint pt = QPoint(0, p->theTransform.map(parallelLines.at(i).at(0)).y());
QPoint ptt = pt.toPoint() + QPoint(5, -5);
- P.drawText(ptt, QString("%1").arg(p->theProjection.inverse2Coord(parallelLines.at(i).at(0)).y(), 0, 'f', 2-prec));
+ P.drawText(ptt, QString("%1").arg(p->theProjection.inverse(parallelLines.at(i).at(0)).y(), 0, 'f', 2-prec));
}
for (int i=0; i<medianLines.size(); ++i) {
@@ -534,7 +534,7 @@ void MapView::drawLatLonGrid(QPainter & P)
continue;
// QPoint pt = QPoint(p->theTransform.map(medianLines.at(i).at(0)).x(), 0);
QPoint ptt = pt.toPoint() + QPoint(5, 10);
- P.drawText(ptt, QString("%1").arg(p->theProjection.inverse2Coord(medianLines.at(i).at(0)).x(), 0, 'f', 2-prec));
+ P.drawText(ptt, QString("%1").arg(p->theProjection.inverse(medianLines.at(i).at(0)).x(), 0, 'f', 2-prec));
}
P.restore();
@@ -760,7 +760,7 @@ QPoint MapView::toView(Node* aPt) const
Coord MapView::fromView(const QPoint& aPt) const
{
- return p->theProjection.inverse2Coord(p->theInvertedTransform.map(QPointF(aPt)));
+ return p->theProjection.inverse(p->theInvertedTransform.map(QPointF(aPt)));
}

View File

@ -1,14 +0,0 @@
$OpenBSD: patch-src_common_Painting_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/common/Painting.cpp
--- src/common/Painting.cpp.orig
+++ src/common/Painting.cpp
@@ -160,7 +160,7 @@ void buildPolygonFromRoad(Way *R, Projection const &th
{
for (int i=0; i<R->size(); ++i)
if (R->getNode(i)->isVisible() && !R->getNode(i)->isVirtual())
- Polygon.append(theProjection.project(R->getNode(i)));
+ Polygon.append(theProjection.project(R->getNode(i)->position()));
}
/// draws way with oneway markers

View File

@ -1,370 +0,0 @@
$OpenBSD: patch-src_common_Projection_cpp,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/common/Projection.cpp
--- src/common/Projection.cpp.orig
+++ src/common/Projection.cpp
@@ -12,107 +12,50 @@
#define EQUATORIALMETERHALFCIRCUMFERENCE 20037508.34
#define EQUATORIALMETERPERDEGREE 222638.981555556
-#include "Node.h"
-
-Projection::Projection(void)
+ProjectionBackend::ProjectionBackend(QString initProjection, std::function<QString(QString)> mapProjectionName)
: ProjectionRevision(0)
, IsMercator(false)
, IsLatLong(false)
+ , mapProjectionName(mapProjectionName)
{
-#if defined(Q_OS_WIN) && !defined(_MOBILE)
+
+
+ projCtx = std::shared_ptr<PJ_CONTEXT>(proj_context_create(), proj_context_destroy);
+#if defined(Q_OS_WIN)
QString pdir(QDir::toNativeSeparators(qApp->applicationDirPath() + "/" STRINGIFY(SHARE_DIR) "/proj"));
const char* proj_dir = pdir.toUtf8().constData();
- // const char* proj_dir = "E:\\cbro\\src\\merkaartor-devel\\binaries\\bin\\share\\proj";
- pj_set_searchpath(1, &proj_dir);
+ proj_context_set_search_paths(projCtx.get(), 1, &proj_dir);
#endif // Q_OS_WIN
-
-
-#ifndef _MOBILE
- theProj = NULL;
- theWGS84Proj = Projection::getProjection("+proj=longlat +ellps=WGS84 +datum=WGS84");
- setProjectionType(M_PREFS->getProjectionType());
-#endif
+ projTransform = std::shared_ptr<PJ>(nullptr);
+ projMutex = std::shared_ptr<QMutex>(new QMutex());
+ setProjectionType(initProjection);
}
-Projection::~Projection(void)
+QPointF ProjectionBackend::project(const QPointF & Map) const
{
- /* TODO: pj_free should be called, but it segfaults if two of the same
- * Projection objects have the same projPJ. A better machinism, perhaps
- * projPJ caching, should be provided.
- *
- * In the meantime, pj_free is not called, which does little harm as it's
- * usually called at exit only.
- * */
-#ifndef _MOBILE
- if (theProj) {
- //pj_free(theProj);
- }
-#endif // _MOBILE
-}
-
-QPointF Projection::inverse2Point(const QPointF & Map) const
-{
- if (IsLatLong)
- return latlonInverse(Map);
- else
- if (IsMercator)
- return mercatorInverse(Map);
-#ifndef _MOBILE
- else
- return projInverse(Map);
-#endif
- return QPointF();
-}
-
-QPointF Projection::project(const QPointF & Map) const
-{
if (IsMercator)
return mercatorProject(Map);
- else
- if (IsLatLong)
- return latlonProject(Map);
-#ifndef _MOBILE
- else
- return projProject(Map);
-#endif
- return QPointF();
+ if (IsLatLong)
+ return latlonProject(Map);
+ return projProject(Map);
}
-QPointF Projection::project(Node* aNode) const
+QLineF ProjectionBackend::project(const QLineF & Map) const
{
- return project(aNode->position());
+ return QLineF(project(Map.p1()), project(Map.p2()));
}
-QLineF Projection::project(const QLineF & Map) const
-{
- if (IsMercator)
- return QLineF (mercatorProject(Map.p1()), mercatorProject(Map.p2()));
- else
- if (IsLatLong)
- return QLineF (latlonProject(Map.p1()), latlonProject(Map.p2()));
-#ifndef _MOBILE
- else
- return QLineF(projProject(Map.p1()), projProject(Map.p2()));
-#endif
- return QLineF();
-}
-
-Coord Projection::inverse2Coord(const QPointF & projPoint) const
+QPointF ProjectionBackend::inverse(const QPointF & projPoint) const
{
- if (IsLatLong)
+ if (IsLatLong)
return latlonInverse(projPoint);
- else
- if (IsMercator)
- return mercatorInverse(projPoint);
-#ifndef _MOBILE
- else
- return projInverse(projPoint);
-#endif
- return Coord();
+ if (IsMercator)
+ return mercatorInverse(projPoint);
+ return projInverse(projPoint);
}
-QRectF Projection::toProjectedRectF(const QRectF& Viewport, const QRect& screen) const
+QRectF ProjectionBackend::toProjectedRectF(const QRectF& Viewport, const QRect& screen) const
{
QPointF tl, br;
QRectF pViewport;
@@ -143,88 +86,55 @@ QRectF Projection::toProjectedRectF(const QRectF& View
return pViewport;
}
-CoordBox Projection::fromProjectedRectF(const QRectF& Viewport) const
+CoordBox ProjectionBackend::fromProjectedRectF(const QRectF& Viewport) const
{
Coord tl, br;
CoordBox bbox;
- tl = inverse2Coord(Viewport.topLeft());
- br = inverse2Coord(Viewport.bottomRight());
+ tl = inverse(Viewport.topLeft());
+ br = inverse(Viewport.bottomRight());
bbox = CoordBox(tl, br);
return bbox;
}
-#ifndef _MOBILE
-
-void Projection::projTransform(ProjProjection srcdefn,
- ProjProjection dstdefn,
- long point_count, int point_offset, qreal *x, qreal *y, qreal *z )
+QPointF ProjectionBackend::projProject(const QPointF & Map) const
{
- pj_transform(srcdefn, dstdefn, point_count, point_offset, (double *)x, (double *)y, (double *)z);
+ QMutexLocker locker(projMutex.get());
+ auto trans = proj_trans(projTransform.get(), PJ_DIRECTION::PJ_FWD, {{Map.x(), Map.y(), 0}});
+ //qDebug() << "Project(fromWSG84, " << getProjectionType() << "): " << Map << " -> " << qSetRealNumberPrecision(20) << x << "," << y;
+ return QPointF(trans.xy.x, trans.xy.y);
}
-void Projection::projTransformFromWGS84(long point_count, int point_offset, qreal *x, qreal *y, qreal *z ) const
+Coord ProjectionBackend::projInverse(const QPointF & pProj) const
{
- pj_transform (theWGS84Proj, theProj, point_count, point_offset, (double *)x, (double *)y, (double *)z);
+ QMutexLocker locker(projMutex.get());
+ auto trans = proj_trans(projTransform.get(), PJ_DIRECTION::PJ_INV, {{pProj.x(), pProj.y(), 0}});
+ return Coord(trans.xy.x, trans.xy.y);
}
-void Projection::projTransformToWGS84(long point_count, int point_offset, qreal *x, qreal *y, qreal *z ) const
+bool ProjectionBackend::projIsLatLong() const
{
- pj_transform(theProj, theWGS84Proj, point_count, point_offset, (double *)x, (double *)y, (double *)z);
-}
-
-QPointF Projection::projProject(const QPointF & Map) const
-{
- qreal x = angToRad(Map.x());
- qreal y = angToRad(Map.y());
-
- projTransformFromWGS84(1, 0, &x, &y, NULL);
-
- return QPointF(x, y);
-}
-
-Coord Projection::projInverse(const QPointF & pProj) const
-{
- qreal x = pProj.x();
- qreal y = pProj.y();
-
- projTransformToWGS84(1, 0, &x, &y, NULL);
-
- return Coord(radToAng(x), radToAng(y));
-}
-#endif // _MOBILE
-
-bool Projection::projIsLatLong() const
-{
return IsLatLong;
}
-//bool Projection::projIsMercator()
-//{
-// return IsMercator;
-//}
-
-
-#ifndef _MOBILE
-ProjProjection Projection::getProjection(QString projString)
+PJ* ProjectionBackend::getProjection(QString projString)
{
- ProjProjection theProj = pj_init_plus(QString("%1 +over").arg(projString).toLatin1());
- return theProj;
+ QString WGS84("+proj=longlat +ellps=WGS84 +datum=WGS84 +xy_in=deg");
+ PJ* proj = proj_create_crs_to_crs(projCtx.get(), WGS84.toLatin1(), projString.toLatin1(), 0);
+ if (!proj) {
+ qDebug() << "Failed to initialize projection" << WGS84 << "to" << projString << "with error:" << proj_errno_string(proj_errno(nullptr));
+ }
+ return proj;
}
-#endif // _MOBILE
-bool Projection::setProjectionType(QString aProjectionType)
+bool ProjectionBackend::setProjectionType(QString aProjectionType)
{
+ QMutexLocker locker(projMutex.get());
if (aProjectionType == projType)
return true;
-#ifndef _MOBILE
- if (theProj) {
- pj_free(theProj);
- theProj = NULL;
- }
-#endif // _MOBILE
+ projTransform = nullptr;
ProjectionRevision++;
projType = aProjectionType;
@@ -246,77 +156,60 @@ bool Projection::setProjectionType(QString aProjection
return true;
}
// Hardcode "lat/long " projection
- if (
- projType.toUpper().contains("EPSG:4326")
- )
+ if ( projType.toUpper() == "EPSG:4326" )
{
IsLatLong = true;
projType = "EPSG:4326";
return true;
}
-#ifndef _MOBILE
- try {
- projProj4 = M_PREFS->getProjection(aProjectionType).projection;
- theProj = getProjection(projProj4);
- if (!theProj) {
- projType = "EPSG:3857";
- IsMercator = true;
- return false;
- }
- // else {
- // if (pj_is_latlong(theProj))
- // projType = "EPSG:4326";
- // IsLatLong = true;
- // }
- } catch (...) {
+ projProj4 = mapProjectionName(aProjectionType);
+ projTransform = std::shared_ptr<PJ>(getProjection(projProj4), proj_destroy);
+ if (!projTransform) {
+ // Fall back to the EPSG:3857 and return false. getProjection already logged the error into qDebug().
+ projType = "EPSG:3857";
+ IsMercator = true;
return false;
}
- return (theProj != NULL || IsLatLong || IsMercator);
-#else
- return false;
-#endif // _MOBILE
+ return (projTransform != NULL || IsLatLong || IsMercator);
}
-QString Projection::getProjectionType() const
+QString ProjectionBackend::getProjectionType() const
{
return projType;
}
-QString Projection::getProjectionProj4() const
+QString ProjectionBackend::getProjectionProj4() const
{
- if (IsLatLong)
+ QMutexLocker locker(projMutex.get());
+ if (IsLatLong)
return "+init=EPSG:4326";
- else if (IsMercator)
+ if (IsMercator)
return "+init=EPSG:3857";
-#ifndef _MOBILE
- else
- return QString(pj_get_def(theProj, 0));
-#endif
- return QString();
+ return QString(proj_pj_info(projTransform.get()).definition);
}
-int Projection::projectionRevision() const
+int ProjectionBackend::projectionRevision() const
{
return ProjectionRevision;
}
// Common routines
-qreal Projection::latAnglePerM() const
+qreal ProjectionBackend::latAnglePerM() const
{
qreal LengthOfOneDegreeLat = EQUATORIALRADIUS * M_PI / 180;
return 1 / LengthOfOneDegreeLat;
}
-qreal Projection::lonAnglePerM(qreal Lat) const
+qreal ProjectionBackend::lonAnglePerM(qreal Lat) const
{
qreal LengthOfOneDegreeLat = EQUATORIALRADIUS * M_PI / 180;
qreal LengthOfOneDegreeLon = LengthOfOneDegreeLat * fabs(cos(Lat));
return 1 / LengthOfOneDegreeLon;
}
-bool Projection::toXML(QXmlStreamWriter& stream)
+bool ProjectionBackend::toXML(QXmlStreamWriter& stream)
{
bool OK = true;
@@ -331,7 +224,7 @@ bool Projection::toXML(QXmlStreamWriter& stream)
return OK;
}
-void Projection::fromXML(QXmlStreamReader& stream)
+void ProjectionBackend::fromXML(QXmlStreamReader& stream)
{
if (stream.name() == "Projection") {
QString proj;
@@ -349,7 +242,7 @@ void Projection::fromXML(QXmlStreamReader& stream)
}
}
-QPointF Projection::mercatorProject(const QPointF& c) const
+QPointF ProjectionBackend::mercatorProject(const QPointF& c) const
{
qreal x = c.x() / 180. * EQUATORIALMETERHALFCIRCUMFERENCE;
qreal y = log(tan(angToRad(c.y())) + 1/cos(angToRad(c.y()))) / M_PI * (EQUATORIALMETERHALFCIRCUMFERENCE);
@@ -357,7 +250,7 @@ QPointF Projection::mercatorProject(const QPointF& c)
return QPointF(x, y);
}
-Coord Projection::mercatorInverse(const QPointF& point) const
+Coord ProjectionBackend::mercatorInverse(const QPointF& point) const
{
qreal longitude = point.x()*180.0/EQUATORIALMETERHALFCIRCUMFERENCE;
qreal latitude = radToAng(atan(sinh(point.y()/EQUATORIALMETERHALFCIRCUMFERENCE*M_PI)));

View File

@ -1,123 +0,0 @@
$OpenBSD: patch-src_common_Projection_h,v 1.1 2021/04/12 10:17:11 landry Exp $
Index: src/common/Projection.h
--- src/common/Projection.h.orig
+++ src/common/Projection.h
@@ -4,77 +4,53 @@
#include "IProjection.h"
#include "Coord.h"
-#include <QPointF>
-
-#ifndef _MOBILE
#include "MerkaartorPreferences.h"
-/* TODO: Proj.4 version 6.0.0 introduces new API changes, but is not widely
- * available yet. Until it is available on most distros, we will keep using the legacy API.
- * A migration will eventually be necessary (more research is needed). */
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1
-#include <proj_api.h>
-typedef projPJ ProjProjection;
+#include <QPointF>
+#include <proj.h>
+#include <functional>
+#include <memory>
-#endif // _MOBILE
-
class QRect;
class Node;
-class Projection : public IProjection
+class ProjectionBackend : public IProjection
{
public:
- Projection(void);
- virtual ~Projection(void);
+ ProjectionBackend(QString initProjection, std::function<QString(QString)> mapProjectionName);
qreal latAnglePerM() const;
qreal lonAnglePerM(qreal Lat) const;
QLineF project(const QLineF & Map) const;
QPointF project(const QPointF& Map) const;
- Coord inverse2Coord(const QPointF& Screen) const;
- QPointF inverse2Point(const QPointF& Map) const;
+ QPointF inverse(const QPointF& Map) const;
bool setProjectionType(QString aProjectionType);
QString getProjectionType() const;
bool projIsLatLong() const;
- QPointF project(Node* aNode) const;
QRectF toProjectedRectF(const QRectF& Viewport, const QRect& screen) const;
CoordBox fromProjectedRectF(const QRectF& Viewport) const;
int projectionRevision() const;
QString getProjectionProj4() const;
-#ifndef _MOBILE
-
- static ProjProjection getProjection(QString projString);
- static void projTransform(ProjProjection srcdefn,
- ProjProjection dstdefn,
- long point_count, int point_offset, qreal *x, qreal *y, qreal *z );
- void projTransformToWGS84(long point_count, int point_offset, qreal *x, qreal *y, qreal *z ) const;
- void projTransformFromWGS84(long point_count, int point_offset, qreal *x, qreal *y, qreal *z ) const;
-
-#endif
bool toXML(QXmlStreamWriter& stream);
void fromXML(QXmlStreamReader& stream);
protected:
-#ifndef _MOBILE
- ProjProjection theProj;
+ PJ* getProjection(QString projString);
QPointF projProject(const QPointF& Map) const;
Coord projInverse(const QPointF& Screen) const;
- ProjProjection theWGS84Proj;
-#endif
-
QString projType;
QString projProj4;
QRectF ProjectedViewport;
int ProjectionRevision;
bool IsMercator;
bool IsLatLong;
-
+ std::function<QString(QString)> mapProjectionName;
protected:
QPointF mercatorProject(const QPointF& c) const;
Coord mercatorInverse(const QPointF& point) const;
@@ -88,7 +64,30 @@ class Projection : public IProjection (protected)
{
return Coord(point.x()/*/EQUATORIALMETERPERDEGREE*/, point.y()/*/EQUATORIALMETERPERDEGREE*/);
}
+private:
+ // Note: keep the order of projCtx and projTransform, as projTransform depends on projCtx.
+ std::shared_ptr<PJ_CONTEXT> projCtx;
+ std::shared_ptr<PJ> projTransform;
+ std::shared_ptr<QMutex> projMutex;
+ // TODO: projTransform is not thread-safe by itself, so we need to protect
+ // it by a mutex. In theory, each thread could have it's own projection
+ // object, but currently the object is copied around. Until this changes,
+ // the mutex stays here.
+};
+/**
+ * Proxy class to inject M_PREFS externally and allow unit testing of ProjectionBackend itself.
+ */
+class Projection : public ProjectionBackend {
+ public:
+ static QString mapProjectionName(QString projName) {
+ return M_PREFS->getProjection(projName).projection;
+ }
+
+ Projection(void) :
+ ProjectionBackend(M_PREFS->getProjectionType(), mapProjectionName)
+ {
+ }
};

View File

@ -1,4 +1,4 @@
@comment $OpenBSD: PLIST,v 1.13 2019/11/20 12:57:05 landry Exp $
@comment $OpenBSD: PLIST,v 1.14 2021/09/10 06:45:01 landry Exp $
@bin bin/merkaartor
lib/merkaartor/
lib/merkaartor/plugins/
@ -39,28 +39,25 @@ share/merkaartor/Projections.xml
share/merkaartor/TmsServersList.xml
share/merkaartor/WmsServersList.xml
share/merkaartor/translations/
share/merkaartor/translations/merkaartor_ar.qm
share/merkaartor/translations/merkaartor_cs.qm
share/merkaartor/translations/merkaartor_de.qm
share/merkaartor/translations/merkaartor_de_AT.qm
share/merkaartor/translations/merkaartor_en.qm
share/merkaartor/translations/merkaartor_es.qm
share/merkaartor/translations/merkaartor_et.qm
share/merkaartor/translations/merkaartor_fi.qm
share/merkaartor/translations/merkaartor_fr.qm
share/merkaartor/translations/merkaartor_hr.qm
share/merkaartor/translations/merkaartor_hu.qm
share/merkaartor/translations/merkaartor_id_ID.qm
share/merkaartor/translations/merkaartor_it.qm
share/merkaartor/translations/merkaartor_ja.qm
share/merkaartor/translations/merkaartor_nl.qm
share/merkaartor/translations/merkaartor_pl.qm
share/merkaartor/translations/merkaartor_pt.qm
share/merkaartor/translations/merkaartor_pt_BR.qm
share/merkaartor/translations/merkaartor_ru.qm
share/merkaartor/translations/merkaartor_sk.qm
share/merkaartor/translations/merkaartor_sv.qm
share/merkaartor/translations/merkaartor_uk.qm
share/merkaartor/translations/merkaartor_vi.qm
share/merkaartor/translations/merkaartor_zh_CN.qm
share/merkaartor/translations/merkaartor_zh_TW.qm
share/metainfo/
share/metainfo/org.merkaartor.merkaartor.appdata.xml
@tag gtk-update-icon-cache %D/share/icons/hicolor
@tag update-desktop-database