From 1e1e07855a99318da172dc9bb04c16519aba6e5b Mon Sep 17 00:00:00 2001 From: Matthias Kuehlewein Date: Thu, 6 Jul 2023 10:09:49 +0200 Subject: [PATCH] IofCourseExport: Add 'Map' element The 'Map' element is added to the IOF 3.0 compliant xml export of course data. --- src/fileformats/iof_course_export.cpp | 28 ++++++++++++++++++++++++++- src/fileformats/iof_course_export.h | 6 ++++-- test/data/export/iof-3.0-course.xml | 7 ++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/fileformats/iof_course_export.cpp b/src/fileformats/iof_course_export.cpp index 227cdf67c..1e6744ba5 100644 --- a/src/fileformats/iof_course_export.cpp +++ b/src/fileformats/iof_course_export.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2021 Kai Pastor + * Copyright 2021-2023 Kai Pastor * * This file is part of OpenOrienteering. * @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -97,11 +98,36 @@ void IofCourseExport::writeXml(const PathObject& object) } { XmlElementWriter event(*xml, QLatin1String("RaceCourseData")); + writeMap(); writeControls(object.getRawCoordinateVector()); writeCourse(object.getRawCoordinateVector()); } } +void IofCourseExport::writeMap() +{ + XmlElementWriter map_data(*xml, QLatin1String("Map")); + xml->writeTextElement(QLatin1String("Scale"), QString::number(map->getScaleDenominator())); + + // IOF.xsd proposes for 'MapPositionTopLeft': "The position of the map's top left corner given in the map's coordinate system, usually (0, 0)." + // With this the bottom right position is determined by the (negative) size of the map extent. + // Alternatively use real coordinates from the map_extent structure below. + // NOTE: templates are not considered when determining the map extent. + auto map_extent = map->calculateExtent(true, false, nullptr); + { + XmlElementWriter map_position_topleft(*xml, QLatin1String("MapPositionTopLeft")); + map_position_topleft.writeAttribute(QLatin1String("x"), QString::number(0.0f)); + map_position_topleft.writeAttribute(QLatin1String("y"), QString::number(0.0f)); + map_position_topleft.writeAttribute(QLatin1String("unit"), QLatin1String("mm")); // optional attribute, default is 'mm' + } + { + XmlElementWriter map_position_bottomright(*xml, QLatin1String("MapPositionBottomRight")); + map_position_bottomright.writeAttribute(QLatin1String("x"), QString::number(-map_extent.width())); + map_position_bottomright.writeAttribute(QLatin1String("y"), QString::number(-map_extent.height())); + map_position_bottomright.writeAttribute(QLatin1String("unit"), QLatin1String("mm")); // optional attribute, default is 'mm' + } +} + void IofCourseExport::writeControls(const std::vector& coords) { auto next = [](auto current) { diff --git a/src/fileformats/iof_course_export.h b/src/fileformats/iof_course_export.h index b47b2df85..5c6e8093f 100644 --- a/src/fileformats/iof_course_export.h +++ b/src/fileformats/iof_course_export.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 Kai Pastor + * Copyright 2021-2023 Kai Pastor * * This file is part of OpenOrienteering. * @@ -31,8 +31,8 @@ namespace OpenOrienteering { class LatLon; class Map; -class MapView; class MapCoord; +class MapView; class PathObject; class SimpleCourseExport; @@ -60,6 +60,8 @@ class IofCourseExport : public Exporter void writeXml(const PathObject& object); + void writeMap(); + void writeControls(const std::vector& coords); void writeCourse(const std::vector& coords); diff --git a/test/data/export/iof-3.0-course.xml b/test/data/export/iof-3.0-course.xml index 136965b7f..93311e4ab 100644 --- a/test/data/export/iof-3.0-course.xml +++ b/test/data/export/iof-3.0-course.xml @@ -1,9 +1,14 @@ - + Test event + + 10000 + + + S1