Skip to content
Open
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
181 changes: 74 additions & 107 deletions src/gdal/ogr_file_format.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2016-2020 Kai Pastor
* Copyright 2025 Matthias Kühlewein
*
* This file is part of OpenOrienteering.
*
Expand All @@ -26,8 +27,8 @@
#include <functional>
#include <iterator>
#include <memory>
#include <vector>
#include <utility>
#include <vector>

#include <cpl_conv.h>
#include <gdal.h>
Expand Down Expand Up @@ -1972,137 +1973,103 @@ bool OgrFileExport::exportImplementation()

// Setup style table
populateStyleTable(symbols);

auto is_point_object = [](const Object* object) {
const auto* symbol = object->getSymbol();
return symbol && symbol->getContainedTypes() & Symbol::Point;
};

auto is_text_object = [](const Object* object) {
const auto* symbol = object->getSymbol();
return symbol && symbol->getContainedTypes() & Symbol::Text;
};

auto is_line_object = [](const Object* object) {
const auto* symbol = object->getSymbol();
return symbol && (symbol->getType() == Symbol::Line
|| (symbol->getType() == Symbol::Combined && !(symbol->getContainedTypes() & Symbol::Area)));
};

auto is_area_object = [](const Object* object) {
const auto* symbol = object->getSymbol();
return symbol && symbol->getContainedTypes() & Symbol::Area;
};

OGRLayerH layer = nullptr;

enum class ExportMode
{
SingleLayer,
LayerPerSymbol,
LayerPerType
} export_mode = ExportMode::LayerPerType;

if (quirks & SingleLayer)
{
auto layer = createLayer("Layer", wkbUnknown);
export_mode = ExportMode::SingleLayer;
layer = createLayer("Layer", wkbUnknown);
if (layer == nullptr)
throw FileFormatException(tr("Failed to create layer: %2").arg(QString::fromLatin1(CPLGetLastErrorMsg())));

for (auto symbol : symbols)
{
auto match_symbol = [symbol](auto object) { return object->getSymbol() == symbol; };
switch (symbol->getType())
{
case Symbol::Point:
addPointsToLayer(layer, match_symbol);
break;
case Symbol::Text:
addTextToLayer(layer, match_symbol);
break;
case Symbol::Line:
addLinesToLayer(layer, match_symbol);
break;
case Symbol::Combined:
if (!(symbol->getContainedTypes() & Symbol::Area))
{
addLinesToLayer(layer, match_symbol);
break;
}
Q_FALLTHROUGH();
case Symbol::Area:
addAreasToLayer(layer, match_symbol);
break;
case Symbol::NoSymbol:
case Symbol::AllSymbols:
Q_UNREACHABLE();
}
}
}
else if (option(QString::fromLatin1("Per Symbol Layers")).toBool())
{
// Add points, lines, areas in this order for driver compatibility (esp GPX)
for (auto symbol : symbols)
export_mode = ExportMode::LayerPerSymbol;
}

// Add points, lines, areas in this order for driver compatibility (esp GPX)
// First type: points
if (export_mode == ExportMode::LayerPerType)
{
layer = nullptr;
layer = createLayer(QString::fromLatin1("%1_points").arg(info.baseName()).toLatin1(), wkbPoint);
}
for (auto symbol : symbols)
{
if (symbol->getType() == Symbol::Point)
{
if (symbol->getType() == Symbol::Point)
{
auto layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbPoint);
if (layer != nullptr)
addPointsToLayer(layer, [&symbol](const Object* object) {
const auto* sym = object->getSymbol();
return sym == symbol;
});
}
else if (symbol->getType() == Symbol::Text)
if (export_mode == ExportMode::LayerPerSymbol)
{
auto layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbPoint);
if (layer != nullptr)
addTextToLayer(layer, [&symbol](const Object* object) {
const auto* sym = object->getSymbol();
return sym == symbol;
});
layer = nullptr;
layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbPoint);
}
if (layer != nullptr)
addPointsToLayer(layer, [symbol](auto object) { return object->getSymbol() == symbol; });
}

