Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Added "centroid fill" symbol layer which draws a marker on …
…polygon's centroid.

Developed for Faunalia (http://www.faunalia.it) with funding from Regione Toscana - Sistema Informativo per la Gestione del Territorio e dell' Ambiente [RT-SIGTA].
For the project: "Sviluppo di prodotti software GIS open-source basati sui prodotti QuantumGIS e Postgis (CIG 037728516E)"


git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@14810 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
wonder committed Nov 30, 2010
1 parent c1cbb0b commit ad69c00
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 38 deletions.
167 changes: 132 additions & 35 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp
Expand Up @@ -10,7 +10,7 @@
#include <QSvgRenderer>

QgsSimpleFillSymbolLayerV2::QgsSimpleFillSymbolLayerV2( QColor color, Qt::BrushStyle style, QColor borderColor, Qt::PenStyle borderStyle, double borderWidth )
: mBrushStyle( style ), mBorderColor( borderColor ), mBorderStyle( borderStyle ), mBorderWidth( borderWidth )
: mBrushStyle( style ), mBorderColor( borderColor ), mBorderStyle( borderStyle ), mBorderWidth( borderWidth )
{
mColor = color;
}
Expand All @@ -25,17 +25,17 @@ QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::create( const QgsStringMap& props
double borderWidth = DEFAULT_SIMPLEFILL_BORDERWIDTH;
QPointF offset;

if( props.contains( "color" ) )
if ( props.contains( "color" ) )
color = QgsSymbolLayerV2Utils::decodeColor( props["color"] );
if( props.contains( "style" ) )
if ( props.contains( "style" ) )
style = QgsSymbolLayerV2Utils::decodeBrushStyle( props["style"] );
if( props.contains( "color_border" ) )
if ( props.contains( "color_border" ) )
borderColor = QgsSymbolLayerV2Utils::decodeColor( props["color_border"] );
if( props.contains( "style_border" ) )
if ( props.contains( "style_border" ) )
borderStyle = QgsSymbolLayerV2Utils::decodePenStyle( props["style_border"] );
if( props.contains( "width_border" ) )
if ( props.contains( "width_border" ) )
borderWidth = props["width_border"].toDouble();
if( props.contains( "offset" ) )
if ( props.contains( "offset" ) )
offset = QgsSymbolLayerV2Utils::decodePoint( props["offset"] );

QgsSimpleFillSymbolLayerV2* sl = new QgsSimpleFillSymbolLayerV2( color, style, borderColor, borderStyle, borderWidth );
Expand All @@ -56,15 +56,15 @@ void QgsSimpleFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context

// scale brush content for printout
double rasterScaleFactor = context.renderContext().rasterScaleFactor();
if( rasterScaleFactor != 1.0 )
if ( rasterScaleFactor != 1.0 )
{
mBrush.setMatrix( QMatrix().scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ) );
}

QColor selColor = context.selectionColor();
// selColor.setAlphaF( context.alpha() );
mSelBrush = QBrush( selColor );
if( selectFillStyle ) mSelBrush.setStyle( mBrushStyle );
if ( selectFillStyle ) mSelBrush.setStyle( mBrushStyle );
mBorderColor.setAlphaF( context.alpha() );
mPen = QPen( mBorderColor );
mPen.setStyle( mBorderStyle );
Expand All @@ -78,20 +78,20 @@ void QgsSimpleFillSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
void QgsSimpleFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
QPainter* p = context.renderContext().painter();
if( !p )
if ( !p )
{
return;
}

p->setBrush( context.selected() ? mSelBrush : mBrush );
p->setPen( mPen );

if( !mOffset.isNull() )
if ( !mOffset.isNull() )
p->translate( mOffset );

_renderPolygon( p, points, rings );

if( !mOffset.isNull() )
if ( !mOffset.isNull() )
p->translate( -mOffset );
}

