Skip to content

Commit

Permalink
Data defined size / color / rotation for marker export
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Nov 29, 2013
1 parent fa509b8 commit bcad16d
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 37 deletions.
24 changes: 18 additions & 6 deletions src/core/dxf/qgsdxfexport.cpp
Expand Up @@ -481,14 +481,19 @@ void QgsDxfExport::writeBlocks()
QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > >::const_iterator slIt = slList.constBegin();
for ( ; slIt != slList.constEnd(); ++slIt )
{
//if point symbol layer and no data defined properties: write block
QgsMarkerSymbolLayerV2* ml = dynamic_cast< QgsMarkerSymbolLayerV2*>( slIt->first );
if ( ml )
{
//if point symbol layer and no data defined properties: write block
QgsRenderContext ct;
QgsSymbolV2RenderContext ctx( ct, QgsSymbolV2::MapUnit, slIt->second->alpha(), false, slIt->second->renderHints(), 0 );
ml->startRender( ctx );

//markers with data defined properties are inserted inline
if ( hasDataDefinedProperties( ml, slIt->second ) )
{
continue;
ml->stopRender( ctx );
}
writeGroup( 0, "BLOCK" );
writeGroup( 8, 0 );
Expand All @@ -500,17 +505,18 @@ void QgsDxfExport::writeBlocks()
//todo: consider anchor point
double size = ml->size();
size *= mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits );
writeGroup( 10, size / 2.0 );
writeGroup( 20, size / 2.0 );
writeGroup( 10, 0 );
writeGroup( 20, 0 );
writeGroup( 30, 0 );
writeGroup( 3, blockName );

ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ), "0", 0, 0 ); //maplayer 0 -> block receives layer from INSERT statement
ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ), "0", &ctx, 0 ); //maplayer 0 -> block receives layer from INSERT statement

writeGroup( 0, "ENDBLK" );
writeGroup( 8, 0 );

mPointSymbolBlocks.insert( ml, blockName );
ml->stopRender( ctx );
}
}
endSection();
Expand All @@ -531,17 +537,22 @@ void QgsDxfExport::writeEntities()
continue;
}

QgsRenderContext ctx;
QgsFeatureRendererV2* renderer = vl->rendererV2();
renderer->startRender( ctx, vl );

if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology && renderer->usingSymbolLevels() )
{
writeEntitiesSymbolLevels( vl );
renderer->stopRender( ctx );
continue;
}

QgsVectorDataProvider* dp = vl->dataProvider();
if ( !dp )
{
continue;
renderer->stopRender( ctx );
}


Expand Down Expand Up @@ -575,6 +586,7 @@ void QgsDxfExport::writeEntities()
addFeature( fet, vl->name(), s->symbolLayer( 0 ), s );
}
}
renderer->stopRender( ctx );
}

endSection();
Expand Down Expand Up @@ -1134,8 +1146,8 @@ bool QgsDxfExport::hasDataDefinedProperties( const QgsSymbolLayerV2* sl, const Q
return false;
}

if ( symbol->renderHints() | QgsSymbolV2::DataDefinedSizeScale ||
symbol->renderHints() | QgsSymbolV2::DataDefinedRotation )
if ( symbol->renderHints() & QgsSymbolV2::DataDefinedSizeScale ||
symbol->renderHints() & QgsSymbolV2::DataDefinedRotation )
{
return true;
}
Expand Down
8 changes: 8 additions & 0 deletions src/core/dxf/qgsdxfpaintdevice.cpp
Expand Up @@ -89,4 +89,12 @@ void QgsDxfPaintDevice::setLayer( const QString& layer )
}
}

void QgsDxfPaintDevice::setShift( const QPointF& shift )
{
if ( mPaintEngine )
{
mPaintEngine->setShift( shift );
}
}


2 changes: 2 additions & 0 deletions src/core/dxf/qgsdxfpaintdevice.h
Expand Up @@ -50,6 +50,8 @@ class QgsDxfPaintDevice: public QPaintDevice

void setLayer( const QString& layer );

void setShift( const QPointF& shift );


private:
QgsDxfPaintEngine* mPaintEngine;
Expand Down
6 changes: 3 additions & 3 deletions src/core/dxf/qgsdxfpaintengine.cpp
Expand Up @@ -54,11 +54,11 @@ void QgsDxfPaintEngine::drawPixmap( const QRectF& r, const QPixmap& pm, const QR

void QgsDxfPaintEngine::updateState( const QPaintEngineState& state )
{
if ( state.state() | QPaintEngine::DirtyTransform )
if ( state.state() & QPaintEngine::DirtyTransform )
{
mTransform = state.transform();
}
if ( state.state() | QPaintEngine::DirtyPen )
if ( state.state() & QPaintEngine::DirtyPen )
{
mPen = state.pen();
}
Expand Down Expand Up @@ -140,7 +140,7 @@ QgsPoint QgsDxfPaintEngine::toDxfCoordinates( const QPointF& pt ) const
return QgsPoint( pt.x(), pt.y() );
}

QPointF dxfPt = mPaintDevice->dxfCoordinates( mTransform.map( pt ) );
QPointF dxfPt = mPaintDevice->dxfCoordinates( mTransform.map( pt ) ) + mShift;
return QgsPoint( dxfPt.x(), dxfPt.y() );
}