// Line symbols
for (auto symbol : symbols)
}
for (auto symbol : symbols)
{
if (symbol->getType() == Symbol::Text)
{
if (symbol->getType() == Symbol::Line
|| (symbol->getType() == Symbol::Combined && !(symbol->getContainedTypes() & Symbol::Area)))
if (export_mode == ExportMode::LayerPerSymbol)
{
auto layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbLineString);
if (layer != nullptr)
addLinesToLayer(layer, [&symbol](const Object* object) {
const auto* sym = object->getSymbol();
return sym == symbol;
});
layer = nullptr;
layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbPoint);
}
if (layer != nullptr)
addTextToLayer(layer, [symbol](auto object) { return object->getSymbol() == symbol; });
}

// Area symbols
for (auto symbol : symbols)
}

// Second type: lines
if (export_mode == ExportMode::LayerPerType)
{
layer = nullptr;
layer = createLayer(QString::fromLatin1("%1_lines").arg(info.baseName()).toLatin1(), wkbLineString);
}
for (auto symbol : symbols)
{
if (symbol->getType() == Symbol::Line
|| (symbol->getType() == Symbol::Combined && !(symbol->getContainedTypes() & Symbol::Area)))
{
if (symbol->getContainedTypes() & Symbol::Area)
if (export_mode == ExportMode::LayerPerSymbol)
{
auto layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbPolygon);
if (layer != nullptr)
addAreasToLayer(layer, [&symbol](const Object* object) {
const auto* sym = object->getSymbol();
return sym == symbol;
});
layer = nullptr;
layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbLineString);
}
if (layer != nullptr)
addLinesToLayer(layer, [symbol](auto object) { return object->getSymbol() == symbol; });
}
}
else

// Third type: areas
if (export_mode == ExportMode::LayerPerType)
{
layer = nullptr;
layer = createLayer(QString::fromLatin1("%1_areas").arg(info.baseName()).toLatin1(), wkbPolygon);
}
for (auto symbol : symbols)
{
// Add points, lines, areas in this order for driver compatibility (esp GPX)
auto point_layer = createLayer(QString::fromLatin1("%1_points").arg(info.baseName()).toLatin1(), wkbPoint);
if (point_layer != nullptr)
if (symbol->getContainedTypes() & Symbol::Area)
{
addPointsToLayer(point_layer, is_point_object);
addTextToLayer(point_layer, is_text_object);
if (export_mode == ExportMode::LayerPerSymbol)
{
layer = nullptr;
layer = createLayer(QString::fromUtf8("%1_%2").arg(info.baseName(), symbol->getPlainTextName()).toUtf8(), wkbPolygon);
}
if (layer != nullptr)
addAreasToLayer(layer, [symbol](auto object) { return object->getSymbol() == symbol; });
}

auto line_layer = createLayer(QString::fromLatin1("%1_lines").arg(info.baseName()).toLatin1(), wkbLineString);
if (line_layer != nullptr)
addLinesToLayer(line_layer, is_line_object);

auto area_layer = createLayer(QString::fromLatin1("%1_areas").arg(info.baseName()).toLatin1(), wkbPolygon);
if (area_layer != nullptr)
addAreasToLayer(area_layer, is_area_object);
}

return true;
}