Expand Down Expand Up @@ -138,7 +138,7 @@ QgsSVGFillSymbolLayer::~QgsSVGFillSymbolLayer()
void QgsSVGFillSymbolLayer::setSvgFilePath( const QString& svgPath )
{
QFile svgFile( svgPath );
if( svgFile.open( QFile::ReadOnly ) )
if ( svgFile.open( QFile::ReadOnly ) )
{
mSvgData = svgFile.readAll();
storeViewBox();
Expand All @@ -153,24 +153,24 @@ QgsSymbolLayerV2* QgsSVGFillSymbolLayer::create( const QgsStringMap& properties
QString svgFilePath;


if( properties.contains( "width" ) )
if ( properties.contains( "width" ) )
{
width = properties["width"].toDouble();
}
if( properties.contains( "svgFile" ) )
if ( properties.contains( "svgFile" ) )
{
QString svgName = properties["svgFile"];
QString savePath = QgsSvgMarkerSymbolLayerV2::symbolNameToPath( svgName );
svgFilePath = ( savePath.isEmpty() ? svgName : savePath );
}

if( !svgFilePath.isEmpty() )
if ( !svgFilePath.isEmpty() )
{
return new QgsSVGFillSymbolLayer( svgFilePath, width );
}
else
{
if( properties.contains( "data" ) )
if ( properties.contains( "data" ) )
{
data = QByteArray::fromHex( properties["data"].toLocal8Bit() );
}
Expand All @@ -186,7 +186,7 @@ QString QgsSVGFillSymbolLayer::layerType() const

void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
{
if( mSvgViewBox.isNull() )
if ( mSvgViewBox.isNull() )
{
return;
}
Expand All @@ -201,13 +201,13 @@ void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
//rasterise byte array to image
QPainter p( &textureImage );
QSvgRenderer r( mSvgData );
if( !r.isValid() )
if ( !r.isValid() )
{
return;
}
r.render( &p );

if( context.alpha() < 1.0 )
if ( context.alpha() < 1.0 )
{
QgsSymbolLayerV2Utils::multiplyImageOpacity( &textureImage, context.alpha() );
}
Expand All @@ -217,15 +217,15 @@ void QgsSVGFillSymbolLayer::startRender( QgsSymbolV2RenderContext& context )
mBrush.setTextureImage( textureImage );
mBrush.setTransform( brushTransform );

if( mOutline )
if ( mOutline )
{
mOutline->startRender( context.renderContext() );
}
}

void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
{
if( mOutline )
if ( mOutline )
{
mOutline->stopRender( context.renderContext() );
}
Expand All @@ -234,27 +234,27 @@ void QgsSVGFillSymbolLayer::stopRender( QgsSymbolV2RenderContext& context )
void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
QPainter* p = context.renderContext().painter();
if( !p )
if ( !p )
{
return;
}
p->setPen( QPen( Qt::NoPen ) );
if( context.selected() )
if ( context.selected() )
{
QColor selColor = context.selectionColor();
if( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
if ( ! selectionIsOpaque ) selColor.setAlphaF( context.alpha() );
p->setBrush( QBrush( selColor ) );
_renderPolygon( p, points, rings );
}
p->setBrush( mBrush );
_renderPolygon( p, points, rings );
if( mOutline )
if ( mOutline )
{
mOutline->renderPolyline( points, context.renderContext(), -1, selectFillBorder && context.selected() );
if( rings )
if ( rings )
{
QList<QPolygonF>::const_iterator ringIt = rings->constBegin();
for( ; ringIt != rings->constEnd(); ++ringIt )
for ( ; ringIt != rings->constEnd(); ++ringIt )
{
mOutline->renderPolyline( *ringIt, context.renderContext(), -1, selectFillBorder && context.selected() );
}
Expand All @@ -265,7 +265,7 @@ void QgsSVGFillSymbolLayer::renderPolygon( const QPolygonF& points, QList<QPolyg
QgsStringMap QgsSVGFillSymbolLayer::properties() const
{
QgsStringMap map;
if( !mSvgFilePath.isEmpty() )
if ( !mSvgFilePath.isEmpty() )
{
map.insert( "svgFile", QgsSvgMarkerSymbolLayerV2::symbolPathToName( mSvgFilePath ) );
}
Expand All @@ -281,7 +281,7 @@ QgsStringMap QgsSVGFillSymbolLayer::properties() const
QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone() const
{
QgsSymbolLayerV2* clonedLayer = 0;
if( !mSvgFilePath.isEmpty() )
if ( !mSvgFilePath.isEmpty() )
{
clonedLayer = new QgsSVGFillSymbolLayer( mSvgFilePath, mPatternWidth );
}
Expand All @@ -290,7 +290,7 @@ QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone() const
clonedLayer = new QgsSVGFillSymbolLayer( mSvgData, mPatternWidth );
}

if( mOutline )
if ( mOutline )
{
clonedLayer->setSubSymbol( mOutline->clone() );
}
Expand All @@ -299,10 +299,10 @@ QgsSymbolLayerV2* QgsSVGFillSymbolLayer::clone() const

void QgsSVGFillSymbolLayer::storeViewBox()
{
if( !mSvgData.isEmpty() )
if ( !mSvgData.isEmpty() )
{
QSvgRenderer r( mSvgData );
if( r.isValid() )
if ( r.isValid() )
{
mSvgViewBox = r.viewBoxF();
return;
Expand All @@ -315,14 +315,14 @@ void QgsSVGFillSymbolLayer::storeViewBox()

bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
{
if( !symbol || symbol->type() != QgsSymbolV2::Line )
if ( !symbol || symbol->type() != QgsSymbolV2::Line )
{
delete symbol;
return false;
}

QgsLineSymbolV2* lineSymbol = dynamic_cast<QgsLineSymbolV2*>( symbol );
if( lineSymbol )
if ( lineSymbol )
{
delete mOutline;
mOutline = lineSymbol;
Expand All @@ -332,3 +332,100 @@ bool QgsSVGFillSymbolLayer::setSubSymbol( QgsSymbolV2* symbol )
delete symbol;
return false;
}


//////////////


QgsCentroidFillSymbolLayerV2::QgsCentroidFillSymbolLayerV2()
{
mMarker = NULL;
setSubSymbol( new QgsMarkerSymbolV2() );
}

QgsCentroidFillSymbolLayerV2::~QgsCentroidFillSymbolLayerV2()
{
delete mMarker;
}

QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::create( const QgsStringMap& /*properties*/ )
{
return new QgsCentroidFillSymbolLayerV2();
}

QString QgsCentroidFillSymbolLayerV2::layerType() const
{
return "CentroidFill";
}

void QgsCentroidFillSymbolLayerV2::setColor( const QColor& color )
{
mMarker->setColor( color );
mColor = color;
}

void QgsCentroidFillSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
{
mMarker->setAlpha( context.alpha() );
mMarker->setOutputUnit( context.outputUnit() );

mMarker->startRender( context.renderContext() );
}

void QgsCentroidFillSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
{
mMarker->stopRender( context.renderContext() );
}

void QgsCentroidFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
// calculate centroid
double cx = 0, cy = 0;
double area, sum = 0;
for ( int i = points.count() - 1, j = 0; j < points.count(); i = j++ )
{
const QPointF& p1 = points[i];
const QPointF& p2 = points[j];
area = p1.x() * p2.y() - p1.y() * p2.x();
sum += area;
cx += ( p1.x() + p2.x() ) * area;
cy += ( p1.y() + p2.y() ) * area;
}
sum *= 3.0;
cx /= sum;
cy /= sum;

mMarker->renderPoint( QPointF( cx, cy ), context.renderContext(), -1, context.selected() );
}

QgsStringMap QgsCentroidFillSymbolLayerV2::properties() const
{
return QgsStringMap();
}

QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::clone() const
{
QgsCentroidFillSymbolLayerV2* x = new QgsCentroidFillSymbolLayerV2();
x->setSubSymbol( mMarker->clone() );
return x;
}


QgsSymbolV2* QgsCentroidFillSymbolLayerV2::subSymbol()
{
return mMarker;
}

bool QgsCentroidFillSymbolLayerV2::setSubSymbol( QgsSymbolV2* symbol )
{
if ( symbol == NULL || symbol->type() != QgsSymbolV2::Marker )
{
delete symbol;
return false;
}

delete mMarker;
mMarker = static_cast<QgsMarkerSymbolV2*>( symbol );
mColor = mMarker->color();
return true;
}
35 changes: 35 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.h
Expand Up @@ -121,4 +121,39 @@ class CORE_EXPORT QgsSVGFillSymbolLayer: public QgsFillSymbolLayerV2
void storeViewBox();
};



class CORE_EXPORT QgsCentroidFillSymbolLayerV2 : public QgsFillSymbolLayerV2
{
public:
QgsCentroidFillSymbolLayerV2();
~QgsCentroidFillSymbolLayerV2();

// static stuff

static QgsSymbolLayerV2* create( const QgsStringMap& properties = QgsStringMap() );

// implemented from base classes

QString layerType() const;

void startRender( QgsSymbolV2RenderContext& context );

void stopRender( QgsSymbolV2RenderContext& context );

void renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context );

QgsStringMap properties() const;

QgsSymbolLayerV2* clone() const;

void setColor( const QColor& color );

QgsSymbolV2* subSymbol();
bool setSubSymbol( QgsSymbolV2* symbol );

protected:
QgsMarkerSymbolV2* mMarker;
};

#endif
5 changes: 4 additions & 1 deletion src/core/symbology-ng/qgssymbollayerv2registry.cpp
Expand Up @@ -26,7 +26,10 @@ QgsSymbolLayerV2Registry::QgsSymbolLayerV2Registry()

addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SimpleFill", QObject::tr( "Simple fill" ), QgsSymbolV2::Fill,
QgsSimpleFillSymbolLayerV2::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SVGFill", QObject::tr( "SVG fill" ), QgsSymbolV2::Fill, QgsSVGFillSymbolLayer::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "SVGFill", QObject::tr( "SVG fill" ), QgsSymbolV2::Fill,
QgsSVGFillSymbolLayer::create ) );
addSymbolLayerType( new QgsSymbolLayerV2Metadata( "CentroidFill", QObject::tr( "Centroid fill" ), QgsSymbolV2::Fill,
QgsCentroidFillSymbolLayerV2::create ) );
}

QgsSymbolLayerV2Registry::~QgsSymbolLayerV2Registry()
Expand Down

0 comments on commit ad69c00

Please sign in to comment.