Expand Down
3 changes: 3 additions & 0 deletions src/core/dxf/qgsdxfpaintengine.h
Expand Up @@ -46,6 +46,8 @@ class QgsDxfPaintEngine: public QPaintEngine
void setLayer( const QString& layer ) { mLayer = layer; }
QString layer() const { return mLayer; }

void setShift( const QPointF& shift ) { mShift = shift; }

private:
const QgsDxfPaintDevice* mPaintDevice;
QgsDxfExport* mDxf;
Expand All @@ -54,6 +56,7 @@ class QgsDxfPaintEngine: public QPaintEngine
QTransform mTransform;
QPen mPen;
QString mLayer;
QPointF mShift;

QgsPoint toDxfCoordinates( const QPointF& pt ) const;
int currentPenColor() const;
Expand Down
132 changes: 110 additions & 22 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Expand Up @@ -702,7 +702,7 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon
}
}

void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset ) const
void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
{
//data defined size?
double size = mSize;
Expand Down Expand Up @@ -738,41 +738,72 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc
size *= mmMapUnitScaleFactor;
}
double halfSize = size / 2.0;
int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() );

//data defined size

QColor c = mBrush.color();
QgsExpression* colorExpression = expression( "color" );
if ( colorExpression )
{
c = QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( *f ).toString() );
}
int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() );

//offset
double offsetX = 0;
double offsetY = 0;
markerOffset( *context, offsetX, offsetY );
QPointF off( offsetX, offsetY );

//angle
double angle = mAngle;
QgsExpression* angleExpression = expression( "angle" );
if ( angleExpression )
{
angle = angleExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
}
angle = -angle; //rotation in Qt is counterclockwise
if ( angle )
off = _rotatedOffset( off, angle );

if ( mSizeUnit == QgsSymbolV2::MM )
{
off *= mmMapUnitScaleFactor;
}

//data defined color, rotation, offset
QTransform t;
t.translate( shift.x() + offsetX, shift.y() + offsetY );

if ( angle != 0 )
t.rotate( angle );

//data defined symbol name

if ( mName == "circle" )
{
e.writeGroup( 0, "CIRCLE" );
e.writeGroup( 8, layerName );

e.writeGroup( 62, colorIndex );
e.writeGroup( 10, halfSize + offset.x() );
e.writeGroup( 20, halfSize + offset.y() );
e.writeGroup( 10, halfSize + shift.x() );
e.writeGroup( 20, halfSize + shift.y() );
e.writeGroup( 30, 0.0 );
e.writeGroup( 40, halfSize );
}
else if ( mName == "square" || mName == "rectangle" )
{
QgsPoint pt1( 0.0 + offset.x(), 0.0 + offset.y() );
QgsPoint pt2( size + offset.x(), 0.0 + offset.y() );
QgsPoint pt3( 0.0 + offset.x(), size + offset.y() );
QgsPoint pt4( size + offset.x(), size + offset.y() );
e.writeSolid( layerName, colorIndex, pt1, pt2, pt3, pt4 );
QPointF pt1 = t.map( QPointF( -halfSize, -halfSize ) );
QPointF pt2 = t.map( QPointF( halfSize, -halfSize ) );
QPointF pt3 = t.map( QPointF( -halfSize, halfSize ) );
QPointF pt4 = t.map( QPointF( halfSize, halfSize ) );
e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
}
else if ( mName == "diamond" )
{
QgsPoint pt1( 0.0 + offset.x(), halfSize + offset.y() );
QgsPoint pt2( halfSize + offset.x(), 0.0 + offset.y() );
QgsPoint pt3( halfSize + offset.x(), size + offset.y() );
QgsPoint pt4( size + offset.x(), halfSize + offset.y() );
e.writeSolid( layerName, colorIndex, pt1, pt2, pt3, pt4 );
QPointF pt1 = t.map( QPointF( -halfSize, 0 ) );
QPointF pt2 = t.map( QPointF( 0, -halfSize ) );
QPointF pt3 = t.map( QPointF( 0, halfSize ) );
QPointF pt4 = t.map( QPointF( halfSize, 0 ) );
e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) );
}
}

Expand Down Expand Up @@ -1182,10 +1213,10 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element
}

