Skip to content

Commit df82f78

Browse files
dl3sdodg0yt
andauthored
LineSymbol: Fix dashed line with mid symbols (GH-2099)
Correctly draw whole line segments (i.e. dashes) in the same way as if there were no mid symbols. Simplify outputting od mid symbols. Add a rendering test to cover relevant code. Closes GH-2064 (unexpected curve around mid symbol of dashed line). --------- Co-authored-by: Kai Pastor <[email protected]>
1 parent 6bdf26f commit df82f78

File tree

4 files changed

+51
-29
lines changed

4 files changed

+51
-29
lines changed

src/core/symbols/line_symbol.cpp

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright 2012, 2013 Thomas Schöps
3-
* Copyright 2012-2020 Kai Pastor
3+
* Copyright 2012-2020, 2024, 2025 Kai Pastor
44
*
55
* This file is part of OpenOrienteering.
66
*
@@ -792,42 +792,35 @@ void LineSymbol::processContinuousLine(
792792
MapCoordVectorF& processed_coords,
793793
ObjectRenderables& output ) const
794794
{
795-
auto mid_symbol_distance_f = length_type(0.001) * mid_symbol_distance;
796-
auto mid_symbols_length = (qMax(1, mid_symbols_per_spot) - 1) * mid_symbol_distance_f;
797-
auto effective_end_length = end.clen;
798-
799-
auto split = start;
795+
path.copy(start, end, processed_flags, processed_coords);
796+
processed_flags.back().setGapPoint(true);
797+
Q_ASSERT(!processed_flags[processed_flags.size()-2].isCurveStart());
800798

801799
set_mid_symbols = set_mid_symbols && mid_symbol && !mid_symbol->isEmpty() && mid_symbols_per_spot;
802-
if (set_mid_symbols && mid_symbols_length <= effective_end_length - split.clen)
800+
if (!set_mid_symbols)
801+
return;
802+
803+
const auto mid_symbol_distance_f = length_type(0.001) * mid_symbol_distance;
804+
const auto mid_symbols_length = (qMax(1, mid_symbols_per_spot) - 1) * mid_symbol_distance_f;
805+
if (mid_symbols_length <= end.clen - start.clen)
803806
{
804-
auto mid_position = (split.clen + effective_end_length - mid_symbols_length) / 2;
805-
auto next_split = SplitPathCoord::at(mid_position, split);
806-
path.copy(split, next_split, processed_flags, processed_coords);
807-
split = next_split;
807+
const auto mid_symbol_rotatable = mid_symbol->isRotatable();
808808

809+
auto mid_position = (start.clen + end.clen - mid_symbols_length) / 2;
810+
auto next_split = SplitPathCoord::at(mid_position, start);
809811
auto orientation = qreal(0);
810-
bool mid_symbol_rotatable = bool(mid_symbol) && mid_symbol->isRotatable();
811-
for (auto i = mid_symbols_per_spot; i > 0; --i)
812+
if (mid_symbol_rotatable)
813+
orientation = next_split.tangentVector().angle();
814+
mid_symbol->createRenderablesScaled(next_split.pos, orientation, output);
815+
for (auto i = 2; i <= mid_symbols_per_spot; ++i)
812816
{
817+
mid_position += mid_symbol_distance_f;
818+
next_split = SplitPathCoord::at(mid_position, next_split);
813819
if (mid_symbol_rotatable)
814-
orientation = split.tangentVector().angle();
815-
mid_symbol->createRenderablesScaled(split.pos, orientation, output);
816-
817-
if (i > 1)
818-
{
819-
mid_position += mid_symbol_distance_f;
820-
next_split = SplitPathCoord::at(mid_position, split);
821-
path.copy(split, next_split, processed_flags, processed_coords);
822-
split = next_split;
823-
}
820+
orientation = next_split.tangentVector().angle();
821+
mid_symbol->createRenderablesScaled(next_split.pos, orientation, output);
824822
}
825823
}
826-
827-
path.copy(split, end, processed_flags, processed_coords);
828-
829-
processed_flags.back().setGapPoint(true);
830-
Q_ASSERT(!processed_flags[processed_flags.size()-2].isCurveStart());
831824
}
832825

