Skip to content

Commit 80ae9ef

Browse files
author
Hugo Mercier
committedMay 26, 2014
Inverted polygon renderer: add an option to preprocess polygons using an union
1 parent 19041a8 commit 80ae9ef

15 files changed

+329
-40
lines changed
 

‎src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include <QDomElement>
2929

3030
QgsInvertedPolygonRenderer::QgsInvertedPolygonRenderer( const QgsFeatureRendererV2* subRenderer )
31-
: QgsFeatureRendererV2( "invertedPolygonRenderer" )
31+
: QgsFeatureRendererV2( "invertedPolygonRenderer" ), mPreprocessingEnabled( false )
3232
{
3333
if ( subRenderer ) {
3434
setEmbeddedRenderer( subRenderer );
@@ -154,15 +154,6 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
154154
return false;
155155
}
156156

157-
// We build here a "reversed" geometry of all the polygons
158-
//
159-
// The final geometry is a multipolygon F, with :
160-
// * the first polygon of F having the current extent as its exterior ring
161-
// * each polygon's exterior ring is added as interior ring of the first polygon of F
162-
// * each polygon's interior ring is added as new polygons in F
163-
//
164-
// No validity check is done, on purpose, it will be very slow and painting
165-
// operations do not need geometries to be valid
166157
if ( ! mFeaturesCategoryMap.contains(catId) )
167158
{
168159
// the exterior ring must be a square in the destination CRS
@@ -173,7 +164,7 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
173164
mFeaturesCategoryMap.insert( catId, cFeat );
174165
}
175166

176-
// update the gometry
167+
// update the geometry
177168
CombinedFeature& cFeat = mFeaturesCategoryMap[catId];
178169
QgsMultiPolygon multi;
179170
QgsGeometry* geom = feature.geometry();
@@ -190,37 +181,69 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
190181
multi = geom->asMultiPolygon();
191182
}
192183

