mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Merge pull request #1380 from Oslandia/mask_renderer
[FEATURE] Inverted polygons renderer
This commit is contained in:
commit
0775a89ed5
@ -206,6 +206,7 @@
|
||||
%Include symbology-ng/qgssinglesymbolrendererv2.sip
|
||||
%Include symbology-ng/qgspointdisplacementrenderer.sip
|
||||
%Include symbology-ng/qgsrulebasedrendererv2.sip
|
||||
%Include symbology-ng/qgsinvertedpolygonrenderer.sip
|
||||
%Include symbology-ng/qgsrendererv2.sip
|
||||
%Include symbology-ng/qgsrendererv2registry.sip
|
||||
|
||||
|
70
python/core/symbology-ng/qgsinvertedpolygonrenderer.sip
Normal file
70
python/core/symbology-ng/qgsinvertedpolygonrenderer.sip
Normal file
@ -0,0 +1,70 @@
|
||||
class QgsInvertedPolygonRenderer : public QgsFeatureRendererV2
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsinvertedpolygonrenderer.h>
|
||||
%End
|
||||
public:
|
||||
|
||||
/** Constructor
|
||||
* @param embeddedRenderer optional embeddedRenderer. If null, a default one will be assigned
|
||||
*/
|
||||
QgsInvertedPolygonRenderer( const QgsFeatureRendererV2* embeddedRenderer = 0 );
|
||||
virtual ~QgsInvertedPolygonRenderer();
|
||||
|
||||
/** Used to clone this feature renderer.*/
|
||||
virtual QgsFeatureRendererV2* clone();
|
||||
|
||||
virtual void startRender( QgsRenderContext& context, const QgsFields& fields );
|
||||
|
||||
/** Renders a given feature.
|
||||
* This will here collect features. The actual rendering will be postponed to stopRender()
|
||||
* @param feature the feature to render
|
||||
* @param context the rendering context
|
||||
* @param layer the symbol layer to render, if that makes sense
|
||||
* @param selected whether this feature has been selected (this will add decorations)
|
||||
* @param drawVertexMarker whether this feature has vertex markers (in edit mode usually)
|
||||
* @returns true if the rendering was ok
|
||||
*/
|
||||
virtual bool renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false );
|
||||
|
||||
/**
|
||||
* The actual rendering will take place here.
|
||||
* Features collected during renderFeature() are rendered using the embedded feature renderer
|
||||
*/
|
||||
virtual void stopRender( QgsRenderContext& context );
|
||||
|
||||
/** @returns a textual reprensation of the renderer */
|
||||
virtual QString dump() const;
|
||||
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QList<QString> usedAttributes();
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual int capabilities();
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsSymbolV2List symbols();
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsSymbolV2List symbolsForFeature( QgsFeature& feat );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsLegendSymbologyList legendSymbologyItems( QSize iconSize );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual bool willRenderFeature( QgsFeature& feat );
|
||||
|
||||
/** Creates a renderer out of an XML, for loading*/
|
||||
static QgsFeatureRendererV2* create( QDomElement& element );
|
||||
|
||||
/** Creates an XML representation of the renderer. Used for saving purpose
|
||||
* @param doc the XML document where to create the XML subtree
|
||||
* @returns the created XML subtree
|
||||
*/
|
||||
virtual QDomElement save( QDomDocument& doc );
|
||||
|
||||
/** sets the embedded renderer
|
||||
* @param subRenderer the embedded renderer (will be cloned)
|
||||
*/
|
||||
void setEmbeddedRenderer( const QgsFeatureRendererV2* subRenderer );
|
||||
/** @returns the current embedded renderer
|
||||
*/
|
||||
const QgsFeatureRendererV2* embeddedRenderer() const;
|
||||
};
|
@ -122,6 +122,7 @@
|
||||
%Include symbology-ng/qgscptcitycolorrampv2dialog.sip
|
||||
%Include symbology-ng/qgsellipsesymbollayerv2widget.sip
|
||||
%Include symbology-ng/qgsgraduatedsymbolrendererv2widget.sip
|
||||
%Include symbology-ng/qgsinvertedpolygonrendererwidget.sip
|
||||
%Include symbology-ng/qgslayerpropertieswidget.sip
|
||||
%Include symbology-ng/qgspenstylecombobox.sip
|
||||
%Include symbology-ng/qgspointdisplacementrendererwidget.sip
|
||||
|
23
python/gui/symbology-ng/qgsinvertedpolygonrendererwidget.sip
Normal file
23
python/gui/symbology-ng/qgsinvertedpolygonrendererwidget.sip
Normal file
@ -0,0 +1,23 @@
|
||||
class QgsInvertedPolygonRendererWidget : public QgsRendererV2Widget, private Ui::QgsInvertedPolygonRendererWidgetBase
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsinvertedpolygonrendererwidget.h>
|
||||
%End
|
||||
public:
|
||||
/** static creation method
|
||||
* @param layer the layer where this renderer is applied
|
||||
* @param style
|
||||
* @param renderer the mask renderer (will take ownership)
|
||||
*/
|
||||
static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
|
||||
|
||||
/** Constructor
|
||||
* @param layer the layer where this renderer is applied
|
||||
* @param style
|
||||
* @param renderer the mask renderer (will take ownership)
|
||||
*/
|
||||
QgsInvertedPolygonRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
|
||||
|
||||
/** @returns the current feature renderer */
|
||||
virtual QgsFeatureRendererV2* renderer();
|
||||
};
|
@ -36,6 +36,7 @@ SET(QGIS_CORE_SRCS
|
||||
symbology-ng/qgscategorizedsymbolrendererv2.cpp
|
||||
symbology-ng/qgsgraduatedsymbolrendererv2.cpp
|
||||
symbology-ng/qgsrulebasedrendererv2.cpp
|
||||
symbology-ng/qgsinvertedpolygonrenderer.cpp
|
||||
symbology-ng/qgsvectorcolorrampv2.cpp
|
||||
symbology-ng/qgscptcityarchive.cpp
|
||||
symbology-ng/qgsstylev2.cpp
|
||||
@ -585,6 +586,7 @@ SET(QGIS_CORE_HDRS
|
||||
symbology-ng/qgsrendererv2registry.h
|
||||
symbology-ng/qgsrulebasedrendererv2.h
|
||||
symbology-ng/qgssinglesymbolrendererv2.h
|
||||
symbology-ng/qgsinvertedpolygonrenderer.h
|
||||
symbology-ng/qgsstylev2.h
|
||||
symbology-ng/qgssvgcache.h
|
||||
symbology-ng/qgssymbollayerv2.h
|
||||
|
367
src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp
Normal file
367
src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp
Normal file
@ -0,0 +1,367 @@
|
||||
/***************************************************************************
|
||||
qgsinvertedpolygonrenderer.cpp
|
||||
---------------------
|
||||
begin : April 2014
|
||||
copyright : (C) 2014 Hugo Mercier / Oslandia
|
||||
email : hugo dot mercier at oslandia dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsinvertedpolygonrenderer.h"
|
||||
|
||||
#include "qgssymbolv2.h"
|
||||
#include "qgssymbollayerv2utils.h"
|
||||
|
||||
#include "qgslogger.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgssymbollayerv2.h"
|
||||
#include "qgsogcutils.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
|
||||
QgsInvertedPolygonRenderer::QgsInvertedPolygonRenderer( const QgsFeatureRendererV2* subRenderer )
|
||||
: QgsFeatureRendererV2( "invertedPolygonRenderer" )
|
||||
{
|
||||
if ( subRenderer ) {
|
||||
setEmbeddedRenderer( subRenderer );
|
||||
}
|
||||
else {
|
||||
mSubRenderer.reset( QgsFeatureRendererV2::defaultRenderer( QGis::Polygon ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsInvertedPolygonRenderer::~QgsInvertedPolygonRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsInvertedPolygonRenderer::setEmbeddedRenderer( const QgsFeatureRendererV2* subRenderer )
|
||||
{
|
||||
if ( subRenderer ) {
|
||||
mSubRenderer.reset( const_cast<QgsFeatureRendererV2*>(subRenderer)->clone() );
|
||||
}
|
||||
else {
|
||||
mSubRenderer.reset( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
const QgsFeatureRendererV2* QgsInvertedPolygonRenderer::embeddedRenderer() const
|
||||
{
|
||||
return mSubRenderer.data();
|
||||
}
|
||||
|
||||
void QgsInvertedPolygonRenderer::startRender( QgsRenderContext& context, const QgsFields& fields )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSubRenderer->startRender( context, fields );
|
||||
mFeaturesCategoryMap.clear();
|
||||
mFeatureDecorations.clear();
|
||||
mFields = fields;
|
||||
|
||||
// We compute coordinates of the extent which will serve as exterior ring
|
||||
// for the final polygon
|
||||
// It must be computed in the destination CRS if reprojection is enabled.
|
||||
const QgsMapToPixel& mtp( context.mapToPixel() );
|
||||
|
||||
// convert viewport to dest CRS
|
||||
QRect e( context.painter()->viewport() );
|
||||
// add some space to hide borders and tend to infinity
|
||||
e.adjust( -e.width()*10, -e.height()*10, e.width()*10, e.height()*10 );
|
||||
QgsPolyline exteriorRing;
|
||||
exteriorRing << mtp.toMapCoordinates( e.topLeft() );
|
||||
exteriorRing << mtp.toMapCoordinates( e.topRight() );
|
||||
exteriorRing << mtp.toMapCoordinates( e.bottomRight() );
|
||||
exteriorRing << mtp.toMapCoordinates( e.bottomLeft() );
|
||||
exteriorRing << mtp.toMapCoordinates( e.topLeft() );
|
||||
|
||||
mTransform = context.coordinateTransform();
|
||||
// If reprojection is enabled, we must reproject during renderFeature
|
||||
// and act as if there is no reprojection
|
||||
// If we don't do that, there is no need to have a simple rectangular extent
|
||||
// that covers the whole screen
|
||||
// (a rectangle in the destCRS cannot be expressed as valid coordinates in the sourceCRS in general)
|
||||
if (mTransform)
|
||||
{
|
||||
// disable projection
|
||||
context.setCoordinateTransform(0);
|
||||
}
|
||||
|
||||
mExtentPolygon.clear();
|
||||
mExtentPolygon.append(exteriorRing);
|
||||
}
|
||||
|
||||
bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
|
||||
{
|
||||
Q_UNUSED( context );
|
||||
|
||||
// store this feature as a feature to render with decoration if needed
|
||||
if ( selected || drawVertexMarker )
|
||||
{
|
||||
mFeatureDecorations.append( FeatureDecoration( feature, selected, drawVertexMarker, layer) );
|
||||
}
|
||||
|
||||
// Features are grouped by category of symbols (returned by symbol(s)ForFeature)
|
||||
// This way, users can have multiple inverted polygon fills for a layer,
|
||||
// for instance, with rule based renderer and different symbols
|
||||
// that have transparency.
|
||||
//
|
||||
// In order to assign a unique category to a set of symbols
|
||||
// during each rendering session (between startRender() and stopRender()),
|
||||
// we build an unique id as a QByteArray that is the concatenation
|
||||
// of each symbol's memory address.
|
||||
// The only assumption made here is that symbol(s)ForFeature will
|
||||
// always return the same address for the same symbol(s) shared amongst
|
||||
// different features.
|
||||
// This QByteArray can then be used as a key for a QMap where the list of
|
||||
// features for this category is stored
|
||||
QByteArray catId;
|
||||
if ( capabilities() & MoreSymbolsPerFeature ) {
|
||||
QgsSymbolV2List syms( mSubRenderer->symbolsForFeature( feature ) );
|
||||
foreach ( QgsSymbolV2* sym, syms )
|
||||
{
|
||||
// append the memory address
|
||||
catId.append( reinterpret_cast<const char*>(&sym), sizeof(sym) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsSymbolV2* sym = mSubRenderer->symbolForFeature( feature );
|
||||
if (sym) {
|
||||
catId.append( reinterpret_cast<const char*>(&sym), sizeof(sym) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( catId.isEmpty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We build here a "reversed" geometry of all the polygons
|
||||
//
|
||||
// The final geometry is a multipolygon F, with :
|
||||
// * the first polygon of F having the current extent as its exterior ring
|
||||
// * each polygon's exterior ring is added as interior ring of the first polygon of F
|
||||
// * each polygon's interior ring is added as new polygons in F
|
||||
//
|
||||
// No validity check is done, on purpose, it will be very slow and painting
|
||||
// operations do not need geometries to be valid
|
||||
if ( ! mFeaturesCategoryMap.contains(catId) )
|
||||
{
|
||||
// the exterior ring must be a square in the destination CRS
|
||||
CombinedFeature cFeat;
|
||||
cFeat.multiPolygon.append( mExtentPolygon );
|
||||
// store the first feature
|
||||
cFeat.feature = feature;
|
||||
mFeaturesCategoryMap.insert( catId, cFeat );
|
||||
}
|
||||
|
||||
// update the gometry
|
||||
CombinedFeature& cFeat = mFeaturesCategoryMap[catId];
|
||||
QgsMultiPolygon multi;
|
||||
QgsGeometry* geom = feature.geometry();
|
||||
if ( !geom )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( (geom->wkbType() == QGis::WKBPolygon) ||
|
||||
(geom->wkbType() == QGis::WKBPolygon25D) ) {
|
||||
multi.append(geom->asPolygon() );
|
||||
}
|
||||
else if ( (geom->wkbType() == QGis::WKBMultiPolygon) ||
|
||||
(geom->wkbType() == QGis::WKBMultiPolygon25D) ) {
|
||||
multi = geom->asMultiPolygon();
|
||||
}
|
||||
|
||||
for ( int i = 0; i < multi.size(); i++ ) {
|
||||
// add the exterior ring as interior ring to the first polygon
|
||||
if ( mTransform ) {
|
||||
QgsPolyline new_ls;
|
||||
QgsPolyline& old_ls = multi[i][0];
|
||||
for ( int k = 0; k < old_ls.size(); k++ ) {
|
||||
new_ls.append( mTransform->transform( old_ls[k] ) );
|
||||
}
|
||||
cFeat.multiPolygon[0].append( new_ls );
|
||||
}
|
||||
else
|
||||
{
|
||||
cFeat.multiPolygon[0].append( multi[i][0] );
|
||||
}
|
||||
// add interior rings as new polygons
|
||||
for ( int j = 1; j < multi[i].size(); j++ ) {
|
||||
QgsPolygon new_poly;
|
||||
if ( mTransform ) {
|
||||
QgsPolyline new_ls;
|
||||
QgsPolyline& old_ls = multi[i][j];
|
||||
for ( int k = 0; k < old_ls.size(); k++ ) {
|
||||
new_ls.append( mTransform->transform( old_ls[k] ) );
|
||||
}
|
||||
new_poly.append( new_ls );
|
||||
}
|
||||
else
|
||||
{
|
||||
new_poly.append( multi[i][j] );
|
||||
}
|
||||
|
||||
cFeat.multiPolygon.append( new_poly );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( FeatureCategoryMap::iterator cit = mFeaturesCategoryMap.begin(); cit != mFeaturesCategoryMap.end(); ++cit)
|
||||
{
|
||||
QgsFeature feat( cit.value().feature );
|
||||
feat.setGeometry( QgsGeometry::fromMultiPolygon( cit.value().multiPolygon ) );
|
||||
mSubRenderer->renderFeature( feat, context );
|
||||
}
|
||||
|
||||
// when no features are visible, we still have to draw the exterior rectangle
|
||||
// warning: when sub renderers have more than one possible symbols,
|
||||
// there is no way to choose a correct one, because there is no attribute here
|
||||
// in that case, nothing will be rendered
|
||||
if ( mFeaturesCategoryMap.isEmpty() )
|
||||
{
|
||||
// empty feature with default attributes
|
||||
QgsFeature feat( mFields );
|
||||
feat.setGeometry( QgsGeometry::fromPolygon( mExtentPolygon ) );
|
||||
mSubRenderer->renderFeature( feat, context );
|
||||
}
|
||||
|
||||
// draw feature decorations
|
||||
foreach (FeatureDecoration deco, mFeatureDecorations )
|
||||
{
|
||||
mSubRenderer->renderFeature( deco.feature, context, deco.layer, deco.selected, deco.drawMarkers );
|
||||
}
|
||||
|
||||
mSubRenderer->stopRender( context );
|
||||
|
||||
if ( mTransform )
|
||||
{
|
||||
// restore the coordinate transform if needed
|
||||
context.setCoordinateTransform( mTransform );
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsInvertedPolygonRenderer::dump() const
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return "INVERTED: NULL";
|
||||
}
|
||||
return "INVERTED [" + mSubRenderer->dump() + "]";
|
||||
}
|
||||
|
||||
QgsFeatureRendererV2* QgsInvertedPolygonRenderer::clone()
|
||||
{
|
||||
if ( mSubRenderer.isNull() )
|
||||
{
|
||||
return new QgsInvertedPolygonRenderer( 0 );
|
||||
}
|
||||
// else
|
||||
return new QgsInvertedPolygonRenderer( mSubRenderer->clone() );
|
||||
}
|
||||
|
||||
QgsFeatureRendererV2* QgsInvertedPolygonRenderer::create( QDomElement& element )
|
||||
{
|
||||
QgsInvertedPolygonRenderer* r = new QgsInvertedPolygonRenderer();
|
||||
//look for an embedded renderer <renderer-v2>
|
||||
QDomElement embeddedRendererElem = element.firstChildElement( "renderer-v2" );
|
||||
if ( !embeddedRendererElem.isNull() )
|
||||
{
|
||||
r->setEmbeddedRenderer( QgsFeatureRendererV2::load( embeddedRendererElem ) );
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
QDomElement QgsInvertedPolygonRenderer::save( QDomDocument& doc )
|
||||
{
|
||||
QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME );
|
||||
rendererElem.setAttribute( "type", "invertedPolygonRenderer" );
|
||||
|
||||
if ( mSubRenderer )
|
||||
{
|
||||
QDomElement embeddedRendererElem = mSubRenderer->save( doc );
|
||||
rendererElem.appendChild( embeddedRendererElem );
|
||||
}
|
||||
|
||||
return rendererElem;
|
||||
}
|
||||
|
||||
QgsSymbolV2* QgsInvertedPolygonRenderer::symbolForFeature( QgsFeature& feature )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return 0;
|
||||
}
|
||||
return mSubRenderer->symbolForFeature( feature );
|
||||
}
|
||||
|
||||
QgsSymbolV2List QgsInvertedPolygonRenderer::symbolsForFeature( QgsFeature& feature )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return QgsSymbolV2List();
|
||||
}
|
||||
return mSubRenderer->symbolsForFeature( feature );
|
||||
}
|
||||
|
||||
QgsSymbolV2List QgsInvertedPolygonRenderer::symbols()
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return QgsSymbolV2List();
|
||||
}
|
||||
return mSubRenderer->symbols();
|
||||
}
|
||||
|
||||
int QgsInvertedPolygonRenderer::capabilities()
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return 0;
|
||||
}
|
||||
return mSubRenderer->capabilities();
|
||||
}
|
||||
|
||||
QList<QString> QgsInvertedPolygonRenderer::usedAttributes()
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return QList<QString>();
|
||||
}
|
||||
return mSubRenderer->usedAttributes();
|
||||
}
|
||||
|
||||
QgsLegendSymbologyList QgsInvertedPolygonRenderer::legendSymbologyItems( QSize iconSize )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return QgsLegendSymbologyList();
|
||||
}
|
||||
return mSubRenderer->legendSymbologyItems( iconSize );
|
||||
}
|
||||
|
||||
QgsLegendSymbolList QgsInvertedPolygonRenderer::legendSymbolItems( double scaleDenominator, QString rule )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return QgsLegendSymbolList();
|
||||
}
|
||||
return mSubRenderer->legendSymbolItems( scaleDenominator, rule );
|
||||
}
|
||||
|
||||
bool QgsInvertedPolygonRenderer::willRenderFeature( QgsFeature& feat )
|
||||
{
|
||||
if ( !mSubRenderer ) {
|
||||
return false;
|
||||
}
|
||||
return mSubRenderer->willRenderFeature( feat );
|
||||
}
|
151
src/core/symbology-ng/qgsinvertedpolygonrenderer.h
Normal file
151
src/core/symbology-ng/qgsinvertedpolygonrenderer.h
Normal file
@ -0,0 +1,151 @@
|
||||
/***************************************************************************
|
||||
qgsinvertedpolygonrenderer.h
|
||||
---------------------
|
||||
begin : April 2014
|
||||
copyright : (C) 2014 Hugo Mercier / Oslandia
|
||||
email : hugo dot mercier at oslandia dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSINVERTEDPOLYGONRENDERER_H
|
||||
#define QGSINVERTEDPOLYGONRENDERER_H
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsrendererv2.h"
|
||||
#include "qgssymbolv2.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include <QScopedPointer>
|
||||
|
||||
/**
|
||||
* QgsInvertedPolygonRenderer is a polygon-only feature renderer used to
|
||||
* display features inverted, where the exterior is turned to an interior
|
||||
* and where the exterior theoretically spans the entire plane, allowing
|
||||
* to mask the surroundings of some features.
|
||||
*
|
||||
* It is designed on top of another feature renderer, which is called "embedded"
|
||||
* Most of the methods are then only proxies to the embedded renderer.
|
||||
*
|
||||
* Features are collected to form one "inverted" polygon
|
||||
* during renderFeature() and rendered on stopRender().
|
||||
*/
|
||||
class CORE_EXPORT QgsInvertedPolygonRenderer : public QgsFeatureRendererV2
|
||||
{
|
||||
public:
|
||||
|
||||
/** Constructor
|
||||
* @param embeddedRenderer optional embeddedRenderer. If null, a default one will be assigned
|
||||
*/
|
||||
QgsInvertedPolygonRenderer( const QgsFeatureRendererV2* embeddedRenderer = 0 );
|
||||
virtual ~QgsInvertedPolygonRenderer();
|
||||
|
||||
/** Used to clone this feature renderer.*/
|
||||
virtual QgsFeatureRendererV2* clone();
|
||||
|
||||
virtual void startRender( QgsRenderContext& context, const QgsFields& fields );
|
||||
|
||||
/** Renders a given feature.
|
||||
* This will here collect features. The actual rendering will be postponed to stopRender()
|
||||
* @param feature the feature to render
|
||||
* @param context the rendering context
|
||||
* @param layer the symbol layer to render, if that makes sense
|
||||
* @param selected whether this feature has been selected (this will add decorations)
|
||||
* @param drawVertexMarker whether this feature has vertex markers (in edit mode usually)
|
||||
* @returns true if the rendering was ok
|
||||
*/
|
||||
virtual bool renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false );
|
||||
|
||||
/**
|
||||
* The actual rendering will take place here.
|
||||
* Features collected during renderFeature() are rendered using the embedded feature renderer
|
||||
*/
|
||||
virtual void stopRender( QgsRenderContext& context );
|
||||
|
||||
/** @returns a textual reprensation of the renderer */
|
||||
virtual QString dump() const;
|
||||
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QList<QString> usedAttributes();
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual int capabilities();
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsSymbolV2List symbols();
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsSymbolV2List symbolsForFeature( QgsFeature& feat );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsLegendSymbologyList legendSymbologyItems( QSize iconSize );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = "" );
|
||||
/** Proxy that will call this method on the embedded renderer. */
|
||||
virtual bool willRenderFeature( QgsFeature& feat );
|
||||
|
||||
/** Creates a renderer out of an XML, for loading*/
|
||||
static QgsFeatureRendererV2* create( QDomElement& element );
|
||||
|
||||
/** Creates an XML representation of the renderer. Used for saving purpose
|
||||
* @param doc the XML document where to create the XML subtree
|
||||
* @returns the created XML subtree
|
||||
*/
|
||||
virtual QDomElement save( QDomDocument& doc );
|
||||
|
||||
/** sets the embedded renderer
|
||||
* @param subRenderer the embedded renderer (will be cloned)
|
||||
*/
|
||||
void setEmbeddedRenderer( const QgsFeatureRendererV2* subRenderer );
|
||||
/** @returns the current embedded renderer
|
||||
*/
|
||||
const QgsFeatureRendererV2* embeddedRenderer() const;
|
||||
|
||||
private:
|
||||
/** Private copy constructor. @see clone() */
|
||||
QgsInvertedPolygonRenderer( const QgsInvertedPolygonRenderer& );
|
||||
/** Private assignment operator. @see clone() */
|
||||
QgsInvertedPolygonRenderer& operator=( const QgsInvertedPolygonRenderer& );
|
||||
|
||||
/** Embedded renderer */
|
||||
QScopedPointer<QgsFeatureRendererV2> mSubRenderer;
|
||||
|
||||
/** Structure where the reversed geometry is built during renderFeature */
|
||||
struct CombinedFeature
|
||||
{
|
||||
QgsMultiPolygon multiPolygon; //< the final combined geometry
|
||||
QgsFeature feature; //< one feature (for attriute-based rendering)
|
||||
};
|
||||
typedef QMap< QByteArray, CombinedFeature > FeatureCategoryMap;
|
||||
/** where features are stored, based on their symbol category */
|
||||
FeatureCategoryMap mFeaturesCategoryMap;
|
||||
|
||||
/** the polygon used as exterior ring that covers the current extent */
|
||||
QgsPolygon mExtentPolygon;
|
||||
|
||||
/** the current coordinate transform (or null) */
|
||||
const QgsCoordinateTransform* mTransform;
|
||||
|
||||
/** fields of each feature*/
|
||||
QgsFields mFields;
|
||||
|
||||
/** Class used to represent features that must be rendered
|
||||
with decorations (selection, vertex markers)
|
||||
*/
|
||||
struct FeatureDecoration
|
||||
{
|
||||
QgsFeature feature;
|
||||
bool selected;
|
||||
bool drawMarkers;
|
||||
int layer;
|
||||
FeatureDecoration( QgsFeature& a_feature, bool a_selected, bool a_drawMarkers, int a_layer ) :
|
||||
feature(a_feature),selected(a_selected), drawMarkers(a_drawMarkers), layer(a_layer) {}
|
||||
};
|
||||
QList<FeatureDecoration> mFeatureDecorations;
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSMASKRENDERERV2_H
|
@ -20,6 +20,7 @@
|
||||
#include "qgsgraduatedsymbolrendererv2.h"
|
||||
#include "qgsrulebasedrendererv2.h"
|
||||
#include "qgspointdisplacementrenderer.h"
|
||||
#include "qgsinvertedpolygonrenderer.h"
|
||||
|
||||
QgsRendererV2Registry::QgsRendererV2Registry()
|
||||
{
|
||||
@ -44,6 +45,10 @@ QgsRendererV2Registry::QgsRendererV2Registry()
|
||||
addRenderer( new QgsRendererV2Metadata( "pointDisplacement",
|
||||
QObject::tr( "Point displacement" ),
|
||||
QgsPointDisplacementRenderer::create ) );
|
||||
|
||||
addRenderer( new QgsRendererV2Metadata( "invertedPolygonRenderer",
|
||||
QObject::tr( "Inverted polygons" ),
|
||||
QgsInvertedPolygonRenderer::create ) );
|
||||
}
|
||||
|
||||
QgsRendererV2Registry::~QgsRendererV2Registry()
|
||||
|
@ -20,6 +20,7 @@ symbology-ng/qgssinglesymbolrendererv2widget.cpp
|
||||
symbology-ng/qgscategorizedsymbolrendererv2widget.cpp
|
||||
symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp
|
||||
symbology-ng/qgsrulebasedrendererv2widget.cpp
|
||||
symbology-ng/qgsinvertedpolygonrendererwidget.cpp
|
||||
symbology-ng/qgsrendererv2propertiesdialog.cpp
|
||||
symbology-ng/qgsstylev2managerdialog.cpp
|
||||
symbology-ng/qgssymbollevelsv2dialog.cpp
|
||||
@ -231,6 +232,7 @@ symbology-ng/qgscategorizedsymbolrendererv2widget.h
|
||||
symbology-ng/qgsdatadefinedsymboldialog.h
|
||||
symbology-ng/qgsgraduatedsymbolrendererv2widget.h
|
||||
symbology-ng/qgsrulebasedrendererv2widget.h
|
||||
symbology-ng/qgsinvertedpolygonrendererwidget.h
|
||||
symbology-ng/qgsrendererv2widget.h
|
||||
symbology-ng/qgsrendererv2propertiesdialog.h
|
||||
symbology-ng/qgsstylev2managerdialog.h
|
||||
|
132
src/gui/symbology-ng/qgsinvertedpolygonrendererwidget.cpp
Normal file
132
src/gui/symbology-ng/qgsinvertedpolygonrendererwidget.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/***************************************************************************
|
||||
qgsinvertedpolygonrendererwidget.cpp
|
||||
---------------------
|
||||
begin : April 2014
|
||||
copyright : (C) 2014 Hugo Mercier / Oslandia
|
||||
email : hugo dot mercier at oslandia dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsinvertedpolygonrendererwidget.h"
|
||||
#include "qgsinvertedpolygonrenderer.h"
|
||||
#include "qgsrendererv2registry.h"
|
||||
|
||||
#include "qgssymbolv2.h"
|
||||
|
||||
#include "qgslogger.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
QgsRendererV2Widget* QgsInvertedPolygonRendererWidget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
|
||||
{
|
||||
return new QgsInvertedPolygonRendererWidget( layer, style, renderer );
|
||||
}
|
||||
|
||||
QgsInvertedPolygonRendererWidget::QgsInvertedPolygonRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
|
||||
: QgsRendererV2Widget( layer, style )
|
||||
{
|
||||
if ( !layer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// the renderer only applies to polygon vector layers
|
||||
if ( layer->wkbType() != QGis::WKBPolygon &&
|
||||
layer->wkbType() != QGis::WKBPolygon25D &&
|
||||
layer->wkbType() != QGis::WKBMultiPolygon &&
|
||||
layer->wkbType() != QGis::WKBMultiPolygon25D )
|
||||
{
|
||||
//setup blank dialog
|
||||
mRenderer.reset( 0 );
|
||||
QGridLayout* layout = new QGridLayout( this );
|
||||
QLabel* label = new QLabel( tr( "The inverted polygon renderer only applies to polygon and multipolygon layers. \n"
|
||||
"'%1' is not a polygon layer and then cannot be displayed" )
|
||||
.arg( layer->name() ), this );
|
||||
layout->addWidget( label );
|
||||
return;
|
||||
}
|
||||
setupUi( this );
|
||||
|
||||
// try to recognize the previous renderer
|
||||
// (null renderer means "no previous renderer")
|
||||
if ( !renderer )
|
||||
{
|
||||
// a new renderer
|
||||
mRenderer.reset( new QgsInvertedPolygonRenderer() );
|
||||
}
|
||||
else if ( renderer && renderer->type() != "invertedPolygonRenderer" )
|
||||
{
|
||||
// an existing renderer, but not an inverted renderer
|
||||
// create an inverted renderer, with the existing renderer embedded
|
||||
mRenderer.reset( new QgsInvertedPolygonRenderer( renderer ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// an existing inverted renderer
|
||||
mRenderer.reset( static_cast<QgsInvertedPolygonRenderer*>(renderer) );
|
||||
}
|
||||
|
||||
int currentEmbeddedIdx = 0;
|
||||
//insert possible renderer types
|
||||
QStringList rendererList = QgsRendererV2Registry::instance()->renderersList();
|
||||
QStringList::const_iterator it = rendererList.constBegin();
|
||||
int idx = 0;
|
||||
mRendererComboBox->blockSignals( true );
|
||||
for ( ; it != rendererList.constEnd(); ++it, ++idx )
|
||||
{
|
||||
if (( *it != "invertedPolygonRenderer" ) && //< an inverted renderer cannot contain another inverted renderer
|
||||
( *it != "pointDisplacement" )) //< an inverted renderer can only contain a polygon renderer
|
||||
{
|
||||
QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( *it );
|
||||
mRendererComboBox->addItem( m->icon(), m->visibleName(), /* data */ *it );
|
||||
const QgsFeatureRendererV2* embeddedRenderer = mRenderer->embeddedRenderer();
|
||||
if ( embeddedRenderer && embeddedRenderer->type() == m->name() )
|
||||
{
|
||||
// store the combo box index of the current renderer
|
||||
currentEmbeddedIdx = idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
mRendererComboBox->blockSignals( false );
|
||||
|
||||
int oldIdx = mRendererComboBox->currentIndex();
|
||||
mRendererComboBox->setCurrentIndex( currentEmbeddedIdx );
|
||||
if ( oldIdx == currentEmbeddedIdx )
|
||||
{
|
||||
// force update
|
||||
on_mRendererComboBox_currentIndexChanged( currentEmbeddedIdx );
|
||||
}
|
||||
}
|
||||
|
||||
QgsFeatureRendererV2* QgsInvertedPolygonRendererWidget::renderer()
|
||||
{
|
||||
if ( mRenderer && mEmbeddedRendererWidget )
|
||||
{
|
||||
QgsFeatureRendererV2* embeddedRenderer = mEmbeddedRendererWidget->renderer();
|
||||
if ( embeddedRenderer )
|
||||
{
|
||||
mRenderer->setEmbeddedRenderer( embeddedRenderer->clone() );
|
||||
}
|
||||
}
|
||||
return mRenderer.data();
|
||||
}
|
||||
|
||||
void QgsInvertedPolygonRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
|
||||
{
|
||||
QString rendererId = mRendererComboBox->itemData( index ).toString();
|
||||
QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( rendererId );
|
||||
if ( m )
|
||||
{
|
||||
mEmbeddedRendererWidget.reset( m->createRendererWidget( mLayer, mStyle, const_cast<QgsFeatureRendererV2*>(mRenderer->embeddedRenderer())->clone() ) );
|
||||
|
||||
if ( mLayout->count() > 1 ) {
|
||||
// remove the current renderer widget
|
||||
mLayout->takeAt( 1 );
|
||||
}
|
||||
mLayout->addWidget( mEmbeddedRendererWidget.data() );
|
||||
}
|
||||
}
|
||||
|
60
src/gui/symbology-ng/qgsinvertedpolygonrendererwidget.h
Normal file
60
src/gui/symbology-ng/qgsinvertedpolygonrendererwidget.h
Normal file
@ -0,0 +1,60 @@
|
||||
/***************************************************************************
|
||||
qgsinvertedpolygonrendererwidget.h
|
||||
---------------------
|
||||
begin : April 2014
|
||||
copyright : (C) 2014 Hugo Mercier / Oslandia
|
||||
email : hugo dot mercier at oslandia dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSINVERTEDPOLYGONRENDERERWIDGET_H
|
||||
#define QGSINVERTEDPOLYGONRENDERERWIDGET_H
|
||||
|
||||
#include "ui_qgsinvertedpolygonrendererwidgetbase.h"
|
||||
#include "qgsinvertedpolygonrenderer.h"
|
||||
#include "qgsrendererv2widget.h"
|
||||
|
||||
class QMenu;
|
||||
|
||||
/**
|
||||
* A widget used represent options of a QgsInvertedPolygonRenderer
|
||||
*/
|
||||
class GUI_EXPORT QgsInvertedPolygonRendererWidget : public QgsRendererV2Widget, private Ui::QgsInvertedPolygonRendererWidgetBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/** static creation method
|
||||
* @param layer the layer where this renderer is applied
|
||||
* @param style
|
||||
* @param renderer the mask renderer (will take ownership)
|
||||
*/
|
||||
static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
|
||||
|
||||
/** Constructor
|
||||
* @param layer the layer where this renderer is applied
|
||||
* @param style
|
||||
* @param renderer the mask renderer (will take ownership)
|
||||
*/
|
||||
QgsInvertedPolygonRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
|
||||
|
||||
/** @returns the current feature renderer */
|
||||
virtual QgsFeatureRendererV2* renderer();
|
||||
|
||||
protected:
|
||||
/** the mask renderer */
|
||||
QScopedPointer<QgsInvertedPolygonRenderer> mRenderer;
|
||||
/** the widget used to represent the mask's embedded renderer */
|
||||
QScopedPointer<QgsRendererV2Widget> mEmbeddedRendererWidget;
|
||||
|
||||
private slots:
|
||||
void on_mRendererComboBox_currentIndexChanged( int index );
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSMASKRENDERERV2WIDGET_H
|
@ -23,6 +23,7 @@
|
||||
#include "qgsgraduatedsymbolrendererv2widget.h"
|
||||
#include "qgsrulebasedrendererv2widget.h"
|
||||
#include "qgspointdisplacementrendererwidget.h"
|
||||
#include "qgsinvertedpolygonrendererwidget.h"
|
||||
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslogger.h"
|
||||
@ -66,6 +67,7 @@ static void _initRendererWidgetFunctions()
|
||||
_initRenderer( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create, "rendererGraduatedSymbol.png" );
|
||||
_initRenderer( "RuleRenderer", QgsRuleBasedRendererV2Widget::create );
|
||||
_initRenderer( "pointDisplacement", QgsPointDisplacementRendererWidget::create );
|
||||
_initRenderer( "invertedPolygonRenderer", QgsInvertedPolygonRendererWidget::create );
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
|
35
src/ui/qgsinvertedpolygonrendererwidgetbase.ui
Normal file
35
src/ui/qgsinvertedpolygonrendererwidgetbase.ui
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsInvertedPolygonRendererWidgetBase</class>
|
||||
<widget class="QWidget" name="QgsInvertedPolygonRendererWidgetBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>390</width>
|
||||
<height>79</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="mLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="mRendererLabel">
|
||||
<property name="text">
|
||||
<string>Sub renderer:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mRendererComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -121,3 +121,4 @@ ADD_QGIS_TEST(vectorlayercachetest testqgsvectorlayercache.cpp )
|
||||
ADD_QGIS_TEST(spatialindextest testqgsspatialindex.cpp)
|
||||
ADD_QGIS_TEST(gradienttest testqgsgradients.cpp )
|
||||
ADD_QGIS_TEST(shapebursttest testqgsshapeburst.cpp )
|
||||
ADD_QGIS_TEST(invertedpolygontest testqgsinvertedpolygonrenderer.cpp )
|
||||
|
152
tests/src/core/testqgsinvertedpolygonrenderer.cpp
Normal file
152
tests/src/core/testqgsinvertedpolygonrenderer.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/***************************************************************************
|
||||
testqgsinvertedpolygonrenderer.cpp
|
||||
--------------------------------------
|
||||
Date : 23 may 2014
|
||||
Copyright : (C) 2014 by Hugo Mercier / Oslandia
|
||||
Email : hugo dot mercier at oslandia dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include <QtTest>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QObject>
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QDesktopServices>
|
||||
|
||||
#include <iostream>
|
||||
//qgis includes...
|
||||
#include <qgsmaprenderer.h>
|
||||
#include <qgsmaplayer.h>
|
||||
#include <qgsvectorlayer.h>
|
||||
#include <qgsapplication.h>
|
||||
#include <qgsproviderregistry.h>
|
||||
#include <qgsmaplayerregistry.h>
|
||||
//qgis test includes
|
||||
#include "qgsrenderchecker.h"
|
||||
|
||||
/** \ingroup UnitTests
|
||||
* This is a unit test for the different renderers for vector layers.
|
||||
*/
|
||||
class TestQgsInvertedPolygon: public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
private slots:
|
||||
void initTestCase();// will be called before the first testfunction is executed.
|
||||
void cleanupTestCase();// will be called after the last testfunction was executed.
|
||||
void init() {};// will be called before each testfunction is executed.
|
||||
void cleanup() {};// will be called after every testfunction.
|
||||
|
||||
void singleSubRenderer();
|
||||
void graduatedSubRenderer();
|
||||
|
||||
private:
|
||||
bool mTestHasError;
|
||||
bool setQml( QString qmlFile );
|
||||
bool imageCheck( QString theType );
|
||||
QgsMapSettings mMapSettings;
|
||||
QgsVectorLayer * mpPolysLayer;
|
||||
QString mTestDataDir;
|
||||
QString mReport;
|
||||
};
|
||||
|
||||
|
||||
void TestQgsInvertedPolygon::initTestCase()
|
||||
{
|
||||
mTestHasError = false;
|
||||
// init QGIS's paths - true means that all path will be inited from prefix
|
||||
QgsApplication::init();
|
||||
QgsApplication::initQgis();
|
||||
QgsApplication::showSettings();
|
||||
|
||||
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
|
||||
mTestDataDir = myDataDir + QDir::separator();
|
||||
|
||||
//
|
||||
//create a poly layer that will be used in all tests...
|
||||
//
|
||||
QString myPolysFileName = mTestDataDir + "polys.shp";
|
||||
QFileInfo myPolyFileInfo( myPolysFileName );
|
||||
mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
|
||||
myPolyFileInfo.completeBaseName(), "ogr" );
|
||||
QgsVectorSimplifyMethod simplifyMethod;
|
||||
simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
|
||||
mpPolysLayer->setSimplifyMethod( simplifyMethod );
|
||||
|
||||
// Register the layer with the registry
|
||||
QgsMapLayerRegistry::instance()->addMapLayers(
|
||||
QList<QgsMapLayer *>() << mpPolysLayer );
|
||||
|
||||
mMapSettings.setLayers( QStringList() << mpPolysLayer->id() );
|
||||
mReport += "<h1>Inverted Polygon Renderer Tests</h1>\n";
|
||||
}
|
||||
|
||||
void TestQgsInvertedPolygon::cleanupTestCase()
|
||||
{
|
||||
QString myReportFile = QDir::tempPath() + QDir::separator() + "qgistest.html";
|
||||
QFile myFile( myReportFile );
|
||||
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
|
||||
{
|
||||
QTextStream myQTextStream( &myFile );
|
||||
myQTextStream << mReport;
|
||||
myFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void TestQgsInvertedPolygon::singleSubRenderer()
|
||||
{
|
||||
mReport += "<h2>Inverted polygon renderer, single sub renderer test</h2>\n";
|
||||
QVERIFY( setQml( "inverted_polys_single.qml" ) );
|
||||
QVERIFY( imageCheck( "inverted_polys_single" ) );
|
||||
}
|
||||
|
||||
void TestQgsInvertedPolygon::graduatedSubRenderer()
|
||||
{
|
||||
mReport += "<h2>Inverted polygon renderer, graduated sub renderer test</h2>\n";
|
||||
QVERIFY( setQml( "inverted_polys_graduated.qml" ) );
|
||||
QVERIFY( imageCheck( "inverted_polys_graduated" ) );
|
||||
}
|
||||
|
||||
//
|
||||
// Private helper functions not called directly by CTest
|
||||
//
|
||||
|
||||
bool TestQgsInvertedPolygon::setQml( QString qmlFile )
|
||||
{
|
||||
//load a qml style and apply to our layer
|
||||
//the style will correspond to the renderer
|
||||
//type we are testing
|
||||
bool myStyleFlag = false;
|
||||
QString myFileName = mTestDataDir + qmlFile;
|
||||
QString error = mpPolysLayer->loadNamedStyle( myFileName, myStyleFlag );
|
||||
if ( !myStyleFlag )
|
||||
{
|
||||
qDebug( "%s", error.toLocal8Bit().constData() );
|
||||
return false;
|
||||
}
|
||||
return myStyleFlag;
|
||||
}
|
||||
|
||||
bool TestQgsInvertedPolygon::imageCheck( QString theTestType )
|
||||
{
|
||||
//use the QgsRenderChecker test utility class to
|
||||
//ensure the rendered output matches our control image
|
||||
mMapSettings.setExtent( mpPolysLayer->extent() );
|
||||
QgsRenderChecker myChecker;
|
||||
myChecker.setControlName( "expected_" + theTestType );
|
||||
myChecker.setMapSettings( mMapSettings );
|
||||
bool myResultFlag = myChecker.runTest( theTestType );
|
||||
mReport += myChecker.report();
|
||||
return myResultFlag;
|
||||
}
|
||||
|
||||
QTEST_MAIN( TestQgsInvertedPolygon )
|
||||
#include "moc_testqgsinvertedpolygonrenderer.cxx"
|
Binary file not shown.
After Width: | Height: | Size: 626 KiB |
BIN
tests/testdata/control_images/expected_inverted_polys_single/expected_inverted_polys_single.png
vendored
Normal file
BIN
tests/testdata/control_images/expected_inverted_polys_single/expected_inverted_polys_single.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 626 KiB |
228
tests/testdata/inverted_polys_graduated.qml
vendored
Normal file
228
tests/testdata/inverted_polys_graduated.qml
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
||||
<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">
|
||||
<renderer-v2 type="invertedPolygonRenderer">
|
||||
<renderer-v2 attr="Name" symbollevels="0" type="categorizedSymbol">
|
||||
<categories>
|
||||
<category symbol="0" value="Dam" label="Dam"/>
|
||||
<category symbol="1" value="Lake" label="Lake"/>
|
||||
</categories>
|
||||
<symbols>
|
||||
<symbol alpha="1" type="fill" name="0">
|
||||
<layer pass="0" class="ShapeburstFill" locked="0">
|
||||
<prop k="blur_radius" v="0"/>
|
||||
<prop k="color1" v="0,0,255,255"/>
|
||||
<prop k="color2" v="0,255,0,255"/>
|
||||
<prop k="color_type" v="0"/>
|
||||
<prop k="discrete" v="0"/>
|
||||
<prop k="distance_map_unit_scale" v="0,0"/>
|
||||
<prop k="distance_unit" v="MM"/>
|
||||
<prop k="ignore_rings" v="0"/>
|
||||
<prop k="max_distance" v="5"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="shapeburst_color" v="27,54,212,255"/>
|
||||
<prop k="shapeburst_color2" v="255,255,255,0"/>
|
||||
<prop k="use_whole_shape" v="0"/>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol alpha="1" type="fill" name="1">
|
||||
<layer pass="0" class="ShapeburstFill" locked="0">
|
||||
<prop k="blur_radius" v="0"/>
|
||||
<prop k="color1" v="0,0,255,255"/>
|
||||
<prop k="color2" v="0,255,0,255"/>
|
||||
<prop k="color_type" v="0"/>
|
||||
<prop k="discrete" v="0"/>
|
||||
<prop k="distance_map_unit_scale" v="0,0"/>
|
||||
<prop k="distance_unit" v="MM"/>
|
||||
<prop k="ignore_rings" v="0"/>
|
||||
<prop k="max_distance" v="5"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="shapeburst_color" v="110,194,217,255"/>
|
||||
<prop k="shapeburst_color2" v="255,255,255,0"/>
|
||||
<prop k="use_whole_shape" v="0"/>
|
||||
</layer>
|
||||
</symbol>
|
||||
</symbols>
|
||||
<rotation/>
|
||||
<sizescale scalemethod="area"/>
|
||||
</renderer-v2>
|
||||
</renderer-v2>
|
||||
<customproperties>
|
||||
<property key="labeling" value="pal"/>
|
||||
<property key="labeling/addDirectionSymbol" value="false"/>
|
||||
<property key="labeling/angleOffset" value="0"/>
|
||||
<property key="labeling/blendMode" value="0"/>
|
||||
<property key="labeling/bufferBlendMode" value="0"/>
|
||||
<property key="labeling/bufferColorA" value="255"/>
|
||||
<property key="labeling/bufferColorB" value="255"/>
|
||||
<property key="labeling/bufferColorG" value="255"/>
|
||||
<property key="labeling/bufferColorR" value="255"/>
|
||||
<property key="labeling/bufferDraw" value="false"/>
|
||||
<property key="labeling/bufferJoinStyle" value="64"/>
|
||||
<property key="labeling/bufferNoFill" value="false"/>
|
||||
<property key="labeling/bufferSize" value="1"/>
|
||||
<property key="labeling/bufferSizeInMapUnits" value="false"/>
|
||||
<property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/bufferTransp" value="0"/>
|
||||
<property key="labeling/centroidWhole" value="false"/>
|
||||
<property key="labeling/decimals" value="3"/>
|
||||
<property key="labeling/displayAll" value="false"/>
|
||||
<property key="labeling/dist" value="0"/>
|
||||
<property key="labeling/distInMapUnits" value="false"/>
|
||||
<property key="labeling/distMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/distMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/enabled" value="false"/>
|
||||
<property key="labeling/fieldName" value=""/>
|
||||
<property key="labeling/fontBold" value="true"/>
|
||||
<property key="labeling/fontCapitals" value="0"/>
|
||||
<property key="labeling/fontFamily" value="Ubuntu"/>
|
||||
<property key="labeling/fontItalic" value="true"/>
|
||||
<property key="labeling/fontLetterSpacing" value="0"/>
|
||||
<property key="labeling/fontLimitPixelSize" value="false"/>
|
||||
<property key="labeling/fontMaxPixelSize" value="10000"/>
|
||||
<property key="labeling/fontMinPixelSize" value="3"/>
|
||||
<property key="labeling/fontSize" value="11"/>
|
||||
<property key="labeling/fontSizeInMapUnits" value="false"/>
|
||||
<property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/fontSizeMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/fontStrikeout" value="false"/>
|
||||
<property key="labeling/fontUnderline" value="false"/>
|
||||
<property key="labeling/fontWeight" value="75"/>
|
||||
<property key="labeling/fontWordSpacing" value="0"/>
|
||||
<property key="labeling/formatNumbers" value="false"/>
|
||||
<property key="labeling/isExpression" value="false"/>
|
||||
<property key="labeling/labelOffsetInMapUnits" value="true"/>
|
||||
<property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/labelPerPart" value="false"/>
|
||||
<property key="labeling/leftDirectionSymbol" value="<"/>
|
||||
<property key="labeling/limitNumLabels" value="false"/>
|
||||
<property key="labeling/maxCurvedCharAngleIn" value="20"/>
|
||||
<property key="labeling/maxCurvedCharAngleOut" value="-20"/>
|
||||
<property key="labeling/maxNumLabels" value="2000"/>
|
||||
<property key="labeling/mergeLines" value="false"/>
|
||||
<property key="labeling/minFeatureSize" value="0"/>
|
||||
<property key="labeling/multilineAlign" value="0"/>
|
||||
<property key="labeling/multilineHeight" value="1"/>
|
||||
<property key="labeling/namedStyle" value="Bold Italic"/>
|
||||
<property key="labeling/obstacle" value="true"/>
|
||||
<property key="labeling/placeDirectionSymbol" value="0"/>
|
||||
<property key="labeling/placement" value="0"/>
|
||||
<property key="labeling/placementFlags" value="0"/>
|
||||
<property key="labeling/plussign" value="false"/>
|
||||
<property key="labeling/preserveRotation" value="true"/>
|
||||
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
|
||||
<property key="labeling/priority" value="5"/>
|
||||
<property key="labeling/quadOffset" value="4"/>
|
||||
<property key="labeling/reverseDirectionSymbol" value="false"/>
|
||||
<property key="labeling/rightDirectionSymbol" value=">"/>
|
||||
<property key="labeling/scaleMax" value="10000000"/>
|
||||
<property key="labeling/scaleMin" value="1"/>
|
||||
<property key="labeling/scaleVisibility" value="false"/>
|
||||
<property key="labeling/shadowBlendMode" value="6"/>
|
||||
<property key="labeling/shadowColorB" value="0"/>
|
||||
<property key="labeling/shadowColorG" value="0"/>
|
||||
<property key="labeling/shadowColorR" value="0"/>
|
||||
<property key="labeling/shadowDraw" value="false"/>
|
||||
<property key="labeling/shadowOffsetAngle" value="135"/>
|
||||
<property key="labeling/shadowOffsetDist" value="1"/>
|
||||
<property key="labeling/shadowOffsetGlobal" value="true"/>
|
||||
<property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shadowOffsetUnits" value="1"/>
|
||||
<property key="labeling/shadowRadius" value="1.5"/>
|
||||
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
|
||||
<property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shadowRadiusUnits" value="1"/>
|
||||
<property key="labeling/shadowScale" value="100"/>
|
||||
<property key="labeling/shadowTransparency" value="30"/>
|
||||
<property key="labeling/shadowUnder" value="0"/>
|
||||
<property key="labeling/shapeBlendMode" value="0"/>
|
||||
<property key="labeling/shapeBorderColorA" value="255"/>
|
||||
<property key="labeling/shapeBorderColorB" value="128"/>
|
||||
<property key="labeling/shapeBorderColorG" value="128"/>
|
||||
<property key="labeling/shapeBorderColorR" value="128"/>
|
||||
<property key="labeling/shapeBorderWidth" value="0"/>
|
||||
<property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeBorderWidthUnits" value="1"/>
|
||||
<property key="labeling/shapeDraw" value="false"/>
|
||||
<property key="labeling/shapeFillColorA" value="255"/>
|
||||
<property key="labeling/shapeFillColorB" value="255"/>
|
||||
<property key="labeling/shapeFillColorG" value="255"/>
|
||||
<property key="labeling/shapeFillColorR" value="255"/>
|
||||
<property key="labeling/shapeJoinStyle" value="64"/>
|
||||
<property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeOffsetUnits" value="1"/>
|
||||
<property key="labeling/shapeOffsetX" value="0"/>
|
||||
<property key="labeling/shapeOffsetY" value="0"/>
|
||||
<property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeRadiiUnits" value="1"/>
|
||||
<property key="labeling/shapeRadiiX" value="0"/>
|
||||
<property key="labeling/shapeRadiiY" value="0"/>
|
||||
<property key="labeling/shapeRotation" value="0"/>
|
||||
<property key="labeling/shapeRotationType" value="0"/>
|
||||
<property key="labeling/shapeSVGFile" value=""/>
|
||||
<property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeSizeType" value="0"/>
|
||||
<property key="labeling/shapeSizeUnits" value="1"/>
|
||||
<property key="labeling/shapeSizeX" value="0"/>
|
||||
<property key="labeling/shapeSizeY" value="0"/>
|
||||
<property key="labeling/shapeTransparency" value="0"/>
|
||||
<property key="labeling/shapeType" value="0"/>
|
||||
<property key="labeling/textColorA" value="255"/>
|
||||
<property key="labeling/textColorB" value="0"/>
|
||||
<property key="labeling/textColorG" value="0"/>
|
||||
<property key="labeling/textColorR" value="0"/>
|
||||
<property key="labeling/textTransp" value="0"/>
|
||||
<property key="labeling/upsidedownLabels" value="0"/>
|
||||
<property key="labeling/wrapChar" value=""/>
|
||||
<property key="labeling/xOffset" value="0"/>
|
||||
<property key="labeling/yOffset" value="0"/>
|
||||
</customproperties>
|
||||
<blendMode>0</blendMode>
|
||||
<featureBlendMode>0</featureBlendMode>
|
||||
<layerTransparency>0</layerTransparency>
|
||||
<displayfield>Name</displayfield>
|
||||
<label>0</label>
|
||||
<labelattributes>
|
||||
<label fieldname="" text="Label"/>
|
||||
<family fieldname="" name="Lucida Grande"/>
|
||||
<size fieldname="" units="pt" value="12"/>
|
||||
<bold fieldname="" on="0"/>
|
||||
<italic fieldname="" on="0"/>
|
||||
<underline fieldname="" on="0"/>
|
||||
<strikeout fieldname="" on="0"/>
|
||||
<color fieldname="" red="0" blue="0" green="0"/>
|
||||
<x fieldname=""/>
|
||||
<y fieldname=""/>
|
||||
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
|
||||
<angle fieldname="" value="0" auto="0"/>
|
||||
<alignment fieldname="" value="center"/>
|
||||
<buffercolor fieldname="" red="255" blue="255" green="255"/>
|
||||
<buffersize fieldname="" units="pt" value="1"/>
|
||||
<bufferenabled fieldname="" on=""/>
|
||||
<multilineenabled fieldname="" on=""/>
|
||||
<selectedonly on=""/>
|
||||
</labelattributes>
|
||||
<edittypes>
|
||||
<edittype labelontop="0" editable="1" type="0" name="Name"/>
|
||||
<edittype labelontop="0" editable="1" type="0" name="Value"/>
|
||||
</edittypes>
|
||||
<editform></editform>
|
||||
<editforminit></editforminit>
|
||||
<featformsuppress>0</featformsuppress>
|
||||
<annotationform></annotationform>
|
||||
<editorlayout>generatedlayout</editorlayout>
|
||||
<excludeAttributesWMS/>
|
||||
<excludeAttributesWFS/>
|
||||
<attributeactions/>
|
||||
</qgis>
|
201
tests/testdata/inverted_polys_single.qml
vendored
Normal file
201
tests/testdata/inverted_polys_single.qml
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
||||
<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">
|
||||
<renderer-v2 type="invertedPolygonRenderer">
|
||||
<renderer-v2 symbollevels="0" type="singleSymbol">
|
||||
<symbols>
|
||||
<symbol alpha="1" type="fill" name="0">
|
||||
<layer pass="0" class="SimpleFill" locked="0">
|
||||
<prop k="border_width_map_unit_scale" v="0,0"/>
|
||||
<prop k="border_width_unit" v="MM"/>
|
||||
<prop k="color" v="76,143,160,255"/>
|
||||
<prop k="color_border" v="0,0,0,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<prop k="style_border" v="solid"/>
|
||||
<prop k="width_border" v="0.26"/>
|
||||
</layer>
|
||||
</symbol>
|
||||
</symbols>
|
||||
<rotation/>
|
||||
<sizescale scalemethod="area"/>
|
||||
</renderer-v2>
|
||||
</renderer-v2>
|
||||
<customproperties>
|
||||
<property key="labeling" value="pal"/>
|
||||
<property key="labeling/addDirectionSymbol" value="false"/>
|
||||
<property key="labeling/angleOffset" value="0"/>
|
||||
<property key="labeling/blendMode" value="0"/>
|
||||
<property key="labeling/bufferBlendMode" value="0"/>
|
||||
<property key="labeling/bufferColorA" value="255"/>
|
||||
<property key="labeling/bufferColorB" value="255"/>
|
||||
<property key="labeling/bufferColorG" value="255"/>
|
||||
<property key="labeling/bufferColorR" value="255"/>
|
||||
<property key="labeling/bufferDraw" value="false"/>
|
||||
<property key="labeling/bufferJoinStyle" value="64"/>
|
||||
<property key="labeling/bufferNoFill" value="false"/>
|
||||
<property key="labeling/bufferSize" value="1"/>
|
||||
<property key="labeling/bufferSizeInMapUnits" value="false"/>
|
||||
<property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/bufferTransp" value="0"/>
|
||||
<property key="labeling/centroidWhole" value="false"/>
|
||||
<property key="labeling/decimals" value="3"/>
|
||||
<property key="labeling/displayAll" value="false"/>
|
||||
<property key="labeling/dist" value="0"/>
|
||||
<property key="labeling/distInMapUnits" value="false"/>
|
||||
<property key="labeling/distMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/distMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/enabled" value="false"/>
|
||||
<property key="labeling/fieldName" value=""/>
|
||||
<property key="labeling/fontBold" value="true"/>
|
||||
<property key="labeling/fontCapitals" value="0"/>
|
||||
<property key="labeling/fontFamily" value="Ubuntu"/>
|
||||
<property key="labeling/fontItalic" value="true"/>
|
||||
<property key="labeling/fontLetterSpacing" value="0"/>
|
||||
<property key="labeling/fontLimitPixelSize" value="false"/>
|
||||
<property key="labeling/fontMaxPixelSize" value="10000"/>
|
||||
<property key="labeling/fontMinPixelSize" value="3"/>
|
||||
<property key="labeling/fontSize" value="11"/>
|
||||
<property key="labeling/fontSizeInMapUnits" value="false"/>
|
||||
<property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/fontSizeMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/fontStrikeout" value="false"/>
|
||||
<property key="labeling/fontUnderline" value="false"/>
|
||||
<property key="labeling/fontWeight" value="75"/>
|
||||
<property key="labeling/fontWordSpacing" value="0"/>
|
||||
<property key="labeling/formatNumbers" value="false"/>
|
||||
<property key="labeling/isExpression" value="false"/>
|
||||
<property key="labeling/labelOffsetInMapUnits" value="true"/>
|
||||
<property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/labelPerPart" value="false"/>
|
||||
<property key="labeling/leftDirectionSymbol" value="<"/>
|
||||
<property key="labeling/limitNumLabels" value="false"/>
|
||||
<property key="labeling/maxCurvedCharAngleIn" value="20"/>
|
||||
<property key="labeling/maxCurvedCharAngleOut" value="-20"/>
|
||||
<property key="labeling/maxNumLabels" value="2000"/>
|
||||
<property key="labeling/mergeLines" value="false"/>
|
||||
<property key="labeling/minFeatureSize" value="0"/>
|
||||
<property key="labeling/multilineAlign" value="0"/>
|
||||
<property key="labeling/multilineHeight" value="1"/>
|
||||
<property key="labeling/namedStyle" value="Bold Italic"/>
|
||||
<property key="labeling/obstacle" value="true"/>
|
||||
<property key="labeling/placeDirectionSymbol" value="0"/>
|
||||
<property key="labeling/placement" value="0"/>
|
||||
<property key="labeling/placementFlags" value="0"/>
|
||||
<property key="labeling/plussign" value="false"/>
|
||||
<property key="labeling/preserveRotation" value="true"/>
|
||||
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
|
||||
<property key="labeling/priority" value="5"/>
|
||||
<property key="labeling/quadOffset" value="4"/>
|
||||
<property key="labeling/reverseDirectionSymbol" value="false"/>
|
||||
<property key="labeling/rightDirectionSymbol" value=">"/>
|
||||
<property key="labeling/scaleMax" value="10000000"/>
|
||||
<property key="labeling/scaleMin" value="1"/>
|
||||
<property key="labeling/scaleVisibility" value="false"/>
|
||||
<property key="labeling/shadowBlendMode" value="6"/>
|
||||
<property key="labeling/shadowColorB" value="0"/>
|
||||
<property key="labeling/shadowColorG" value="0"/>
|
||||
<property key="labeling/shadowColorR" value="0"/>
|
||||
<property key="labeling/shadowDraw" value="false"/>
|
||||
<property key="labeling/shadowOffsetAngle" value="135"/>
|
||||
<property key="labeling/shadowOffsetDist" value="1"/>
|
||||
<property key="labeling/shadowOffsetGlobal" value="true"/>
|
||||
<property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shadowOffsetUnits" value="1"/>
|
||||
<property key="labeling/shadowRadius" value="1.5"/>
|
||||
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
|
||||
<property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shadowRadiusUnits" value="1"/>
|
||||
<property key="labeling/shadowScale" value="100"/>
|
||||
<property key="labeling/shadowTransparency" value="30"/>
|
||||
<property key="labeling/shadowUnder" value="0"/>
|
||||
<property key="labeling/shapeBlendMode" value="0"/>
|
||||
<property key="labeling/shapeBorderColorA" value="255"/>
|
||||
<property key="labeling/shapeBorderColorB" value="128"/>
|
||||
<property key="labeling/shapeBorderColorG" value="128"/>
|
||||
<property key="labeling/shapeBorderColorR" value="128"/>
|
||||
<property key="labeling/shapeBorderWidth" value="0"/>
|
||||
<property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeBorderWidthUnits" value="1"/>
|
||||
<property key="labeling/shapeDraw" value="false"/>
|
||||
<property key="labeling/shapeFillColorA" value="255"/>
|
||||
<property key="labeling/shapeFillColorB" value="255"/>
|
||||
<property key="labeling/shapeFillColorG" value="255"/>
|
||||
<property key="labeling/shapeFillColorR" value="255"/>
|
||||
<property key="labeling/shapeJoinStyle" value="64"/>
|
||||
<property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeOffsetUnits" value="1"/>
|
||||
<property key="labeling/shapeOffsetX" value="0"/>
|
||||
<property key="labeling/shapeOffsetY" value="0"/>
|
||||
<property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeRadiiUnits" value="1"/>
|
||||
<property key="labeling/shapeRadiiX" value="0"/>
|
||||
<property key="labeling/shapeRadiiY" value="0"/>
|
||||
<property key="labeling/shapeRotation" value="0"/>
|
||||
<property key="labeling/shapeRotationType" value="0"/>
|
||||
<property key="labeling/shapeSVGFile" value=""/>
|
||||
<property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
|
||||
<property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
|
||||
<property key="labeling/shapeSizeType" value="0"/>
|
||||
<property key="labeling/shapeSizeUnits" value="1"/>
|
||||
<property key="labeling/shapeSizeX" value="0"/>
|
||||
<property key="labeling/shapeSizeY" value="0"/>
|
||||
<property key="labeling/shapeTransparency" value="0"/>
|
||||
<property key="labeling/shapeType" value="0"/>
|
||||
<property key="labeling/textColorA" value="255"/>
|
||||
<property key="labeling/textColorB" value="0"/>
|
||||
<property key="labeling/textColorG" value="0"/>
|
||||
<property key="labeling/textColorR" value="0"/>
|
||||
<property key="labeling/textTransp" value="0"/>
|
||||
<property key="labeling/upsidedownLabels" value="0"/>
|
||||
<property key="labeling/wrapChar" value=""/>
|
||||
<property key="labeling/xOffset" value="0"/>
|
||||
<property key="labeling/yOffset" value="0"/>
|
||||
</customproperties>
|
||||
<blendMode>0</blendMode>
|
||||
<featureBlendMode>0</featureBlendMode>
|
||||
<layerTransparency>0</layerTransparency>
|
||||
<displayfield>Name</displayfield>
|
||||
<label>0</label>
|
||||
<labelattributes>
|
||||
<label fieldname="" text="Label"/>
|
||||
<family fieldname="" name="Lucida Grande"/>
|
||||
<size fieldname="" units="pt" value="12"/>
|
||||
<bold fieldname="" on="0"/>
|
||||
<italic fieldname="" on="0"/>
|
||||
<underline fieldname="" on="0"/>
|
||||
<strikeout fieldname="" on="0"/>
|
||||
<color fieldname="" red="0" blue="0" green="0"/>
|
||||
<x fieldname=""/>
|
||||
<y fieldname=""/>
|
||||
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
|
||||
<angle fieldname="" value="0" auto="0"/>
|
||||
<alignment fieldname="" value="center"/>
|
||||
<buffercolor fieldname="" red="255" blue="255" green="255"/>
|
||||
<buffersize fieldname="" units="pt" value="1"/>
|
||||
<bufferenabled fieldname="" on=""/>
|
||||
<multilineenabled fieldname="" on=""/>
|
||||
<selectedonly on=""/>
|
||||
</labelattributes>
|
||||
<edittypes>
|
||||
<edittype labelontop="0" editable="1" type="0" name="Name"/>
|
||||
<edittype labelontop="0" editable="1" type="0" name="Value"/>
|
||||
</edittypes>
|
||||
<editform></editform>
|
||||
<editforminit></editforminit>
|
||||
<featformsuppress>0</featformsuppress>
|
||||
<annotationform></annotationform>
|
||||
<editorlayout>generatedlayout</editorlayout>
|
||||
<excludeAttributesWMS/>
|
||||
<excludeAttributesWFS/>
|
||||
<attributeactions/>
|
||||
</qgis>
|
Loading…
x
Reference in New Issue
Block a user