Skip to content

Commit 509a285

Browse files
committed
Fix endpoint swap on negative marker line offset
Fixes #13811 Includes testcase (cherry-picked from 824fd7b)
1 parent 60335db commit 509a285

File tree

5 files changed

+444
-1
lines changed

5 files changed

+444
-1
lines changed

src/core/symbology-ng/qgssymbollayerv2utils.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,11 @@ QList<QPolygonF> offsetLine( QPolygonF polyline, double dist, QGis::GeometryType
781781

782782
if ( QGis::flatType( tempGeometry->wkbType() ) == QGis::WKBLineString )
783783
{
784-
resultLine.append( makeOffsetGeometry( tempGeometry->asPolyline() ) );
784+
QgsPolyline line = tempGeometry->asPolyline();
785+
// Reverse the line if offset was negative, see
786+
// http://hub.qgis.org/issues/13811
787+
if ( dist < 0 ) std::reverse(line.begin(), line.end() );
788+
resultLine.append( makeOffsetGeometry( line ) );
785789
delete tempGeometry;
786790
return resultLine;
787791
}

tests/src/core/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ ADD_QGIS_TEST(maprenderertest testqgsmaprenderer.cpp)
142142
ADD_QGIS_TEST(maprotationtest testqgsmaprotation.cpp)
143143
ADD_QGIS_TEST(mapsettingstest testqgsmapsettings.cpp)
144144
ADD_QGIS_TEST(maptopixeltest testqgsmaptopixel.cpp)
145+
ADD_QGIS_TEST(markerlinessymboltest testqgsmarkerlinesymbol.cpp)
145146
ADD_QGIS_TEST(networkcontentfetcher testqgsnetworkcontentfetcher.cpp )
146147
ADD_QGIS_TEST(ogcutilstest testqgsogcutils.cpp)
147148
ADD_QGIS_TEST(painteffectregistrytest testqgspainteffectregistry.cpp)
+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/***************************************************************************
2+
testqgsmarkerlinesymbol.cpp
3+
--------------------------------------
4+
Date : Nov 12 2015
5+
Copyright : (C) 2015 by Sandro Santilli
6+
Email : strk@keybit.net
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#include <QtTest/QtTest>
16+
#include <QObject>
17+
#include <QString>
18+
#include <QStringList>
19+
#include <QApplication>
20+
#include <QFileInfo>
21+
#include <QDir>
22+
23+
//qgis includes...
24+
#include "qgsrasterlayer.h"
25+
#include "qgsvectorlayer.h"
26+
#include "qgsmultibandcolorrenderer.h"
27+
#include "qgsmaplayerregistry.h"
28+
#include "qgsapplication.h"
29+
#include "qgsmaprenderer.h"
30+
#include "qgspallabeling.h"
31+
#include "qgsfontutils.h"
32+
33+
//qgis unit test includes
34+
#include <qgsrenderchecker.h>
35+
36+
/** \ingroup UnitTests
37+
* This is a unit test for the Marker Line symbol
38+
*/
39+
class TestQgsMarkerLineSymbol : public QObject
40+
{
41+
Q_OBJECT
42+
public:
43+
TestQgsMarkerLineSymbol()
44+
: mLinesLayer( 0 )
45+
, mMapSettings( 0 )
46+
{
47+
mTestDataDir = QString( TEST_DATA_DIR ) + '/';
48+
}
49+
50+
~TestQgsMarkerLineSymbol();
51+
52+
private slots:
53+
void initTestCase();// will be called before the first testfunction is executed.
54+
void cleanupTestCase();// will be called after the last testfunction was executed.
55+
void init() {} // will be called before each testfunction is executed.
56+
void cleanup() {} // will be called after every testfunction.
57+
58+
void lineOffset();
59+
60+
private:
61+
bool render( const QString& theFileName );
62+
63+
QString mTestDataDir;
64+
QgsVectorLayer* mLinesLayer;
65+
QgsMapSettings *mMapSettings;
66+
QString mReport;
67+
};
68+
69+
//runs before all tests
70+
void TestQgsMarkerLineSymbol::initTestCase()
71+
{
72+
// init QGIS's paths - true means that all path will be inited from prefix
73+
QgsApplication::init();
74+
QgsApplication::initQgis();
75+
76+
mMapSettings = new QgsMapSettings();
77+
78+
QList<QgsMapLayer *> mapLayers;
79+
80+
//create a line layer that will be used in all tests...
81+
QString myLinesFileName = mTestDataDir + "lines_cardinals.shp";
82+
QFileInfo myLinesFileInfo( myLinesFileName );
83+
mLinesLayer = new QgsVectorLayer( myLinesFileInfo.filePath(),
84+
myLinesFileInfo.completeBaseName(), "ogr" );
85+
mapLayers << mLinesLayer;
86+
87+
// Register all layers with the registry
88+
QgsMapLayerRegistry::instance()->addMapLayers( mapLayers );
89+
90+
// This is needed to correctly set rotation center,
91+
// the actual size doesn't matter as QgsRenderChecker will
92+
// re-set it to the size of the expected image
93+
mMapSettings->setOutputSize( QSize( 256, 256 ) );
94+
95+
mReport += "<h1>Line Marker Symbol Tests</h1>\n";
96+
97+
QgsFontUtils::loadStandardTestFonts( QStringList() << "Bold" );
98+
}
99+
100+
TestQgsMarkerLineSymbol::~TestQgsMarkerLineSymbol()
101+
{
102+
103+
}
104+
105+
//runs after all tests
106+
void TestQgsMarkerLineSymbol::cleanupTestCase()
107+
{
108+
delete mMapSettings;
109+
QgsApplication::exitQgis();
110+
111+
QString myReportFile = QDir::tempPath() + "/qgistest.html";
112+
QFile myFile( myReportFile );
113+
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
114+
{
115+
QTextStream myQTextStream( &myFile );
116+
myQTextStream << mReport;
117+
myFile.close();
118+
}
119+
}
120+
121+
void TestQgsMarkerLineSymbol::lineOffset()
122+
{
123+
mMapSettings->setLayers( QStringList() << mLinesLayer->id() );
124+
125+
// Negative offset on marker line
126+
// See http://hub.qgis.org/issues/13811
127+
128+
QString qml = mTestDataDir + "marker_line_offset.qml";
129+
bool success = false;
130+
mLinesLayer->loadNamedStyle( qml, success );
131+
132+
QVERIFY( success );
133+
mMapSettings->setExtent( QgsRectangle(-140,-140,140,140) );
134+
QVERIFY( render( "line_offset" ) );
135+
136+
// TODO: -0.0 offset, see
137+
// http://hub.qgis.org/issues/13811#note-1
138+
}
139+
140+
bool TestQgsMarkerLineSymbol::render( const QString& theTestType )
141+
{
142+
mReport += "<h2>" + theTestType + "</h2>\n";
143+
mMapSettings->setOutputDpi( 96 );
144+
QgsRenderChecker checker;
145+
checker.setControlPathPrefix( "markerlinesymbol" );
146+
checker.setControlName( "expected_" + theTestType );
147+
checker.setMapSettings( *mMapSettings );
148+
bool result = checker.runTest( theTestType );
149+
mReport += "\n\n\n" + checker.report();
150+
return result;
151+
}
152+
153+
QTEST_MAIN( TestQgsMarkerLineSymbol )
154+
#include "testqgsmarkerlinesymbol.moc"
Loading

0 commit comments

Comments
 (0)