193-
for ( int i = 0; i < multi.size(); i++ ) {
194-
// add the exterior ring as interior ring to the first polygon
195-
if ( mTransform ) {
196-
QgsPolyline new_ls;
197-
QgsPolyline& old_ls = multi[i][0];
198-
for ( int k = 0; k < old_ls.size(); k++ ) {
199-
new_ls.append( mTransform->transform( old_ls[k] ) );
200-
}
201-
cFeat.multiPolygon[0].append( new_ls );
184+
if ( mPreprocessingEnabled )
185+
{
186+
// preprocessing
187+
if ( ! cFeat.feature.geometry() )
188+
{
189+
// first feature: add the current geometry
190+
cFeat.feature.setGeometry( new QgsGeometry(*geom) );
202191
}
203192
else
204193
{
205-
cFeat.multiPolygon[0].append( multi[i][0] );
194+
// other features: combine them (union)
195+
QgsGeometry* combined = cFeat.feature.geometry()->combine( geom );
196+
if ( combined && combined->isGeosValid() )
197+
{
198+
cFeat.feature.setGeometry( combined );
199+
}
206200
}
207-
// add interior rings as new polygons
208-
for ( int j = 1; j < multi[i].size(); j++ ) {
209-
QgsPolygon new_poly;
201+
}
202+
else
203+
{
204+
// No preprocessing involved.
205+
// We build here a "reversed" geometry of all the polygons
206+
//
207+
// The final geometry is a multipolygon F, with :
208+
// * the first polygon of F having the current extent as its exterior ring
209+
// * each polygon's exterior ring is added as interior ring of the first polygon of F
210+
// * each polygon's interior ring is added as new polygons in F
211+
//
212+
// No validity check is done, on purpose, it will be very slow and painting
213+
// operations do not need geometries to be valid
214+
215+
for ( int i = 0; i < multi.size(); i++ ) {
216+
// add the exterior ring as interior ring to the first polygon
210217
if ( mTransform ) {
211218
QgsPolyline new_ls;
212-
QgsPolyline& old_ls = multi[i][j];
219+
QgsPolyline& old_ls = multi[i][0];
213220
for ( int k = 0; k < old_ls.size(); k++ ) {
214221
new_ls.append( mTransform->transform( old_ls[k] ) );
215222
}
216-
new_poly.append( new_ls );
223+
cFeat.multiPolygon[0].append( new_ls );
217224
}
218225
else
219226
{
220-
new_poly.append( multi[i][j] );
227+
cFeat.multiPolygon[0].append( multi[i][0] );
221228
}
229+
// add interior rings as new polygons
230+
for ( int j = 1; j < multi[i].size(); j++ ) {
231+
QgsPolygon new_poly;
232+
if ( mTransform ) {
233+
QgsPolyline new_ls;
234+
QgsPolyline& old_ls = multi[i][j];
235+
for ( int k = 0; k < old_ls.size(); k++ ) {
236+
new_ls.append( mTransform->transform( old_ls[k] ) );
237+
}
238+
new_poly.append( new_ls );
239+
}
240+
else
241+
{
242+
new_poly.append( multi[i][j] );
243+
}
222244

223-
cFeat.multiPolygon.append( new_poly );
245+
cFeat.multiPolygon.append( new_poly );
246+
}
224247
}
225248
}
226249
return true;
@@ -239,7 +262,24 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
239262
for ( FeatureCategoryMap::iterator cit = mFeaturesCategoryMap.begin(); cit != mFeaturesCategoryMap.end(); ++cit)
240263
{
241264
QgsFeature feat( cit.value().feature );
242-
feat.setGeometry( QgsGeometry::fromMultiPolygon( cit.value().multiPolygon ) );
265+
if ( !mPreprocessingEnabled )
266+
{
267+
// no preprocessing - the final polygon has already been prepared
268+
feat.setGeometry( QgsGeometry::fromMultiPolygon( cit.value().multiPolygon ) );
269+
}
270+
else
271+
{
272+
// preprocessing mode - we still have to invert (using difference)
273+
if ( feat.geometry() )
274+
{
275+
QScopedPointer<QgsGeometry> rect( QgsGeometry::fromPolygon( mExtentPolygon ) );
276+
QgsGeometry *final = rect->difference( feat.geometry() );
277+
if ( final )
278+
{
279+
feat.setGeometry( final );
280+
}
281+
}
282+
}
243283
mSubRenderer->renderFeature( feat, context );
244284
}
245285

@@ -280,12 +320,17 @@ QString QgsInvertedPolygonRenderer::dump() const
280320

281321
QgsFeatureRendererV2* QgsInvertedPolygonRenderer::clone()
282322
{
323+
QgsInvertedPolygonRenderer* newRenderer;
283324
if ( mSubRenderer.isNull() )
284325
{
285-
return new QgsInvertedPolygonRenderer( 0 );
326+
newRenderer = new QgsInvertedPolygonRenderer( 0 );
327+
}
328+
else
329+
{
330+
newRenderer = new QgsInvertedPolygonRenderer( mSubRenderer->clone() );
286331
}
287-
// else
288-
return new QgsInvertedPolygonRenderer( mSubRenderer->clone() );
332+
newRenderer->setPreprocessingEnabled( preprocessingEnabled() );
333+
return newRenderer;
289334
}
290335

291336
QgsFeatureRendererV2* QgsInvertedPolygonRenderer::create( QDomElement& element )
@@ -297,13 +342,15 @@ QgsFeatureRendererV2* QgsInvertedPolygonRenderer::create( QDomElement& element )
297342
{
298343
r->setEmbeddedRenderer( QgsFeatureRendererV2::load( embeddedRendererElem ) );
299344
}
345+
r->setPreprocessingEnabled( element.attribute( "preprocessing", "0" ).toInt() == 1 );
300346
return r;
301347
}
302348

303349
QDomElement QgsInvertedPolygonRenderer::save( QDomDocument& doc )
304350
{
305351
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
306352
rendererElem.setAttribute( "type", "invertedPolygonRenderer" );
353+
rendererElem.setAttribute( "preprocessing", preprocessingEnabled() ? "1" : "0" );
307354

308355
if ( mSubRenderer )
309356
{

‎src/core/symbology-ng/qgsinvertedpolygonrenderer.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ class CORE_EXPORT QgsInvertedPolygonRenderer : public QgsFeatureRendererV2
104104
*/
105105
const QgsFeatureRendererV2* embeddedRenderer() const;
106106

107+
/** @returns true if the geometries are to be preprocessed (merged with an union) before rendering.*/
108+
bool preprocessingEnabled() const { return mPreprocessingEnabled; }
109+
/**
110+
@param enabled enables or disables the preprocessing.
111+
When enabled, geometries will be merged with an union before being rendered.
112+
It allows to fix some rendering artefacts (when rendering overlapping polygons for instance).
113+
This will involve some CPU-demanding computations and is thus disabled by default.
114+
*/
115+
void setPreprocessingEnabled( bool enabled ) { mPreprocessingEnabled = enabled; }
116+
107117
private:
108118
/** Private copy constructor. @see clone() */
109119
QgsInvertedPolygonRenderer( const QgsInvertedPolygonRenderer& );
@@ -145,6 +155,9 @@ class CORE_EXPORT QgsInvertedPolygonRenderer : public QgsFeatureRendererV2
145155
feature(a_feature),selected(a_selected), drawMarkers(a_drawMarkers), layer(a_layer) {}
146156
};
147157
QList<FeatureDecoration> mFeatureDecorations;
158+
159+
/** whether to preprocess (merge) geometries before rendering*/
160+
bool mPreprocessingEnabled;
148161
};
149162

150163

‎src/gui/symbology-ng/qgsinvertedpolygonrendererwidget.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ QgsInvertedPolygonRendererWidget::QgsInvertedPolygonRendererWidget( QgsVectorLay
6767
{
6868
// an existing inverted renderer
6969
mRenderer.reset( static_cast<QgsInvertedPolygonRenderer*>(renderer) );
70+
mMergePolygonsCheckBox->blockSignals( true );
71+
mMergePolygonsCheckBox->setCheckState( mRenderer->preprocessingEnabled() ? Qt::Checked : Qt::Unchecked );
72+
mMergePolygonsCheckBox->blockSignals( false );
7073
}
7174

7275
int currentEmbeddedIdx = 0;
@@ -122,11 +125,15 @@ void QgsInvertedPolygonRendererWidget::on_mRendererComboBox_currentIndexChanged(
122125
{
123126
mEmbeddedRendererWidget.reset( m->createRendererWidget( mLayer, mStyle, const_cast<QgsFeatureRendererV2*>(mRenderer->embeddedRenderer())->clone() ) );
124127

125-
if ( mLayout->count() > 1 ) {
128+
if ( mLayout->count() > 2 ) {
126129
// remove the current renderer widget
127-
mLayout->takeAt( 1 );
130+
mLayout->takeAt( 2 );
128131
}
129132
mLayout->addWidget( mEmbeddedRendererWidget.data() );
130133
}
131134
}
132135

136+
void QgsInvertedPolygonRendererWidget::on_mMergePolygonsCheckBox_stateChanged( int state )
137+
{
138+
mRenderer->setPreprocessingEnabled( state == Qt::Checked );
139+
}

‎src/gui/symbology-ng/qgsinvertedpolygonrendererwidget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class GUI_EXPORT QgsInvertedPolygonRendererWidget : public QgsRendererV2Widget,
5454

5555
private slots:
5656
void on_mRendererComboBox_currentIndexChanged( int index );
57+
void on_mMergePolygonsCheckBox_stateChanged( int state );
5758
};
5859

5960

‎src/ui/qgsinvertedpolygonrendererwidgetbase.ui

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>390</width>
10-
<height>79</height>
9+
<width>316</width>
10+
<height>75</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -28,6 +28,16 @@
2828
</item>
2929
</layout>
3030
</item>
31+
<item>
32+
<widget class="QCheckBox" name="mMergePolygonsCheckBox">
33+
<property name="toolTip">
34+
<string/>
35+
</property>
36+
<property name="text">
37+
<string>Merge polygons before rendering (slow)</string>
38+
</property>
39+
</widget>
40+
</item>
3141
</layout>
3242
</widget>
3343
<resources/>

‎tests/src/core/testqgsinvertedpolygonrenderer.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class TestQgsInvertedPolygon: public QObject
4747

4848
void singleSubRenderer();
4949
void graduatedSubRenderer();
50+
void preprocess();
5051

5152
private:
5253
bool mTestHasError;
@@ -73,7 +74,7 @@ void TestQgsInvertedPolygon::initTestCase()
7374
//
7475
//create a poly layer that will be used in all tests...
7576
//
76-
QString myPolysFileName = mTestDataDir + "polys.shp";
77+
QString myPolysFileName = mTestDataDir + "polys_overlapping.shp";
7778
QFileInfo myPolyFileInfo( myPolysFileName );
7879
mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
7980
myPolyFileInfo.completeBaseName(), "ogr" );
@@ -115,6 +116,14 @@ void TestQgsInvertedPolygon::graduatedSubRenderer()
115116
QVERIFY( imageCheck( "inverted_polys_graduated" ) );
116117
}
117118

119+
void TestQgsInvertedPolygon::preprocess()
120+
{
121+
// FIXME will have to find some overlapping polygons
122+
mReport += "<h2>Inverted polygon renderer, preprocessing test</h2>\n";
123+
QVERIFY( setQml( "inverted_polys_preprocess.qml" ) );
124+
QVERIFY( imageCheck( "inverted_polys_preprocess" ) );
125+
}
126+
118127
//
119128
// Private helper functions not called directly by CTest
120129
//

‎tests/testdata/inverted_polys_graduated.qml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
22
<qgis version="2.3.0-Master" minimumScale="1" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="1" maxLabelScale="1e+08" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
3-
<renderer-v2 type="invertedPolygonRenderer">
4-
<renderer-v2 attr="Name" symbollevels="0" type="categorizedSymbol">
3+
<renderer-v2 preprocessing="0" type="invertedPolygonRenderer">
4+
<renderer-v2 attr="Name" symbollevels="1" type="categorizedSymbol">
55
<categories>
66
<category symbol="0" value="Dam" label="Dam"/>
77
<category symbol="1" value="Lake" label="Lake"/>
@@ -27,7 +27,7 @@
2727
</layer>
2828
</symbol>
2929
<symbol alpha="1" type="fill" name="1">
30-
<layer pass="0" class="ShapeburstFill" locked="0">
30+
<layer pass="1" class="ShapeburstFill" locked="0">
3131
<prop k="blur_radius" v="0"/>
3232
<prop k="color1" v="0,0,255,255"/>
3333
<prop k="color2" v="0,255,0,255"/>
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
2+
<qgis version="2.3.0-Master" minimumScale="1" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="1" maxLabelScale="1e+08" simplifyDrawingTol="1" simplifyMaxScale="1" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
3+
<renderer-v2 type="invertedPolygonRenderer" preprocessing="1">
4+
<renderer-v2 symbollevels="0" type="singleSymbol">
5+
<symbols>
6+
<symbol alpha="1" type="fill" name="0">
7+
<layer pass="0" class="SimpleFill" locked="0">
8+
<prop k="border_width_map_unit_scale" v="0,0"/>
9+
<prop k="border_width_unit" v="MM"/>
10+
<prop k="color" v="76,143,160,255"/>
11+
<prop k="color_border" v="0,0,0,255"/>
12+
<prop k="joinstyle" v="bevel"/>
13+
<prop k="offset" v="0,0"/>
14+
<prop k="offset_map_unit_scale" v="0,0"/>
15+
<prop k="offset_unit" v="MM"/>
16+
<prop k="style" v="solid"/>
17+
<prop k="style_border" v="solid"/>
18+
<prop k="width_border" v="0.26"/>
19+
</layer>
20+
</symbol>
21+
</symbols>
22+
<rotation/>
23+
<sizescale scalemethod="area"/>
24+
</renderer-v2>
25+
</renderer-v2>
26+
<customproperties>
27+
<property key="labeling" value="pal"/>
28+
<property key="labeling/addDirectionSymbol" value="false"/>
29+
<property key="labeling/angleOffset" value="0"/>
30+
<property key="labeling/blendMode" value="0"/>
31+
<property key="labeling/bufferBlendMode" value="0"/>
32+
<property key="labeling/bufferColorA" value="255"/>
33+
<property key="labeling/bufferColorB" value="255"/>
34+
<property key="labeling/bufferColorG" value="255"/>
35+
<property key="labeling/bufferColorR" value="255"/>
36+
<property key="labeling/bufferDraw" value="false"/>
37+
<property key="labeling/bufferJoinStyle" value="64"/>
38+
<property key="labeling/bufferNoFill" value="false"/>
39+
<property key="labeling/bufferSize" value="1"/>
40+
<property key="labeling/bufferSizeInMapUnits" value="false"/>
41+
<property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
42+
<property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
43+
<property key="labeling/bufferTransp" value="0"/>
44+
<property key="labeling/centroidWhole" value="false"/>
45+
<property key="labeling/decimals" value="3"/>
46+
<property key="labeling/displayAll" value="false"/>
47+
<property key="labeling/dist" value="0"/>
48+
<property key="labeling/distInMapUnits" value="false"/>
49+
<property key="labeling/distMapUnitMaxScale" value="0"/>
50+
<property key="labeling/distMapUnitMinScale" value="0"/>
51+
<property key="labeling/enabled" value="false"/>
52+
<property key="labeling/fieldName" value=""/>
53+
<property key="labeling/fontBold" value="true"/>
54+
<property key="labeling/fontCapitals" value="0"/>
55+
<property key="labeling/fontFamily" value="Ubuntu"/>
56+
<property key="labeling/fontItalic" value="true"/>
57+
<property key="labeling/fontLetterSpacing" value="0"/>
58+
<property key="labeling/fontLimitPixelSize" value="false"/>
59+
<property key="labeling/fontMaxPixelSize" value="10000"/>
60+
<property key="labeling/fontMinPixelSize" value="3"/>
61+
<property key="labeling/fontSize" value="11"/>
62+
<property key="labeling/fontSizeInMapUnits" value="false"/>
63+
<property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
64+
<property key="labeling/fontSizeMapUnitMinScale" value="0"/>
65+
<property key="labeling/fontStrikeout" value="false"/>
66+
<property key="labeling/fontUnderline" value="false"/>
67+
<property key="labeling/fontWeight" value="75"/>
68+
<property key="labeling/fontWordSpacing" value="0"/>
69+
<property key="labeling/formatNumbers" value="false"/>
70+
<property key="labeling/isExpression" value="false"/>
71+
<property key="labeling/labelOffsetInMapUnits" value="true"/>
72+
<property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
73+
<property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
74+
<property key="labeling/labelPerPart" value="false"/>
75+
<property key="labeling/leftDirectionSymbol" value="&lt;"/>
76+
<property key="labeling/limitNumLabels" value="false"/>
77+
<property key="labeling/maxCurvedCharAngleIn" value="20"/>
78+
<property key="labeling/maxCurvedCharAngleOut" value="-20"/>
79+
<property key="labeling/maxNumLabels" value="2000"/>
80+
<property key="labeling/mergeLines" value="false"/>
81+
<property key="labeling/minFeatureSize" value="0"/>
82+
<property key="labeling/multilineAlign" value="0"/>
83+
<property key="labeling/multilineHeight" value="1"/>
84+
<property key="labeling/namedStyle" value="Bold Italic"/>
85+
<property key="labeling/obstacle" value="true"/>
86+
<property key="labeling/placeDirectionSymbol" value="0"/>
87+
<property key="labeling/placement" value="0"/>
88+
<property key="labeling/placementFlags" value="0"/>
89+
<property key="labeling/plussign" value="false"/>
90+
<property key="labeling/preserveRotation" value="true"/>
91+
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
92+
<property key="labeling/priority" value="5"/>
93+
<property key="labeling/quadOffset" value="4"/>
94+
<property key="labeling/reverseDirectionSymbol" value="false"/>
95+
<property key="labeling/rightDirectionSymbol" value=">"/>
96+
<property key="labeling/scaleMax" value="10000000"/>
97+
<property key="labeling/scaleMin" value="1"/>
98+
<property key="labeling/scaleVisibility" value="false"/>
99+
<property key="labeling/shadowBlendMode" value="6"/>
100+
<property key="labeling/shadowColorB" value="0"/>
101+
<property key="labeling/shadowColorG" value="0"/>
102+
<property key="labeling/shadowColorR" value="0"/>
103+
<property key="labeling/shadowDraw" value="false"/>
104+
<property key="labeling/shadowOffsetAngle" value="135"/>
105+
<property key="labeling/shadowOffsetDist" value="1"/>
106+
<property key="labeling/shadowOffsetGlobal" value="true"/>
107+
<property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
108+
<property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
109+
<property key="labeling/shadowOffsetUnits" value="1"/>
110+
<property key="labeling/shadowRadius" value="1.5"/>
111+
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
112+
<property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
113+
<property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
114+
<property key="labeling/shadowRadiusUnits" value="1"/>
115+
<property key="labeling/shadowScale" value="100"/>
116+
<property key="labeling/shadowTransparency" value="30"/>
117+
<property key="labeling/shadowUnder" value="0"/>
118+
<property key="labeling/shapeBlendMode" value="0"/>
119+
<property key="labeling/shapeBorderColorA" value="255"/>
120+
<property key="labeling/shapeBorderColorB" value="128"/>
121+
<property key="labeling/shapeBorderColorG" value="128"/>
122+
<property key="labeling/shapeBorderColorR" value="128"/>
123+
<property key="labeling/shapeBorderWidth" value="0"/>
124+
<property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
125+
<property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
126+
<property key="labeling/shapeBorderWidthUnits" value="1"/>
127+
<property key="labeling/shapeDraw" value="false"/>
128+
<property key="labeling/shapeFillColorA" value="255"/>
129+
<property key="labeling/shapeFillColorB" value="255"/>
130+
<property key="labeling/shapeFillColorG" value="255"/>
131+
<property key="labeling/shapeFillColorR" value="255"/>
132+
<property key="labeling/shapeJoinStyle" value="64"/>
133+
<property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
134+
<property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
135+
<property key="labeling/shapeOffsetUnits" value="1"/>
136+
<property key="labeling/shapeOffsetX" value="0"/>
137+
<property key="labeling/shapeOffsetY" value="0"/>
138+
<property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
139+
<property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
140+
<property key="labeling/shapeRadiiUnits" value="1"/>
141+
<property key="labeling/shapeRadiiX" value="0"/>
142+
<property key="labeling/shapeRadiiY" value="0"/>
143+
<property key="labeling/shapeRotation" value="0"/>
144+
<property key="labeling/shapeRotationType" value="0"/>
145+
<property key="labeling/shapeSVGFile" value=""/>
146+
<property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
147+
<property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
148+
<property key="labeling/shapeSizeType" value="0"/>
149+
<property key="labeling/shapeSizeUnits" value="1"/>
150+
<property key="labeling/shapeSizeX" value="0"/>
151+
<property key="labeling/shapeSizeY" value="0"/>
152+
<property key="labeling/shapeTransparency" value="0"/>
153+
<property key="labeling/shapeType" value="0"/>
154+
<property key="labeling/textColorA" value="255"/>
155+
<property key="labeling/textColorB" value="0"/>
156+
<property key="labeling/textColorG" value="0"/>
157+
<property key="labeling/textColorR" value="0"/>
158+
<property key="labeling/textTransp" value="0"/>
159+
<property key="labeling/upsidedownLabels" value="0"/>
160+
<property key="labeling/wrapChar" value=""/>
161+
<property key="labeling/xOffset" value="0"/>
162+
<property key="labeling/yOffset" value="0"/>
163+
</customproperties>
164+
<blendMode>0</blendMode>
165+
<featureBlendMode>0</featureBlendMode>
166+
<layerTransparency>0</layerTransparency>
167+
<displayfield>Name</displayfield>
168+
<label>0</label>
169+
<labelattributes>
170+
<label fieldname="" text="Label"/>
171+
<family fieldname="" name="Lucida Grande"/>
172+
<size fieldname="" units="pt" value="12"/>
173+
<bold fieldname="" on="0"/>
174+
<italic fieldname="" on="0"/>
175+
<underline fieldname="" on="0"/>
176+
<strikeout fieldname="" on="0"/>
177+
<color fieldname="" red="0" blue="0" green="0"/>
178+
<x fieldname=""/>
179+
<y fieldname=""/>
180+
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
181+
<angle fieldname="" value="0" auto="0"/>
182+
<alignment fieldname="" value="center"/>
183+
<buffercolor fieldname="" red="255" blue="255" green="255"/>
184+
<buffersize fieldname="" units="pt" value="1"/>
185+
<bufferenabled fieldname="" on=""/>
186+
<multilineenabled fieldname="" on=""/>
187+
<selectedonly on=""/>
188+
</labelattributes>
189+
<edittypes>
190+
<edittype labelontop="0" editable="1" type="0" name="Name"/>
191+
<edittype labelontop="0" editable="1" type="0" name="Value"/>
192+
</edittypes>
193+
<editform></editform>
194+
<editforminit></editforminit>
195+
<featformsuppress>0</featformsuppress>
196+
<annotationform></annotationform>
197+
<editorlayout>generatedlayout</editorlayout>
198+
<excludeAttributesWMS/>
199+
<excludeAttributesWFS/>
200+
<attributeactions/>
201+
</qgis>

‎tests/testdata/polys_overlapping.dbf

1.22 KB
Binary file not shown.

‎tests/testdata/polys_overlapping.prj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GEOGCS["WGS 84",DATUM["unknown",SPHEROID["WGS84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]

‎tests/testdata/polys_overlapping.shp

10.7 KB
Binary file not shown.

‎tests/testdata/polys_overlapping.shx

188 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)
Please sign in to comment.