Expand Down
50 changes: 50 additions & 0 deletions test/data/helper-hidden-symbols.omap
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<map xmlns="http://openorienteering.org/apps/mapper/xml/v2" version="9">
<notes></notes>
<georeferencing scale="10000" grid_scale_factor="0.9996" auxiliary_scale_factor="1" grivation="-0.01"><projected_crs id="UTM"><spec language="PROJ.4">+proj=utm +datum=WGS84 +zone=32</spec><parameter>32 N</parameter><ref_point x="500745.955034" y="5316300.272828"/></projected_crs><geographic_crs id="Geographic coordinates"><spec language="PROJ.4">+proj=latlong +datum=WGS84</spec><ref_point_deg lat="48" lon="9.01"/></geographic_crs></georeferencing>
<colors count="4">
<color priority="0" name="Black 100%" c="0" m="0" y="0" k="1" opacity="1"><spotcolors><namedcolor>BLACK</namedcolor></spotcolors><cmyk method="custom"/><rgb method="cmyk" r="0" g="0" b="0"/></color>
<color priority="1" name="Green 100%" c="0.76" m="0" y="0.91" k="0" opacity="1"><spotcolors><namedcolor>GREEN</namedcolor></spotcolors><cmyk method="custom"/><rgb method="cmyk" r="0.24" g="1" b="0.09"/></color>
<color priority="2" name="Brown 100%" c="0" m="0.56" y="1" k="0.18" opacity="1"><spotcolors><namedcolor>BROWN</namedcolor></spotcolors><cmyk method="custom"/><rgb method="cmyk" r="0.82" g="0.361" b="0"/></color>
<color priority="3" name="Green 100% for area features" c="0.76" m="0" y="0.91" k="0" opacity="1"><spotcolors knockout="true"><component factor="1" spotcolor="1"/></spotcolors><cmyk method="spotcolor"/><rgb method="spotcolor" r="0.24" g="1" b="0.09"/></color>
</colors>
<barrier version="6" required="0.6.0">
<symbols count="12" id="ISOM 2017-2">
<symbol type="2" id="0" code="101.1" name="Line"><line_symbol color="2" line_width="210" minimum_length="0" join_style="2" cap_style="1" start_offset="0" end_offset="0" segment_length="6000" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="6000" break_length="1500" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="1" mid_symbol_distance="0"><start_symbol><symbol type="1" code="" name="Start symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></start_symbol><mid_symbol><symbol type="1" code="" name="Mid symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></mid_symbol><end_symbol><symbol type="1" code="" name="End symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></end_symbol><dash_symbol><symbol type="1" code="" name="Dash symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></dash_symbol></line_symbol></symbol>
<symbol type="2" id="1" code="101.2" name="Line" is_hidden="true"><line_symbol color="2" line_width="210" minimum_length="0" join_style="2" cap_style="1" start_offset="0" end_offset="0" segment_length="6000" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="6000" break_length="1500" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="1" mid_symbol_distance="0"><start_symbol><symbol type="1" code="" name="Start symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></start_symbol><mid_symbol><symbol type="1" code="" name="Mid symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></mid_symbol><end_symbol><symbol type="1" code="" name="End symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></end_symbol><dash_symbol><symbol type="1" code="" name="Dash symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></dash_symbol></line_symbol></symbol>
<symbol type="2" id="2" code="101.3" name="Line" is_helper_symbol="true"><line_symbol color="2" line_width="210" minimum_length="0" join_style="2" cap_style="1" start_offset="0" end_offset="0" segment_length="6000" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="6000" break_length="1500" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="1" mid_symbol_distance="0"><start_symbol><symbol type="1" code="" name="Start symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></start_symbol><mid_symbol><symbol type="1" code="" name="Mid symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></mid_symbol><end_symbol><symbol type="1" code="" name="End symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></end_symbol><dash_symbol><symbol type="1" code="" name="Dash symbol"><point_symbol rotatable="true" inner_radius="1000" inner_color="-1" outer_width="0" outer_color="-1" elements="0"/></symbol></dash_symbol></line_symbol></symbol>
<symbol type="4" id="3" code="410.1" name="Area"><area_symbol inner_color="3" min_area="675" patterns="0"/></symbol>
<symbol type="4" id="4" code="410.2" name="Area" is_hidden="true"><area_symbol inner_color="3" min_area="675" patterns="0"/></symbol>
<symbol type="4" id="5" code="410.3" name="Area" is_helper_symbol="true"><area_symbol inner_color="3" min_area="675" patterns="0"/></symbol>
<symbol type="1" id="6" code="526" name="Point" is_hidden="true"><point_symbol inner_radius="105" inner_color="0" outer_width="0" outer_color="-1" elements="1"><element><symbol type="1" code=""><point_symbol inner_radius="360" inner_color="-1" outer_width="240" outer_color="0" elements="0"/></symbol><object type="0"><coords count="1">0 0;</coords></object></element></point_symbol></symbol>
<symbol type="1" id="7" code="530" name="Point"><point_symbol inner_radius="360" inner_color="-1" outer_width="240" outer_color="0" elements="0"/></symbol>
<symbol type="1" id="8" code="531" name="Point" is_helper_symbol="true"><point_symbol inner_radius="1500" inner_color="-1" outer_width="0" outer_color="-1" elements="2"><element><symbol type="2" code=""><line_symbol color="0" line_width="240" minimum_length="0" join_style="1" cap_style="0" start_offset="0" end_offset="0" segment_length="6000" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="6000" break_length="1500" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="1" mid_symbol_distance="0"/></symbol><object type="1"><coords count="2">-516 -516;516 516;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object></element><element><symbol type="2" code=""><line_symbol color="0" line_width="240" minimum_length="0" join_style="1" cap_style="0" start_offset="0" end_offset="0" segment_length="6000" end_length="0" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="6000" break_length="1500" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="1" mid_symbol_distance="0"/></symbol><object type="1"><coords count="2">516 -516;-516 516;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object></element></point_symbol></symbol>
<symbol type="8" id="9" code="603.1" name="Text"><text_symbol icon_text="321" rotatable="true"><font family="Sans Serif" size="3143"/><text color="0" line_spacing="1" paragraph_spacing="0" character_spacing="0" kerning="true"/></text_symbol></symbol>
<symbol type="8" id="10" code="603.2" name="Text" is_hidden="true"><text_symbol icon_text="321" rotatable="true"><font family="Sans Serif" size="3143"/><text color="0" line_spacing="1" paragraph_spacing="0" character_spacing="0" kerning="true"/></text_symbol></symbol>
<symbol type="8" id="11" code="603.3" name="Text" is_helper_symbol="true"><text_symbol icon_text="321" rotatable="true"><font family="Sans Serif" size="3143"/><text color="0" line_spacing="1" paragraph_spacing="0" character_spacing="0" kerning="true"/></text_symbol></symbol>
</symbols>
<parts count="1" current="0">
<part name="default part"><objects count="12">
<object type="0" symbol="7"><coords count="1">-40995 -66807;</coords></object>
<object type="0" symbol="6"><coords count="1">-37893 -61525;</coords></object>
<object type="0" symbol="8"><coords count="1">-35119 -56047;</coords></object>
<object type="4" symbol="9" h_align="1" v_align="2"><coords count="1">-33469 -67203;</coords><text>normal</text></object>
<object type="4" symbol="10" h_align="1" v_align="2"><coords count="1">-30169 -61922;</coords><text>hidden</text></object>
<object type="4" symbol="11" h_align="1" v_align="2"><coords count="1">-27462 -56442;</coords><text>helper</text></object>
<object type="1" symbol="5"><coords count="13">-42372 -56765 1;-42785 -55708;-42262 -54517;-41205 -54104 1;-40148 -53692;-38957 -54214;-38544 -55271 1;-38132 -56328;-38654 -57520;-39711 -57932 1;-40768 -58345;-41960 -57822;-42372 -56765 18;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
<object type="1" symbol="4"><coords count="13">-46667 -62647 1;-47105 -61744;-46729 -60658;-45826 -60219 1;-44924 -59781;-43837 -60157;-43399 -61060 1;-42961 -61962;-43337 -63049;-44239 -63487 1;-45142 -63925;-46228 -63549;-46667 -62647 18;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
<object type="1" symbol="3"><coords count="13">-47974 -67595 1;-48360 -66692;-47942 -65647;-47040 -65261 1;-46138 -64874;-45093 -65292;-44706 -66194 1;-44319 -67097;-44737 -68142;-45640 -68528 1;-46542 -68915;-47587 -68497;-47974 -67595 18;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
<object type="1" symbol="0"><coords count="4">-24820 -66754;-22767 -67968;-19779 -66194;-16511 -67501;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
<object type="1" symbol="1"><coords count="4">-23420 -60126;-20526 -61900;-17818 -59939;-14738 -61620;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
<object type="1" symbol="2"><coords count="4">-19499 -54991;-15858 -56578;-13244 -55085;-9976 -56298;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
</objects></part>
</parts>
<templates count="0" first_front_template="0">
<defaults use_meters_per_pixel="true" meters_per_pixel="0" dpi="0" scale="0"/>
</templates>
<view>
<grid color="#646464" display="0" alignment="0" additional_rotation="0" unit="1" h_spacing="500" v_spacing="500" h_offset="0" v_offset="0" snapping_enabled="true"/>
<map_view zoom="2.82843" position_x="-36397" position_y="-44815"><map opacity="1" visible="true"/><templates count="0"/></map_view>
</view>
</barrier>
</map>
Loading