void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f,
const QPointF& offset ) const
const QPointF& shift ) const
{
Q_UNUSED( layerName );
Q_UNUSED( offset ); //todo...
Q_UNUSED( shift ); //todo...

QSvgRenderer r( mPath );
if ( !r.isValid() )
Expand All @@ -1195,12 +1226,69 @@ void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale

QgsDxfPaintDevice pd( &e );
pd.setDrawingSize( QSizeF( r.defaultSize() ) );
double size = mSize * mmMapUnitScaleFactor ;
pd.setOutputSize( QRectF( 0, 0, size, size ) );
pd.setLayer( layerName );
QPainter p;

//size
double size = mSize;
QgsExpression* sizeExpression = expression( "size" );
bool hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression;

if ( sizeExpression )
{
size = sizeExpression->evaluate( *f ).toDouble();
}
if ( mSizeUnit == QgsSymbolV2::MM )
{
size *= mmMapUnitScaleFactor;
}

if ( hasDataDefinedSize )
{
switch ( mScaleMethod )
{
case QgsSymbolV2::ScaleArea:
size = sqrt( size );
break;
case QgsSymbolV2::ScaleDiameter:
break;
}
}

double halfSize = size / 2.0;

//offset, angle
QPointF offset = mOffset;
QgsExpression* offsetExpression = expression( "offset" );
if ( offsetExpression )
{
QString offsetString = offsetExpression->evaluate( *f ).toString();
offset = QgsSymbolLayerV2Utils::decodePoint( offsetString );
}
double offsetX = offset.x();
double offsetY = offset.y();
if ( mSizeUnit == QgsSymbolV2::MM )
{
offsetX *= mmMapUnitScaleFactor;
offsetY *= mmMapUnitScaleFactor;
}

QPointF outputOffset( offsetX, offsetY );

double angle = mAngle;
QgsExpression* angleExpression = expression( "angle" );
if ( angleExpression )
{
angle = angleExpression->evaluate( *f ).toDouble();
}
//angle = -angle; //rotation in Qt is counterclockwise
if ( angle )
outputOffset = _rotatedOffset( outputOffset, angle );

QPainter p;
p.begin( &pd );
p.rotate( angle );
pd.setShift( shift - QPointF( halfSize, halfSize ) );
pd.setOutputSize( QRectF( 0, 0, size, size ) );
pd.setLayer( layerName );
r.render( &p );
p.end();
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.h
Expand Up @@ -76,7 +76,7 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
QgsSymbolV2::OutputUnit outlineWidthUnit() const { return mOutlineWidthUnit; }
void setOutlineWidthUnit( QgsSymbolV2::OutputUnit u ) { mOutlineWidthUnit = u; }

void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset = QPointF( 0.0, 0.0 ) ) const;
void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift = QPointF( 0.0, 0.0 ) ) const;

protected:

Expand Down Expand Up @@ -159,7 +159,7 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
void setOutputUnit( QgsSymbolV2::OutputUnit unit );
QgsSymbolV2::OutputUnit outputUnit() const;

void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset = QPointF( 0.0, 0.0 ) ) const;
void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift = QPointF( 0.0, 0.0 ) ) const;

protected:
QString mPath;
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgssymbollayerv2.cpp
Expand Up @@ -175,7 +175,7 @@ void QgsMarkerSymbolLayerV2::setOutputUnit( QgsSymbolV2::OutputUnit unit )
mOffsetUnit = unit;
}

void QgsMarkerSymbolLayerV2::markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY )
void QgsMarkerSymbolLayerV2::markerOffset( const QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY ) const
{
offsetX = mOffset.x();
offsetY = mOffset.y();
Expand Down
6 changes: 3 additions & 3 deletions src/core/symbology-ng/qgssymbollayerv2.h
Expand Up @@ -94,8 +94,8 @@ class CORE_EXPORT QgsSymbolLayerV2
virtual void removeDataDefinedProperties();
bool hasDataDefinedProperties() const { return mDataDefinedProperties.size() > 0; }

virtual void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset = QPointF( 0.0, 0.0 ) ) const
{ Q_UNUSED( e ); Q_UNUSED( mmMapUnitScaleFactor ); Q_UNUSED( layerName ); Q_UNUSED( context ); Q_UNUSED( f ); Q_UNUSED( offset ); }
virtual void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift = QPointF( 0.0, 0.0 ) ) const
{ Q_UNUSED( e ); Q_UNUSED( mmMapUnitScaleFactor ); Q_UNUSED( layerName ); Q_UNUSED( context ); Q_UNUSED( f ); Q_UNUSED( shift ); }

protected:
QgsSymbolLayerV2( QgsSymbolV2::SymbolType type, bool locked = false )
Expand Down Expand Up @@ -158,7 +158,7 @@ class CORE_EXPORT QgsMarkerSymbolLayerV2 : public QgsSymbolLayerV2

protected:
QgsMarkerSymbolLayerV2( bool locked = false );
void markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY );
void markerOffset( const QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY ) const;
static QPointF _rotatedOffset( const QPointF& offset, double angle );

double mAngle;
Expand Down

0 comments on commit bcad16d

Please sign in to comment.