Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WGS84 (G2139) as the geographic CRS #2205

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 193 additions & 112 deletions src/core/georeferencing.cpp

Large diffs are not rendered by default.

77 changes: 65 additions & 12 deletions src/core/georeferencing.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,35 +47,47 @@ namespace OpenOrienteering {


/**
* A utility which encapsulates PROJ API variants and resource management.
* Utilities which encapsulate PROJ API variants and resource management.
*/
struct ProjCRS
{
ProjCRS(const ProjCRS&) = delete;
ProjCRS(ProjCRS&& other) noexcept;
ProjCRS(const QString& crs_spec);
~ProjCRS();

ProjCRS& operator=(const ProjCRS& other) = delete;
ProjCRS& operator=(ProjCRS&& other) noexcept;

bool isValid() const noexcept;
bool isGeographic() const;
private:
ProjTransformData* pj = nullptr;

friend struct ProjTransform;
};

struct ProjTransform
{
ProjTransform() noexcept = default;
ProjTransform() noexcept;
ProjTransform(const ProjTransform&) = delete;
ProjTransform(ProjTransform&& other) noexcept;
ProjTransform(const QString& crs_spec);
ProjTransform(const QString& crs_spec, const QString& geographic_crs_spec);
~ProjTransform();

ProjTransform& operator=(const ProjTransform& other) = delete;
ProjTransform& operator=(ProjTransform&& other) noexcept;

/// Create a PROJ CRS object.
static ProjTransform crs(const QString& crs_spec);

bool isValid() const noexcept;
bool isGeographic() const;

QPointF forward(const LatLon& lat_lon, bool* ok) const;
LatLon inverse(const QPointF& projected, bool* ok) const;

QString errorText() const;

private:
ProjTransform(ProjTransformData* pj) noexcept;

ProjTransformData* pj = nullptr;

ProjCRS geographic_crs;
};


Expand Down Expand Up @@ -133,7 +145,7 @@ friend QDebug operator<<(QDebug dbg, const Georeferencing& georef);
/**
* A shared PROJ specification of a WGS84 geographic CRS.
*/
static const QString geographic_crs_spec;
static const QString ballpark_geographic_crs_spec;


/**
Expand Down Expand Up @@ -427,6 +439,38 @@ friend QDebug operator<<(QDebug dbg, const Georeferencing& georef);
*/
bool setProjectedCRS(const QString& id, QString spec, std::vector< QString > params = std::vector<QString>());

/**
* Returns the specification of the WGS84-based geographic coordinate
* reference system (CRS) used by Georeferencing.
* This is the target CRS of the toGeographicCoords methods,
* and also the source CRS when applicable.
* @return a PROJ specification of the geographic CRS
*/
const QString& getGeographicCRSSpec() const { return realization_crs_spec.isEmpty()
? ballpark_geographic_crs_spec
: realization_crs_spec; }

/**
* Returns whether transformations use loose accuracy around the WGS84
* datum for explicitly requested compatibility with older releases of Mapper.
* @return true if transformations are set compatible, false otherwise
*/
bool isDatumBallpark() const { return explicit_realization && realization_crs_spec.isEmpty(); }

/**
* Sets the coordinate reference system (CRS) of the geographical coordinates,
* to either the ballpark CRS or the GNSS CRS.
*
* This setting determines the "pivot" coordinates used to transform one pair
* of projected coordinates to another, also the transformation of map
* coordinates to geographical, also transformation of GNSS coordinates to
* map coordinates.
*
* @param ballpark whether to make the datum "ballpark", otherwise make it a realization of WGS84
* @return true if the resulting transformation is valid, false otherwise
*/
bool setDatumBallpark(bool ballpark);

/**
* Calculates the convergence at the reference point.
*
Expand Down Expand Up @@ -480,7 +524,8 @@ friend QDebug operator<<(QDebug dbg, const Georeferencing& georef);
LatLon toGeographicCoords(const MapCoordF& map_coords, bool* ok = 0) const;

/**
* Transforms CRS coordinates to geographic coordinates (lat/lon).
* Transforms CRS coordinates to geographic coordinates (lat/lon)
* using a WGS84 datum.
*/
LatLon toGeographicCoords(const QPointF& projected_coords, bool* ok = 0) const;

Expand Down Expand Up @@ -632,6 +677,11 @@ friend QDebug operator<<(QDebug dbg, const Georeferencing& georef);
void setScaleFactors(double combined_scale_factor, double auxiliary_scale_factor);
void setDeclinationAndGrivation(double declination, double grivation);

/**
* PROJ specification of an accurate realization of the WGS84 geographic CRS.
*/
static const QString gnss_crs_spec;

State state;

unsigned int scale_denominator;
Expand Down Expand Up @@ -672,6 +722,9 @@ friend QDebug operator<<(QDebug dbg, const Georeferencing& georef);
QString projected_crs_id;
QString projected_crs_spec;
std::vector< QString > projected_crs_parameters;

QString realization_crs_spec;
bool explicit_realization;

ProjTransform proj_transform;

Expand Down
9 changes: 9 additions & 0 deletions src/fileformats/xml_file_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,15 @@ void XMLFileImporter::validateGeoreferencing()
auto const& loaded_georef = map->getGeoreferencing();
if (loaded_georef.getState() != Georeferencing::Geospatial)
return;

// Check for 'is_realization' not set.
if (!loaded_georef.isDatumBallpark()
&& Georeferencing::ballpark_geographic_crs_spec == loaded_georef.getGeographicCRSSpec())
{
addWarning(tr("This map was saved by an older version of Mapper, "
"with less accurate template alignment.\n\n"
"Adjust Georeferencing to confirm or change."));
}

// Check for georeferencings with inconsistent declination/grivation,
// e.g. from GH-1206 (georef setup bug)
Expand Down
16 changes: 16 additions & 0 deletions src/gdal/ogr_file_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,22 @@ bool OgrFileImport::setSRS(OGRSpatialReferenceH srs)
if (srs && data_srs != srs)
{
// New SRS, indeed.
auto& georef = map->getGeoreferencing();
if (OSRIsGeographic(srs) && !georef.isDatumBallpark())
{
auto ballpark_srs = ogr::unique_srs { OSRNewSpatialReference(nullptr) };
OSRSetWellKnownGeogCS(ballpark_srs.get(), "WGS84");

if (!strcmp(OSRGetAuthorityName(srs, nullptr), OSRGetAuthorityName(ballpark_srs.get(), nullptr))
&& !strcmp(OSRGetAuthorityCode(srs, nullptr), OSRGetAuthorityCode(ballpark_srs.get(), nullptr)))
{
// Substitute an accurate, recent realization of WGS84.
auto gnss_srs = ogr::unique_srs { OSRNewSpatialReference(nullptr) };
OSRSetWellKnownGeogCS(gnss_srs.get(), georef.getGeographicCRSSpec().toUtf8());
OSRCopyGeogCSFrom(srs, gnss_srs.get());
}
}

auto transformation = ogr::unique_transformation{ OCTNewCoordinateTransformation(srs, map_srs.get()) };
if (!transformation)
{
Expand Down
6 changes: 3 additions & 3 deletions src/gdal/ogr_template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ try
{
is_georeferenced = true;
// Data is to be transformed to the map CRS directly.
track_crs_spec = Georeferencing::geographic_crs_spec;
track_crs_spec = georef.getGeographicCRSSpec();
return true;
}
}
Expand All @@ -318,7 +318,7 @@ try
preserveRefPoints(*data_georef, initial_georef);
explicit_georef = std::move(data_georef);
// Data is to be transformed to the projected CRS.
track_crs_spec = Georeferencing::geographic_crs_spec;
track_crs_spec = explicit_georef->getGeographicCRSSpec();
projected_crs_spec = explicit_georef->getProjectedCRSSpec();
}

Expand Down Expand Up @@ -600,7 +600,7 @@ bool OgrTemplate::finishTypeSpecificTemplateConfiguration()
// Data is to be transformed to the map CRS directly.
Q_ASSERT(projected_crs_spec.isEmpty());
}
else if (!track_crs_spec.contains(QLatin1String("+proj=latlong")))
else if (!ProjCRS(track_crs_spec).isGeographic())
{
// Nothing to do with this configuration
Q_ASSERT(projected_crs_spec.isEmpty());
Expand Down
20 changes: 20 additions & 0 deletions src/gui/map/map_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2370,6 +2370,26 @@ void MapEditorController::showTagsWindow(bool show)

void MapEditorController::editGeoreferencing()
{
// Check for 'is_realization' not set.
const Georeferencing& georef = getMap()->getGeoreferencing();
if (georef.getState() == Georeferencing::Geospatial
&& !georef.isDatumBallpark()
&& Georeferencing::ballpark_geographic_crs_spec == georef.getGeographicCRSSpec())
{
auto message =
tr("This map was saved by an older version of Mapper, "
"with less accurate template alignment.\n\n"
"Press Yes for more accurate alignment.\n"
"Press No to retain template alignment.");
int result = QMessageBox::question(getWindow(), tr("Warning"), message, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes);
if (QMessageBox::Yes == result || QMessageBox::No == result)
{
auto local_georef = Georeferencing(georef);
local_georef.setDatumBallpark(QMessageBox::No == result);
map->setGeoreferencing(local_georef);
}
}

if (georeferencing_dialog.isNull())
{
auto* dialog = new GeoreferencingDialog(this);
Expand Down
4 changes: 2 additions & 2 deletions src/gui/select_crs_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ SelectCRSDialog::SelectCRSDialog(
crs_selector->setCurrentIndex(crs_selector->findData(SpecialCRS::TemplateFile));
else if (crs_spec == georef.getProjectedCRSSpec())
crs_selector->setCurrentIndex(crs_selector->findData(SpecialCRS::SameAsMap));
else if (crs_spec == Georeferencing::geographic_crs_spec)
else if (crs_spec == georef.getGeographicCRSSpec())
crs_selector->setCurrentIndex(crs_selector->findData(SpecialCRS::Geographic));
else
crs_selector->setCurrentCRS(CRSTemplateRegistry().find(QString::fromLatin1("PROJ.4")), { crs_spec });
Expand Down Expand Up @@ -130,7 +130,7 @@ QString SelectCRSDialog::currentCRSSpec() const
// nothing
break;
case SpecialCRS::Geographic:
spec = Georeferencing::geographic_crs_spec;
spec = georef.getGeographicCRSSpec();
break;
case SpecialCRS::TemplateFile:
spec = options.template_file.crs_spec;
Expand Down
6 changes: 3 additions & 3 deletions src/templates/template_track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ TemplateTrack::TemplateTrack(const QString& path, Map* map)
: Template(path, map)
{
// set default value
track_crs_spec = Georeferencing::geographic_crs_spec;
track_crs_spec = Georeferencing::ballpark_geographic_crs_spec;

const Georeferencing& georef = map->getGeoreferencing();
connect(&georef, &Georeferencing::projectionChanged, this, &TemplateTrack::updateGeoreferencing);
Expand Down Expand Up @@ -257,7 +257,7 @@ bool TemplateTrack::loadTemplateFileImpl()
return false;
}

if (!track_crs_spec.isEmpty() && track_crs_spec != Georeferencing::geographic_crs_spec)
if (!track_crs_spec.isEmpty() && track_crs_spec != Georeferencing::ballpark_geographic_crs_spec)
{
setErrorString(tr("This template must be loaded with GDAL/OGR."));
return false;
Expand Down Expand Up @@ -580,7 +580,7 @@ void TemplateTrack::configureForGPSTrack()
{
is_georeferenced = true;

track_crs_spec = Georeferencing::geographic_crs_spec;
track_crs_spec = Georeferencing::ballpark_geographic_crs_spec;

projected_crs_spec.clear();
track.changeMapGeoreferencing(map->getGeoreferencing());
Expand Down
1 change: 1 addition & 0 deletions test/data/templates/geotiff.xmap
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<realization_spec language="PROJ.4">EPSG:9057</realization_spec>
<ref_point_deg lat="51.3793253" lon="21.15318339"/>
</geographic_crs>
</georeferencing>
Expand Down
1 change: 1 addition & 0 deletions test/data/templates/ogr-template.xmap
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<realization_spec language="PROJ.4">EPSG:9057</realization_spec>
<ref_point_deg lat="51.3793253" lon="21.15318339"/>
</geographic_crs>
</georeferencing>
Expand Down
65 changes: 65 additions & 0 deletions test/data/templates/template-track-NA-ballpark-GDAL.xmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://openorienteering.org/apps/mapper/xml/v2" version="9">
<notes></notes>
<georeferencing scale="4000" auxiliary_scale_factor="1.0004" declination="8" grivation="8">
<projected_crs id="EPSG">
<spec language="PROJ.4">+init=epsg:6342</spec>
<parameter>6342</parameter>
<ref_point x="500000" y="4430000"/>
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<realization_spec/>
<ref_point_deg lat="40.02021349" lon="-105.00001013"/>
</geographic_crs>
</georeferencing>
<colors count="1">
<color priority="0" name="Purple" c="0.2" m="1" y="0" k="0" opacity="1">
<spotcolors>
<namedcolor>PURPLE</namedcolor>
</spotcolors>
<cmyk method="custom"/>
<rgb method="cmyk" r="0.8" g="0" b="1"/>
</color>
</colors>
<barrier version="6" required="0.6.0">
<symbols count="1">
<symbol type="2" id="0" code="1" name="Line">
<line_symbol color="0" line_width="100" minimum_length="0" join_style="1" cap_style="0" start_offset="0" end_offset="0" segment_length="4000" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="4000" break_length="1000" dashes_in_group="1" in_group_break_length="500" mid_symbols_per_spot="1" mid_symbol_distance="0"/>
</symbol>
</symbols>
<parts count="1" current="0">
<part name="default part">
<objects count="1">
<object type="1" symbol="0">
<coords count="5">
<coord x="-158217" y="170205"/>
<coord x="-157505" y="175272"/>
<coord x="-150981" y="174356"/>
<coord x="-151693" y="169288"/>
<coord x="-158217" y="170205" flags="18"/>
</coords>
<pattern rotation="0">
<coord x="0" y="0"/>
</pattern>
</object>
</objects>
</part>
</parts>
<templates count="1" first_front_template="1">
<template type="OgrTemplate" open="true" name="template-track-NA-2019.gpx" path="template-track-NA-2019.gpx" relpath="template-track-NA-2019.gpx" georef="true">
<crs_spec>+proj=latlong +datum=WGS84</crs_spec>
</template>
<defaults use_meters_per_pixel="true" meters_per_pixel="0" dpi="0" scale="0"/>
</templates>
<view>
<grid color="#646464" display="0" alignment="1" additional_rotation="0" unit="0" h_spacing="0.1" v_spacing="0.1" h_offset="0" v_offset="0" snapping_enabled="true"/>
<map_view zoom="32" position_x="-154564" position_y="171849">
<map opacity="1" visible="true"/>
<templates count="1">
<ref template="0" visible="true" opacity="1"/>
</templates>
</map_view>
</view>
</barrier>
</map>
1 change: 1 addition & 0 deletions test/data/templates/template-track-NA.xmap
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<realization_spec language="PROJ.4">EPSG:9057</realization_spec>
<ref_point_deg lat="40.02021349" lon="-105.00001013"/>
</geographic_crs>
</georeferencing>
Expand Down
1 change: 1 addition & 0 deletions test/data/templates/template-track.xmap
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<realization_spec language="PROJ.4">EPSG:9057</realization_spec>
<ref_point_deg lat="51.3793253" lon="21.15318339"/>
</geographic_crs>
</georeferencing>
Expand Down
1 change: 1 addition & 0 deletions test/data/templates/world-file.xmap
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<realization_spec language="PROJ.4">EPSG:9057</realization_spec>
<ref_point_deg lat="51.3793253" lon="21.15318339"/>
</geographic_crs>
</georeferencing>
Expand Down
1 change: 1 addition & 0 deletions test/file_format_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ namespace
QCOMPARE(actual_georef.getProjectedCRSName(), expected_georef.getProjectedCRSName());
QCOMPARE(actual_georef.getProjectedCoordinatesName(), expected_georef.getProjectedCoordinatesName());
QCOMPARE(actual_georef.getProjectedCRSSpec(), expected_georef.getProjectedCRSSpec());
QCOMPARE(actual_georef.getGeographicCRSSpec(), expected_georef.getGeographicCRSSpec());
QVERIFY(qAbs(actual_georef.getGeographicRefPoint().latitude() - expected_georef.getGeographicRefPoint().latitude()) < 0.5e-8);
QVERIFY(qAbs(actual_georef.getGeographicRefPoint().longitude() - expected_georef.getGeographicRefPoint().longitude()) < 0.5e-8);

Expand Down
Loading