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

Keep orthographic projections consistent #2020

Closed
wants to merge 5 commits into from
Closed
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
14 changes: 14 additions & 0 deletions src/core/georeferencing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ void Georeferencing::load(QXmlStreamReader& xml, bool load_scale_only)
if (language != literal::proj_4)
throw FileFormatException(tr("Unknown CRS specification language: %1").arg(language));
projected_crs_spec = xml.readElementText();
ensureOrthoIsSpheroidal(projected_crs_spec);
}
else if (xml.name() == literal::parameter)
{
Expand Down Expand Up @@ -1239,6 +1240,19 @@ QString Georeferencing::degToDMS(double val)
return ret;
}

void Georeferencing::ensureOrthoIsSpheroidal(QString &spec)
{
const QString ortho_proj = QLatin1String("+proj=ortho ");
auto flattening_param = QLatin1String(" +f=");
auto i = spec.indexOf(ortho_proj);
if (i >= 0 && !spec.contains(flattening_param))
{
auto pos = i + ortho_proj.length() - 1;
// Insert to make "+proj=ortho +f=0", no flattening.
spec.insert(pos, flattening_param + QLatin1String("0"));
}
}

QDebug operator<<(QDebug dbg, const Georeferencing &georef)
{
auto state = [](auto state) -> const char* {
Expand Down
5 changes: 5 additions & 0 deletions src/core/georeferencing.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,11 @@ friend QDebug operator<<(QDebug dbg, const Georeferencing& georef);
*/
static QString degToDMS(double val);

/**
* Ensure specs using ortho projection are explicitly spheroidal.
*/
static void ensureOrthoIsSpheroidal(QString &spec);


/**
* Updates the transformation parameters between map coordinates and
Expand Down
2 changes: 1 addition & 1 deletion src/gdal/ogr_file_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ ogr::unique_srs OgrFileImport::importGeoreferencing(OGRDataSourceH data_source)
auto ortho_georef = Georeferencing();
ortho_georef.setScaleDenominator(int(map->getScaleDenominator()));
ortho_georef.setProjectedCRS(QString{},
QString::fromLatin1("+proj=ortho +datum=WGS84 +ellps=WGS84 +units=m +lat_0=%1 +lon_0=%2 +no_defs")
QString::fromLatin1("+proj=ortho +f=0 +datum=WGS84 +ellps=WGS84 +units=m +lat_0=%1 +lon_0=%2 +no_defs")
.arg(latitude, 0, 'f')
.arg(longitude, 0, 'f') );
ortho_georef.setProjectedRefPoint({}, false, false);
Expand Down
5 changes: 3 additions & 2 deletions src/gdal/ogr_template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,12 @@ std::unique_ptr<Georeferencing> OgrTemplate::makeOrthographicGeoreferencing(cons
/// \todo Use the template's datum etc. instead of WGS84?
auto georef = std::make_unique<Georeferencing>();
georef->setScaleDenominator(int(map->getGeoreferencing().getScaleDenominator()));
georef->setProjectedCRS(QString{}, QStringLiteral("+proj=ortho +datum=WGS84 +ellps=WGS84 +units=m +no_defs"));
georef->setProjectedCRS(QString{}, QStringLiteral("+proj=ortho +f=0 +datum=WGS84 +ellps=WGS84 +units=m +no_defs"));
if (OgrFileImport::checkGeoreferencing(path, *georef))
{
auto center = OgrFileImport::calcAverageLatLon(path);
georef->setProjectedCRS(QString{},
QString::fromLatin1("+proj=ortho +datum=WGS84 +ellps=WGS84 +units=m +lat_0=%1 +lon_0=%2 +no_defs")
QString::fromLatin1("+proj=ortho +f=0 +datum=WGS84 +ellps=WGS84 +units=m +lat_0=%1 +lon_0=%2 +no_defs")
.arg(center.latitude()).arg(center.longitude()));
georef->setProjectedRefPoint({}, false, false);
georef->setCombinedScaleFactor(1.0);
Expand Down Expand Up @@ -573,6 +573,7 @@ bool OgrTemplate::loadTypeSpecificTemplateConfiguration(QXmlStreamReader& xml)
else if (xml.name() == literal::crs_spec)
{
track_crs_spec = xml.readElementText();
Georeferencing::ensureOrthoIsSpheroidal(track_crs_spec);
template_track_compatibility = true;
}
else if (xml.name() == literal::projected_crs_spec)
Expand Down
1 change: 1 addition & 0 deletions src/gui/georeferencing_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ void GeoreferencingDialog::crsEdited()
Q_ASSERT(crs_template);
if (spec.isEmpty())
spec = QStringLiteral(" "); // intentionally non-empty: enforce non-local state.
Georeferencing::ensureOrthoIsSpheroidal(spec);
georef_copy.setProjectedCRS(crs_template->id(), spec, crs_selector->parameters());
Q_ASSERT(georef_copy.getState() != Georeferencing::Local);
if (keep_geographic_radio->isChecked())
Expand Down
1 change: 1 addition & 0 deletions src/templates/template_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ bool TemplateImage::loadTypeSpecificTemplateConfiguration(QXmlStreamReader& xml)
{
/// \todo check specification language
available_georef.effective.crs_spec = xml.readElementText();
Georeferencing::ensureOrthoIsSpheroidal(available_georef.effective.crs_spec);
}
else
xml.skipCurrentElement(); // unsupported
Expand Down
3 changes: 2 additions & 1 deletion src/templates/template_track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ bool TemplateTrack::loadTypeSpecificTemplateConfiguration(QXmlStreamReader& xml)
if (xml.name() == QLatin1String("crs_spec"))
{
track_crs_spec = xml.readElementText();
Georeferencing::ensureOrthoIsSpheroidal(track_crs_spec);
}
else if (xml.name() == QLatin1String("projected_crs_spec"))
{
Expand Down Expand Up @@ -601,7 +602,7 @@ void TemplateTrack::updateGeoreferencing()
QString TemplateTrack::calculateLocalGeoreferencing() const
{
LatLon proj_center = track.calcAveragePosition();
return QString::fromLatin1("+proj=ortho +datum=WGS84 +lat_0=%1 +lon_0=%2")
return QString::fromLatin1("+proj=ortho +f=0 +datum=WGS84 +lat_0=%1 +lon_0=%2")
.arg(proj_center.latitude(), 0, 'f')
.arg(proj_center.longitude(), 0, 'f');

Expand Down
92 changes: 92 additions & 0 deletions test/data/templates/template-track-ortho.xmap
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://openorienteering.org/apps/mapper/xml/v2" version="9">
<notes>This map to demonstrate issue GH-2016, trimmed for testing purposes.
In order to get an orthographic projection, this map was initially created by import from a .osm map similar to 'map.osm', but in the region of template-track.gpx.
Then the OpenStreetMap objects were deleted, and the template-track.xmap was imported to get its line objects. Templates were added for template-track.gpx so that template_t.cpp could easily be expanded to validate the handling of this projection.</notes>
<georeferencing scale="10000" auxiliary_scale_factor="1.000738">
<projected_crs>
<spec language="PROJ.4">+proj=ortho +datum=WGS84 +ellps=WGS84 +units=m +lat_0=51.394000 +lon_0=21.199000 +no_defs</spec>
</projected_crs>
<geographic_crs id="Geographic coordinates">
<spec language="PROJ.4">+proj=latlong +datum=WGS84</spec>
<ref_point_deg lat="51.394" lon="21.199"/>
</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="40" minimum_length="0" join_style="1" cap_style="0" start_offset="0" end_offset="0" segment_length="1600" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="1600" break_length="400" dashes_in_group="1" in_group_break_length="200" mid_symbols_per_spot="1" mid_symbol_distance="0"/>
</symbol>
</symbols>
<parts count="1" current="0">
<part name="default part">
<objects count="4">
<object type="1" symbol="0">
<coords count="2">
<coord x="-385441" y="-4732"/>
<coord x="-382440" y="-4643"/>
</coords>
<pattern rotation="0">
<coord x="-318340" y="163259"/>
</pattern>
</object>
<object type="1" symbol="0">
<coords count="2">
<coord x="-385495" y="-2685"/>
<coord x="-382486" y="-2596"/>
</coords>
<pattern rotation="0">
<coord x="-318340" y="163259"/>
</pattern>
</object>
<object type="1" symbol="0">
<coords count="2">
<coord x="-385322" y="-2509"/>
<coord x="-385253" y="-4896" flags="16"/>
</coords>
<pattern rotation="0">
<coord x="-318340" y="163259"/>
</pattern>
</object>
<object type="1" symbol="0">
<coords count="2">
<coord x="-382685" y="-2433"/>
<coord x="-382615" y="-4828"/>
</coords>
<pattern rotation="0">
<coord x="-318340" y="163259"/>
</pattern>
</object>
</objects>
</part>
</parts>
<templates count="2" first_front_template="0">
<template type="TemplateTrack" open="true" name="template-track.gpx" path="/home/scott/mapper/work/test/data/templates/template-track.gpx" relpath="template-track.gpx" georef="true">
<crs_spec>+proj=latlong +datum=WGS84</crs_spec>
</template>
<template type="TemplateTrack" open="true" name="template-track.gpx" path="/home/scott/mapper/work/test/data/templates/template-track.gpx" relpath="template-track.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="1" h_spacing="1" v_spacing="1" h_offset="0" v_offset="0" snapping_enabled="true"/>
<map_view zoom="32" position_x="-383674" position_y="-3816">
<map opacity="1" visible="true"/>
<templates count="2">
<ref template="0" visible="true" opacity="1"/>
<ref template="1" visible="true" opacity="1"/>
</templates>
</map_view>
</view>
</barrier>
</map>
4 changes: 4 additions & 0 deletions test/template_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ private slots:
QTest::newRow("OgrTemplate NAD83") << QStringLiteral("testdata:templates/template-track-NA.xmap") << 1;
QTest::newRow("TemplateTrack from v0.8.4") << QStringLiteral("testdata:templates/template-track-NA-084.xmap") << 0;
QTest::newRow("TemplateTrack from v0.9.3") << QStringLiteral("testdata:templates/template-track-NA-093-PROJ.xmap") << 0;
QTest::newRow("TemplateTrack ortho") << QStringLiteral("testdata:templates/template-track-ortho.xmap") << 0;
QTest::newRow("OgrTemplate ortho") << QStringLiteral("testdata:templates/template-track-ortho.xmap") << 1;
}

void templateTrackTest()
Expand Down Expand Up @@ -476,6 +478,8 @@ private slots:
QTest::newRow("OgrTemplate NAD83") << QStringLiteral("testdata:templates/template-track-NA.xmap") << 1;
QTest::newRow("TemplateTrack from v0.8.4") << QStringLiteral("testdata:templates/template-track-NA-084.xmap") << 0;
QTest::newRow("OGRTemplate from v0.9.3") << QStringLiteral("testdata:templates/template-track-NA-093-GDAL.xmap") << 0;
QTest::newRow("TemplateTrack ortho") << QStringLiteral("testdata:templates/template-track-ortho.xmap") << 0;
QTest::newRow("OgrTemplate ortho") << QStringLiteral("testdata:templates/template-track-ortho.xmap") << 1;
}

void ogrTemplateTest()
Expand Down