833826
void LineSymbol::createPointedLineCap(
@@ -1201,7 +1194,7 @@ SplitPathCoord LineSymbol::createDashGroups(
12011194
bool is_first_dash = is_first_dashgroup && dash == 1;
12021195
bool is_last_dash = is_last_dashgroup && dash == dashes_in_group;
12031196

1204-
// The dash has an start if it is not the first dash in a half first group.
1197+
// The dash has a start if it is not the first dash in a half first group.
12051198
bool has_start = !(is_first_dash && half_first_group);
12061199
// The dash has an end if it is not the last dash in a half last group.
12071200
bool has_end = !(is_last_dash && half_last_group);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<map xmlns="http://openorienteering.org/apps/mapper/xml/v2" version="9">
3+
<notes></notes>
4+
<georeferencing scale="10000"><projected_crs id="Local"/></georeferencing>
5+
<colors count="1">
6+
<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>
7+
</colors>
8+
<barrier version="6" required="0.6.0">
9+
<symbols count="2">
10+
<symbol type="2" id="0" code="1" name="A"><line_symbol color="0" line_width="210" minimum_length="5475" join_style="1" cap_style="0" start_offset="0" end_offset="0" dashed="true" segment_length="3750" end_length="1875" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="3000" break_length="525" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="2" mid_symbol_distance="1500"><mid_symbol><symbol type="1" code="" name="Mid symbol"><point_symbol rotatable="true" inner_radius="300" inner_color="0" outer_width="0" outer_color="-1" elements="0"/></symbol></mid_symbol></line_symbol></symbol>
11+
<symbol type="2" id="1" code="2" name="B"><line_symbol color="0" line_width="50" minimum_length="5475" join_style="1" cap_style="0" start_offset="0" end_offset="0" dashed="true" segment_length="3750" end_length="1875" show_at_least_one_symbol="true" minimum_mid_symbol_count="0" minimum_mid_symbol_count_when_closed="0" dash_length="3000" break_length="525" dashes_in_group="1" in_group_break_length="750" mid_symbols_per_spot="1" mid_symbol_distance="0"><mid_symbol><symbol type="1" code="" name="Mid symbol"><point_symbol rotatable="true" inner_radius="1500" inner_color="-1" outer_width="0" outer_color="-1" elements="1"><element><symbol type="2" code=""><line_symbol color="0" line_width="50" 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">0 0;375 650;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object></element></point_symbol></symbol></mid_symbol></line_symbol></symbol>
12+
</symbols>
13+
<parts count="1" current="0">
14+
<part name="default part"><objects count="2">
15+
<object type="1" symbol="0"><coords count="7">-40280 -65313 1;-39258 -66072;-40623 -68494;-39724 -69181 1;-38416 -70181;-39233 -71180;-36859 -70732;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
16+
<object type="1" symbol="1"><coords count="7">-47979 -65916 1;-46790 -66102;-47260 -69147;-46711 -69502 1;-45227 -70462;-43504 -67304;-42086 -69484 16;</coords><pattern rotation="0"><coord x="0" y="0"/></pattern></object>
17+
</objects></part>
18+
</parts>
19+
<templates count="0" first_front_template="0">
20+
<defaults use_meters_per_pixel="true" meters_per_pixel="0" dpi="0" scale="0"/>
21+
</templates>
22+
<view>
23+
<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"/>
24+
<map_view zoom="8.66327" position_x="-42411" position_y="-68185"><map opacity="1" visible="true"/><templates count="0"/></map_view>
25+
</view>
26+
<print scale="10000" resolution="600" mode="vector"><page_format paper_size="A4" orientation="portrait" h_overlap="5" v_overlap="5"><dimensions width="210" height="297"/><page_rect left="4.23" top="4.23" width="201.54" height="288.54"/></page_format><print_area left="-55.772" top="-71.333" width="18.932" height="9.427"/></print>
27+
</barrier>
28+
</map>
7.82 KB
Loading

test/symbol_t.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ private slots:
236236
{ "testdata:symbols/line-symbol-cap-variants.omap", 50 },
237237
{ "testdata:symbols/line-symbol-start-end-symbol.omap", 50 },
238238
{ "testdata:symbols/line-symbol-mid-symbol-variants.omap", 50 },
239+
{ "testdata:symbols/dashed-line-with-mid-symbols.omap", 80 },
239240
#ifdef ENABLE_VOLATILE_RENDER_TESTS
240241
{ "data:examples/complete map.omap", 5 },
241242
{ "data:examples/forest sample.omap", 10 },

0 commit comments

Comments
 (0)