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