From 6dad30c2662ffebb99c254e1207e8bc90e852468 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 13 Sep 2013 15:33:38 +0200 Subject: [PATCH 01/38] [FEATURE]: Start implementation of native dxf export --- python/core/core.sip | 1 + python/core/qgsdxfexport.sip | 29 ++++++++++++++++++++ src/core/CMakeLists.txt | 1 + src/core/qgsdxfexport.cpp | 52 ++++++++++++++++++++++++++++++++++++ src/core/qgsdxfexport.h | 47 ++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 python/core/qgsdxfexport.sip create mode 100644 src/core/qgsdxfexport.cpp create mode 100644 src/core/qgsdxfexport.h diff --git a/python/core/core.sip b/python/core/core.sip index 588f7051222..348b9f50fc7 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -27,6 +27,7 @@ %Include qgsdatasourceuri.sip %Include qgsdbfilterproxymodel.sip %Include qgsdistancearea.sip +%Include qgsdxfexport.sip %Include qgserror.sip %Include qgsexpression.sip %Include qgsfeature.sip diff --git a/python/core/qgsdxfexport.sip b/python/core/qgsdxfexport.sip new file mode 100644 index 00000000000..598b6be8881 --- /dev/null +++ b/python/core/qgsdxfexport.sip @@ -0,0 +1,29 @@ +/*************************************************************************** + qgsdxfexport.sip + ---------------- + begin : September 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +class QgsDxfExport +{ +%TypeHeaderCode +#include +%End + public: + QgsDxfExport(); + ~QgsDxfExport(); + + void addLayers( QList< QgsMapLayer* >& layers ); + int writeToFile( QIODevice* d ); +}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 982c0ab9467..aafc4ac7980 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -62,6 +62,7 @@ SET(QGIS_CORE_SRCS qgsdbfilterproxymodel.cpp qgsdiagramrendererv2.cpp qgsdistancearea.cpp + qgsdxfexport.cpp qgserror.cpp qgsexpression.cpp qgsexpression_texts.cpp diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp new file mode 100644 index 00000000000..9c0f8f7d12b --- /dev/null +++ b/src/core/qgsdxfexport.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + qgsdxfexport.cpp + ---------------- + begin : September 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qgsdxfexport.h" +#include +#include + +QgsDxfExport::QgsDxfExport() +{ +} + +QgsDxfExport::~QgsDxfExport() +{ + +} + +int QgsDxfExport::writeToFile( QIODevice* d ) +{ + if ( !d ) + { + return 1; + } + + if ( !d->open( QIODevice::WriteOnly ) ) + { + return 2; + } + + QTextStream outStream( d ); + writeHeader( outStream ); + return 0; +} + +int QgsDxfExport::writeHeader( QTextStream& stream ) +{ + stream << "Hello, dxf!"; + return 0; //soon... +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h new file mode 100644 index 00000000000..5628eefab7d --- /dev/null +++ b/src/core/qgsdxfexport.h @@ -0,0 +1,47 @@ +/*************************************************************************** + qgsdxfexport.h + -------------- + begin : September 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QGSDXFEXPORT_H +#define QGSDXFEXPORT_H + +#include + +class QgsMapLayer; +class QIODevice; +class QTextStream; + +class QgsDxfExport +{ + public: + QgsDxfExport(); + ~QgsDxfExport(); + + void addLayers( QList< QgsMapLayer* >& layers ) { mLayers = layers; } + int writeToFile( QIODevice* d ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? + + private: + + QList< QgsMapLayer* > mLayers; + + int writeHeader( QTextStream& stream ); + //collect styles + //writeEntities + + //Option: export feature once / multiple export (considering symbol layers / symbol levels) +}; + +#endif // QGSDXFEXPORT_H From edc3b5ffaf67a879a39d01046d047edede316e57 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 13 Sep 2013 18:15:15 +0200 Subject: [PATCH 02/38] Write dxf header and eof --- src/core/qgsdxfexport.cpp | 22 +++++++++++++++++++--- src/core/qgsdxfexport.h | 3 ++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 9c0f8f7d12b..e5da7b2b771 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -45,8 +45,24 @@ int QgsDxfExport::writeToFile( QIODevice* d ) return 0; } -int QgsDxfExport::writeHeader( QTextStream& stream ) +void QgsDxfExport::writeHeader( QTextStream& stream ) { - stream << "Hello, dxf!"; - return 0; //soon... + stream << "999\n"; + stream << "DXF created from QGIS\n"; + stream << " 0\n"; + stream << "SECTION\n"; + stream << " 2\n"; + stream << "HEADER\n"; + stream << " 9\n"; + stream << "$LTSCALE\n"; + stream << " 40\n"; + stream << "1\n"; + stream << " 0\n"; + stream << "ENDSEC\n"; +} + +void QgsDxfExport::writeEndFile( QTextStream& stream ) +{ + stream << " 0\n"; + stream << "ENDSEC\n"; } diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 5628eefab7d..6614369e5a3 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -37,7 +37,8 @@ class QgsDxfExport QList< QgsMapLayer* > mLayers; - int writeHeader( QTextStream& stream ); + void writeHeader( QTextStream& stream ); + void writeEndFile( QTextStream& stream ); //collect styles //writeEntities From ddee21c0e39649f6fc51cf060ea0d51899364ecc Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 13 Sep 2013 21:04:28 +0200 Subject: [PATCH 03/38] First implementation of dxf feature writing (but it does not work yet) --- src/core/qgsdxfexport.cpp | 83 ++++++++++++++++++++++++++++++++++++++- src/core/qgsdxfexport.h | 16 +++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index e5da7b2b771..45318529245 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -16,6 +16,10 @@ ***************************************************************************/ #include "qgsdxfexport.h" +#include "qgsvectordataprovider.h" +#include "qgspoint.h" +#include "qgsrendererv2.h" +#include "qgsvectorlayer.h" #include #include @@ -28,7 +32,7 @@ QgsDxfExport::~QgsDxfExport() } -int QgsDxfExport::writeToFile( QIODevice* d ) +int QgsDxfExport::writeToFile( QIODevice* d, SymbologyExport s ) { if ( !d ) { @@ -42,6 +46,8 @@ int QgsDxfExport::writeToFile( QIODevice* d ) QTextStream outStream( d ); writeHeader( outStream ); + writeEntities( outStream ); + writeEndFile( outStream ); return 0; } @@ -61,8 +67,83 @@ void QgsDxfExport::writeHeader( QTextStream& stream ) stream << "ENDSEC\n"; } +void QgsDxfExport::writeEntities( QTextStream& stream ) +{ + stream << "0\n"; + stream << "SECTION\n"; + stream << " 2\n"; + stream << "ENTITIES\n"; + + //iterate through the maplayers + QList< QgsMapLayer* >::iterator layerIt = mLayers.begin(); + for ( ; layerIt != mLayers.end(); ++layerIt ) + { + QgsVectorLayer* vl = qobject_cast( *layerIt ); + if ( !vl ) + { + continue; + } + QgsVectorDataProvider* dp = vl->dataProvider(); + if ( !dp ) + { + continue; + } + + QgsFeatureRendererV2* renderer = vl->rendererV2(); + QgsFeatureIterator featureIt = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( + renderer->usedAttributes(), dp->fields() ) ); + QgsFeature fet; + while ( featureIt.nextFeature( fet ) ) + { + //get geometry and write it. Todo: consider symbolisation + QgsGeometry* geom = fet.geometry(); + if ( geom ) + { + //try with line first + writePolyline( stream, geom->asPolyline(), vl->name() ); //todo....... + } + } + } + + stream << " 0\n"; + stream << "ENDSEC\n"; +} + void QgsDxfExport::writeEndFile( QTextStream& stream ) { stream << " 0\n"; stream << "ENDSEC\n"; } + +void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, bool closed ) +{ + stream << " 0\n"; + stream << "POLYLINE\n"; + stream << " 8\n"; + stream << layer << "\n"; + stream << " 66\n"; + stream << " 1\n"; + stream << " 70\n"; + int type = closed ? 32 : 0; + stream << type << "\n"; + + QgsPolyline::const_iterator lineIt = line.constBegin(); + for ( ; lineIt != line.constEnd(); ++lineIt ) + { + writeVertex( stream, *lineIt, layer ); + } +} + +void QgsDxfExport::writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ) +{ + stream << " 0\n"; + stream << "VERTEX\n"; + stream << " 8\n"; + stream << layer << "\n"; + stream << " 10\n"; + stream << pt.x() << "\n"; + stream << " 20\n"; + stream << pt.y() << "\n"; + stream << " 30\n"; + stream << "0.0\n"; +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 6614369e5a3..3b0f4c4cfc4 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -18,27 +18,41 @@ #ifndef QGSDXFEXPORT_H #define QGSDXFEXPORT_H +#include "qgsgeometry.h" #include class QgsMapLayer; +class QgsPoint; class QIODevice; class QTextStream; class QgsDxfExport { public: + enum SymbologyExport + { + NoSymbology = 0, //export only data + FeatureSymbology, //Keeps the number of features and export symbology per feature + SymbolLayerSymbology //Exports one feature per symbol layer (considering symbol levels) + }; + QgsDxfExport(); ~QgsDxfExport(); void addLayers( QList< QgsMapLayer* >& layers ) { mLayers = layers; } - int writeToFile( QIODevice* d ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? + int writeToFile( QIODevice* d, SymbologyExport s = SymbolLayerSymbology ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? private: QList< QgsMapLayer* > mLayers; void writeHeader( QTextStream& stream ); + void writeEntities( QTextStream& stream ); void writeEndFile( QTextStream& stream ); + + void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, bool closed = false ); + void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); + //collect styles //writeEntities From 06e933926d24e9265ab78a5b1411ff4d6c726fe8 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sat, 14 Sep 2013 19:22:59 +0200 Subject: [PATCH 04/38] Write additional header field and table section --- src/core/qgsdxfexport.cpp | 61 ++++++++++++++++++++++++++++++++++----- src/core/qgsdxfexport.h | 4 +++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 45318529245..3bde3d16b99 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -46,6 +46,7 @@ int QgsDxfExport::writeToFile( QIODevice* d, SymbologyExport s ) QTextStream outStream( d ); writeHeader( outStream ); + writeTables( outStream ); writeEntities( outStream ); writeEndFile( outStream ); return 0; @@ -55,22 +56,56 @@ void QgsDxfExport::writeHeader( QTextStream& stream ) { stream << "999\n"; stream << "DXF created from QGIS\n"; - stream << " 0\n"; - stream << "SECTION\n"; + startSection( stream ); stream << " 2\n"; stream << "HEADER\n"; stream << " 9\n"; + stream << "$ACADVER"; + stream << "AC1009\n"; + stream << " 9\n"; stream << "$LTSCALE\n"; stream << " 40\n"; stream << "1\n"; + endSection( stream ); +} + +void QgsDxfExport::writeTables( QTextStream& stream ) +{ + startSection( stream ); + stream << " 2\n"; + stream << "TABLES\n"; + + // stream << " 0\n"; - stream << "ENDSEC\n"; + stream << "TABLE\n"; + stream << " 0\n"; + stream << "LAYER\n"; + QList< QgsMapLayer* >::iterator layerIt = mLayers.begin(); + for ( ; layerIt != mLayers.end(); ++layerIt ) + { + stream << " 0\n"; + stream << "LAYER\n"; + stream << " 2\n"; + if ( *layerIt ) + { + stream << ( *layerIt )->name() << "\n"; + } + stream << " 70\n"; //layer property + stream << "64\n"; + stream << " 62\n"; //layer color + stream << "1\n"; + stream << " 6\n"; //layer line type + stream << "CONTINUOUS\n"; + } + stream << " 0\n"; + stream << "ENDTAB\n"; + + endSection( stream ); } void QgsDxfExport::writeEntities( QTextStream& stream ) { - stream << "0\n"; - stream << "SECTION\n"; + startSection( stream ); stream << " 2\n"; stream << "ENTITIES\n"; @@ -100,16 +135,26 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) if ( geom ) { //try with line first - writePolyline( stream, geom->asPolyline(), vl->name() ); //todo....... + writePolyline( stream, geom->asPolyline(), vl->name() ); } } } - stream << " 0\n"; - stream << "ENDSEC\n"; + endSection( stream ); } void QgsDxfExport::writeEndFile( QTextStream& stream ) +{ + endSection( stream ); +} + +void QgsDxfExport::startSection( QTextStream& stream ) +{ + stream << " 0\n"; + stream << "SECTION\n"; +} + +void QgsDxfExport::endSection( QTextStream& stream ) { stream << " 0\n"; stream << "ENDSEC\n"; diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 3b0f4c4cfc4..9ac64c8d8a0 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -47,9 +47,13 @@ class QgsDxfExport QList< QgsMapLayer* > mLayers; void writeHeader( QTextStream& stream ); + void writeTables( QTextStream& stream ); void writeEntities( QTextStream& stream ); void writeEndFile( QTextStream& stream ); + void startSection( QTextStream& stream ); + void endSection( QTextStream& stream ); + void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, bool closed = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); From 32221fdc3277d00bfdd856bcc1bb92846301b065 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sun, 15 Sep 2013 12:29:56 +0200 Subject: [PATCH 05/38] Dxf: add more header fields, min/max extent and a test linestyle --- src/core/qgsdxfexport.cpp | 82 ++++++++++++++++++++++++++++++++++++++- src/core/qgsdxfexport.h | 2 + 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 3bde3d16b99..bfb8e4c939b 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -59,12 +59,48 @@ void QgsDxfExport::writeHeader( QTextStream& stream ) startSection( stream ); stream << " 2\n"; stream << "HEADER\n"; + //ACADVER stream << " 9\n"; - stream << "$ACADVER"; + stream << "$ACADVER\n"; + stream << " 1\n"; stream << "AC1009\n"; + + QgsRectangle ext = dxfExtent(); + if ( !ext.isEmpty() ) + { + //EXTMIN + stream << " 9\n"; + stream << "$EXTMIN\n"; + stream << " 10\n"; + stream << ext.xMinimum() << "\n"; + stream << " 20\n"; + stream << ext.yMinimum() << "\n"; + stream << " 30\n"; + stream << "0\n"; + //EXTMAX + stream << " 9\n"; + stream << "$EXTMAX\n"; + stream << " 10\n"; + stream << ext.xMaximum() << "\n"; + stream << " 20\n"; + stream << ext.yMaximum() << "\n"; + stream << " 30\n"; + stream << "0\n"; + } + //LTSCALE stream << " 9\n"; stream << "$LTSCALE\n"; stream << " 40\n"; + stream << "1.0\n"; + //PDMODE + stream << " 9\n"; + stream << "$PDMODE\n"; + stream << " 70\n"; + stream << "33\n"; + //PDSIZE + stream << " 9\n"; + stream << "$PDSIZE\n"; + stream << " 40\n"; stream << "1\n"; endSection( stream ); } @@ -75,7 +111,27 @@ void QgsDxfExport::writeTables( QTextStream& stream ) stream << " 2\n"; stream << "TABLES\n"; - // + //LTYPE + stream << " 0\n"; + stream << "TABLE\n"; + stream << " 0\n"; + stream << "LTYPE\n"; + stream << " 2\n"; + stream << "CONTINUOUS\n"; + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "Defaultstyle\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << "0\n"; + stream << " 40\n"; //todo: add segments in group 49 + stream << "0\n"; + stream << " 0\n"; + stream << "ENDTAB\n"; + + //LAYER stream << " 0\n"; stream << "TABLE\n"; stream << " 0\n"; @@ -192,3 +248,25 @@ void QgsDxfExport::writeVertex( QTextStream& stream, const QgsPoint& pt, const Q stream << " 30\n"; stream << "0.0\n"; } + +QgsRectangle QgsDxfExport::dxfExtent() const +{ + QgsRectangle extent; + QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin(); + for ( ; layerIt != mLayers.constEnd(); ++layerIt ) + { + if ( *layerIt ) + { + if ( extent.isEmpty() ) + { + extent = ( *layerIt )->extent(); + } + else + { + QgsRectangle layerExtent = ( *layerIt )->extent(); + extent.combineExtentWith( &layerExtent ); + } + } + } + return extent; +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 9ac64c8d8a0..c472361464e 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -57,6 +57,8 @@ class QgsDxfExport void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, bool closed = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); + QgsRectangle dxfExtent() const; + //collect styles //writeEntities From dc62376fd2e25b7dceaf511077f699053492e5f1 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sun, 15 Sep 2013 17:45:56 +0200 Subject: [PATCH 06/38] More symbology updates for dxf --- src/core/qgsdxfexport.cpp | 92 ++++++++++++++++++++++++++++++++++++++- src/core/qgsdxfexport.h | 23 ++++++++-- 2 files changed, 109 insertions(+), 6 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index bfb8e4c939b..595e38a19c5 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -103,6 +103,11 @@ void QgsDxfExport::writeHeader( QTextStream& stream ) stream << " 40\n"; stream << "1\n"; endSection( stream ); + //PSLTSCALE + stream << " 9\n"; + stream << "$PSLTSCALE\n"; + stream << " 70\n"; + stream << "0\n"; } void QgsDxfExport::writeTables( QTextStream& stream ) @@ -186,6 +191,31 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) QgsFeature fet; while ( featureIt.nextFeature( fet ) ) { + if ( mSymbologyExport == NoSymbology ) + { + addFeature( fet, stream, vl->name(), 0 ); //no symbology at all + } + else + { + if ( !renderer ) + { + continue; + } + QgsSymbolV2List symbolList = renderer->symbolsForFeature( fet ); + if ( symbolList.size() < 1 ) + { + continue; + } + + //take first symbollayer from first symbol + QgsSymbolV2* s = symbolList.first(); + if ( !s || s->symbolLayerCount() < 1 ) + { + continue; + } + addFeature( fet, stream, vl->name(), s->symbolLayer( 0 ) ); + } +#if 0 //get geometry and write it. Todo: consider symbolisation QgsGeometry* geom = fet.geometry(); if ( geom ) @@ -193,12 +223,18 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) //try with line first writePolyline( stream, geom->asPolyline(), vl->name() ); } +#endif //0 } } endSection( stream ); } +void QgsDxfExport::writeEntitiesSymbolLevels( QTextStream& stream ) +{ + //todo.... +} + void QgsDxfExport::writeEndFile( QTextStream& stream ) { endSection( stream ); @@ -216,17 +252,26 @@ void QgsDxfExport::endSection( QTextStream& stream ) stream << "ENDSEC\n"; } -void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, bool closed ) +void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, int color, + double width, bool closed ) { stream << " 0\n"; stream << "POLYLINE\n"; stream << " 8\n"; stream << layer << "\n"; + stream << " 6\n"; + stream << "CONTINUOUS\n"; //todo: reference to linetype here + stream << " 62\n"; + stream << color << "\n"; stream << " 66\n"; - stream << " 1\n"; + stream << "1\n"; stream << " 70\n"; int type = closed ? 32 : 0; stream << type << "\n"; + stream << " 40\n"; + stream << width << "\n"; + stream << " 41\n"; + stream << width << "\n"; QgsPolyline::const_iterator lineIt = line.constBegin(); for ( ; lineIt != line.constEnd(); ++lineIt ) @@ -270,3 +315,46 @@ QgsRectangle QgsDxfExport::dxfExtent() const } return extent; } + +void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) +{ + QgsGeometry* geom = fet.geometry(); + if ( geom ) + { + //get color from symbollayer + int c = colorFromSymbolLayer( symbolLayer ); + //get width from symbollayer + double width = widthFromSymbolLayer( symbolLayer ); + writePolyline( stream, geom->asPolyline(), layer, c, width ); + } +} + +double QgsDxfExport::scaleToMapUnits( double value, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) const +{ + if ( symbolUnits == QgsSymbolV2::MapUnit ) + { + return 1.0; + } + + //symbology in mm + value *= mSymbologyScaleDenominator / 1000; + if ( mapUnits == QGis::Feet ) + { + value *= 0.3048; + } + else if ( mapUnits == QGis::Degrees ) + { + value /= 111120; + } + return value; +} + +int QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) +{ + return 5; //todo... +} + +double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) +{ + return 50; //todo... +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index c472361464e..306f3d11cc8 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -19,10 +19,12 @@ #define QGSDXFEXPORT_H #include "qgsgeometry.h" +#include "qgssymbolv2.h" #include class QgsMapLayer; class QgsPoint; +class QgsSymbolLayerV2; class QIODevice; class QTextStream; @@ -42,27 +44,40 @@ class QgsDxfExport void addLayers( QList< QgsMapLayer* >& layers ) { mLayers = layers; } int writeToFile( QIODevice* d, SymbologyExport s = SymbolLayerSymbology ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? + void setSymbologyScaleDenominator( double d ) { mSymbologyScaleDenominator = d; } + double symbologyScaleDenominator() const { return mSymbologyScaleDenominator; } + + void setSymbologyExport( SymbologyExport e ) { mSymbologyExport = e; } + SymbologyExport symbologyExport() const { return mSymbologyExport; } + private: QList< QgsMapLayer* > mLayers; + /**Scale for symbology export (used if symbols units are mm)*/ + double mSymbologyScaleDenominator; + SymbologyExport mSymbologyExport; void writeHeader( QTextStream& stream ); void writeTables( QTextStream& stream ); void writeEntities( QTextStream& stream ); + void writeEntitiesSymbolLevels( QTextStream& stream ); void writeEndFile( QTextStream& stream ); void startSection( QTextStream& stream ); void endSection( QTextStream& stream ); - void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, bool closed = false ); + void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, int color, + double width = -1, bool closed = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); QgsRectangle dxfExtent() const; - //collect styles - //writeEntities + void addFeature( const QgsFeature& fet, QTextStream& stream, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); + double scaleToMapUnits( double value, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) const; - //Option: export feature once / multiple export (considering symbol layers / symbol levels) + //returns dxf palette index from symbol layer color + int colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); + double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); }; #endif // QGSDXFEXPORT_H From 93122767e4e55e2dd3d943cbad7c07ed853e989a Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Mon, 16 Sep 2013 12:28:17 +0200 Subject: [PATCH 07/38] Prepare color palette matching for dxf --- src/core/qgsdxfexport.cpp | 39 ++++++++++++++++++++++++++++++++++++++- src/core/qgsdxfexport.h | 6 ++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 595e38a19c5..6b60c82483e 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -23,7 +23,7 @@ #include #include -QgsDxfExport::QgsDxfExport() +QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ) { } @@ -351,6 +351,12 @@ double QgsDxfExport::scaleToMapUnits( double value, QgsSymbolV2::OutputUnit symb int QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) { + if ( !symbolLayer ) + { + return 0; + } + + return 5; //todo... } @@ -358,3 +364,34 @@ double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) { return 50; //todo... } + +int QgsDxfExport::closestMatch( QRgb pixel, const QVector& palette ) +{ + int idx = 0; + int current_distance = INT_MAX; + for ( int i = 0; i < palette.size(); ++i ) + { + int dist = pixel_distance( pixel, palette.at( i ) ); + if ( dist < current_distance ) + { + current_distance = dist; + idx = i; + } + } + return idx; +} + +int QgsDxfExport::pixel_distance( QRgb p1, QRgb p2 ) +{ + int r1 = qRed( p1 ); + int g1 = qGreen( p1 ); + int b1 = qBlue( p1 ); + int a1 = qAlpha( p1 ); + + int r2 = qRed( p2 ); + int g2 = qGreen( p2 ); + int b2 = qBlue( p2 ); + int a2 = qAlpha( p2 ); + + return abs( r1 - r2 ) + abs( g1 - g2 ) + abs( b1 - b2 ) + abs( a1 - a2 ); +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 306f3d11cc8..b3feb0b16ef 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -20,6 +20,7 @@ #include "qgsgeometry.h" #include "qgssymbolv2.h" +#include #include class QgsMapLayer; @@ -78,6 +79,11 @@ class QgsDxfExport //returns dxf palette index from symbol layer color int colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); + + //functions for dxf palette + static int closestMatch( QRgb pixel, const QVector& palette ); + static int pixel_distance( QRgb p1, QRgb p2 ); + }; #endif // QGSDXFEXPORT_H From 523f1e1ca42fa193f2768310770092d932c7e546 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Tue, 29 Oct 2013 13:33:30 +0100 Subject: [PATCH 08/38] Fix TABLE sections --- src/core/qgsdxfexport.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 6b60c82483e..4760ee2d615 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -119,6 +119,10 @@ void QgsDxfExport::writeTables( QTextStream& stream ) //LTYPE stream << " 0\n"; stream << "TABLE\n"; + stream << " 2\n"; + stream << "LTYPE\n"; + stream << " 70\n"; + stream << " 1\n"; //number of linetypes stream << " 0\n"; stream << "LTYPE\n"; stream << " 2\n"; @@ -139,8 +143,10 @@ void QgsDxfExport::writeTables( QTextStream& stream ) //LAYER stream << " 0\n"; stream << "TABLE\n"; - stream << " 0\n"; + stream << " 2\n"; stream << "LAYER\n"; + stream << " 70\n"; + stream << mLayers.count() << "\n"; QList< QgsMapLayer* >::iterator layerIt = mLayers.begin(); for ( ; layerIt != mLayers.end(); ++layerIt ) { @@ -237,7 +243,8 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QTextStream& stream ) void QgsDxfExport::writeEndFile( QTextStream& stream ) { - endSection( stream ); + stream << " 0\n"; + stream << "EOF\n"; } void QgsDxfExport::startSection( QTextStream& stream ) @@ -278,6 +285,8 @@ void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, { writeVertex( stream, *lineIt, layer ); } + stream << " 0\n"; + stream << "SEQEND\n"; } void QgsDxfExport::writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ) From f98ecf753fca68d81cd389a5a96cf2c7c3fb2bcf Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 31 Oct 2013 08:23:50 +0100 Subject: [PATCH 09/38] Dxf color palette --- src/core/qgsdxfexport.cpp | 17 ++++++++++++++++- src/core/qgsdxfexport.h | 3 +++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 4760ee2d615..5d7d2a6b305 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -25,6 +25,7 @@ QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ) { + initColorPalette(); } QgsDxfExport::~QgsDxfExport() @@ -366,7 +367,7 @@ int QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) } - return 5; //todo... + return 1; //todo... } double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) @@ -404,3 +405,17 @@ int QgsDxfExport::pixel_distance( QRgb p1, QRgb p2 ) return abs( r1 - r2 ) + abs( g1 - g2 ) + abs( b1 - b2 ) + abs( a1 - a2 ); } + +void QgsDxfExport::initColorPalette() +{ + mDxfColorPalette.resize( 256 ); + mDxfColorPalette[1] = qRgb( 255, 0, 0 ); + mDxfColorPalette[2] = qRgb( 255, 255, 0 ); + mDxfColorPalette[3] = qRgb( 0, 255, 0 ); + mDxfColorPalette[4] = qRgb( 0, 255, 255 ); + mDxfColorPalette[5] = qRgb( 0, 0, 255 ); + mDxfColorPalette[6] = qRgb( 255, 0, 255 ); + mDxfColorPalette[7] = qRgb( 255, 255, 255 ); + mDxfColorPalette[8] = qRgb( 255, 255, 255 ); + mDxfColorPalette[9] = qRgb( 255, 255, 255 ); +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index b3feb0b16ef..b2795d3572c 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -58,6 +58,8 @@ class QgsDxfExport double mSymbologyScaleDenominator; SymbologyExport mSymbologyExport; + QVector mDxfColorPalette; + void writeHeader( QTextStream& stream ); void writeTables( QTextStream& stream ); void writeEntities( QTextStream& stream ); @@ -81,6 +83,7 @@ class QgsDxfExport double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); //functions for dxf palette + void initColorPalette(); static int closestMatch( QRgb pixel, const QVector& palette ); static int pixel_distance( QRgb p1, QRgb p2 ); From eee9a4976dd39f5649559f73ec3bbaf44fd6ca67 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sun, 3 Nov 2013 15:07:13 +0100 Subject: [PATCH 10/38] Try to find closest color in dxf palette --- src/core/qgsdxfexport.cpp | 306 ++++++++++++++++++++++++++++++++++---- src/core/qgsdxfexport.h | 8 +- 2 files changed, 283 insertions(+), 31 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 5d7d2a6b305..363b26b2f17 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -19,13 +19,274 @@ #include "qgsvectordataprovider.h" #include "qgspoint.h" #include "qgsrendererv2.h" +#include "qgssymbollayerv2.h" #include "qgsvectorlayer.h" #include #include +//dxf color palette +double QgsDxfExport::mDxfColors[][3] = +{ + {0, 0, 0}, // unused + {1, 0, 0}, // 1 + {1, 1, 0}, + {0, 1, 0}, + {0, 1, 1}, + {0, 0, 1}, + {1, 0, 1}, + {1, 1, 1}, // black or white + {0.5, 0.5, 0.5}, + {0.75, 0.75, 0.75}, + {1, 0, 0}, // 10 + {1, 0.5, 0.5}, + {0.65, 0, 0}, + {0.65, 0.325, 0.325}, + {0.5, 0, 0}, + {0.5, 0.25, 0.25}, + {0.3, 0, 0}, + {0.3, 0.15, 0.15}, + {0.15, 0, 0}, + {0.15, 0.075, 0.075}, + {1, 0.25, 0}, // 20 + {1, 0.625, 0.5}, + {0.65, 0.1625, 0}, + {0.65, 0.4063, 0.325}, + {0.5, 0.125, 0}, + {0.5, 0.3125, 0.25}, + {0.3, 0.075, 0}, + {0.3, 0.1875, 0.15}, + {0.15, 0.0375, 0}, + {0.15, 0.0938, 0.075}, + {1, 0.5, 0}, // 30 + {1, 0.75, 0.5}, + {0.65, 0.325, 0}, + {0.65, 0.4875, 0.325}, + {0.5, 0.25, 0}, + {0.5, 0.375, 0.25}, + {0.3, 0.15, 0}, + {0.3, 0.225, 0.15}, + {0.15, 0.075, 0}, + {0.15, 0.1125, 0.075}, + {1, 0.75, 0}, // 40 + {1, 0.875, 0.5}, + {0.65, 0.4875, 0}, + {0.65, 0.5688, 0.325}, + {0.5, 0.375, 0}, + {0.5, 0.4375, 0.25}, + {0.3, 0.225, 0}, + {0.3, 0.2625, 0.15}, + {0.15, 0.1125, 0}, + {0.15, 0.1313, 0.075}, + {1, 1, 0}, // 50 + {1, 1, 0.5}, + {0.65, 0.65, 0}, + {0.65, 0.65, 0.325}, + {0.5, 0.5, 0}, + {0.5, 0.5, 0.25}, + {0.3, 0.3, 0}, + {0.3, 0.3, 0.15}, + {0.15, 0.15, 0}, + {0.15, 0.15, 0.075}, + {0.75, 1, 0}, // 60 + {0.875, 1, 0.5}, + {0.4875, 0.65, 0}, + {0.5688, 0.65, 0.325}, + {0.375, 0.5, 0}, + {0.4375, 0.5, 0.25}, + {0.225, 0.3, 0}, + {0.2625, 0.3, 0.15}, + {0.1125, 0.15, 0}, + {0.1313, 0.15, 0.075}, + {0.5, 1, 0}, // 70 + {0.75, 1, 0.5}, + {0.325, 0.65, 0}, + {0.4875, 0.65, 0.325}, + {0.25, 0.5, 0}, + {0.375, 0.5, 0.25}, + {0.15, 0.3, 0}, + {0.225, 0.3, 0.15}, + {0.075, 0.15, 0}, + {0.1125, 0.15, 0.075}, + {0.25, 1, 0}, // 80 + {0.625, 1, 0.5}, + {0.1625, 0.65, 0}, + {0.4063, 0.65, 0.325}, + {0.125, 0.5, 0}, + {0.3125, 0.5, 0.25}, + {0.075, 0.3, 0}, + {0.1875, 0.3, 0.15}, + {0.0375, 0.15, 0}, + {0.0938, 0.15, 0.075}, + {0, 1, 0}, // 90 + {0.5, 1, 0.5}, + {0, 0.65, 0}, + {0.325, 0.65, 0.325}, + {0, 0.5, 0}, + {0.25, 0.5, 0.25}, + {0, 0.3, 0}, + {0.15, 0.3, 0.15}, + {0, 0.15, 0}, + {0.075, 0.15, 0.075}, + {0, 1, 0.25}, // 100 + {0.5, 1, 0.625}, + {0, 0.65, 0.1625}, + {0.325, 0.65, 0.4063}, + {0, 0.5, 0.125}, + {0.25, 0.5, 0.3125}, + {0, 0.3, 0.075}, + {0.15, 0.3, 0.1875}, + {0, 0.15, 0.0375}, + {0.075, 0.15, 0.0938}, + {0, 1, 0.5}, // 110 + {0.5, 1, 0.75}, + {0, 0.65, 0.325}, + {0.325, 0.65, 0.4875}, + {0, 0.5, 0.25}, + {0.25, 0.5, 0.375}, + {0, 0.3, 0.15}, + {0.15, 0.3, 0.225}, + {0, 0.15, 0.075}, + {0.075, 0.15, 0.1125}, + {0, 1, 0.75}, // 120 + {0.5, 1, 0.875}, + {0, 0.65, 0.4875}, + {0.325, 0.65, 0.5688}, + {0, 0.5, 0.375}, + {0.25, 0.5, 0.4375}, + {0, 0.3, 0.225}, + {0.15, 0.3, 0.2625}, + {0, 0.15, 0.1125}, + {0.075, 0.15, 0.1313}, + {0, 1, 1}, // 130 + {0.5, 1, 1}, + {0, 0.65, 0.65}, + {0.325, 0.65, 0.65}, + {0, 0.5, 0.5}, + {0.25, 0.5, 0.5}, + {0, 0.3, 0.3}, + {0.15, 0.3, 0.3}, + {0, 0.15, 0.15}, + {0.075, 0.15, 0.15}, + {0, 0.75, 1}, // 140 + {0.5, 0.875, 1}, + {0, 0.4875, 0.65}, + {0.325, 0.5688, 0.65}, + {0, 0.375, 0.5}, + {0.25, 0.4375, 0.5}, + {0, 0.225, 0.3}, + {0.15, 0.2625, 0.3}, + {0, 0.1125, 0.15}, + {0.075, 0.1313, 0.15}, + {0, 0.5, 1}, // 150 + {0.5, 0.75, 1}, + {0, 0.325, 0.65}, + {0.325, 0.4875, 0.65}, + {0, 0.25, 0.5}, + {0.25, 0.375, 0.5}, + {0, 0.15, 0.3}, + {0.15, 0.225, 0.3}, + {0, 0.075, 0.15}, + {0.075, 0.1125, 0.15}, + {0, 0.25, 1}, // 160 + {0.5, 0.625, 1}, + {0, 0.1625, 0.65}, + {0.325, 0.4063, 0.65}, + {0, 0.125, 0.5}, + {0.25, 0.3125, 0.5}, + {0, 0.075, 0.3}, + {0.15, 0.1875, 0.3}, + {0, 0.0375, 0.15}, + {0.075, 0.0938, 0.15}, + {0, 0, 1}, // 170 + {0.5, 0.5, 1}, + {0, 0, 0.65}, + {0.325, 0.325, 0.65}, + {0, 0, 0.5}, + {0.25, 0.25, 0.5}, + {0, 0, 0.3}, + {0.15, 0.15, 0.3}, + {0, 0, 0.15}, + {0.075, 0.075, 0.15}, + {0.25, 0, 1}, // 180 + {0.625, 0.5, 1}, + {0.1625, 0, 0.65}, + {0.4063, 0.325, 0.65}, + {0.125, 0, 0.5}, + {0.3125, 0.25, 0.5}, + {0.075, 0, 0.3}, + {0.1875, 0.15, 0.3}, + {0.0375, 0, 0.15}, + {0.0938, 0.075, 0.15}, + {0.5, 0, 1}, // 190 + {0.75, 0.5, 1}, + {0.325, 0, 0.65}, + {0.4875, 0.325, 0.65}, + {0.25, 0, 0.5}, + {0.375, 0.25, 0.5}, + {0.15, 0, 0.3}, + {0.225, 0.15, 0.3}, + {0.075, 0, 0.15}, + {0.1125, 0.075, 0.15}, + {0.75, 0, 1}, // 200 + {0.875, 0.5, 1}, + {0.4875, 0, 0.65}, + {0.5688, 0.325, 0.65}, + {0.375, 0, 0.5}, + {0.4375, 0.25, 0.5}, + {0.225, 0, 0.3}, + {0.2625, 0.15, 0.3}, + {0.1125, 0, 0.15}, + {0.1313, 0.075, 0.15}, + {1, 0, 1}, // 210 + {1, 0.5, 1}, + {0.65, 0, 0.65}, + {0.65, 0.325, 0.65}, + {0.5, 0, 0.5}, + {0.5, 0.25, 0.5}, + {0.3, 0, 0.3}, + {0.3, 0.15, 0.3}, + {0.15, 0, 0.15}, + {0.15, 0.075, 0.15}, + {1, 0, 0.75}, // 220 + {1, 0.5, 0.875}, + {0.65, 0, 0.4875}, + {0.65, 0.325, 0.5688}, + {0.5, 0, 0.375}, + {0.5, 0.25, 0.4375}, + {0.3, 0, 0.225}, + {0.3, 0.15, 0.2625}, + {0.15, 0, 0.1125}, + {0.15, 0.075, 0.1313}, + {1, 0, 0.5}, // 230 + {1, 0.5, 0.75}, + {0.65, 0, 0.325}, + {0.65, 0.325, 0.4875}, + {0.5, 0, 0.25}, + {0.5, 0.25, 0.375}, + {0.3, 0, 0.15}, + {0.3, 0.15, 0.225}, + {0.15, 0, 0.075}, + {0.15, 0.075, 0.1125}, + {1, 0, 0.25}, // 240 + {1, 0.5, 0.625}, + {0.65, 0, 0.1625}, + {0.65, 0.325, 0.4063}, + {0.5, 0, 0.125}, + {0.5, 0.25, 0.3125}, + {0.3, 0, 0.075}, + {0.3, 0.15, 0.1875}, + {0.15, 0, 0.0375}, + {0.15, 0.075, 0.0938}, + {0.33, 0.33, 0.33}, // 250 + {0.464, 0.464, 0.464}, + {0.598, 0.598, 0.598}, + {0.732, 0.732, 0.732}, + {0.866, 0.866, 0.866}, + {1, 1, 1} // 255 +}; + QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ) { - initColorPalette(); } QgsDxfExport::~QgsDxfExport() @@ -366,8 +627,8 @@ int QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) return 0; } - - return 1; //todo... + QColor c = symbolLayer->color(); + return closestColorMatch( c.rgba() ); } double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) @@ -375,13 +636,13 @@ double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) return 50; //todo... } -int QgsDxfExport::closestMatch( QRgb pixel, const QVector& palette ) +int QgsDxfExport::closestColorMatch( QRgb pixel ) { int idx = 0; int current_distance = INT_MAX; - for ( int i = 0; i < palette.size(); ++i ) + for ( int i = 1; i < 256; ++i ) { - int dist = pixel_distance( pixel, palette.at( i ) ); + int dist = color_distance( pixel, i ); if ( dist < current_distance ) { current_distance = dist; @@ -391,31 +652,20 @@ int QgsDxfExport::closestMatch( QRgb pixel, const QVector& palette ) return idx; } -int QgsDxfExport::pixel_distance( QRgb p1, QRgb p2 ) +int QgsDxfExport::color_distance( QRgb p1, int index ) { - int r1 = qRed( p1 ); - int g1 = qGreen( p1 ); - int b1 = qBlue( p1 ); - int a1 = qAlpha( p1 ); + if ( index > 255 || index < 0 ) + { + return 0; + } - int r2 = qRed( p2 ); - int g2 = qGreen( p2 ); - int b2 = qBlue( p2 ); - int a2 = qAlpha( p2 ); - - return abs( r1 - r2 ) + abs( g1 - g2 ) + abs( b1 - b2 ) + abs( a1 - a2 ); + double redDiff = qRed( p1 ) - mDxfColors[index][0] * 255; + double greenDiff = qGreen( p1 ) - mDxfColors[index][1] * 255; + double blueDiff = qBlue( p1 ) - mDxfColors[index][2] * 255; + return ( redDiff * redDiff + greenDiff * greenDiff + blueDiff * blueDiff ); } -void QgsDxfExport::initColorPalette() +QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b ) { - mDxfColorPalette.resize( 256 ); - mDxfColorPalette[1] = qRgb( 255, 0, 0 ); - mDxfColorPalette[2] = qRgb( 255, 255, 0 ); - mDxfColorPalette[3] = qRgb( 0, 255, 0 ); - mDxfColorPalette[4] = qRgb( 0, 255, 255 ); - mDxfColorPalette[5] = qRgb( 0, 0, 255 ); - mDxfColorPalette[6] = qRgb( 255, 0, 255 ); - mDxfColorPalette[7] = qRgb( 255, 255, 255 ); - mDxfColorPalette[8] = qRgb( 255, 255, 255 ); - mDxfColorPalette[9] = qRgb( 255, 255, 255 ); + return QColor::fromRgbF( r, g, b ).rgb(); } diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index b2795d3572c..f3805c1f101 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -83,9 +83,11 @@ class QgsDxfExport double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); //functions for dxf palette - void initColorPalette(); - static int closestMatch( QRgb pixel, const QVector& palette ); - static int pixel_distance( QRgb p1, QRgb p2 ); + static int closestColorMatch( QRgb pixel ); + static int color_distance( QRgb p1, int index ); + static QRgb createRgbEntry( qreal r, qreal g, qreal b ); + + static double mDxfColors[][3]; }; From d131b7ae77300d73c9717430357908007f71a5bf Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Mon, 4 Nov 2013 11:06:30 +0100 Subject: [PATCH 11/38] Support multilines / polygons / multipolygons (as closed linestrings for now) --- src/core/qgsdxfexport.cpp | 55 ++++++++++++++++++++++++++++++++++----- src/core/qgsdxfexport.h | 2 +- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 363b26b2f17..b487975c467 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -459,7 +459,7 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) QgsFeature fet; while ( featureIt.nextFeature( fet ) ) { - if ( mSymbologyExport == NoSymbology ) + if ( 0 /*mSymbologyExport == NoSymbology*/ ) { addFeature( fet, stream, vl->name(), 0 ); //no symbology at all } @@ -522,7 +522,7 @@ void QgsDxfExport::endSection( QTextStream& stream ) } void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, int color, - double width, bool closed ) + double width, bool polygon ) { stream << " 0\n"; stream << "POLYLINE\n"; @@ -535,7 +535,7 @@ void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, stream << " 66\n"; stream << "1\n"; stream << " 70\n"; - int type = closed ? 32 : 0; + int type = polygon ? 49 : 0; stream << type << "\n"; stream << " 40\n"; stream << width << "\n"; @@ -592,11 +592,54 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsGeometry* geom = fet.geometry(); if ( geom ) { - //get color from symbollayer int c = colorFromSymbolLayer( symbolLayer ); - //get width from symbollayer double width = widthFromSymbolLayer( symbolLayer ); - writePolyline( stream, geom->asPolyline(), layer, c, width ); + + //todo: write point symbols as blocks + + QGis::WkbType geometryType = geom->wkbType(); + //single line + if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) + { + writePolyline( stream, geom->asPolyline(), layer, c, width, false ); + } + + //multiline + if ( geometryType == QGis::WKBMultiLineString || geometryType == QGis::WKBMultiLineString25D ) + { + QgsMultiPolyline multiLine = geom->asMultiPolyline(); + QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); + for ( ; lIt != multiLine.constEnd(); ++lIt ) + { + writePolyline( stream, *lIt, layer, c, width, false ); + } + } + + //polygon + if ( geometryType == QGis::WKBPolygon || geometryType == QGis::WKBPolygon25D ) + { + QgsPolygon polygon = geom->asPolygon(); + QgsPolygon::const_iterator polyIt = polygon.constBegin(); + for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings + { + writePolyline( stream, *polyIt, layer, c, width, true ); + } + } + + //multipolygon or polygon + if ( geometryType == QGis::WKBMultiPolygon || geometryType == QGis::WKBMultiPolygon25D ) + { + QgsMultiPolygon mp = geom->asMultiPolygon(); + QgsMultiPolygon::const_iterator mpIt = mp.constBegin(); + for ( ; mpIt != mp.constEnd(); ++mpIt ) + { + QgsPolygon::const_iterator polyIt = mpIt->constBegin(); + for ( ; polyIt != mpIt->constEnd(); ++polyIt ) + { + writePolyline( stream, *polyIt, layer, c, width, true ); + } + } + } } } diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index f3805c1f101..2ffac7748b8 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -70,7 +70,7 @@ class QgsDxfExport void endSection( QTextStream& stream ); void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, int color, - double width = -1, bool closed = false ); + double width = -1, bool polygon = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); QgsRectangle dxfExtent() const; From 446b6d632f1be00fcd2882048beb73a21e0e0c86 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Tue, 5 Nov 2013 15:26:31 +0100 Subject: [PATCH 12/38] Add dxf export gui and menu entry in qgisapp --- src/app/CMakeLists.txt | 2 + src/app/qgisapp.cpp | 66 +++++++++++---- src/app/qgisapp.h | 2 + src/app/qgsdxfexportdialog.cpp | 119 +++++++++++++++++++++++++++ src/app/qgsdxfexportdialog.h | 25 ++++++ src/ui/qgisapp.ui | 8 +- src/ui/qgsdxfexportdialogbase.ui | 136 +++++++++++++++++++++++++++++++ 7 files changed, 339 insertions(+), 19 deletions(-) create mode 100644 src/app/qgsdxfexportdialog.cpp create mode 100644 src/app/qgsdxfexportdialog.h create mode 100644 src/ui/qgsdxfexportdialogbase.ui diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index a335f482df5..2e6771482bc 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -27,6 +27,7 @@ SET(QGIS_APP_SRCS qgsdecorationscalebardialog.cpp qgsdecorationgrid.cpp qgsdecorationgriddialog.cpp + qgsdxfexportdialog.cpp qgsformannotationdialog.cpp qgshtmlannotationdialog.cpp qgsdelattrdialog.cpp @@ -187,6 +188,7 @@ SET (QGIS_APP_MOC_HDRS qgsdelattrdialog.h qgsdiagramproperties.h qgsdisplayangle.h + qgsdxfexportdialog.h qgsfeatureaction.h qgsfieldcalculator.h qgsfieldsproperties.h diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index e4db5171431..9ffeff3a34d 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -118,6 +118,8 @@ #include "qgscustomization.h" #include "qgscustomprojectiondialog.h" #include "qgsdatasourceuri.h" +#include "qgsdxfexport.h" +#include "qgsdxfexportdialog.h" #include "qgsdecorationcopyright.h" #include "qgsdecorationnortharrow.h" #include "qgsdecorationscalebar.h" @@ -947,6 +949,7 @@ void QgisApp::createActions() connect( mActionNewPrintComposer, SIGNAL( triggered() ), this, SLOT( newPrintComposer() ) ); connect( mActionShowComposerManager, SIGNAL( triggered() ), this, SLOT( showComposerManager() ) ); connect( mActionExit, SIGNAL( triggered() ), this, SLOT( fileExit() ) ); + connect( mActionDxfExport, SIGNAL( triggered() ), this, SLOT( dxfExport() ) ); // Edit Menu Items @@ -1778,7 +1781,7 @@ void QgisApp::setTheme( QString theThemeName ) mActionRotateFeature->setIcon( QgsApplication::getThemeIcon( "/mActionRotateFeature.png" ) ); mActionReshapeFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionReshape.png" ) ); mActionSplitFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionSplitFeatures.svg" ) ); - mActionSplitParts->setIcon( QgsApplication::getThemeIcon( "/mActionSplitParts.svg" ) ); + mActionSplitParts->setIcon( QgsApplication::getThemeIcon( "/mActionSplitParts.svg" ) ); mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.svg" ) ); mActionNodeTool->setIcon( QgsApplication::getThemeIcon( "/mActionNodeTool.png" ) ); mActionSimplifyFeature->setIcon( QgsApplication::getThemeIcon( "/mActionSimplify.png" ) ); @@ -3797,6 +3800,33 @@ void QgisApp::fileSaveAs() } } // QgisApp::fileSaveAs +void QgisApp::dxfExport() +{ + QgsDxfExportDialog d( QgsMapLayerRegistry::instance()->mapLayers().keys() ); + if ( d.exec() == QDialog::Accepted ) + { + QgsDxfExport dxfExport; + + QList layerList; + QList layerIdList = d.layers(); + QList::const_iterator layerIt = layerIdList.constBegin(); + for ( ; layerIt != layerIdList.constEnd(); ++layerIt ) + { + QgsMapLayer* l = QgsMapLayerRegistry::instance()->mapLayer( *layerIt ); + if ( l ) + { + layerList.append( l ); + } + } + + dxfExport.addLayers( layerList ); + dxfExport.setSymbologyScaleDenominator( d.symbologyScale() ); + dxfExport.setSymbologyExport( d.symbologyMode() ); + QFile dxfFile( d.saveFile() ); + dxfExport.writeToFile( &dxfFile ); + } +} + // Open the project file corresponding to the // path at the given index in mRecentProjectPaths void QgisApp::openProject( QAction *action ) @@ -8873,27 +8903,27 @@ bool QgisApp::addRasterLayers( QStringList const &theFileNameQStringList, bool g /////////////////////////////////////////////////////////////////// #ifdef ANDROID -void QgisApp::keyReleaseEvent(QKeyEvent *event) +void QgisApp::keyReleaseEvent( QKeyEvent *event ) { -static bool accepted=true; - if (event->key()==Qt::Key_Close) + static bool accepted = true; + if ( event->key() == Qt::Key_Close ) + { + // do something useful here + int ret = QMessageBox::question( this, tr( "Exit QGIS" ), + tr( "Do you really want to quit QGIS?" ), + QMessageBox::Yes | QMessageBox::No ); + switch ( ret ) { - // do something useful here - int ret = QMessageBox::question(this, tr("Exit QGIS"), - tr("Do you really want to quit QGIS?"), - QMessageBox::Yes | QMessageBox::No); - switch(ret) - { - case QMessageBox::Yes: - this->close(); - break; + case QMessageBox::Yes: + this->close(); + break; - case QMessageBox::No: - break; - } - event->setAccepted(accepted); // dont't close my Top Level Widget ! - accepted=false;// close the app next time when the user press back button + case QMessageBox::No: + break; } + event->setAccepted( accepted ); // dont't close my Top Level Widget ! + accepted = false;// close the app next time when the user press back button + } } #endif diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index 0942891b281..6a039ea4773 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -827,6 +827,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow bool fileSave(); //! Save project as void fileSaveAs(); + //! Export project in dxf format + void dxfExport(); //! Open the project file corresponding to the //! text)= of the given action. void openProject( QAction *action ); diff --git a/src/app/qgsdxfexportdialog.cpp b/src/app/qgsdxfexportdialog.cpp new file mode 100644 index 00000000000..2a9b4bf5bd6 --- /dev/null +++ b/src/app/qgsdxfexportdialog.cpp @@ -0,0 +1,119 @@ +#include "qgsdxfexportdialog.h" +#include "qgsmaplayer.h" +#include "qgsmaplayerregistry.h" +#include "qgis.h" +#include +#include +#include + +QgsDxfExportDialog::QgsDxfExportDialog( const QList& layerKeys, QWidget* parent, Qt::WindowFlags f ): QDialog( parent, f ) +{ + setupUi( this ); + connect( mFileLineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( setOkEnabled() ) ); + connect( this, SIGNAL( accepted() ), this, SLOT( saveSettings() ) ); + + QList::const_iterator layerIt = layerKeys.constBegin(); + for ( ; layerIt != layerKeys.constEnd(); ++layerIt ) + { + QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( *layerIt ); + if ( layer ) + { + if ( layer->type() == QgsMapLayer::VectorLayer ) + { + QListWidgetItem* layerItem = new QListWidgetItem( layer->name() ); + layerItem->setData( Qt::UserRole, *layerIt ); + layerItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ); + layerItem->setCheckState( Qt::Checked ); + mLayersListWidget->addItem( layerItem ); + } + } + } + + //last dxf symbology mode + QSettings s; + mSymbologyModeComboBox->setCurrentIndex( s.value( "qgis/lastDxfSymbologyMode", "2" ).toInt() ); + //last symbol scale + mSymbologyScaleLineEdit->setText( s.value( "qgis/lastSymbologyExportScale", "50000" ).toString() ); + + buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false ); +} + +QgsDxfExportDialog::~QgsDxfExportDialog() +{ + +} + +QList QgsDxfExportDialog::layers() const +{ + QList layerKeyList; + int nItems = mLayersListWidget->count(); + for ( int i = 0; i < nItems; ++i ) + { + QListWidgetItem* currentItem = mLayersListWidget->item( i ); + if ( currentItem->checkState() == Qt::Checked ) + { + layerKeyList.append( currentItem->data( Qt::UserRole ).toString() ); + } + } + return layerKeyList; +} + +double QgsDxfExportDialog::symbologyScale() const +{ + double scale = mSymbologyScaleLineEdit->text().toDouble(); + if ( qgsDoubleNear( scale, 0.0 ) ) + { + return 1.0; + } + return scale; +} + +QString QgsDxfExportDialog::saveFile() const +{ + return mFileLineEdit->text(); +} + +QgsDxfExport::SymbologyExport QgsDxfExportDialog::symbologyMode() const +{ + return ( QgsDxfExport::SymbologyExport )mSymbologyModeComboBox->currentIndex(); +} + +void QgsDxfExportDialog::on_mFileSelectionButton_clicked() +{ + //get last dxf save directory + QSettings s; + QString lastSavePath = s.value( "qgis/lastDxfDir" ).toString(); + + QString filePath = QFileDialog::getSaveFileName( 0, tr( "Export as DXF" ), lastSavePath, tr( "DXF files *.dxf *.DXF" ) ); + if ( !filePath.isEmpty() ) + { + mFileLineEdit->setText( filePath ); + } +} + +void QgsDxfExportDialog::setOkEnabled() +{ + QPushButton* btn = buttonBox->button( QDialogButtonBox::Ok ); + + QString filePath = mFileLineEdit->text(); + if ( filePath.isEmpty() ) + { + btn->setEnabled( false ); + } + + QFileInfo fi( filePath ); + btn->setEnabled( fi.absoluteDir().exists() ); +} + +void QgsDxfExportDialog::saveSettings() +{ + QSettings s; + + //last dxf dir + QFileInfo dxfFileInfo( mFileLineEdit->text() ); + s.setValue( "qgis/lastDxfDir", dxfFileInfo.absolutePath() ); + + //last dxf symbology mode + s.setValue( "qgis/lastDxfSymbologyMode", mSymbologyModeComboBox->currentIndex() ); + s.setValue( "qgis/lastSymbologyExportScale", mSymbologyScaleLineEdit->text() ); +} diff --git a/src/app/qgsdxfexportdialog.h b/src/app/qgsdxfexportdialog.h new file mode 100644 index 00000000000..5e75b9e3cd7 --- /dev/null +++ b/src/app/qgsdxfexportdialog.h @@ -0,0 +1,25 @@ +#ifndef QGSDXFEXPORTDIALOG_H +#define QGSDXFEXPORTDIALOG_H + +#include "ui_qgsdxfexportdialogbase.h" +#include "qgsdxfexport.h" + +class QgsDxfExportDialog: public QDialog, private Ui::QgsDxfExportDialogBase +{ + Q_OBJECT + public: + QgsDxfExportDialog( const QList& layerKeys, QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~QgsDxfExportDialog(); + + QList layers() const; + double symbologyScale() const; + QgsDxfExport::SymbologyExport symbologyMode() const; + QString saveFile() const; + + private slots: + void on_mFileSelectionButton_clicked(); + void setOkEnabled(); + void saveSettings(); +}; + +#endif // QGSDXFEXPORTDIALOG_H diff --git a/src/ui/qgisapp.ui b/src/ui/qgisapp.ui index 2158e6cad3f..a998772edae 100644 --- a/src/ui/qgisapp.ui +++ b/src/ui/qgisapp.ui @@ -17,7 +17,7 @@ 0 0 1050 - 31 + 20 @@ -47,6 +47,7 @@ + @@ -2136,6 +2137,11 @@ Acts on currently active editable layer Paste features in clipboard into a new memory vector layer. + + + DXF Export... + + diff --git a/src/ui/qgsdxfexportdialogbase.ui b/src/ui/qgsdxfexportdialogbase.ui new file mode 100644 index 00000000000..1061aac98af --- /dev/null +++ b/src/ui/qgsdxfexportdialogbase.ui @@ -0,0 +1,136 @@ + + + QgsDxfExportDialogBase + + + + 0 + 0 + 373 + 288 + + + + Dialog + + + + + 20 + 260 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 10 + 10 + 361 + 247 + + + + + + + + + + Symbology mode + + + + + + + Symbology scale + + + + + + + Save as + + + + + + + ... + + + + + + + + No symbology + + + + + Feature symbology + + + + + Symbol layer symbology + + + + + + + + + + + + + + + + + buttonBox + accepted() + QgsDxfExportDialogBase + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + QgsDxfExportDialogBase + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From 705ccf50c2fbe7e2bbbb276178244638386c11cb Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Wed, 6 Nov 2013 16:44:48 +0100 Subject: [PATCH 13/38] Implement line width and symbol level support --- src/app/qgisapp.cpp | 8 ++ src/core/qgsdxfexport.cpp | 177 ++++++++++++++++++++++++++++++++++---- src/core/qgsdxfexport.h | 19 ++-- 3 files changed, 183 insertions(+), 21 deletions(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 9ffeff3a34d..a754f3adb7a 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -3822,6 +3822,14 @@ void QgisApp::dxfExport() dxfExport.addLayers( layerList ); dxfExport.setSymbologyScaleDenominator( d.symbologyScale() ); dxfExport.setSymbologyExport( d.symbologyMode() ); + if ( mapCanvas() ) + { + QgsMapRenderer* r = mapCanvas()->mapRenderer(); + if ( r ) + { + dxfExport.setMapUnits( r->mapUnits() ); + } + } QFile dxfFile( d.saveFile() ); dxfExport.writeToFile( &dxfFile ); } diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index b487975c467..9dea50c5bb4 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -285,7 +285,7 @@ double QgsDxfExport::mDxfColors[][3] = {1, 1, 1} // 255 }; -QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ) +QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ) { } @@ -294,7 +294,7 @@ QgsDxfExport::~QgsDxfExport() } -int QgsDxfExport::writeToFile( QIODevice* d, SymbologyExport s ) +int QgsDxfExport::writeToFile( QIODevice* d ) { if ( !d ) { @@ -447,19 +447,27 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) { continue; } + + QgsFeatureRendererV2* renderer = vl->rendererV2(); + if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology && renderer->usingSymbolLevels() ) + { + writeEntitiesSymbolLevels( stream, vl ); + continue; + } + QgsVectorDataProvider* dp = vl->dataProvider(); if ( !dp ) { continue; } - QgsFeatureRendererV2* renderer = vl->rendererV2(); + QgsFeatureIterator featureIt = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( renderer->usedAttributes(), dp->fields() ) ); QgsFeature fet; while ( featureIt.nextFeature( fet ) ) { - if ( 0 /*mSymbologyExport == NoSymbology*/ ) + if ( mSymbologyExport == NoSymbology ) { addFeature( fet, stream, vl->name(), 0 ); //no symbology at all } @@ -483,24 +491,93 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) } addFeature( fet, stream, vl->name(), s->symbolLayer( 0 ) ); } -#if 0 - //get geometry and write it. Todo: consider symbolisation - QgsGeometry* geom = fet.geometry(); - if ( geom ) - { - //try with line first - writePolyline( stream, geom->asPolyline(), vl->name() ); - } -#endif //0 } } endSection( stream ); } -void QgsDxfExport::writeEntitiesSymbolLevels( QTextStream& stream ) +void QgsDxfExport::writeEntitiesSymbolLevels( QTextStream& stream, QgsVectorLayer* layer ) { - //todo.... + if ( !layer ) + { + return; + } + + QgsFeatureRendererV2* renderer = layer->rendererV2(); + if ( !renderer ) + { + //return error + } + QHash< QgsSymbolV2*, QList > features; + + startRender( layer ); + + //get iterator + QgsFeatureRequest req; + if ( layer->wkbType() == QGis::WKBNoGeometry ) + { + req.setFlags( QgsFeatureRequest::NoGeometry ); + } + req.setSubsetOfAttributes( QStringList( renderer->usedAttributes() ), layer->pendingFields() ); + QgsFeatureIterator fit = layer->getFeatures( req ); + + //fetch features + QgsFeature fet; + QgsSymbolV2* featureSymbol = 0; + while ( fit.nextFeature( fet ) ) + { + featureSymbol = renderer->symbolForFeature( fet ); + if ( !featureSymbol ) + { + continue; + } + + QHash< QgsSymbolV2*, QList >::iterator it = features.find( featureSymbol ); + if ( it == features.end() ) + { + it = features.insert( featureSymbol, QList() ); + } + it.value().append( fet ); + } + + //find out order + QgsSymbolV2LevelOrder levels; + QgsSymbolV2List symbols = renderer->symbols(); + for ( int i = 0; i < symbols.count(); i++ ) + { + QgsSymbolV2* sym = symbols[i]; + for ( int j = 0; j < sym->symbolLayerCount(); j++ ) + { + int level = sym->symbolLayer( j )->renderingPass(); + if ( level < 0 || level >= 1000 ) // ignore invalid levels + continue; + QgsSymbolV2LevelItem item( sym, j ); + while ( level >= levels.count() ) // append new empty levels + levels.append( QgsSymbolV2Level() ); + levels[level].append( item ); + } + } + + //export symbol layers and symbology + for ( int l = 0; l < levels.count(); l++ ) + { + QgsSymbolV2Level& level = levels[l]; + for ( int i = 0; i < level.count(); i++ ) + { + QgsSymbolV2LevelItem& item = level[i]; + QHash< QgsSymbolV2*, QList >::iterator levelIt = features.find( item.symbol() ); + + int llayer = item.layer(); + QList& featureList = levelIt.value(); + QList::iterator featureIt = featureList.begin(); + for ( ; featureIt != featureList.end(); ++featureIt ) + { + addFeature( *featureIt, stream, layer->name(), levelIt.key()->symbolLayer( llayer ) ); + } + } + } + stopRender( layer ); } void QgsDxfExport::writeEndFile( QTextStream& stream ) @@ -676,7 +753,18 @@ int QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) { - return 50; //todo... + //line symbol layer has width and width units + if ( symbolLayer && symbolLayer->type() == QgsSymbolV2::Line ) + { + const QgsLineSymbolLayerV2* lineSymbolLayer = static_cast( symbolLayer ); + return ( lineSymbolLayer->width() * mapUnitScaleFactor( mSymbologyScaleDenominator, lineSymbolLayer->widthUnit(), mMapUnits ) ); + } + + return 1.0; + + //marker symbol layer: check for embedded line layers? + + //mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) } int QgsDxfExport::closestColorMatch( QRgb pixel ) @@ -712,3 +800,60 @@ QRgb QgsDxfExport::createRgbEntry( qreal r, qreal g, qreal b ) { return QColor::fromRgbF( r, g, b ).rgb(); } + +QgsRenderContext QgsDxfExport::renderContext() const +{ + QgsRenderContext context; + context.setRendererScale( mSymbologyScaleDenominator ); + return context; +} + +void QgsDxfExport::startRender( QgsVectorLayer* vl ) const +{ + if ( !vl ) + { + return; + } + + QgsFeatureRendererV2* renderer = vl->rendererV2(); + if ( !renderer ) + { + return; + } + + QgsRenderContext ctx = renderContext(); + renderer->startRender( ctx, vl ); +} + +void QgsDxfExport::stopRender( QgsVectorLayer* vl ) const +{ + if ( !vl ) + { + return; + } + + QgsFeatureRendererV2* renderer = vl->rendererV2(); + if ( !renderer ) + { + return; + } + + QgsRenderContext ctx = renderContext(); + renderer->stopRender( ctx ); +} + +double QgsDxfExport::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) +{ + if ( symbolUnits == QgsSymbolV2::MapUnit ) + { + return 1.0; + } + else + { + if ( symbolUnits == QgsSymbolV2::MM && mapUnits == QGis::Meters ) + { + return scaleDenominator / 1000; + } + } + return 1.0; +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 2ffac7748b8..21be4646ad9 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -35,7 +35,7 @@ class QgsDxfExport enum SymbologyExport { NoSymbology = 0, //export only data - FeatureSymbology, //Keeps the number of features and export symbology per feature + FeatureSymbology, //Keeps the number of features and export symbology per feature (using the first symbol level) SymbolLayerSymbology //Exports one feature per symbol layer (considering symbol levels) }; @@ -43,11 +43,14 @@ class QgsDxfExport ~QgsDxfExport(); void addLayers( QList< QgsMapLayer* >& layers ) { mLayers = layers; } - int writeToFile( QIODevice* d, SymbologyExport s = SymbolLayerSymbology ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? + int writeToFile( QIODevice* d ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? void setSymbologyScaleDenominator( double d ) { mSymbologyScaleDenominator = d; } double symbologyScaleDenominator() const { return mSymbologyScaleDenominator; } + void setMapUnits( QGis::UnitType u ) { mMapUnits = u; } + QGis::UnitType mapUnits() const { return mMapUnits; } + void setSymbologyExport( SymbologyExport e ) { mSymbologyExport = e; } SymbologyExport symbologyExport() const { return mSymbologyExport; } @@ -57,13 +60,16 @@ class QgsDxfExport /**Scale for symbology export (used if symbols units are mm)*/ double mSymbologyScaleDenominator; SymbologyExport mSymbologyExport; + QGis::UnitType mMapUnits; QVector mDxfColorPalette; + static double mDxfColors[][3]; + void writeHeader( QTextStream& stream ); void writeTables( QTextStream& stream ); void writeEntities( QTextStream& stream ); - void writeEntitiesSymbolLevels( QTextStream& stream ); + void writeEntitiesSymbolLevels( QTextStream& stream, QgsVectorLayer* layer ); void writeEndFile( QTextStream& stream ); void startSection( QTextStream& stream ); @@ -87,8 +93,11 @@ class QgsDxfExport static int color_distance( QRgb p1, int index ); static QRgb createRgbEntry( qreal r, qreal g, qreal b ); - static double mDxfColors[][3]; - + //helper functions for symbology export + QgsRenderContext renderContext() const; + void startRender( QgsVectorLayer* vl ) const; + void stopRender( QgsVectorLayer* vl ) const; + static double mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ); }; #endif // QGSDXFEXPORT_H From 4984ad6de9ac0f32cf3fe1d0a217a568d4e019a4 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 8 Nov 2013 09:14:13 +0100 Subject: [PATCH 14/38] Use linetype 1 for polygons, check if iodevice is already open --- src/core/qgsdxfexport.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 9dea50c5bb4..b10c20848e4 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -301,7 +301,7 @@ int QgsDxfExport::writeToFile( QIODevice* d ) return 1; } - if ( !d->open( QIODevice::WriteOnly ) ) + if ( !d->isOpen() && !d->open( QIODevice::WriteOnly ) ) { return 2; } @@ -409,8 +409,8 @@ void QgsDxfExport::writeTables( QTextStream& stream ) stream << "LAYER\n"; stream << " 70\n"; stream << mLayers.count() << "\n"; - QList< QgsMapLayer* >::iterator layerIt = mLayers.begin(); - for ( ; layerIt != mLayers.end(); ++layerIt ) + QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin(); + for ( ; layerIt != mLayers.constEnd(); ++layerIt ) { stream << " 0\n"; stream << "LAYER\n"; @@ -612,7 +612,7 @@ void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, stream << " 66\n"; stream << "1\n"; stream << " 70\n"; - int type = polygon ? 49 : 0; + int type = polygon ? 1 : 0; stream << type << "\n"; stream << " 40\n"; stream << width << "\n"; From ae2b72b8f64bc8fa22173bf9de4691ed6ab36a4f Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 8 Nov 2013 15:44:13 +0100 Subject: [PATCH 15/38] Write linetypes for simple line with custom dash pattern --- src/core/qgsdxfexport.cpp | 156 ++++++++++++++++++++++++++++++++++++-- src/core/qgsdxfexport.h | 9 ++- 2 files changed, 156 insertions(+), 9 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index b10c20848e4..63ebe376a57 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -20,6 +20,7 @@ #include "qgspoint.h" #include "qgsrendererv2.h" #include "qgssymbollayerv2.h" +#include "qgslinesymbollayerv2.h" #include "qgsvectorlayer.h" #include #include @@ -285,7 +286,7 @@ double QgsDxfExport::mDxfColors[][3] = {1, 1, 1} // 255 }; -QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ) +QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ) { } @@ -378,14 +379,24 @@ void QgsDxfExport::writeTables( QTextStream& stream ) stream << " 2\n"; stream << "TABLES\n"; + //iterate through all layers and get symbol layer pointers + QList slList; + if ( mSymbologyExport != NoSymbology ) + { + slList = symbolLayers(); + } + //LTYPE + mLineStyles.clear(); stream << " 0\n"; stream << "TABLE\n"; stream << " 2\n"; stream << "LTYPE\n"; stream << " 70\n"; - stream << " 1\n"; //number of linetypes + stream << QString( "%1\n" ).arg( nLineTypes( slList ) ); //number of linetypes stream << " 0\n"; + + //add continuous style as default stream << "LTYPE\n"; stream << " 2\n"; stream << "CONTINUOUS\n"; @@ -399,6 +410,14 @@ void QgsDxfExport::writeTables( QTextStream& stream ) stream << "0\n"; stream << " 40\n"; //todo: add segments in group 49 stream << "0\n"; + + //add symbol layer linestyles + QList::const_iterator slIt = slList.constBegin(); + for ( ; slIt != slList.constEnd(); ++slIt ) + { + writeSymbolLayerLinestyle( stream, *slIt ); + } + stream << " 0\n"; stream << "ENDTAB\n"; @@ -598,7 +617,7 @@ void QgsDxfExport::endSection( QTextStream& stream ) stream << "ENDSEC\n"; } -void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, int color, +void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width, bool polygon ) { stream << " 0\n"; @@ -606,7 +625,7 @@ void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, stream << " 8\n"; stream << layer << "\n"; stream << " 6\n"; - stream << "CONTINUOUS\n"; //todo: reference to linetype here + stream << QString( "%1\n" ).arg( lineStyleName ); stream << " 62\n"; stream << color << "\n"; stream << " 66\n"; @@ -671,6 +690,12 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const { int c = colorFromSymbolLayer( symbolLayer ); double width = widthFromSymbolLayer( symbolLayer ); + QString lineStyleName = "CONTINUOUS"; + QHash< const QgsSymbolLayerV2*, QString >::const_iterator lineTypeIt = mLineStyles.find( symbolLayer ); + if ( lineTypeIt != mLineStyles.constEnd() ) + { + lineStyleName = lineTypeIt.value(); + } //todo: write point symbols as blocks @@ -678,7 +703,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { - writePolyline( stream, geom->asPolyline(), layer, c, width, false ); + writePolyline( stream, geom->asPolyline(), layer, lineStyleName, c, width, false ); } //multiline @@ -688,7 +713,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); for ( ; lIt != multiLine.constEnd(); ++lIt ) { - writePolyline( stream, *lIt, layer, c, width, false ); + writePolyline( stream, *lIt, layer, lineStyleName, c, width, false ); } } @@ -699,7 +724,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = polygon.constBegin(); for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings { - writePolyline( stream, *polyIt, layer, c, width, true ); + writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); } } @@ -713,7 +738,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = mpIt->constBegin(); for ( ; polyIt != mpIt->constEnd(); ++polyIt ) { - writePolyline( stream, *polyIt, layer, c, width, true ); + writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); } } } @@ -857,3 +882,118 @@ double QgsDxfExport::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::O } return 1.0; } + +QList QgsDxfExport::symbolLayers() +{ + QList symbolLayers; + + QList< QgsMapLayer* >::iterator lIt = mLayers.begin(); + for ( ; lIt != mLayers.end(); ++lIt ) + { + //cast to vector layer + QgsVectorLayer* vl = qobject_cast( *lIt ); + if ( !vl ) + { + continue; + } + + //get rendererv2 + QgsFeatureRendererV2* r = vl->rendererV2(); + if ( !r ) + { + continue; + } + + //get all symbols + QgsSymbolV2List symbols = r->symbols(); + QgsSymbolV2List::iterator symbolIt = symbols.begin(); + for ( ; symbolIt != symbols.end(); ++symbolIt ) + { + int maxSymbolLayers = ( *symbolIt )->symbolLayerCount(); + if ( mSymbologyExport != SymbolLayerSymbology ) + { + maxSymbolLayers = 1; + } + for ( int i = 0; i < maxSymbolLayers; ++i ) + { + symbolLayers.append(( *symbolIt )->symbolLayer( i ) ); + } + } + } + + return symbolLayers; +} + +void QgsDxfExport::writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ) +{ + if ( !symbolLayer ) + { + return; + } + + //QgsSimpleLineSymbolLayer can have customDashVector() / customDashPatternUnit() + const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( symbolLayer ); + if ( simpleLine ) + { + if ( simpleLine->useCustomDashPattern() ) + { + ++mSymbolLayerCounter; + QString name = QString( "symbolLayer%1" ).arg( mSymbolLayerCounter ); + + QVector dashPattern = simpleLine->customDashVector(); + double length = 0; + QVector::const_iterator dashIt = dashPattern.constBegin(); + for ( ; dashIt != dashPattern.constEnd(); ++dashIt ) + { + length += *dashIt; + } + + stream << "LTYPE\n"; + stream << " 2\n"; + + stream << QString( "%1\n" ).arg( name ); + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << QString( "%1\n" ).arg( dashPattern.size() ); //number of segments + stream << " 40\n"; //todo: add segments in group 49 + stream << QString( "%1\n" ).arg( length ); + + dashIt = dashPattern.constBegin(); + bool isSpace = false; + for ( ; dashIt != dashPattern.constEnd(); ++dashIt ) + { + stream << "49\n"; + + //map units or mm? + double segmentLength = ( isSpace ? -*dashIt : *dashIt ); + segmentLength *= mapUnitScaleFactor( mSymbologyScaleDenominator, simpleLine->customDashPatternUnit(), mMapUnits ); + stream << QString( "%1\n" ).arg( segmentLength ); + isSpace = !isSpace; + } + mLineStyles.insert( symbolLayer, name ); + } + } +} + +int QgsDxfExport::nLineTypes( const QList& symbolLayers ) +{ + int nLineTypes = 0; + QList::const_iterator slIt = symbolLayers.constBegin(); + for ( ; slIt != symbolLayers.constEnd(); ++slIt ) + { + const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( *slIt ); + if ( simpleLine ) + { + if ( simpleLine->useCustomDashPattern() ) + { + ++nLineTypes; + } + } + } + return nLineTypes; +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 21be4646ad9..18b66fdaba5 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -66,6 +66,9 @@ class QgsDxfExport static double mDxfColors[][3]; + int mSymbolLayerCounter; //internal counter + QHash< const QgsSymbolLayerV2*, QString > mLineStyles; //symbol layer name types + void writeHeader( QTextStream& stream ); void writeTables( QTextStream& stream ); void writeEntities( QTextStream& stream ); @@ -75,7 +78,7 @@ class QgsDxfExport void startSection( QTextStream& stream ); void endSection( QTextStream& stream ); - void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, int color, + void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width = -1, bool polygon = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); @@ -98,6 +101,10 @@ class QgsDxfExport void startRender( QgsVectorLayer* vl ) const; void stopRender( QgsVectorLayer* vl ) const; static double mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ); + QList symbolLayers(); + static int nLineTypes( const QList& symbolLayers ); + + void writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ); }; #endif // QGSDXFEXPORT_H From 608b3ffeed3d423aa94b1d716a9f4f29819a4653 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Mon, 11 Nov 2013 14:49:38 +0100 Subject: [PATCH 16/38] Fix bug in linestyle export --- src/core/qgsdxfexport.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 63ebe376a57..b5359771c77 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -393,10 +393,10 @@ void QgsDxfExport::writeTables( QTextStream& stream ) stream << " 2\n"; stream << "LTYPE\n"; stream << " 70\n"; - stream << QString( "%1\n" ).arg( nLineTypes( slList ) ); //number of linetypes - stream << " 0\n"; + stream << QString( "%1\n" ).arg( nLineTypes( slList ) + 1 ); //number of linetypes //add continuous style as default + stream << " 0\n"; stream << "LTYPE\n"; stream << " 2\n"; stream << "CONTINUOUS\n"; @@ -409,7 +409,7 @@ void QgsDxfExport::writeTables( QTextStream& stream ) stream << " 73\n"; stream << "0\n"; stream << " 40\n"; //todo: add segments in group 49 - stream << "0\n"; + stream << "0.0\n"; //add symbol layer linestyles QList::const_iterator slIt = slList.constBegin(); @@ -948,9 +948,9 @@ void QgsDxfExport::writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymb length += *dashIt; } + stream << " 0\n"; stream << "LTYPE\n"; stream << " 2\n"; - stream << QString( "%1\n" ).arg( name ); stream << " 70\n"; stream << "64\n"; @@ -960,14 +960,14 @@ void QgsDxfExport::writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymb stream << "65\n"; stream << " 73\n"; stream << QString( "%1\n" ).arg( dashPattern.size() ); //number of segments - stream << " 40\n"; //todo: add segments in group 49 + stream << " 40\n"; //total length of segments stream << QString( "%1\n" ).arg( length ); dashIt = dashPattern.constBegin(); bool isSpace = false; for ( ; dashIt != dashPattern.constEnd(); ++dashIt ) { - stream << "49\n"; + stream << " 49\n"; //map units or mm? double segmentLength = ( isSpace ? -*dashIt : *dashIt ); From 421c030c27186b08faf41df9159b5681a945ffa6 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Wed, 13 Nov 2013 10:52:55 +0100 Subject: [PATCH 17/38] Move dxf dash writing into separated function --- src/core/qgsdxfexport.cpp | 74 +++++++++++++++++++++------------------ src/core/qgsdxfexport.h | 1 + 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index b5359771c77..c7a5b9a8a31 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -939,42 +939,8 @@ void QgsDxfExport::writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymb { ++mSymbolLayerCounter; QString name = QString( "symbolLayer%1" ).arg( mSymbolLayerCounter ); - QVector dashPattern = simpleLine->customDashVector(); - double length = 0; - QVector::const_iterator dashIt = dashPattern.constBegin(); - for ( ; dashIt != dashPattern.constEnd(); ++dashIt ) - { - length += *dashIt; - } - - stream << " 0\n"; - stream << "LTYPE\n"; - stream << " 2\n"; - stream << QString( "%1\n" ).arg( name ); - stream << " 70\n"; - stream << "64\n"; - stream << " 3\n"; - stream << "\n"; - stream << " 72\n"; - stream << "65\n"; - stream << " 73\n"; - stream << QString( "%1\n" ).arg( dashPattern.size() ); //number of segments - stream << " 40\n"; //total length of segments - stream << QString( "%1\n" ).arg( length ); - - dashIt = dashPattern.constBegin(); - bool isSpace = false; - for ( ; dashIt != dashPattern.constEnd(); ++dashIt ) - { - stream << " 49\n"; - - //map units or mm? - double segmentLength = ( isSpace ? -*dashIt : *dashIt ); - segmentLength *= mapUnitScaleFactor( mSymbologyScaleDenominator, simpleLine->customDashPatternUnit(), mMapUnits ); - stream << QString( "%1\n" ).arg( segmentLength ); - isSpace = !isSpace; - } + writeLinestyle( stream, name, dashPattern, simpleLine->customDashPatternUnit() ); mLineStyles.insert( symbolLayer, name ); } } @@ -997,3 +963,41 @@ int QgsDxfExport::nLineTypes( const QList& symbolLayers ) } return nLineTypes; } + +void QgsDxfExport::writeLinestyle( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ) +{ + double length = 0; + QVector::const_iterator dashIt = pattern.constBegin(); + for ( ; dashIt != pattern.constEnd(); ++dashIt ) + { + length += *dashIt; + } + + stream << " 0\n"; + stream << "LTYPE\n"; + stream << " 2\n"; + stream << QString( "%1\n" ).arg( styleName ); + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << QString( "%1\n" ).arg( pattern.size() ); //number of segments + stream << " 40\n"; //total length of segments + stream << QString( "%1\n" ).arg( length ); + + dashIt = pattern.constBegin(); + bool isSpace = false; + for ( ; dashIt != pattern.constEnd(); ++dashIt ) + { + stream << " 49\n"; + + //map units or mm? + double segmentLength = ( isSpace ? -*dashIt : *dashIt ); + segmentLength *= mapUnitScaleFactor( mSymbologyScaleDenominator, u, mMapUnits ); + stream << QString( "%1\n" ).arg( segmentLength ); + isSpace = !isSpace; + } +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 18b66fdaba5..12c6550fe54 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -105,6 +105,7 @@ class QgsDxfExport static int nLineTypes( const QList& symbolLayers ); void writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ); + void writeLinestyle( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); }; #endif // QGSDXFEXPORT_H From 09103b58f0534e4c9cf3ed0ce502e545ef5e2378 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Wed, 13 Nov 2013 17:35:24 +0100 Subject: [PATCH 18/38] First attempt to write AC1018 --- src/core/qgsdxfexport.cpp | 328 +++++++++++++++++++++++++++++++++++++- src/core/qgsdxfexport.h | 20 ++- 2 files changed, 339 insertions(+), 9 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index c7a5b9a8a31..c683c79a8c8 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -286,7 +286,7 @@ double QgsDxfExport::mDxfColors[][3] = {1, 1, 1} // 255 }; -QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ) +QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ), mNextHandleId( 10 ) { } @@ -308,8 +308,8 @@ int QgsDxfExport::writeToFile( QIODevice* d ) } QTextStream outStream( d ); - writeHeader( outStream ); - writeTables( outStream ); + writeHeaderAC1018( outStream ); + writeTablesAC1018( outStream ); writeEntities( outStream ); writeEndFile( outStream ); return 0; @@ -703,7 +703,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { - writePolyline( stream, geom->asPolyline(), layer, lineStyleName, c, width, false ); + writePolylineAC1018( stream, geom->asPolyline(), layer, lineStyleName, c, width, false ); } //multiline @@ -713,7 +713,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); for ( ; lIt != multiLine.constEnd(); ++lIt ) { - writePolyline( stream, *lIt, layer, lineStyleName, c, width, false ); + writePolylineAC1018( stream, *lIt, layer, lineStyleName, c, width, false ); } } @@ -724,7 +724,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = polygon.constBegin(); for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings { - writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); + writePolylineAC1018( stream, *polyIt, layer, lineStyleName, c, width, true ); } } @@ -738,7 +738,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = mpIt->constBegin(); for ( ; polyIt != mpIt->constEnd(); ++polyIt ) { - writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); + writePolylineAC1018( stream, *polyIt, layer, lineStyleName, c, width, true ); } } } @@ -1001,3 +1001,317 @@ void QgsDxfExport::writeLinestyle( QTextStream& stream, const QString& styleName isSpace = !isSpace; } } + +/******************************************************AC_1018 methods***************************************************************/ + +void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) +{ + stream << "999\n"; + stream << "DXF created from QGIS\n"; + startSection( stream ); + stream << " 2\n"; + stream << "HEADER\n"; + //ACADVER + stream << " 9\n"; + stream << "$ACADVER\n"; + stream << " 1\n"; + stream << "AC1018\n"; + + QgsRectangle ext = dxfExtent(); + if ( !ext.isEmpty() ) + { + //EXTMIN + stream << " 9\n"; + stream << "$EXTMIN\n"; + stream << " 10\n"; + stream << ext.xMinimum() << "\n"; + stream << " 20\n"; + stream << ext.yMinimum() << "\n"; + stream << " 30\n"; + stream << "0\n"; + //EXTMAX + stream << " 9\n"; + stream << "$EXTMAX\n"; + stream << " 10\n"; + stream << ext.xMaximum() << "\n"; + stream << " 20\n"; + stream << ext.yMaximum() << "\n"; + stream << " 30\n"; + stream << "0\n"; + } + //LTSCALE + stream << " 9\n"; + stream << "$LTSCALE\n"; + stream << " 40\n"; + stream << "1.0\n"; + //PDMODE + stream << " 9\n"; + stream << "$PDMODE\n"; + stream << " 70\n"; + stream << "33\n"; + //PDSIZE + stream << " 9\n"; + stream << "$PDSIZE\n"; + stream << " 40\n"; + stream << "1\n"; + endSection( stream ); + //PSLTSCALE + stream << " 9\n"; + stream << "$PSLTSCALE\n"; + stream << " 70\n"; + stream << "0\n"; +} + +void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) +{ + startSection( stream ); + stream << " 2\n"; + stream << "TABLES\n"; + + //todo: VPORT table + + //iterate through all layers and get symbol layer pointers + QList slList; + if ( mSymbologyExport != NoSymbology ) + { + slList = symbolLayers(); + } + + //LTYPE + mLineStyles.clear(); + stream << " 0\n"; + stream << "TABLE\n"; + stream << " 2\n"; + stream << "LTYPE\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTable\n"; + stream << " 70\n"; + stream << QString( "%1\n" ).arg( nLineTypes( slList ) + 1 ); //number of linetypes + + //add continuous style as default + stream << " 0\n"; + stream << "LTYPE\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbLinetypeTableRecord\n"; + stream << " 2\n"; + stream << "CONTINUOUS\n"; + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "Defaultstyle\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << "0\n"; + stream << " 40\n"; //todo: add segments in group 49 + stream << "0.0\n"; + + //add symbol layer linestyles + QList::const_iterator slIt = slList.constBegin(); + for ( ; slIt != slList.constEnd(); ++slIt ) + { + writeSymbolLayerLinestyleAC1018( stream, *slIt ); + } + + stream << " 0\n"; + stream << "ENDTAB\n"; + + //LAYER + stream << " 0\n"; + stream << "TABLE\n"; + stream << " 2\n"; + stream << "LAYER\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTable\n"; + stream << " 70\n"; + stream << mLayers.count() << "\n"; + QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin(); + for ( ; layerIt != mLayers.constEnd(); ++layerIt ) + { + stream << " 0\n"; + stream << "LAYER\n"; + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbLayerTableRecord\n"; + stream << " 2\n"; + if ( *layerIt ) + { + stream << ( *layerIt )->name() << "\n"; + } + stream << " 70\n"; //layer property + stream << "64\n"; + stream << " 62\n"; //layer color + stream << "1\n"; + stream << " 6\n"; //layer line type + stream << "CONTINUOUS\n"; + } + stream << " 0\n"; + stream << "ENDTAB\n"; + + //todo: VIEW table + + //todo: UCS table + + //APPID + stream << " 0\n"; + stream << "TABLE\n"; + stream << " 2\n"; + stream << "APPID\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTable\n"; + stream << " 70\n"; + stream << " 1\n"; + + stream << " 0\n"; + stream << "APPID\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbRegAppTableRecord\n"; + stream << " 2\n"; + stream << "ACAD\n"; + stream << " 70\n"; + stream << " 0\n"; + stream << " 0\n"; + stream << "ENDTAB\n"; + + //todo: DIMSTYLE table + + //todo: BLOCK_RECORD table + + endSection( stream ); +} + +void QgsDxfExport::writeSymbolLayerLinestyleAC1018( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ) +{ + if ( !symbolLayer ) + { + return; + } + + //QgsSimpleLineSymbolLayer can have customDashVector() / customDashPatternUnit() + const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( symbolLayer ); + if ( simpleLine ) + { + if ( simpleLine->useCustomDashPattern() ) + { + ++mSymbolLayerCounter; + QString name = QString( "symbolLayer%1" ).arg( mSymbolLayerCounter ); + QVector dashPattern = simpleLine->customDashVector(); + writeLinestyleAC1018( stream, name, dashPattern, simpleLine->customDashPatternUnit() ); + mLineStyles.insert( symbolLayer, name ); + } + } +} + +void QgsDxfExport::writeLinestyleAC1018( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ) +{ + double length = 0; + QVector::const_iterator dashIt = pattern.constBegin(); + for ( ; dashIt != pattern.constEnd(); ++dashIt ) + { + length += *dashIt; + } + + stream << " 0\n"; + stream << "LTYPE\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbLinetypeTableRecord\n"; + stream << " 2\n"; + stream << QString( "%1\n" ).arg( styleName ); + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << QString( "%1\n" ).arg( pattern.size() ); //number of segments + stream << " 40\n"; //total length of segments + stream << QString( "%1\n" ).arg( length ); + + dashIt = pattern.constBegin(); + bool isSpace = false; + for ( ; dashIt != pattern.constEnd(); ++dashIt ) + { + stream << " 49\n"; + + //map units or mm? + double segmentLength = ( isSpace ? -*dashIt : *dashIt ); + segmentLength *= mapUnitScaleFactor( mSymbologyScaleDenominator, u, mMapUnits ); + stream << QString( "%1\n" ).arg( segmentLength ); + isSpace = !isSpace; + } +} + +void QgsDxfExport::writeEntitiesAC1018( QTextStream& stream ) +{ + //todo... +} + +void QgsDxfExport::writeEntitiesSymbolLevelsAC1018( QTextStream& stream, QgsVectorLayer* layer ) +{ + //todo... +} + +void QgsDxfExport::writePolylineAC1018( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, + double width, bool polygon ) +{ + stream << " 0\n"; + stream << "LWPOLYLINE\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << " 8\n"; + stream << layer << "\n"; + stream << "100\n"; + stream << "AcDbEntity\n"; + stream << "100\n"; + stream << "AcDbPolyline\n"; + + stream << " 6\n"; + stream << QString( "%1\n" ).arg( lineStyleName ); + + stream << " 62\n"; + stream << color << "\n"; + + stream << " 90\n"; + stream << QString( "%1\n" ).arg( line.size() ); + + stream << " 70\n"; + int type = polygon ? 1 : 0; + stream << type << "\n"; + + stream << " 43\n"; + stream << width << "\n"; + + QgsPolyline::const_iterator lineIt = line.constBegin(); + for ( ; lineIt != line.constEnd(); ++lineIt ) + { + writeVertexAC1018( stream, *lineIt ); + } +} + +void QgsDxfExport::writeVertexAC1018( QTextStream& stream, const QgsPoint& pt ) +{ + stream << " 10\n"; + stream << pt.x() << "\n"; + stream << " 20\n"; + stream << pt.y() << "\n"; +} diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 12c6550fe54..2a8ec999523 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -67,8 +67,10 @@ class QgsDxfExport static double mDxfColors[][3]; int mSymbolLayerCounter; //internal counter + int mNextHandleId; QHash< const QgsSymbolLayerV2*, QString > mLineStyles; //symbol layer name types + //AC1009 void writeHeader( QTextStream& stream ); void writeTables( QTextStream& stream ); void writeEntities( QTextStream& stream ); @@ -81,6 +83,20 @@ class QgsDxfExport void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width = -1, bool polygon = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); + void writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ); + void writeLinestyle( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); + + //AC1018 + void writeHeaderAC1018( QTextStream& stream ); + void writeTablesAC1018( QTextStream& stream ); + void writeEntitiesAC1018( QTextStream& stream ); + void writeEntitiesSymbolLevelsAC1018( QTextStream& stream, QgsVectorLayer* layer ); + void writeSymbolLayerLinestyleAC1018( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ); + void writeLinestyleAC1018( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); + void writeVertexAC1018( QTextStream& stream, const QgsPoint& pt ); + void writePolylineAC1018( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, + double width = -1, bool polygon = false ); + QgsRectangle dxfExtent() const; @@ -104,8 +120,8 @@ class QgsDxfExport QList symbolLayers(); static int nLineTypes( const QList& symbolLayers ); - void writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ); - void writeLinestyle( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); + + }; #endif // QGSDXFEXPORT_H From e97db8c55cb16311f314ed36e5002a911090c219 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 14 Nov 2013 17:14:04 +0100 Subject: [PATCH 19/38] Use AC1009 only --- src/core/qgsdxfexport.cpp | 155 +++++++++++++++++++++++++++++--------- 1 file changed, 120 insertions(+), 35 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index c683c79a8c8..d856baba111 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -308,8 +308,8 @@ int QgsDxfExport::writeToFile( QIODevice* d ) } QTextStream outStream( d ); - writeHeaderAC1018( outStream ); - writeTablesAC1018( outStream ); + writeHeader( outStream ); + writeTables( outStream ); writeEntities( outStream ); writeEndFile( outStream ); return 0; @@ -703,7 +703,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { - writePolylineAC1018( stream, geom->asPolyline(), layer, lineStyleName, c, width, false ); + writePolyline( stream, geom->asPolyline(), layer, lineStyleName, c, width, false ); } //multiline @@ -713,7 +713,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); for ( ; lIt != multiLine.constEnd(); ++lIt ) { - writePolylineAC1018( stream, *lIt, layer, lineStyleName, c, width, false ); + writePolyline( stream, *lIt, layer, lineStyleName, c, width, false ); } } @@ -724,7 +724,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = polygon.constBegin(); for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings { - writePolylineAC1018( stream, *polyIt, layer, lineStyleName, c, width, true ); + writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); } } @@ -738,7 +738,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = mpIt->constBegin(); for ( ; polyIt != mpIt->constEnd(); ++polyIt ) { - writePolylineAC1018( stream, *polyIt, layer, lineStyleName, c, width, true ); + writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); } } } @@ -1002,7 +1002,7 @@ void QgsDxfExport::writeLinestyle( QTextStream& stream, const QString& styleName } } -/******************************************************AC_1018 methods***************************************************************/ +/******************************************************Test with AC_1018 methods***************************************************************/ void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) { @@ -1068,7 +1068,75 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) stream << " 2\n"; stream << "TABLES\n"; - //todo: VPORT table + //APPID + stream << " 0\n"; + stream << "TABLE\n"; + stream << " 2\n"; + stream << "APPID\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTable\n"; + stream << " 70\n"; + stream << " 1\n"; + stream << " 0\n"; + stream << "APPID\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbRegAppTableRecord\n"; + stream << " 2\n"; + stream << "ACAD\n"; + stream << " 70\n"; + stream << " 0\n"; + stream << " 0\n"; + stream << "ENDTAB\n"; + + //VPORT table + stream << " 0\n"; + stream << "TABLE\n"; + stream << " 2\n"; + stream << "VPORT\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTable\n"; + stream << " 70\n"; + stream << "1\n"; + stream << " 0\n"; + stream << "VPORT\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbViewportTableRecord\n"; + stream << " 2\n"; + stream << "*Active\n"; + stream << " 70\n"; + stream << " 0\n"; + stream << " 10\n"; + stream << " 0.0\n"; + stream << " 20\n"; + stream << "0.0\n"; + stream << " 11\n"; + stream << " 1.0\n"; + stream << " 21\n"; + stream << "1.0\n"; + stream << " 12\n"; + stream << "80.25\n"; + stream << " 22\n"; + stream << "106.4409457059851\n"; + stream << " 40\n"; + stream << "113.3818914119703\n"; + stream << " 41\n"; + stream << "0.8863849310366128\n"; + stream << " 42\n"; + stream << "50.0\n"; + stream << " 0\n"; + stream << "ENDTAB\n"; //iterate through all layers and get symbol layer pointers QList slList; @@ -1112,6 +1180,48 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) stream << " 40\n"; //todo: add segments in group 49 stream << "0.0\n"; + stream << " 0\n"; + stream << "LTYPE\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbLinetypeTableRecord\n"; + stream << " 2\n"; + stream << "BYBLOCK\n"; + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "Defaultstyle\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << "0\n"; + stream << " 40\n"; //todo: add segments in group 49 + stream << "0.0\n"; + + stream << " 0\n"; + stream << "LTYPE\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); + stream << "100\n"; + stream << "AcDbSymbolTableRecord\n"; + stream << "100\n"; + stream << "AcDbLinetypeTableRecord\n"; + stream << " 2\n"; + stream << "BYLAYER\n"; + stream << " 70\n"; + stream << "64\n"; + stream << " 3\n"; + stream << "Defaultstyle\n"; + stream << " 72\n"; + stream << "65\n"; + stream << " 73\n"; + stream << "0\n"; + stream << " 40\n"; //todo: add segments in group 49 + stream << "0.0\n"; + //add symbol layer linestyles QList::const_iterator slIt = slList.constBegin(); for ( ; slIt != slList.constEnd(); ++slIt ) @@ -1138,6 +1248,8 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) { stream << " 0\n"; stream << "LAYER\n"; + stream << " 5\n"; + stream << QString( "%1\n" ).arg( mNextHandleId++ ); stream << "100\n"; stream << "AcDbSymbolTableRecord\n"; stream << "100\n"; @@ -1161,33 +1273,6 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) //todo: UCS table - //APPID - stream << " 0\n"; - stream << "TABLE\n"; - stream << " 2\n"; - stream << "APPID\n"; - stream << " 5\n"; - stream << QString( "%1\n" ).arg( mNextHandleId++ ); - stream << "100\n"; - stream << "AcDbSymbolTable\n"; - stream << " 70\n"; - stream << " 1\n"; - - stream << " 0\n"; - stream << "APPID\n"; - stream << " 5\n"; - stream << QString( "%1\n" ).arg( mNextHandleId++ ); - stream << "100\n"; - stream << "AcDbSymbolTableRecord\n"; - stream << "100\n"; - stream << "AcDbRegAppTableRecord\n"; - stream << " 2\n"; - stream << "ACAD\n"; - stream << " 70\n"; - stream << " 0\n"; - stream << " 0\n"; - stream << "ENDTAB\n"; - //todo: DIMSTYLE table //todo: BLOCK_RECORD table From d5cfe23e5a3ff6edf4537915a7415e09b8d7641f Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Wed, 20 Nov 2013 09:30:14 +0100 Subject: [PATCH 20/38] Write blocks for point symbols --- src/core/qgsdxfexport.cpp | 93 ++++++++++++++++++- src/core/qgsdxfexport.h | 9 +- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 35 +++++++ .../symbology-ng/qgsmarkersymbollayerv2.h | 2 + src/core/symbology-ng/qgssymbollayerv2.h | 2 + 5 files changed, 139 insertions(+), 2 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index d856baba111..de7cf598b3c 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -286,7 +286,7 @@ double QgsDxfExport::mDxfColors[][3] = {1, 1, 1} // 255 }; -QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ), mNextHandleId( 10 ) +QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ), mNextHandleId( 10 ), mBlockCounter( 0 ) { } @@ -310,6 +310,7 @@ int QgsDxfExport::writeToFile( QIODevice* d ) QTextStream outStream( d ); writeHeader( outStream ); writeTables( outStream ); + writeBlocks( outStream ); writeEntities( outStream ); writeEndFile( outStream ); return 0; @@ -451,6 +452,63 @@ void QgsDxfExport::writeTables( QTextStream& stream ) endSection( stream ); } +void QgsDxfExport::writeBlocks( QTextStream& stream ) +{ + startSection( stream ); + stream << " 2\n"; + stream << "BLOCKS\n"; + + //iterate through all layers and get symbol layer pointers + QList slList; + if ( mSymbologyExport != NoSymbology ) + { + slList = symbolLayers(); + } + + QList::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 ); + if ( ml ) + { + //todo: find out if the marker symbol layer has data defined properties + stream << " 0\n"; + stream << "BLOCK\n"; + stream << " 8\n"; //Layer (0 to take layer where INSERT happens) + stream << "0\n"; + QString blockName = QString( "symbolLayer%1" ).arg( mBlockCounter ); + stream << " 2\n"; + stream << QString( "%1\n" ).arg( blockName ); + stream << " 70\n"; + stream << "64\n"; + + //x/y/z coordinates of reference point + //todo: consider anchor point + double size = ml->size(); + size *= mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ); + stream << "10\n"; + stream << QString( "%1\n" ).arg( size / 2.0 ); + stream << "20\n"; + stream << QString( "%1\n" ).arg( size / 2.0 ); + stream << "30\n"; + stream << "0\n"; + stream << " 3\n"; + stream << QString( "%1\n" ).arg( blockName ); + + ml->writeDxf( stream, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ) ); + + stream << " 0\n"; + stream << "ENDBLK\n"; + stream << " 8\n"; + stream << "0\n"; + + mPointSymbolBlocks.insert( ml, blockName ); + } + } + endSection( stream ); +} + void QgsDxfExport::writeEntities( QTextStream& stream ) { startSection( stream ); @@ -617,6 +675,32 @@ void QgsDxfExport::endSection( QTextStream& stream ) stream << "ENDSEC\n"; } +void QgsDxfExport::writePoint( QTextStream& stream, const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) +{ + //insert block or write point directly? + QHash< const QgsSymbolLayerV2*, QString >::const_iterator blockIt = mPointSymbolBlocks.find( symbolLayer ); + if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() ) + { + //write symbol directly here + } + else + { + //insert block + stream << " 0\n"; + stream << "INSERT\n"; + stream << " 8\n"; + stream << layer << "\n"; + stream << " 2\n"; + stream << blockIt.value() << "\n"; + stream << " 10\n"; + stream << QString( "%1\n" ).arg( pt.x() ); + stream << " 20\n"; + stream << QString( "%1\n" ).arg( pt.y() ); + stream << " 30\n"; + stream << "0\n"; + } +} + void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width, bool polygon ) { @@ -700,6 +784,13 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const //todo: write point symbols as blocks QGis::WkbType geometryType = geom->wkbType(); + + //single point + if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D ) + { + writePoint( stream, geom->asPoint(), layer, symbolLayer ); + } + //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 2a8ec999523..91adcdc228e 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -54,6 +54,9 @@ class QgsDxfExport void setSymbologyExport( SymbologyExport e ) { mSymbologyExport = e; } SymbologyExport symbologyExport() const { return mSymbologyExport; } + //get closest entry in dxf palette + static int closestColorMatch( QRgb pixel ); + private: QList< QgsMapLayer* > mLayers; @@ -68,11 +71,15 @@ class QgsDxfExport int mSymbolLayerCounter; //internal counter int mNextHandleId; + int mBlockCounter; + QHash< const QgsSymbolLayerV2*, QString > mLineStyles; //symbol layer name types + QHash< const QgsSymbolLayerV2*, QString > mPointSymbolBlocks; //reference to point symbol blocks //AC1009 void writeHeader( QTextStream& stream ); void writeTables( QTextStream& stream ); + void writeBlocks( QTextStream& stream ); void writeEntities( QTextStream& stream ); void writeEntitiesSymbolLevels( QTextStream& stream, QgsVectorLayer* layer ); void writeEndFile( QTextStream& stream ); @@ -80,6 +87,7 @@ class QgsDxfExport void startSection( QTextStream& stream ); void endSection( QTextStream& stream ); + void writePoint( QTextStream& stream, const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width = -1, bool polygon = false ); void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); @@ -108,7 +116,6 @@ class QgsDxfExport double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); //functions for dxf palette - static int closestColorMatch( QRgb pixel ); static int color_distance( QRgb p1, int index ); static QRgb createRgbEntry( qreal r, qreal g, qreal b ); diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index f1e2c8dec02..9725e9f3236 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -16,6 +16,7 @@ #include "qgsmarkersymbollayerv2.h" #include "qgssymbollayerv2utils.h" +#include "qgsdxfexport.h" #include "qgsexpression.h" #include "qgsrendercontext.h" #include "qgslogger.h" @@ -700,6 +701,40 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon } } +void QgsSimpleMarkerSymbolLayerV2::writeDxf( QTextStream& str, double mmMapUnitScaleFactor ) const +{ + double size = mSize; + if ( mSizeUnit == QgsSymbolV2::MM ) + { + size *= mmMapUnitScaleFactor; + } + double halfSize = size / 2.0; + + if ( mName == "circle" ) + { + str << " 0\n"; + str << "CIRCLE\n"; + str << " 8\n"; + str << "0\n"; + //todo: linetype in group 6. Needs to be inserted into line table first + + //color in group 62 + str << " 62\n"; + int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() ); + str << QString( "%1\n" ).arg( colorIndex ); + + //x/y/z center + str << " 10\n"; + str << QString( "%1\n" ).arg( halfSize ); + str << " 20\n"; + str << QString( "%1\n" ).arg( halfSize ); + str << " 30\n"; + str << QString( "%1\n" ).arg( halfSize ); + str << " 40\n"; + str << QString( "%1\n" ).arg( halfSize ); + } +} + ////////// diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index a3a6916e638..3c472fe2356 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -76,6 +76,8 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2 QgsSymbolV2::OutputUnit outlineWidthUnit() const { return mOutlineWidthUnit; } void setOutlineWidthUnit( QgsSymbolV2::OutputUnit u ) { mOutlineWidthUnit = u; } + void writeDxf( QTextStream& str, double mmMapUnitScaleFactor ) const; + protected: void drawMarker( QPainter* p, QgsSymbolV2RenderContext& context ); diff --git a/src/core/symbology-ng/qgssymbollayerv2.h b/src/core/symbology-ng/qgssymbollayerv2.h index d5bdd77e3a8..4699f18e743 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.h +++ b/src/core/symbology-ng/qgssymbollayerv2.h @@ -92,6 +92,8 @@ class CORE_EXPORT QgsSymbolLayerV2 virtual void removeDataDefinedProperty( const QString& property ); virtual void removeDataDefinedProperties(); + virtual void writeDxf( QTextStream& str, double mmMapUnitScaleFactor ) const { Q_UNUSED( str ); Q_UNUSED( mmMapUnitScaleFactor ); } + protected: QgsSymbolLayerV2( QgsSymbolV2::SymbolType type, bool locked = false ) : mType( type ), mLocked( locked ), mRenderingPass( 0 ) {} From de6f83e08f662520eba67f9385bb97596d32f76f Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 21 Nov 2013 15:13:10 +0100 Subject: [PATCH 21/38] Clean up dxf export sources --- src/core/qgsdxfexport.cpp | 414 ++++++++---------- src/core/qgsdxfexport.h | 43 +- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 28 +- .../symbology-ng/qgsmarkersymbollayerv2.h | 2 +- src/core/symbology-ng/qgssymbollayerv2.h | 3 +- src/ui/qgsdxfexportdialogbase.ui | 4 +- 6 files changed, 231 insertions(+), 263 deletions(-) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index de7cf598b3c..53e50985c9d 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -23,7 +23,6 @@ #include "qgslinesymbollayerv2.h" #include "qgsvectorlayer.h" #include -#include //dxf color palette double QgsDxfExport::mDxfColors[][3] = @@ -286,13 +285,63 @@ double QgsDxfExport::mDxfColors[][3] = {1, 1, 1} // 255 }; -QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ), mNextHandleId( 10 ), mBlockCounter( 0 ) +QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExport( NoSymbology ), mMapUnits( QGis::Meters ), mSymbolLayerCounter( 0 ), + mNextHandleId( 10 ), mBlockCounter( 0 ) { } QgsDxfExport::~QgsDxfExport() { +} +void QgsDxfExport::writeGroup( int code, int i ) +{ + writeGroupCode( code ); + writeInt( i ); +} + +void QgsDxfExport::writeGroup( int code, double d ) +{ + writeGroupCode( code ); + writeDouble( d ); +} + +void QgsDxfExport::writeGroup( int code, const QString& s ) +{ + writeGroupCode( code ); + writeString( s ); +} + +void QgsDxfExport::writeGroupCode( int code ) +{ + if ( code < 10 ) + { + mTextStream << QString( " %1\n" ).arg( code ); + } + else if ( code < 100 ) + { + mTextStream << QString( " %1\n" ).arg( code ); + } + else + { + mTextStream << QString( "%1\n" ).arg( code ); + } + +} + +void QgsDxfExport::writeInt( int i ) +{ + mTextStream << QString( "%1\n" ).arg( i ); +} + +void QgsDxfExport::writeDouble( double d ) +{ + mTextStream << QString( "%1\n" ).arg( d ); +} + +void QgsDxfExport::writeString( const QString& s ) +{ + mTextStream << s << "\n"; } int QgsDxfExport::writeToFile( QIODevice* d ) @@ -307,78 +356,65 @@ int QgsDxfExport::writeToFile( QIODevice* d ) return 2; } - QTextStream outStream( d ); - writeHeader( outStream ); - writeTables( outStream ); - writeBlocks( outStream ); - writeEntities( outStream ); - writeEndFile( outStream ); + mTextStream.setDevice( d ); + + writeHeader(); + writeTables(); + writeBlocks(); + writeEntities(); + writeEndFile(); return 0; } -void QgsDxfExport::writeHeader( QTextStream& stream ) +void QgsDxfExport::writeHeader() { - stream << "999\n"; - stream << "DXF created from QGIS\n"; - startSection( stream ); - stream << " 2\n"; - stream << "HEADER\n"; + writeGroup( 999, "DXF created from QGIS" ); + startSection(); + writeGroup( 2, "HEADER" ); + //ACADVER - stream << " 9\n"; - stream << "$ACADVER\n"; - stream << " 1\n"; - stream << "AC1009\n"; + writeGroup( 9, "$ACADVER" ); + writeGroup( 1, "AC1009" ); QgsRectangle ext = dxfExtent(); if ( !ext.isEmpty() ) { //EXTMIN - stream << " 9\n"; - stream << "$EXTMIN\n"; - stream << " 10\n"; - stream << ext.xMinimum() << "\n"; - stream << " 20\n"; - stream << ext.yMinimum() << "\n"; - stream << " 30\n"; - stream << "0\n"; + writeGroup( 9, "$EXTMIN" ); + writeGroup( 10, ext.xMinimum() ); + writeGroup( 20, ext.yMinimum() ); + writeGroup( 30, 0.0 ); + //EXTMAX - stream << " 9\n"; - stream << "$EXTMAX\n"; - stream << " 10\n"; - stream << ext.xMaximum() << "\n"; - stream << " 20\n"; - stream << ext.yMaximum() << "\n"; - stream << " 30\n"; - stream << "0\n"; + writeGroup( 9, "$EXTMAX" ); + writeGroup( 10, ext.xMaximum() ); + writeGroup( 20, ext.yMaximum() ); + writeGroup( 30, 0.0 ); } + //LTSCALE - stream << " 9\n"; - stream << "$LTSCALE\n"; - stream << " 40\n"; - stream << "1.0\n"; + writeGroup( 9, "$LTSCALE" ); + writeGroup( 40, 1.0 ); + //PDMODE - stream << " 9\n"; - stream << "$PDMODE\n"; - stream << " 70\n"; - stream << "33\n"; + writeGroup( 9, "$PDMODE" ); + writeGroup( 70, 33 ); + //PDSIZE - stream << " 9\n"; - stream << "$PDSIZE\n"; - stream << " 40\n"; - stream << "1\n"; - endSection( stream ); + writeGroup( 9, "$PDSIZE" ); + writeGroup( 40, 1 ); + //PSLTSCALE - stream << " 9\n"; - stream << "$PSLTSCALE\n"; - stream << " 70\n"; - stream << "0\n"; + writeGroup( 9, "$PSLTSCALE" ); + writeGroup( 70, 0 ); + + endSection(); } -void QgsDxfExport::writeTables( QTextStream& stream ) +void QgsDxfExport::writeTables() { - startSection( stream ); - stream << " 2\n"; - stream << "TABLES\n"; + startSection(); + writeGroup( 2, "TABLES" ); //iterate through all layers and get symbol layer pointers QList slList; @@ -389,74 +425,51 @@ void QgsDxfExport::writeTables( QTextStream& stream ) //LTYPE mLineStyles.clear(); - stream << " 0\n"; - stream << "TABLE\n"; - stream << " 2\n"; - stream << "LTYPE\n"; - stream << " 70\n"; - stream << QString( "%1\n" ).arg( nLineTypes( slList ) + 1 ); //number of linetypes + writeGroup( 0, "TABLE" ); + writeGroup( 2, "LTYPE" ); + writeGroup( 70, nLineTypes( slList ) + 1 ); //add continuous style as default - stream << " 0\n"; - stream << "LTYPE\n"; - stream << " 2\n"; - stream << "CONTINUOUS\n"; - stream << " 70\n"; - stream << "64\n"; - stream << " 3\n"; - stream << "Defaultstyle\n"; - stream << " 72\n"; - stream << "65\n"; - stream << " 73\n"; - stream << "0\n"; - stream << " 40\n"; //todo: add segments in group 49 - stream << "0.0\n"; + writeGroup( 0, "LTYPE" ); + writeGroup( 2, "CONTINUOUS" ); + writeGroup( 70, 64 ); + writeGroup( 3, "Defaultstyle" ); + writeGroup( 72, 65 ); + writeGroup( 73, 0 ); + writeGroup( 40, 0.0 ); //add symbol layer linestyles QList::const_iterator slIt = slList.constBegin(); for ( ; slIt != slList.constEnd(); ++slIt ) { - writeSymbolLayerLinestyle( stream, *slIt ); + writeSymbolLayerLinestyle( *slIt ); } - stream << " 0\n"; - stream << "ENDTAB\n"; + writeGroup( 0, "ENDTAB" ); //LAYER - stream << " 0\n"; - stream << "TABLE\n"; - stream << " 2\n"; - stream << "LAYER\n"; - stream << " 70\n"; - stream << mLayers.count() << "\n"; + writeGroup( 0, "TABLE" ); + writeGroup( 2, "LAYER" ); + writeGroup( 70, mLayers.count() ); + QList< QgsMapLayer* >::const_iterator layerIt = mLayers.constBegin(); for ( ; layerIt != mLayers.constEnd(); ++layerIt ) { - stream << " 0\n"; - stream << "LAYER\n"; - stream << " 2\n"; - if ( *layerIt ) - { - stream << ( *layerIt )->name() << "\n"; - } - stream << " 70\n"; //layer property - stream << "64\n"; - stream << " 62\n"; //layer color - stream << "1\n"; - stream << " 6\n"; //layer line type - stream << "CONTINUOUS\n"; + writeGroup( 0, "LAYER" ); + QString layerName = *layerIt ? ( *layerIt )->name() : ""; + writeGroup( 2, layerName ); + writeGroup( 70, 64 ); + writeGroup( 62, 1 ); + writeGroup( 6, "CONTINUOUS" ); } - stream << " 0\n"; - stream << "ENDTAB\n"; - - endSection( stream ); + writeGroup( 0, "ENDTAB" ); + endSection(); } -void QgsDxfExport::writeBlocks( QTextStream& stream ) +void QgsDxfExport::writeBlocks() { - startSection( stream ); - stream << " 2\n"; - stream << "BLOCKS\n"; + startSection(); + writeGroup( 2, "BLOCKS" ); //iterate through all layers and get symbol layer pointers QList slList; @@ -472,48 +485,37 @@ void QgsDxfExport::writeBlocks( QTextStream& stream ) QgsMarkerSymbolLayerV2* ml = dynamic_cast< QgsMarkerSymbolLayerV2*>( *slIt ); if ( ml ) { - //todo: find out if the marker symbol layer has data defined properties - stream << " 0\n"; - stream << "BLOCK\n"; - stream << " 8\n"; //Layer (0 to take layer where INSERT happens) - stream << "0\n"; + //todo: find out if the marker symbol layer has data defined properties (in that case don't insert it) + writeGroup( 0, "BLOCK" ); + writeGroup( 8, 0 ); QString blockName = QString( "symbolLayer%1" ).arg( mBlockCounter ); - stream << " 2\n"; - stream << QString( "%1\n" ).arg( blockName ); - stream << " 70\n"; - stream << "64\n"; + writeGroup( 2, blockName ); + writeGroup( 70, 64 ); //x/y/z coordinates of reference point //todo: consider anchor point double size = ml->size(); size *= mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ); - stream << "10\n"; - stream << QString( "%1\n" ).arg( size / 2.0 ); - stream << "20\n"; - stream << QString( "%1\n" ).arg( size / 2.0 ); - stream << "30\n"; - stream << "0\n"; - stream << " 3\n"; - stream << QString( "%1\n" ).arg( blockName ); + writeGroup( 10, size / 2.0 ); + writeGroup( 20, size / 2.0 ); + writeGroup( 30, 0 ); + writeGroup( 3, blockName ); - ml->writeDxf( stream, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ) ); + ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ) ); - stream << " 0\n"; - stream << "ENDBLK\n"; - stream << " 8\n"; - stream << "0\n"; + writeGroup( 0, "ENDBLK" ); + writeGroup( 8, 0 ); mPointSymbolBlocks.insert( ml, blockName ); } } - endSection( stream ); + endSection(); } -void QgsDxfExport::writeEntities( QTextStream& stream ) +void QgsDxfExport::writeEntities() { - startSection( stream ); - stream << " 2\n"; - stream << "ENTITIES\n"; + startSection(); + writeGroup( 2, "ENTITIES" ); //iterate through the maplayers QList< QgsMapLayer* >::iterator layerIt = mLayers.begin(); @@ -528,7 +530,7 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) QgsFeatureRendererV2* renderer = vl->rendererV2(); if ( mSymbologyExport == QgsDxfExport::SymbolLayerSymbology && renderer->usingSymbolLevels() ) { - writeEntitiesSymbolLevels( stream, vl ); + writeEntitiesSymbolLevels( vl ); continue; } @@ -546,7 +548,7 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) { if ( mSymbologyExport == NoSymbology ) { - addFeature( fet, stream, vl->name(), 0 ); //no symbology at all + addFeature( fet, vl->name(), 0 ); //no symbology at all } else { @@ -566,15 +568,15 @@ void QgsDxfExport::writeEntities( QTextStream& stream ) { continue; } - addFeature( fet, stream, vl->name(), s->symbolLayer( 0 ) ); + addFeature( fet, vl->name(), s->symbolLayer( 0 ) ); } } } - endSection( stream ); + endSection(); } -void QgsDxfExport::writeEntitiesSymbolLevels( QTextStream& stream, QgsVectorLayer* layer ) +void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer* layer ) { if ( !layer ) { @@ -650,32 +652,29 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QTextStream& stream, QgsVectorLaye QList::iterator featureIt = featureList.begin(); for ( ; featureIt != featureList.end(); ++featureIt ) { - addFeature( *featureIt, stream, layer->name(), levelIt.key()->symbolLayer( llayer ) ); + addFeature( *featureIt, layer->name(), levelIt.key()->symbolLayer( llayer ) ); } } } stopRender( layer ); } -void QgsDxfExport::writeEndFile( QTextStream& stream ) +void QgsDxfExport::writeEndFile() { - stream << " 0\n"; - stream << "EOF\n"; + writeGroup( 0, "EOF" ); } -void QgsDxfExport::startSection( QTextStream& stream ) +void QgsDxfExport::startSection() { - stream << " 0\n"; - stream << "SECTION\n"; + writeGroup( 0, "SECTION" ); } -void QgsDxfExport::endSection( QTextStream& stream ) +void QgsDxfExport::endSection() { - stream << " 0\n"; - stream << "ENDSEC\n"; + writeGroup( 0, "ENDSEC" ); } -void QgsDxfExport::writePoint( QTextStream& stream, const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) +void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) { //insert block or write point directly? QHash< const QgsSymbolLayerV2*, QString >::const_iterator blockIt = mPointSymbolBlocks.find( symbolLayer ); @@ -686,63 +685,44 @@ void QgsDxfExport::writePoint( QTextStream& stream, const QgsPoint& pt, const QS else { //insert block - stream << " 0\n"; - stream << "INSERT\n"; - stream << " 8\n"; - stream << layer << "\n"; - stream << " 2\n"; - stream << blockIt.value() << "\n"; - stream << " 10\n"; - stream << QString( "%1\n" ).arg( pt.x() ); - stream << " 20\n"; - stream << QString( "%1\n" ).arg( pt.y() ); - stream << " 30\n"; - stream << "0\n"; + writeGroup( 0, "INSERT" ); + writeGroup( 8, layer ); + writeGroup( 2, blockIt.value() ); + writeGroup( 10, pt.x() ); + writeGroup( 20, pt.y() ); + writeGroup( 30, 0 ); } } -void QgsDxfExport::writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, +void QgsDxfExport::writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width, bool polygon ) { - stream << " 0\n"; - stream << "POLYLINE\n"; - stream << " 8\n"; - stream << layer << "\n"; - stream << " 6\n"; - stream << QString( "%1\n" ).arg( lineStyleName ); - stream << " 62\n"; - stream << color << "\n"; - stream << " 66\n"; - stream << "1\n"; - stream << " 70\n"; + writeGroup( 0, "POLYLINE" ); + writeGroup( 8, layer ); + writeGroup( 6, lineStyleName ); + writeGroup( 62, color ); + writeGroup( 66, 1 ); int type = polygon ? 1 : 0; - stream << type << "\n"; - stream << " 40\n"; - stream << width << "\n"; - stream << " 41\n"; - stream << width << "\n"; + writeGroup( 70, type ); + writeGroup( 40, width ); + writeGroup( 41, width ); QgsPolyline::const_iterator lineIt = line.constBegin(); for ( ; lineIt != line.constEnd(); ++lineIt ) { - writeVertex( stream, *lineIt, layer ); + writeVertex( *lineIt, layer ); } - stream << " 0\n"; - stream << "SEQEND\n"; + + writeGroup( 0, "SEQEND" ); } -void QgsDxfExport::writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ) +void QgsDxfExport::writeVertex( const QgsPoint& pt, const QString& layer ) { - stream << " 0\n"; - stream << "VERTEX\n"; - stream << " 8\n"; - stream << layer << "\n"; - stream << " 10\n"; - stream << pt.x() << "\n"; - stream << " 20\n"; - stream << pt.y() << "\n"; - stream << " 30\n"; - stream << "0.0\n"; + writeGroup( 0, "VERTEX" ); + writeGroup( 8, layer ); + writeGroup( 10, pt.x() ); + writeGroup( 20, pt.y() ); + writeGroup( 30, 0 ); } QgsRectangle QgsDxfExport::dxfExtent() const @@ -767,7 +747,7 @@ QgsRectangle QgsDxfExport::dxfExtent() const return extent; } -void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) +void QgsDxfExport::addFeature( const QgsFeature& fet, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) { QgsGeometry* geom = fet.geometry(); if ( geom ) @@ -788,13 +768,13 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const //single point if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D ) { - writePoint( stream, geom->asPoint(), layer, symbolLayer ); + writePoint( geom->asPoint(), layer, symbolLayer ); } //single line if ( geometryType == QGis::WKBLineString || geometryType == QGis::WKBLineString25D ) { - writePolyline( stream, geom->asPolyline(), layer, lineStyleName, c, width, false ); + writePolyline( geom->asPolyline(), layer, lineStyleName, c, width, false ); } //multiline @@ -804,7 +784,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsMultiPolyline::const_iterator lIt = multiLine.constBegin(); for ( ; lIt != multiLine.constEnd(); ++lIt ) { - writePolyline( stream, *lIt, layer, lineStyleName, c, width, false ); + writePolyline( *lIt, layer, lineStyleName, c, width, false ); } } @@ -815,7 +795,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = polygon.constBegin(); for ( ; polyIt != polygon.constEnd(); ++polyIt ) //iterate over rings { - writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); + writePolyline( *polyIt, layer, lineStyleName, c, width, true ); } } @@ -829,7 +809,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, QTextStream& stream, const QgsPolygon::const_iterator polyIt = mpIt->constBegin(); for ( ; polyIt != mpIt->constEnd(); ++polyIt ) { - writePolyline( stream, *polyIt, layer, lineStyleName, c, width, true ); + writePolyline( *polyIt, layer, lineStyleName, c, width, true ); } } } @@ -1015,7 +995,7 @@ QList QgsDxfExport::symbolLayers() return symbolLayers; } -void QgsDxfExport::writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ) +void QgsDxfExport::writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ) { if ( !symbolLayer ) { @@ -1031,7 +1011,7 @@ void QgsDxfExport::writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymb ++mSymbolLayerCounter; QString name = QString( "symbolLayer%1" ).arg( mSymbolLayerCounter ); QVector dashPattern = simpleLine->customDashVector(); - writeLinestyle( stream, name, dashPattern, simpleLine->customDashPatternUnit() ); + writeLinestyle( name, dashPattern, simpleLine->customDashPatternUnit() ); mLineStyles.insert( symbolLayer, name ); } } @@ -1055,7 +1035,7 @@ int QgsDxfExport::nLineTypes( const QList& symbolLayers ) return nLineTypes; } -void QgsDxfExport::writeLinestyle( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ) +void QgsDxfExport::writeLinestyle( const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ) { double length = 0; QVector::const_iterator dashIt = pattern.constBegin(); @@ -1064,31 +1044,22 @@ void QgsDxfExport::writeLinestyle( QTextStream& stream, const QString& styleName length += *dashIt; } - stream << " 0\n"; - stream << "LTYPE\n"; - stream << " 2\n"; - stream << QString( "%1\n" ).arg( styleName ); - stream << " 70\n"; - stream << "64\n"; - stream << " 3\n"; - stream << "\n"; - stream << " 72\n"; - stream << "65\n"; - stream << " 73\n"; - stream << QString( "%1\n" ).arg( pattern.size() ); //number of segments - stream << " 40\n"; //total length of segments - stream << QString( "%1\n" ).arg( length ); + writeGroup( 0, "LTYPE" ); + writeGroup( 2, styleName ); + writeGroup( 70, 64 ); + writeGroup( 3, "" ); + writeGroup( 72, 65 ); + writeGroup( 73, pattern.size() ); + writeGroup( 40, length ); dashIt = pattern.constBegin(); bool isSpace = false; for ( ; dashIt != pattern.constEnd(); ++dashIt ) { - stream << " 49\n"; - //map units or mm? double segmentLength = ( isSpace ? -*dashIt : *dashIt ); segmentLength *= mapUnitScaleFactor( mSymbologyScaleDenominator, u, mMapUnits ); - stream << QString( "%1\n" ).arg( segmentLength ); + writeGroup( 49, segmentLength ); isSpace = !isSpace; } } @@ -1099,7 +1070,7 @@ void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) { stream << "999\n"; stream << "DXF created from QGIS\n"; - startSection( stream ); + startSection(); stream << " 2\n"; stream << "HEADER\n"; //ACADVER @@ -1145,7 +1116,7 @@ void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) stream << "$PDSIZE\n"; stream << " 40\n"; stream << "1\n"; - endSection( stream ); + endSection(); //PSLTSCALE stream << " 9\n"; stream << "$PSLTSCALE\n"; @@ -1155,7 +1126,7 @@ void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) { - startSection( stream ); + startSection(); stream << " 2\n"; stream << "TABLES\n"; @@ -1368,7 +1339,7 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) //todo: BLOCK_RECORD table - endSection( stream ); + endSection( ); } void QgsDxfExport::writeSymbolLayerLinestyleAC1018( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ) @@ -1491,3 +1462,4 @@ void QgsDxfExport::writeVertexAC1018( QTextStream& stream, const QgsPoint& pt ) stream << " 20\n"; stream << pt.y() << "\n"; } + diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 91adcdc228e..464617e4227 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -22,12 +22,12 @@ #include "qgssymbolv2.h" #include #include +#include class QgsMapLayer; class QgsPoint; class QgsSymbolLayerV2; class QIODevice; -class QTextStream; class QgsDxfExport { @@ -57,6 +57,14 @@ class QgsDxfExport //get closest entry in dxf palette static int closestColorMatch( QRgb pixel ); + void writeGroup( int code, int i ); + void writeGroup( int code, double d ); + void writeGroup( int code, const QString& s ); + void writeGroupCode( int code ); + void writeInt( int i ); + void writeDouble( double d ); + void writeString( const QString& s ); + private: QList< QgsMapLayer* > mLayers; @@ -65,6 +73,8 @@ class QgsDxfExport SymbologyExport mSymbologyExport; QGis::UnitType mMapUnits; + QTextStream mTextStream; + QVector mDxfColorPalette; static double mDxfColors[][3]; @@ -77,22 +87,22 @@ class QgsDxfExport QHash< const QgsSymbolLayerV2*, QString > mPointSymbolBlocks; //reference to point symbol blocks //AC1009 - void writeHeader( QTextStream& stream ); - void writeTables( QTextStream& stream ); - void writeBlocks( QTextStream& stream ); - void writeEntities( QTextStream& stream ); - void writeEntitiesSymbolLevels( QTextStream& stream, QgsVectorLayer* layer ); - void writeEndFile( QTextStream& stream ); + void writeHeader(); + void writeTables(); + void writeBlocks(); + void writeEntities(); + void writeEntitiesSymbolLevels( QgsVectorLayer* layer ); + void writeEndFile(); - void startSection( QTextStream& stream ); - void endSection( QTextStream& stream ); + void startSection(); + void endSection(); - void writePoint( QTextStream& stream, const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); - void writePolyline( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, + void writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); + void writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width = -1, bool polygon = false ); - void writeVertex( QTextStream& stream, const QgsPoint& pt, const QString& layer ); - void writeSymbolLayerLinestyle( QTextStream& stream, const QgsSymbolLayerV2* symbolLayer ); - void writeLinestyle( QTextStream& stream, const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); + void writeVertex( const QgsPoint& pt, const QString& layer ); + void writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ); + void writeLinestyle( const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); //AC1018 void writeHeaderAC1018( QTextStream& stream ); @@ -108,7 +118,7 @@ class QgsDxfExport QgsRectangle dxfExtent() const; - void addFeature( const QgsFeature& fet, QTextStream& stream, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); + void addFeature( const QgsFeature& fet, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); double scaleToMapUnits( double value, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) const; //returns dxf palette index from symbol layer color @@ -126,9 +136,6 @@ class QgsDxfExport static double mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ); QList symbolLayers(); static int nLineTypes( const QList& symbolLayers ); - - - }; #endif // QGSDXFEXPORT_H diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index 9725e9f3236..befe3c652ff 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -701,7 +701,7 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon } } -void QgsSimpleMarkerSymbolLayerV2::writeDxf( QTextStream& str, double mmMapUnitScaleFactor ) const +void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const { double size = mSize; if ( mSizeUnit == QgsSymbolV2::MM ) @@ -712,26 +712,14 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QTextStream& str, double mmMapUnitS if ( mName == "circle" ) { - str << " 0\n"; - str << "CIRCLE\n"; - str << " 8\n"; - str << "0\n"; - //todo: linetype in group 6. Needs to be inserted into line table first - - //color in group 62 - str << " 62\n"; + e.writeGroup( 0, "CIRCLE" ); + e.writeGroup( 8, 0 ); int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() ); - str << QString( "%1\n" ).arg( colorIndex ); - - //x/y/z center - str << " 10\n"; - str << QString( "%1\n" ).arg( halfSize ); - str << " 20\n"; - str << QString( "%1\n" ).arg( halfSize ); - str << " 30\n"; - str << QString( "%1\n" ).arg( halfSize ); - str << " 40\n"; - str << QString( "%1\n" ).arg( halfSize ); + e.writeGroup( 62, colorIndex ); + e.writeGroup( 10, halfSize ); + e.writeGroup( 20, halfSize ); + e.writeGroup( 30, 0.0 ); + e.writeGroup( 40, halfSize ); } } diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index 3c472fe2356..486a76db2bd 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -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( QTextStream& str, double mmMapUnitScaleFactor ) const; + void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const; protected: diff --git a/src/core/symbology-ng/qgssymbollayerv2.h b/src/core/symbology-ng/qgssymbollayerv2.h index 4699f18e743..1e44716ffdb 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.h +++ b/src/core/symbology-ng/qgssymbollayerv2.h @@ -38,6 +38,7 @@ class QPainter; class QSize; class QPolygonF; +class QgsDxfExport; class QgsExpression; class QgsRenderContext; @@ -92,7 +93,7 @@ class CORE_EXPORT QgsSymbolLayerV2 virtual void removeDataDefinedProperty( const QString& property ); virtual void removeDataDefinedProperties(); - virtual void writeDxf( QTextStream& str, double mmMapUnitScaleFactor ) const { Q_UNUSED( str ); Q_UNUSED( mmMapUnitScaleFactor ); } + virtual void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const { Q_UNUSED( e ); Q_UNUSED( mmMapUnitScaleFactor ); } protected: QgsSymbolLayerV2( QgsSymbolV2::SymbolType type, bool locked = false ) diff --git a/src/ui/qgsdxfexportdialogbase.ui b/src/ui/qgsdxfexportdialogbase.ui index 1061aac98af..592d48d3906 100644 --- a/src/ui/qgsdxfexportdialogbase.ui +++ b/src/ui/qgsdxfexportdialogbase.ui @@ -11,7 +11,7 @@ - Dialog + DXF export @@ -29,7 +29,7 @@ QDialogButtonBox::Cancel|QDialogButtonBox::Ok - + 10 From 222946b36a63b573713a748288ea36f7f8565afc Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 21 Nov 2013 15:45:38 +0100 Subject: [PATCH 22/38] Implement simple marker rect / square --- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index befe3c652ff..67f41223991 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -709,18 +709,37 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc size *= mmMapUnitScaleFactor; } double halfSize = size / 2.0; + int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() ); if ( mName == "circle" ) { e.writeGroup( 0, "CIRCLE" ); - e.writeGroup( 8, 0 ); - int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() ); + e.writeGroup( 8, "0" ); + e.writeGroup( 62, colorIndex ); e.writeGroup( 10, halfSize ); e.writeGroup( 20, halfSize ); e.writeGroup( 30, 0.0 ); e.writeGroup( 40, halfSize ); } + else if ( mName == "square" || mName == "rectangle" ) + { + e.writeGroup( 0, "SOLID" ); + e.writeGroup( 8, "0" ); + e.writeGroup( 62, colorIndex ); + e.writeGroup( 10, 0.0 ); + e.writeGroup( 20, 0.0 ); + e.writeGroup( 30, 0.0 ); + e.writeGroup( 11, size ); + e.writeGroup( 21, 0.0 ); + e.writeGroup( 31, 0.0 ); + e.writeGroup( 12, 0 ); + e.writeGroup( 22, size ); + e.writeGroup( 32, 0.0 ); + e.writeGroup( 13, size ); + e.writeGroup( 23, size ); + e.writeGroup( 33, 0.0 ); + } } ////////// From 5bd70838823c36e09e0b6b5dab184654a1b0e1d7 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 21 Nov 2013 17:27:59 +0100 Subject: [PATCH 23/38] Implement diamond simple marker --- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index 67f41223991..086e62c9c23 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -740,6 +740,24 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc e.writeGroup( 23, size ); e.writeGroup( 33, 0.0 ); } + else if ( mName == "diamond" ) + { + e.writeGroup( 0, "SOLID" ); + e.writeGroup( 8, "0" ); + e.writeGroup( 62, colorIndex ); + e.writeGroup( 10, 0.0 ); + e.writeGroup( 20, halfSize ); + e.writeGroup( 30, 0.0 ); + e.writeGroup( 11, halfSize ); + e.writeGroup( 21, 0.0 ); + e.writeGroup( 31, 0.0 ); + e.writeGroup( 12, halfSize ); + e.writeGroup( 22, size ); + e.writeGroup( 32, 0.0 ); + e.writeGroup( 13, size ); + e.writeGroup( 23, halfSize ); + e.writeGroup( 33, 0.0 ); + } } ////////// From 78fbee39dbc3b818456ad9ecafb5e01c1919a5c8 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 22 Nov 2013 16:58:43 +0100 Subject: [PATCH 24/38] Start implementation of QgsDxfPaintDevice / Engine to export svg markers to dxf --- src/core/CMakeLists.txt | 4 + src/core/dxf/qgsdxfpaintdevice.cpp | 84 +++++++++++++++++ src/core/dxf/qgsdxfpaintdevice.h | 59 ++++++++++++ src/core/dxf/qgsdxfpaintengine.cpp | 89 +++++++++++++++++++ src/core/dxf/qgsdxfpaintengine.h | 54 +++++++++++ .../symbology-ng/qgsmarkersymbollayerv2.cpp | 20 +++++ .../symbology-ng/qgsmarkersymbollayerv2.h | 2 + 7 files changed, 312 insertions(+) create mode 100644 src/core/dxf/qgsdxfpaintdevice.cpp create mode 100644 src/core/dxf/qgsdxfpaintdevice.h create mode 100644 src/core/dxf/qgsdxfpaintengine.cpp create mode 100644 src/core/dxf/qgsdxfpaintengine.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aafc4ac7980..eb7c11ca4dd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -160,6 +160,9 @@ SET(QGIS_CORE_SRCS composer/qgscomposerhtml.cpp composer/qgscomposermultiframe.cpp composer/qgscomposition.cpp + + dxf/qgsdxfpaintdevice.cpp + dxf/qgsdxfpaintengine.cpp pal/costcalculator.cpp pal/feature.cpp @@ -549,6 +552,7 @@ ENDIF (QT_MOBILITY_LOCATION_FOUND) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} composer + dxf pal raster renderer diff --git a/src/core/dxf/qgsdxfpaintdevice.cpp b/src/core/dxf/qgsdxfpaintdevice.cpp new file mode 100644 index 00000000000..45f4de9ea34 --- /dev/null +++ b/src/core/dxf/qgsdxfpaintdevice.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + qgsdxpaintdevice.cpp + -------------------- + begin : November 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qgsdxfpaintdevice.h" + +QgsDxfPaintDevice::QgsDxfPaintDevice( QgsDxfExport* dxf ): QPaintDevice(), mPaintEngine( 0 ) +{ + mPaintEngine = new QgsDxfPaintEngine( this, dxf ); +} + +QgsDxfPaintDevice::~QgsDxfPaintDevice() +{ + delete mPaintEngine; +} + +QPaintEngine* QgsDxfPaintDevice::paintEngine() const +{ + return mPaintEngine; +} + +int QgsDxfPaintDevice::metric( PaintDeviceMetric metric ) const +{ + switch ( metric ) + { + case QPaintDevice::PdmWidth: + return mDrawingSize.width(); + case QPaintDevice::PdmHeight: + return mDrawingSize.height(); + case QPaintDevice::PdmWidthMM: + return mDrawingSize.width(); + case QPaintDevice::PdmHeightMM: + return mDrawingSize.height(); + case QPaintDevice::PdmNumColors: + return INT_MAX; + case QPaintDevice::PdmDepth: + return 32; + case QPaintDevice::PdmDpiX: + case QPaintDevice::PdmDpiY: + case QPaintDevice::PdmPhysicalDpiX: + case QPaintDevice::PdmPhysicalDpiY: + return 96; + } + return 0; +} + +double QgsDxfPaintDevice::widthScaleFactor() const +{ + if ( !mDrawingSize.isValid() || mRectangle.isEmpty() ) + { + return 1.0; + } + + double widthFactor = mRectangle.width() / mDrawingSize.width(); + double heightFactor = mRectangle.height() / mDrawingSize.height(); + return ( widthFactor + heightFactor ) / 2.0; +} + +QPointF QgsDxfPaintDevice::dxfCoordinates( const QPointF& pt ) +{ + if ( !mDrawingSize.isValid() || mRectangle.isEmpty() ) + { + return QPointF( pt.x(), pt.y() ); + } + + double x = mRectangle.left() + pt.x() * ( mRectangle.width() / mDrawingSize.width() ); + double y = mRectangle.bottom() - pt.y() * ( mRectangle.height() / mDrawingSize.height() ); + return QPointF( x, y ); +} + + diff --git a/src/core/dxf/qgsdxfpaintdevice.h b/src/core/dxf/qgsdxfpaintdevice.h new file mode 100644 index 00000000000..fe26d0141be --- /dev/null +++ b/src/core/dxf/qgsdxfpaintdevice.h @@ -0,0 +1,59 @@ +/*************************************************************************** + qgsdxpaintdevice.h + ------------------ + begin : November 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QGSDXFPAINTDEVICE_H +#define QGSDXFPAINTDEVICE_H + +#include +#include "qgsdxfpaintengine.h" + +class QgsDxfExport; +class QPaintEngine; + +/**A paint device for drawing into dxf files*/ + +class QgsDxfPaintDevice: public QPaintDevice +{ + public: + QgsDxfPaintDevice( QgsDxfExport* dxf ); + ~QgsDxfPaintDevice(); + + QPaintEngine* paintEngine() const; + + void setDrawingSize( const QSizeF& size ) { mDrawingSize = size; } + void setOutputSize( const QRectF& r ) { mRectangle = r; } + + /**Returns scale factor for line width*/ + double widthScaleFactor() const; + + /**Converts a point from device coordinates to dxf coordinates*/ + QPointF dxfCoordinates( const QPointF& pt ); + + /*int height() const { return mDrawingSize.height(); } + int width() const { return mDrawingSize.width(); }*/ + + int metric( PaintDeviceMetric metric ) const; + + + private: + QgsDxfPaintEngine* mPaintEngine; + + QSizeF mDrawingSize; //size (in source coordinates) + QRectF mRectangle; //size (in dxf coordinates) +}; + +#endif // QGSDXFPAINTDEVICE_H diff --git a/src/core/dxf/qgsdxfpaintengine.cpp b/src/core/dxf/qgsdxfpaintengine.cpp new file mode 100644 index 00000000000..cf98f801e4e --- /dev/null +++ b/src/core/dxf/qgsdxfpaintengine.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + qgsdxpaintengine.cpp + -------------------- + begin : November 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "qgsdxfpaintengine.h" +#include "qgsdxfexport.h" +#include "qgslogger.h" + +QgsDxfPaintEngine::QgsDxfPaintEngine( const QgsDxfPaintDevice* dxfDevice, QgsDxfExport* dxf ): QPaintEngine( QPaintEngine::AllFeatures /*QPaintEngine::PainterPaths | QPaintEngine::PaintOutsidePaintEvent*/ ) + , mPaintDevice( dxfDevice ), mDxf( dxf ) +{ + +} + +QgsDxfPaintEngine::~QgsDxfPaintEngine() +{ + +} + +bool QgsDxfPaintEngine::begin( QPaintDevice* pdev ) +{ + Q_UNUSED( pdev ); + return true; +} + +bool QgsDxfPaintEngine::end() +{ + return true; +} + +QPaintEngine::Type QgsDxfPaintEngine::type() const +{ + return QPaintEngine::User; +} + +void QgsDxfPaintEngine::drawPixmap( const QRectF& r, const QPixmap& pm, const QRectF& sr ) +{ + Q_UNUSED( r ); Q_UNUSED( pm ); Q_UNUSED( sr ); +} + +void QgsDxfPaintEngine::updateState( const QPaintEngineState& state ) +{ + if ( state.state() | QPaintEngine::DirtyTransform ) + { + mTransform = state.transform(); + } + if ( state.state() | QPaintEngine::DirtyPen ) + { + mPen = state.pen(); + } +} + +void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, PolygonDrawMode mode ) +{ + QgsDebugMsg( "***********************Dxf paint engine: drawing polygon*********************" ); +} + +void QgsDxfPaintEngine::drawRects( const QRectF * rects, int rectCount ) +{ + QgsDebugMsg( "***********************Dxf paint engine: drawing rects*********************" ); +} + +void QgsDxfPaintEngine::drawEllipse( const QRectF& rect ) +{ + QgsDebugMsg( "***********************Dxf paint engine: drawing ellipse*********************" ); +} + +void QgsDxfPaintEngine::drawPath( const QPainterPath& path ) +{ + QgsDebugMsg( "***********************Dxf paint engine: drawing path*********************" ); +} + +void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount ) +{ + QgsDebugMsg( "***********************Dxf paint engine: drawing path*********************" ); +} diff --git a/src/core/dxf/qgsdxfpaintengine.h b/src/core/dxf/qgsdxfpaintengine.h new file mode 100644 index 00000000000..775ced3261b --- /dev/null +++ b/src/core/dxf/qgsdxfpaintengine.h @@ -0,0 +1,54 @@ +/*************************************************************************** + qgsdxpaintengine.h + ------------------ + begin : November 2013 + copyright : (C) 2013 by Marco Hugentobler + email : marco at sourcepole dot ch + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 QGSDXFPAINTENGINE_H +#define QGSDXFPAINTENGINE_H + +#include + +class QgsDxfExport; +class QgsDxfPaintDevice; + +class QgsDxfPaintEngine: public QPaintEngine +{ + public: + QgsDxfPaintEngine( const QgsDxfPaintDevice* dxfDevice, QgsDxfExport* dxf ); + ~QgsDxfPaintEngine(); + + bool begin( QPaintDevice* pdev ); + bool end(); + QPaintEngine::Type type() const; + void updateState( const QPaintEngineState& state ); + + void drawPixmap( const QRectF& r, const QPixmap& pm, const QRectF& sr ); + + void drawPolygon( const QPointF * points, int pointCount, PolygonDrawMode mode ); + void drawRects( const QRectF * rects, int rectCount ); + void drawEllipse( const QRectF& rect ); + void drawPath( const QPainterPath& path ); + void drawLines( const QLineF* lines, int lineCount ); + + private: + const QgsDxfPaintDevice* mPaintDevice; + QgsDxfExport* mDxf; + + //painter state information + QTransform mTransform; + QPen mPen; +}; + +#endif // QGSDXFPAINTENGINE_H diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index 086e62c9c23..5cddb26d037 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -17,6 +17,7 @@ #include "qgssymbollayerv2utils.h" #include "qgsdxfexport.h" +#include "qgsdxfpaintdevice.h" #include "qgsexpression.h" #include "qgsrendercontext.h" #include "qgslogger.h" @@ -1165,6 +1166,25 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element return m; } +void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const +{ + QSvgRenderer r( mPath ); + if ( !r.isValid() ) + { + return; + } + + QgsDxfPaintDevice pd( &e ); + pd.setDrawingSize( QSizeF( r.defaultSize() ) ); + double size = mSize * mmMapUnitScaleFactor ; + pd.setOutputSize( QRectF( 0, 0, size, size ) ); + QPainter p; + + p.begin( &pd ); + r.render( &p ); + p.end(); +} + ////////// QgsFontMarkerSymbolLayerV2::QgsFontMarkerSymbolLayerV2( QString fontFamily, QChar chr, double pointSize, QColor color, double angle ) diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index 486a76db2bd..86e0f286410 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -159,6 +159,8 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2 void setOutputUnit( QgsSymbolV2::OutputUnit unit ); QgsSymbolV2::OutputUnit outputUnit() const; + void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const; + protected: QString mPath; From 34e1bd23775f8cb5ac26d31d67bfaa246f7fd41f Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sat, 23 Nov 2013 18:10:51 +0100 Subject: [PATCH 25/38] Move QgsDxfExport into dxf subdirectory --- src/app/CMakeLists.txt | 2 +- src/core/CMakeLists.txt | 2 +- src/core/{ => dxf}/qgsdxfexport.cpp | 0 src/core/{ => dxf}/qgsdxfexport.h | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename src/core/{ => dxf}/qgsdxfexport.cpp (100%) rename src/core/{ => dxf}/qgsdxfexport.h (100%) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 2e6771482bc..26b6ed24110 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -421,7 +421,7 @@ INCLUDE_DIRECTORIES( ../analysis/raster ../analysis/openstreetmap ../core ../core/gps - ../core/composer ../core/raster ../core/symbology-ng + ../core/composer ../core/dxf ../core/raster ../core/symbology-ng ../gui ../gui/symbology-ng ../gui/attributetable ../gui/raster ../plugins ../python diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index eb7c11ca4dd..356578f1a22 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -62,7 +62,6 @@ SET(QGIS_CORE_SRCS qgsdbfilterproxymodel.cpp qgsdiagramrendererv2.cpp qgsdistancearea.cpp - qgsdxfexport.cpp qgserror.cpp qgsexpression.cpp qgsexpression_texts.cpp @@ -161,6 +160,7 @@ SET(QGIS_CORE_SRCS composer/qgscomposermultiframe.cpp composer/qgscomposition.cpp + dxf/qgsdxfexport.cpp dxf/qgsdxfpaintdevice.cpp dxf/qgsdxfpaintengine.cpp diff --git a/src/core/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp similarity index 100% rename from src/core/qgsdxfexport.cpp rename to src/core/dxf/qgsdxfexport.cpp diff --git a/src/core/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h similarity index 100% rename from src/core/qgsdxfexport.h rename to src/core/dxf/qgsdxfexport.h From a9d92cdcf47de6c669683bcd3688c0fc52ec10e2 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Sat, 23 Nov 2013 18:13:06 +0100 Subject: [PATCH 26/38] Convert painterpath to polygons for dxf --- src/core/dxf/qgsdxfpaintdevice.cpp | 2 +- src/core/dxf/qgsdxfpaintdevice.h | 2 +- src/core/dxf/qgsdxfpaintengine.cpp | 23 ++++++++++++++++++++++- src/core/qgsdxfexport.cpp | 23 +++++++++++++++++++++++ src/core/qgsdxfexport.h | 5 +++-- 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/core/dxf/qgsdxfpaintdevice.cpp b/src/core/dxf/qgsdxfpaintdevice.cpp index 45f4de9ea34..bac69b3329a 100644 --- a/src/core/dxf/qgsdxfpaintdevice.cpp +++ b/src/core/dxf/qgsdxfpaintdevice.cpp @@ -69,7 +69,7 @@ double QgsDxfPaintDevice::widthScaleFactor() const return ( widthFactor + heightFactor ) / 2.0; } -QPointF QgsDxfPaintDevice::dxfCoordinates( const QPointF& pt ) +QPointF QgsDxfPaintDevice::dxfCoordinates( const QPointF& pt ) const { if ( !mDrawingSize.isValid() || mRectangle.isEmpty() ) { diff --git a/src/core/dxf/qgsdxfpaintdevice.h b/src/core/dxf/qgsdxfpaintdevice.h index fe26d0141be..02cc2c30cfd 100644 --- a/src/core/dxf/qgsdxfpaintdevice.h +++ b/src/core/dxf/qgsdxfpaintdevice.h @@ -41,7 +41,7 @@ class QgsDxfPaintDevice: public QPaintDevice double widthScaleFactor() const; /**Converts a point from device coordinates to dxf coordinates*/ - QPointF dxfCoordinates( const QPointF& pt ); + QPointF dxfCoordinates( const QPointF& pt ) const; /*int height() const { return mDrawingSize.height(); } int width() const { return mDrawingSize.width(); }*/ diff --git a/src/core/dxf/qgsdxfpaintengine.cpp b/src/core/dxf/qgsdxfpaintengine.cpp index cf98f801e4e..aea57a052d8 100644 --- a/src/core/dxf/qgsdxfpaintengine.cpp +++ b/src/core/dxf/qgsdxfpaintengine.cpp @@ -17,6 +17,7 @@ #include "qgsdxfpaintengine.h" #include "qgsdxfexport.h" +#include "qgsdxfpaintdevice.h" #include "qgslogger.h" QgsDxfPaintEngine::QgsDxfPaintEngine( const QgsDxfPaintDevice* dxfDevice, QgsDxfExport* dxf ): QPaintEngine( QPaintEngine::AllFeatures /*QPaintEngine::PainterPaths | QPaintEngine::PaintOutsidePaintEvent*/ ) @@ -65,7 +66,21 @@ void QgsDxfPaintEngine::updateState( const QPaintEngineState& state ) void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, PolygonDrawMode mode ) { - QgsDebugMsg( "***********************Dxf paint engine: drawing polygon*********************" ); + if ( !mDxf || !mPaintDevice ) + { + return; + } + + QgsPolyline polyline( pointCount ); + for ( int i = 0; i < pointCount; ++i ) + { + QPointF dxfCoord = mPaintDevice->dxfCoordinates( points[i] ); + polyline[i] = QgsPoint( dxfCoord.x(), dxfCoord.y() ); + } + + int color = mDxf->closestColorMatch( mPen.color().rgb() ); + double width = mPen.widthF() * mPaintDevice->widthScaleFactor(); + mDxf->writePolyline( polyline, "0", "CONTINUOUS", color, width, mode != QPaintEngine::PolylineMode ); } void QgsDxfPaintEngine::drawRects( const QRectF * rects, int rectCount ) @@ -81,6 +96,12 @@ void QgsDxfPaintEngine::drawEllipse( const QRectF& rect ) void QgsDxfPaintEngine::drawPath( const QPainterPath& path ) { QgsDebugMsg( "***********************Dxf paint engine: drawing path*********************" ); + QList polygonList = path.toFillPolygons(); + QList::const_iterator pIt = polygonList.constBegin(); + for ( ; pIt != polygonList.constEnd(); ++pIt ) + { + drawPolygon( pIt->constData(), pIt->size(), pIt->isClosed() ? QPaintEngine::OddEvenMode : QPaintEngine::PolylineMode ); + } } void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount ) diff --git a/src/core/qgsdxfexport.cpp b/src/core/qgsdxfexport.cpp index 53e50985c9d..db449f419c0 100644 --- a/src/core/qgsdxfexport.cpp +++ b/src/core/qgsdxfexport.cpp @@ -676,6 +676,29 @@ void QgsDxfExport::endSection() void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) { + //debug: draw rectangle for debugging + const QgsMarkerSymbolLayerV2* msl = dynamic_cast< const QgsMarkerSymbolLayerV2* >( symbolLayer ); + if ( msl ) + { + double halfSize = msl->size() * mapUnitScaleFactor( mSymbologyScaleDenominator, + msl->sizeUnit(), mMapUnits ) / 2.0; + writeGroup( 0, "SOLID" ); + writeGroup( 8, layer ); + writeGroup( 62, 1 ); + writeGroup( 10, pt.x() - halfSize ); + writeGroup( 20, pt.y() - halfSize ); + writeGroup( 30, 0.0 ); + writeGroup( 11, pt.x() + halfSize ); + writeGroup( 21, pt.y() - halfSize ); + writeGroup( 31, 0.0 ); + writeGroup( 12, pt.x() - halfSize ); + writeGroup( 22, pt.y() + halfSize ); + writeGroup( 32, 0.0 ); + writeGroup( 13, pt.x() + halfSize ); + writeGroup( 23, pt.y() + halfSize ); + writeGroup( 33, 0.0 ); + } + //insert block or write point directly? QHash< const QgsSymbolLayerV2*, QString >::const_iterator blockIt = mPointSymbolBlocks.find( symbolLayer ); if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() ) diff --git a/src/core/qgsdxfexport.h b/src/core/qgsdxfexport.h index 464617e4227..db6d7a8f9b1 100644 --- a/src/core/qgsdxfexport.h +++ b/src/core/qgsdxfexport.h @@ -65,6 +65,9 @@ class QgsDxfExport void writeDouble( double d ); void writeString( const QString& s ); + void writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, + double width = -1, bool polygon = false ); + private: QList< QgsMapLayer* > mLayers; @@ -98,8 +101,6 @@ class QgsDxfExport void endSection(); void writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); - void writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, - double width = -1, bool polygon = false ); void writeVertex( const QgsPoint& pt, const QString& layer ); void writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ); void writeLinestyle( const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); From a10d67545a1ab1e0dad719f0f15ce8063026f749 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Mon, 25 Nov 2013 11:07:00 +0100 Subject: [PATCH 27/38] Cleanup code structure, move code to central functions --- src/core/dxf/qgsdxfexport.cpp | 23 ++++++++- src/core/dxf/qgsdxfexport.h | 2 + src/core/dxf/qgsdxfpaintdevice.cpp | 8 +++ src/core/dxf/qgsdxfpaintdevice.h | 2 + src/core/dxf/qgsdxfpaintengine.cpp | 48 +++++++++++++++--- src/core/dxf/qgsdxfpaintengine.h | 8 +++ .../symbology-ng/qgsmarkersymbollayerv2.cpp | 49 ++++++------------- .../symbology-ng/qgsmarkersymbollayerv2.h | 4 +- src/core/symbology-ng/qgssymbollayerv2.h | 2 +- 9 files changed, 102 insertions(+), 44 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index db449f419c0..52db99898ea 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -501,7 +501,7 @@ void QgsDxfExport::writeBlocks() writeGroup( 30, 0 ); writeGroup( 3, blockName ); - ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ) ); + ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ), "0" ); //maplayer 0 -> block receives layer from INSERT statement writeGroup( 0, "ENDBLK" ); writeGroup( 8, 0 ); @@ -676,6 +676,7 @@ void QgsDxfExport::endSection() void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) { +#if 0 //debug: draw rectangle for debugging const QgsMarkerSymbolLayerV2* msl = dynamic_cast< const QgsMarkerSymbolLayerV2* >( symbolLayer ); if ( msl ) @@ -698,6 +699,7 @@ void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const Q writeGroup( 23, pt.y() + halfSize ); writeGroup( 33, 0.0 ); } +#endif //0 //insert block or write point directly? QHash< const QgsSymbolLayerV2*, QString >::const_iterator blockIt = mPointSymbolBlocks.find( symbolLayer ); @@ -739,6 +741,25 @@ void QgsDxfExport::writePolyline( const QgsPolyline& line, const QString& layer, writeGroup( 0, "SEQEND" ); } +void QgsDxfExport::writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 ) +{ + writeGroup( 0, "SOLID" ); + writeGroup( 8, layer ); + writeGroup( 62, color ); + writeGroup( 10, pt1.x() ); + writeGroup( 20, pt1.y() ); + writeGroup( 30, 0.0 ); + writeGroup( 11, pt2.x() ); + writeGroup( 21, pt2.y() ); + writeGroup( 31, 0.0 ); + writeGroup( 12, pt3.x() ); + writeGroup( 22, pt3.y() ); + writeGroup( 32, 0.0 ); + writeGroup( 13, pt4.x() ); + writeGroup( 23, pt4.y() ); + writeGroup( 33, 0.0 ); +} + void QgsDxfExport::writeVertex( const QgsPoint& pt, const QString& layer ) { writeGroup( 0, "VERTEX" ); diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index db6d7a8f9b1..61e315d0303 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -68,6 +68,8 @@ class QgsDxfExport void writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width = -1, bool polygon = false ); + void writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 ); + private: QList< QgsMapLayer* > mLayers; diff --git a/src/core/dxf/qgsdxfpaintdevice.cpp b/src/core/dxf/qgsdxfpaintdevice.cpp index bac69b3329a..e3178f6fd7a 100644 --- a/src/core/dxf/qgsdxfpaintdevice.cpp +++ b/src/core/dxf/qgsdxfpaintdevice.cpp @@ -81,4 +81,12 @@ QPointF QgsDxfPaintDevice::dxfCoordinates( const QPointF& pt ) const return QPointF( x, y ); } +void QgsDxfPaintDevice::setLayer( const QString& layer ) +{ + if ( mPaintEngine ) + { + mPaintEngine->setLayer( layer ); + } +} + diff --git a/src/core/dxf/qgsdxfpaintdevice.h b/src/core/dxf/qgsdxfpaintdevice.h index 02cc2c30cfd..64b8a709436 100644 --- a/src/core/dxf/qgsdxfpaintdevice.h +++ b/src/core/dxf/qgsdxfpaintdevice.h @@ -48,6 +48,8 @@ class QgsDxfPaintDevice: public QPaintDevice int metric( PaintDeviceMetric metric ) const; + void setLayer( const QString& layer ); + private: QgsDxfPaintEngine* mPaintEngine; diff --git a/src/core/dxf/qgsdxfpaintengine.cpp b/src/core/dxf/qgsdxfpaintengine.cpp index aea57a052d8..6d899e0b59d 100644 --- a/src/core/dxf/qgsdxfpaintengine.cpp +++ b/src/core/dxf/qgsdxfpaintengine.cpp @@ -74,18 +74,32 @@ void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, Poly QgsPolyline polyline( pointCount ); for ( int i = 0; i < pointCount; ++i ) { - QPointF dxfCoord = mPaintDevice->dxfCoordinates( points[i] ); - polyline[i] = QgsPoint( dxfCoord.x(), dxfCoord.y() ); + polyline[i] = toDxfCoordinates( points[i] ); } - int color = mDxf->closestColorMatch( mPen.color().rgb() ); double width = mPen.widthF() * mPaintDevice->widthScaleFactor(); - mDxf->writePolyline( polyline, "0", "CONTINUOUS", color, width, mode != QPaintEngine::PolylineMode ); + mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentPenColor(), width, mode != QPaintEngine::PolylineMode ); } -void QgsDxfPaintEngine::drawRects( const QRectF * rects, int rectCount ) +void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount ) { - QgsDebugMsg( "***********************Dxf paint engine: drawing rects*********************" ); + if ( !mDxf || !mPaintDevice ) + { + return; + } + + for ( int i = 0; i < rectCount; ++i ) + { + double left = rects[i].left(); + double right = rects[i].right(); + double top = rects[i].top(); + double bottom = rects[i].bottom(); + QgsPoint pt1 = toDxfCoordinates( QPointF( left, bottom ) ); + QgsPoint pt2 = toDxfCoordinates( QPointF( right, bottom ) ); + QgsPoint pt3 = toDxfCoordinates( QPointF( left, top ) ); + QgsPoint pt4 = toDxfCoordinates( QPointF( right, top ) ); + mDxf->writeSolid( mLayer, currentPenColor(), pt1, pt2, pt3, pt4 ); + } } void QgsDxfPaintEngine::drawEllipse( const QRectF& rect ) @@ -95,7 +109,6 @@ void QgsDxfPaintEngine::drawEllipse( const QRectF& rect ) void QgsDxfPaintEngine::drawPath( const QPainterPath& path ) { - QgsDebugMsg( "***********************Dxf paint engine: drawing path*********************" ); QList polygonList = path.toFillPolygons(); QList::const_iterator pIt = polygonList.constBegin(); for ( ; pIt != polygonList.constEnd(); ++pIt ) @@ -108,3 +121,24 @@ void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount ) { QgsDebugMsg( "***********************Dxf paint engine: drawing path*********************" ); } + +QgsPoint QgsDxfPaintEngine::toDxfCoordinates( const QPointF& pt ) const +{ + if ( !mPaintDevice || !mDxf ) + { + return QgsPoint( pt.x(), pt.y() ); + } + + QPointF dxfPt = mPaintDevice->dxfCoordinates( mTransform.map( pt ) ); + return QgsPoint( dxfPt.x(), dxfPt.y() ); +} + +int QgsDxfPaintEngine::currentPenColor() const +{ + if ( !mDxf ) + { + return 0; + } + + return mDxf->closestColorMatch( mPen.color().rgb() ); +} diff --git a/src/core/dxf/qgsdxfpaintengine.h b/src/core/dxf/qgsdxfpaintengine.h index 775ced3261b..3514e106914 100644 --- a/src/core/dxf/qgsdxfpaintengine.h +++ b/src/core/dxf/qgsdxfpaintengine.h @@ -22,6 +22,7 @@ class QgsDxfExport; class QgsDxfPaintDevice; +class QgsPoint; class QgsDxfPaintEngine: public QPaintEngine { @@ -42,6 +43,9 @@ class QgsDxfPaintEngine: public QPaintEngine void drawPath( const QPainterPath& path ); void drawLines( const QLineF* lines, int lineCount ); + void setLayer( const QString& layer ) { mLayer = layer; } + QString layer() const { return mLayer; } + private: const QgsDxfPaintDevice* mPaintDevice; QgsDxfExport* mDxf; @@ -49,6 +53,10 @@ class QgsDxfPaintEngine: public QPaintEngine //painter state information QTransform mTransform; QPen mPen; + QString mLayer; + + QgsPoint toDxfCoordinates( const QPointF& pt ) const; + int currentPenColor() const; }; #endif // QGSDXFPAINTENGINE_H diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index 5cddb26d037..14c757c3d86 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -702,7 +702,7 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon } } -void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const +void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const { double size = mSize; if ( mSizeUnit == QgsSymbolV2::MM ) @@ -715,7 +715,7 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc if ( mName == "circle" ) { e.writeGroup( 0, "CIRCLE" ); - e.writeGroup( 8, "0" ); + e.writeGroup( 8, layerName ); e.writeGroup( 62, colorIndex ); e.writeGroup( 10, halfSize ); @@ -725,39 +725,19 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc } else if ( mName == "square" || mName == "rectangle" ) { - e.writeGroup( 0, "SOLID" ); - e.writeGroup( 8, "0" ); - e.writeGroup( 62, colorIndex ); - e.writeGroup( 10, 0.0 ); - e.writeGroup( 20, 0.0 ); - e.writeGroup( 30, 0.0 ); - e.writeGroup( 11, size ); - e.writeGroup( 21, 0.0 ); - e.writeGroup( 31, 0.0 ); - e.writeGroup( 12, 0 ); - e.writeGroup( 22, size ); - e.writeGroup( 32, 0.0 ); - e.writeGroup( 13, size ); - e.writeGroup( 23, size ); - e.writeGroup( 33, 0.0 ); + QgsPoint pt1( 0.0, 0.0 ); + QgsPoint pt2( size, 0.0 ); + QgsPoint pt3( 0.0, size ); + QgsPoint pt4( size, size ); + e.writeSolid( layerName, colorIndex, pt1, pt2, pt3, pt4 ); } else if ( mName == "diamond" ) { - e.writeGroup( 0, "SOLID" ); - e.writeGroup( 8, "0" ); - e.writeGroup( 62, colorIndex ); - e.writeGroup( 10, 0.0 ); - e.writeGroup( 20, halfSize ); - e.writeGroup( 30, 0.0 ); - e.writeGroup( 11, halfSize ); - e.writeGroup( 21, 0.0 ); - e.writeGroup( 31, 0.0 ); - e.writeGroup( 12, halfSize ); - e.writeGroup( 22, size ); - e.writeGroup( 32, 0.0 ); - e.writeGroup( 13, size ); - e.writeGroup( 23, halfSize ); - e.writeGroup( 33, 0.0 ); + QgsPoint pt1( 0.0, halfSize ); + QgsPoint pt2( halfSize, 0.0 ); + QgsPoint pt3( halfSize, size ); + QgsPoint pt4( size, halfSize ); + e.writeSolid( layerName, colorIndex, pt1, pt2, pt3, pt4 ); } } @@ -1166,8 +1146,10 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element return m; } -void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const +void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const { + Q_UNUSED( layerName ); + QSvgRenderer r( mPath ); if ( !r.isValid() ) { @@ -1178,6 +1160,7 @@ void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale pd.setDrawingSize( QSizeF( r.defaultSize() ) ); double size = mSize * mmMapUnitScaleFactor ; pd.setOutputSize( QRectF( 0, 0, size, size ) ); + pd.setLayer( layerName ); QPainter p; p.begin( &pd ); diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index 86e0f286410..965f7946e8b 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -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; + void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const; protected: @@ -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; + void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const; protected: QString mPath; diff --git a/src/core/symbology-ng/qgssymbollayerv2.h b/src/core/symbology-ng/qgssymbollayerv2.h index 1e44716ffdb..d73c806187c 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.h +++ b/src/core/symbology-ng/qgssymbollayerv2.h @@ -93,7 +93,7 @@ class CORE_EXPORT QgsSymbolLayerV2 virtual void removeDataDefinedProperty( const QString& property ); virtual void removeDataDefinedProperties(); - virtual void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor ) const { Q_UNUSED( e ); Q_UNUSED( mmMapUnitScaleFactor ); } + virtual void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const { Q_UNUSED( e ); Q_UNUSED( mmMapUnitScaleFactor ); Q_UNUSED( layerName ); } protected: QgsSymbolLayerV2( QgsSymbolV2::SymbolType type, bool locked = false ) From 9abba4021a87ee5523da836e1781b6197c34e36f Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Mon, 25 Nov 2013 11:46:58 +0100 Subject: [PATCH 28/38] Implement write lines in dxf engine --- src/core/dxf/qgsdxfexport.cpp | 8 ++++++++ src/core/dxf/qgsdxfexport.h | 4 ++++ src/core/dxf/qgsdxfpaintengine.cpp | 31 +++++++++++++++++++++++++----- src/core/dxf/qgsdxfpaintengine.h | 1 + 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 52db99898ea..6973e5af456 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -741,6 +741,14 @@ void QgsDxfExport::writePolyline( const QgsPolyline& line, const QString& layer, writeGroup( 0, "SEQEND" ); } +void QgsDxfExport::writeLine( const QgsPoint& pt1, const QgsPoint& pt2, const QString& layer, const QString& lineStyleName, int color, double width ) +{ + QgsPolyline line( 2 ); + line[0] = pt1; + line[1] = pt2; + writePolyline( line, layer, lineStyleName, color, width, false ); +} + void QgsDxfExport::writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 ) { writeGroup( 0, "SOLID" ); diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index 61e315d0303..cef0f4010b4 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -65,11 +65,15 @@ class QgsDxfExport void writeDouble( double d ); void writeString( const QString& s ); + //draw dxf primitives void writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width = -1, bool polygon = false ); void writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 ); + //write line (as a polyline) + void writeLine( const QgsPoint& pt1, const QgsPoint& pt2, const QString& layer, const QString& lineStyleName, int color, double width = -1 ); + private: QList< QgsMapLayer* > mLayers; diff --git a/src/core/dxf/qgsdxfpaintengine.cpp b/src/core/dxf/qgsdxfpaintengine.cpp index 6d899e0b59d..71cc7171844 100644 --- a/src/core/dxf/qgsdxfpaintengine.cpp +++ b/src/core/dxf/qgsdxfpaintengine.cpp @@ -77,13 +77,12 @@ void QgsDxfPaintEngine::drawPolygon( const QPointF* points, int pointCount, Poly polyline[i] = toDxfCoordinates( points[i] ); } - double width = mPen.widthF() * mPaintDevice->widthScaleFactor(); - mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentPenColor(), width, mode != QPaintEngine::PolylineMode ); + mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentPenColor(), currentWidth(), mode != QPaintEngine::PolylineMode ); } void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount ) { - if ( !mDxf || !mPaintDevice ) + if ( !mDxf || !mPaintDevice || !rects ) { return; } @@ -104,7 +103,9 @@ void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount ) void QgsDxfPaintEngine::drawEllipse( const QRectF& rect ) { - QgsDebugMsg( "***********************Dxf paint engine: drawing ellipse*********************" ); + //map to circle in case of square? + + //todo: create polyline for real ellises } void QgsDxfPaintEngine::drawPath( const QPainterPath& path ) @@ -119,7 +120,17 @@ void QgsDxfPaintEngine::drawPath( const QPainterPath& path ) void QgsDxfPaintEngine::drawLines( const QLineF* lines, int lineCount ) { - QgsDebugMsg( "***********************Dxf paint engine: drawing path*********************" ); + if ( !mDxf || !mPaintDevice || !lines ) + { + return; + } + + for ( int i = 0; i < lineCount; ++i ) + { + QgsPoint pt1 = toDxfCoordinates( lines[i].p1() ); + QgsPoint pt2 = toDxfCoordinates( lines[i].p2() ); + mDxf->writeLine( pt1, pt2, mLayer, "CONTINUOUS", currentPenColor(), currentWidth() ); + } } QgsPoint QgsDxfPaintEngine::toDxfCoordinates( const QPointF& pt ) const @@ -142,3 +153,13 @@ int QgsDxfPaintEngine::currentPenColor() const return mDxf->closestColorMatch( mPen.color().rgb() ); } + +double QgsDxfPaintEngine::currentWidth() const +{ + if ( !mPaintDevice ) + { + return 1; + } + + return mPen.widthF() * mPaintDevice->widthScaleFactor(); +} diff --git a/src/core/dxf/qgsdxfpaintengine.h b/src/core/dxf/qgsdxfpaintengine.h index 3514e106914..79862e78c2e 100644 --- a/src/core/dxf/qgsdxfpaintengine.h +++ b/src/core/dxf/qgsdxfpaintengine.h @@ -57,6 +57,7 @@ class QgsDxfPaintEngine: public QPaintEngine QgsPoint toDxfCoordinates( const QPointF& pt ) const; int currentPenColor() const; + double currentWidth() const; }; #endif // QGSDXFPAINTENGINE_H From fa509b80e03b35a8e4638f3484331ec73a75d80a Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Tue, 26 Nov 2013 16:58:24 +0100 Subject: [PATCH 29/38] Change symbol layer dxf method signature and make first test with a data defined property --- src/core/dxf/qgsdxfexport.cpp | 73 +++++++++++++------ src/core/dxf/qgsdxfexport.h | 9 ++- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 61 +++++++++++++--- .../symbology-ng/qgsmarkersymbollayerv2.h | 4 +- src/core/symbology-ng/qgssymbollayerv2.cpp | 6 +- src/core/symbology-ng/qgssymbollayerv2.h | 6 +- 6 files changed, 113 insertions(+), 46 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 6973e5af456..560f72eb4ad 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -417,7 +417,7 @@ void QgsDxfExport::writeTables() writeGroup( 2, "TABLES" ); //iterate through all layers and get symbol layer pointers - QList slList; + QList< QPair > slList; if ( mSymbologyExport != NoSymbology ) { slList = symbolLayers(); @@ -439,10 +439,10 @@ void QgsDxfExport::writeTables() writeGroup( 40, 0.0 ); //add symbol layer linestyles - QList::const_iterator slIt = slList.constBegin(); + QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = slList.constBegin(); for ( ; slIt != slList.constEnd(); ++slIt ) { - writeSymbolLayerLinestyle( *slIt ); + writeSymbolLayerLinestyle( slIt->first ); } writeGroup( 0, "ENDTAB" ); @@ -472,20 +472,24 @@ void QgsDxfExport::writeBlocks() writeGroup( 2, "BLOCKS" ); //iterate through all layers and get symbol layer pointers - QList slList; + QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > slList; if ( mSymbologyExport != NoSymbology ) { slList = symbolLayers(); } - QList::const_iterator slIt = slList.constBegin(); + 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 ); + QgsMarkerSymbolLayerV2* ml = dynamic_cast< QgsMarkerSymbolLayerV2*>( slIt->first ); if ( ml ) { - //todo: find out if the marker symbol layer has data defined properties (in that case don't insert it) + //markers with data defined properties are inserted inline + if ( hasDataDefinedProperties( ml, slIt->second ) ) + { + continue; + } writeGroup( 0, "BLOCK" ); writeGroup( 8, 0 ); QString blockName = QString( "symbolLayer%1" ).arg( mBlockCounter ); @@ -501,7 +505,7 @@ void QgsDxfExport::writeBlocks() writeGroup( 30, 0 ); writeGroup( 3, blockName ); - ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ), "0" ); //maplayer 0 -> block receives layer from INSERT statement + ml->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, ml->sizeUnit(), mMapUnits ), "0", 0, 0 ); //maplayer 0 -> block receives layer from INSERT statement writeGroup( 0, "ENDBLK" ); writeGroup( 8, 0 ); @@ -548,7 +552,7 @@ void QgsDxfExport::writeEntities() { if ( mSymbologyExport == NoSymbology ) { - addFeature( fet, vl->name(), 0 ); //no symbology at all + addFeature( fet, vl->name(), 0, 0 ); //no symbology at all } else { @@ -568,7 +572,7 @@ void QgsDxfExport::writeEntities() { continue; } - addFeature( fet, vl->name(), s->symbolLayer( 0 ) ); + addFeature( fet, vl->name(), s->symbolLayer( 0 ), s ); } } } @@ -652,7 +656,7 @@ void QgsDxfExport::writeEntitiesSymbolLevels( QgsVectorLayer* layer ) QList::iterator featureIt = featureList.begin(); for ( ; featureIt != featureList.end(); ++featureIt ) { - addFeature( *featureIt, layer->name(), levelIt.key()->symbolLayer( llayer ) ); + addFeature( *featureIt, layer->name(), levelIt.key()->symbolLayer( llayer ), levelIt.key() ); } } } @@ -674,7 +678,7 @@ void QgsDxfExport::endSection() writeGroup( 0, "ENDSEC" ); } -void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) +void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ) { #if 0 //debug: draw rectangle for debugging @@ -706,10 +710,17 @@ void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const Q if ( !symbolLayer || blockIt == mPointSymbolBlocks.constEnd() ) { //write symbol directly here + const QgsMarkerSymbolLayerV2* msl = dynamic_cast< const QgsMarkerSymbolLayerV2* >( symbolLayer ); + if ( symbolLayer && symbol ) + { + QgsRenderContext ct; + QgsSymbolV2RenderContext ctx( ct, QgsSymbolV2::MapUnit, symbol->alpha(), false, symbol->renderHints(), f ); + symbolLayer->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, msl->sizeUnit(), mMapUnits ), layer, &ctx, f, QPointF( pt.x(), pt.y() ) ); + } } else { - //insert block + //insert block reference writeGroup( 0, "INSERT" ); writeGroup( 8, layer ); writeGroup( 2, blockIt.value() ); @@ -799,7 +810,7 @@ QgsRectangle QgsDxfExport::dxfExtent() const return extent; } -void QgsDxfExport::addFeature( const QgsFeature& fet, const QString& layer, const QgsSymbolLayerV2* symbolLayer ) +void QgsDxfExport::addFeature( const QgsFeature& fet, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ) { QgsGeometry* geom = fet.geometry(); if ( geom ) @@ -820,7 +831,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, const QString& layer, cons //single point if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D ) { - writePoint( geom->asPoint(), layer, symbolLayer ); + writePoint( geom->asPoint(), layer, &fet, symbolLayer, symbol ); } //single line @@ -1006,9 +1017,9 @@ double QgsDxfExport::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::O return 1.0; } -QList QgsDxfExport::symbolLayers() +QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > QgsDxfExport::symbolLayers() { - QList symbolLayers; + QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > symbolLayers; QList< QgsMapLayer* >::iterator lIt = mLayers.begin(); for ( ; lIt != mLayers.end(); ++lIt ) @@ -1039,7 +1050,7 @@ QList QgsDxfExport::symbolLayers() } for ( int i = 0; i < maxSymbolLayers; ++i ) { - symbolLayers.append(( *symbolIt )->symbolLayer( i ) ); + symbolLayers.append( qMakePair(( *symbolIt )->symbolLayer( i ), *symbolIt ) ) ; } } } @@ -1069,13 +1080,13 @@ void QgsDxfExport::writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLaye } } -int QgsDxfExport::nLineTypes( const QList& symbolLayers ) +int QgsDxfExport::nLineTypes( const QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > >& symbolLayers ) { int nLineTypes = 0; - QList::const_iterator slIt = symbolLayers.constBegin(); + QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = symbolLayers.constBegin(); for ( ; slIt != symbolLayers.constEnd(); ++slIt ) { - const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( *slIt ); + const QgsSimpleLineSymbolLayerV2* simpleLine = dynamic_cast< const QgsSimpleLineSymbolLayerV2* >( slIt->first ); if ( simpleLine ) { if ( simpleLine->useCustomDashPattern() ) @@ -1116,6 +1127,22 @@ void QgsDxfExport::writeLinestyle( const QString& styleName, const QVectorrenderHints() | QgsSymbolV2::DataDefinedSizeScale || + symbol->renderHints() | QgsSymbolV2::DataDefinedRotation ) + { + return true; + } + + return sl->hasDataDefinedProperties(); +} + /******************************************************Test with AC_1018 methods***************************************************************/ void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) @@ -1256,7 +1283,7 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) QList slList; if ( mSymbologyExport != NoSymbology ) { - slList = symbolLayers(); + //slList = symbolLayers(); //todo... } //LTYPE @@ -1270,7 +1297,7 @@ void QgsDxfExport::writeTablesAC1018( QTextStream& stream ) stream << "100\n"; stream << "AcDbSymbolTable\n"; stream << " 70\n"; - stream << QString( "%1\n" ).arg( nLineTypes( slList ) + 1 ); //number of linetypes + //stream << QString( "%1\n" ).arg( nLineTypes( slList ) + 1 ); //number of linetypes //add continuous style as default stream << " 0\n"; diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index cef0f4010b4..7ace900b1d8 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -106,7 +106,7 @@ class QgsDxfExport void startSection(); void endSection(); - void writePoint( const QgsPoint& pt, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); + void writePoint( const QgsPoint& pt, const QString& layer, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ); void writeVertex( const QgsPoint& pt, const QString& layer ); void writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ); void writeLinestyle( const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); @@ -125,7 +125,7 @@ class QgsDxfExport QgsRectangle dxfExtent() const; - void addFeature( const QgsFeature& fet, const QString& layer, const QgsSymbolLayerV2* symbolLayer ); + void addFeature( const QgsFeature& fet, const QString& layer, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ); double scaleToMapUnits( double value, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) const; //returns dxf palette index from symbol layer color @@ -141,8 +141,9 @@ class QgsDxfExport void startRender( QgsVectorLayer* vl ) const; void stopRender( QgsVectorLayer* vl ) const; static double mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ); - QList symbolLayers(); - static int nLineTypes( const QList& symbolLayers ); + QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > symbolLayers(); + static int nLineTypes( const QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >& symbolLayers ); + static bool hasDataDefinedProperties( const QgsSymbolLayerV2* sl, const QgsSymbolV2* symbol ); }; #endif // QGSDXFEXPORT_H diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index 14c757c3d86..bc963e134db 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -702,9 +702,37 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon } } -void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const +void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset ) const { + //data defined size? double size = mSize; + + QgsExpression *sizeExpression = expression( "size" ); + bool hasDataDefinedSize = false; + if ( context ) + { + hasDataDefinedSize = context->renderHints() & QgsSymbolV2::DataDefinedSizeScale || sizeExpression; + } + + //data defined size + if ( hasDataDefinedSize ) + { + if ( sizeExpression ) + { + size = sizeExpression->evaluate( const_cast( context->feature() ) ).toDouble(); + } + size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context->renderContext(), mSizeUnit ); + + switch ( mScaleMethod ) + { + case QgsSymbolV2::ScaleArea: + size = sqrt( size ); + break; + case QgsSymbolV2::ScaleDiameter: + break; + } + } + if ( mSizeUnit == QgsSymbolV2::MM ) { size *= mmMapUnitScaleFactor; @@ -712,31 +740,38 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc double halfSize = size / 2.0; int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() ); + //data defined size + + + //data defined color, rotation, offset + + + if ( mName == "circle" ) { e.writeGroup( 0, "CIRCLE" ); e.writeGroup( 8, layerName ); e.writeGroup( 62, colorIndex ); - e.writeGroup( 10, halfSize ); - e.writeGroup( 20, halfSize ); + e.writeGroup( 10, halfSize + offset.x() ); + e.writeGroup( 20, halfSize + offset.y() ); e.writeGroup( 30, 0.0 ); e.writeGroup( 40, halfSize ); } else if ( mName == "square" || mName == "rectangle" ) { - QgsPoint pt1( 0.0, 0.0 ); - QgsPoint pt2( size, 0.0 ); - QgsPoint pt3( 0.0, size ); - QgsPoint pt4( size, size ); + 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 ); } else if ( mName == "diamond" ) { - QgsPoint pt1( 0.0, halfSize ); - QgsPoint pt2( halfSize, 0.0 ); - QgsPoint pt3( halfSize, size ); - QgsPoint pt4( size, halfSize ); + 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 ); } } @@ -1146,9 +1181,11 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element return m; } -void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const +void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, + const QPointF& offset ) const { Q_UNUSED( layerName ); + Q_UNUSED( offset ); //todo... QSvgRenderer r( mPath ); if ( !r.isValid() ) diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index 965f7946e8b..ad8ffd8ec43 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -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; + void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset = QPointF( 0.0, 0.0 ) ) const; protected: @@ -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; + void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& offset = QPointF( 0.0, 0.0 ) ) const; protected: QString mPath; diff --git a/src/core/symbology-ng/qgssymbollayerv2.cpp b/src/core/symbology-ng/qgssymbollayerv2.cpp index 47322250804..64ff0bf401d 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.cpp +++ b/src/core/symbology-ng/qgssymbollayerv2.cpp @@ -34,10 +34,10 @@ const QgsExpression* QgsSymbolLayerV2::dataDefinedProperty( const QString& prope return 0; } -QgsExpression* QgsSymbolLayerV2::expression( const QString& property ) +QgsExpression* QgsSymbolLayerV2::expression( const QString& property ) const { - QMap< QString, QgsExpression* >::iterator it = mDataDefinedProperties.find( property ); - if ( it != mDataDefinedProperties.end() ) + QMap< QString, QgsExpression* >::const_iterator it = mDataDefinedProperties.find( property ); + if ( it != mDataDefinedProperties.constEnd() ) { return it.value(); } diff --git a/src/core/symbology-ng/qgssymbollayerv2.h b/src/core/symbology-ng/qgssymbollayerv2.h index d73c806187c..910a3b31818 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.h +++ b/src/core/symbology-ng/qgssymbollayerv2.h @@ -92,8 +92,10 @@ class CORE_EXPORT QgsSymbolLayerV2 virtual void setDataDefinedProperty( const QString& property, const QString& expressionString ); virtual void removeDataDefinedProperty( const QString& property ); virtual void removeDataDefinedProperties(); + bool hasDataDefinedProperties() const { return mDataDefinedProperties.size() > 0; } - virtual void writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName ) const { Q_UNUSED( e ); Q_UNUSED( mmMapUnitScaleFactor ); Q_UNUSED( layerName ); } + 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 ); } protected: QgsSymbolLayerV2( QgsSymbolV2::SymbolType type, bool locked = false ) @@ -112,7 +114,7 @@ class CORE_EXPORT QgsSymbolLayerV2 static const bool selectFillStyle = false; // Fill symbol uses symbol layer style.. virtual void prepareExpressions( const QgsVectorLayer* vl ); - virtual QgsExpression* expression( const QString& property ); + virtual QgsExpression* expression( const QString& property ) const; /**Saves data defined properties to string map*/ void saveDataDefinedProperties( QgsStringMap& stringMap ) const; /**Copies data defined properties of this layer to another symbol layer*/ From bcad16d552b89fc64b6378e30808464379e091af Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 29 Nov 2013 15:13:08 +0100 Subject: [PATCH 30/38] Data defined size / color / rotation for marker export --- src/core/dxf/qgsdxfexport.cpp | 24 +++- src/core/dxf/qgsdxfpaintdevice.cpp | 8 ++ src/core/dxf/qgsdxfpaintdevice.h | 2 + src/core/dxf/qgsdxfpaintengine.cpp | 6 +- src/core/dxf/qgsdxfpaintengine.h | 3 + .../symbology-ng/qgsmarkersymbollayerv2.cpp | 134 +++++++++++++++--- .../symbology-ng/qgsmarkersymbollayerv2.h | 4 +- src/core/symbology-ng/qgssymbollayerv2.cpp | 2 +- src/core/symbology-ng/qgssymbollayerv2.h | 6 +- 9 files changed, 151 insertions(+), 38 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 560f72eb4ad..e14f6fd790d 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -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 ); @@ -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(); @@ -531,10 +537,14 @@ 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; } @@ -542,6 +552,7 @@ void QgsDxfExport::writeEntities() if ( !dp ) { continue; + renderer->stopRender( ctx ); } @@ -575,6 +586,7 @@ void QgsDxfExport::writeEntities() addFeature( fet, vl->name(), s->symbolLayer( 0 ), s ); } } + renderer->stopRender( ctx ); } endSection(); @@ -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; } diff --git a/src/core/dxf/qgsdxfpaintdevice.cpp b/src/core/dxf/qgsdxfpaintdevice.cpp index e3178f6fd7a..ef2a3cb286e 100644 --- a/src/core/dxf/qgsdxfpaintdevice.cpp +++ b/src/core/dxf/qgsdxfpaintdevice.cpp @@ -89,4 +89,12 @@ void QgsDxfPaintDevice::setLayer( const QString& layer ) } } +void QgsDxfPaintDevice::setShift( const QPointF& shift ) +{ + if ( mPaintEngine ) + { + mPaintEngine->setShift( shift ); + } +} + diff --git a/src/core/dxf/qgsdxfpaintdevice.h b/src/core/dxf/qgsdxfpaintdevice.h index 64b8a709436..eb13eb6c98b 100644 --- a/src/core/dxf/qgsdxfpaintdevice.h +++ b/src/core/dxf/qgsdxfpaintdevice.h @@ -50,6 +50,8 @@ class QgsDxfPaintDevice: public QPaintDevice void setLayer( const QString& layer ); + void setShift( const QPointF& shift ); + private: QgsDxfPaintEngine* mPaintEngine; diff --git a/src/core/dxf/qgsdxfpaintengine.cpp b/src/core/dxf/qgsdxfpaintengine.cpp index 71cc7171844..3433d19ec61 100644 --- a/src/core/dxf/qgsdxfpaintengine.cpp +++ b/src/core/dxf/qgsdxfpaintengine.cpp @@ -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(); } @@ -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() ); } diff --git a/src/core/dxf/qgsdxfpaintengine.h b/src/core/dxf/qgsdxfpaintengine.h index 79862e78c2e..7374f91b2ad 100644 --- a/src/core/dxf/qgsdxfpaintengine.h +++ b/src/core/dxf/qgsdxfpaintengine.h @@ -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; @@ -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; diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index bc963e134db..c4ba453e689 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -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; @@ -738,14 +738,45 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc size *= mmMapUnitScaleFactor; } double halfSize = size / 2.0; - int colorIndex = QgsDxfExport::closestColorMatch( mBrush.color().rgb() ); - - //data defined size - //data defined color, rotation, offset + 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( context->feature() ) ).toDouble(); + } + angle = -angle; //rotation in Qt is counterclockwise + if ( angle ) + off = _rotatedOffset( off, angle ); + + if ( mSizeUnit == QgsSymbolV2::MM ) + { + off *= mmMapUnitScaleFactor; + } + + QTransform t; + t.translate( shift.x() + offsetX, shift.y() + offsetY ); + + if ( angle != 0 ) + t.rotate( angle ); + + //data defined symbol name if ( mName == "circle" ) { @@ -753,26 +784,26 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc 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() ) ); } } @@ -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() ) @@ -1195,12 +1226,69 @@ void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale QgsDxfPaintDevice pd( &e ); pd.setDrawingSize( QSizeF( r.defaultSize() ) ); - double size = mSize * mmMapUnitScaleFactor ; + + //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 ); - QPainter p; - - p.begin( &pd ); r.render( &p ); p.end(); } diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index ad8ffd8ec43..3f09df95aa9 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -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: @@ -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; diff --git a/src/core/symbology-ng/qgssymbollayerv2.cpp b/src/core/symbology-ng/qgssymbollayerv2.cpp index 64ff0bf401d..48bdb763422 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.cpp +++ b/src/core/symbology-ng/qgssymbollayerv2.cpp @@ -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(); diff --git a/src/core/symbology-ng/qgssymbollayerv2.h b/src/core/symbology-ng/qgssymbollayerv2.h index 910a3b31818..611365a3c74 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.h +++ b/src/core/symbology-ng/qgssymbollayerv2.h @@ -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 ) @@ -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; From 14de6e6ddee53bc309de1ce383a1b048cb3b3c41 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 29 Nov 2013 16:28:21 +0100 Subject: [PATCH 31/38] Export layers to dxf in drawing order --- src/app/qgisapp.cpp | 8 +- src/app/qgsdxfexportdialog.cpp | 10 +-- src/app/qgsdxfexportdialog.h | 2 +- src/ui/qgsdxfexportdialogbase.ui | 148 ++++++++++++++----------------- 4 files changed, 81 insertions(+), 87 deletions(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index a754f3adb7a..c72055b5174 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -3802,7 +3802,13 @@ void QgisApp::fileSaveAs() void QgisApp::dxfExport() { - QgsDxfExportDialog d( QgsMapLayerRegistry::instance()->mapLayers().keys() ); + QgsLegend* mapLegend = legend(); + if ( !mapLegend ) + { + return; + } + + QgsDxfExportDialog d( mapLegend->layers() ); if ( d.exec() == QDialog::Accepted ) { QgsDxfExport dxfExport; diff --git a/src/app/qgsdxfexportdialog.cpp b/src/app/qgsdxfexportdialog.cpp index 2a9b4bf5bd6..69448339fdb 100644 --- a/src/app/qgsdxfexportdialog.cpp +++ b/src/app/qgsdxfexportdialog.cpp @@ -6,22 +6,22 @@ #include #include -QgsDxfExportDialog::QgsDxfExportDialog( const QList& layerKeys, QWidget* parent, Qt::WindowFlags f ): QDialog( parent, f ) +QgsDxfExportDialog::QgsDxfExportDialog( const QList& layerKeys, QWidget* parent, Qt::WindowFlags f ): QDialog( parent, f ) { setupUi( this ); connect( mFileLineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( setOkEnabled() ) ); connect( this, SIGNAL( accepted() ), this, SLOT( saveSettings() ) ); - QList::const_iterator layerIt = layerKeys.constBegin(); + QList::const_iterator layerIt = layerKeys.constBegin(); for ( ; layerIt != layerKeys.constEnd(); ++layerIt ) { - QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( *layerIt ); + QgsMapLayer* layer = *layerIt; if ( layer ) { if ( layer->type() == QgsMapLayer::VectorLayer ) { QListWidgetItem* layerItem = new QListWidgetItem( layer->name() ); - layerItem->setData( Qt::UserRole, *layerIt ); + layerItem->setData( Qt::UserRole, layer->id() ); layerItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ); layerItem->setCheckState( Qt::Checked ); mLayersListWidget->addItem( layerItem ); @@ -52,7 +52,7 @@ QList QgsDxfExportDialog::layers() const QListWidgetItem* currentItem = mLayersListWidget->item( i ); if ( currentItem->checkState() == Qt::Checked ) { - layerKeyList.append( currentItem->data( Qt::UserRole ).toString() ); + layerKeyList.prepend( currentItem->data( Qt::UserRole ).toString() ); } } return layerKeyList; diff --git a/src/app/qgsdxfexportdialog.h b/src/app/qgsdxfexportdialog.h index 5e75b9e3cd7..564428a751e 100644 --- a/src/app/qgsdxfexportdialog.h +++ b/src/app/qgsdxfexportdialog.h @@ -8,7 +8,7 @@ class QgsDxfExportDialog: public QDialog, private Ui::QgsDxfExportDialogBase { Q_OBJECT public: - QgsDxfExportDialog( const QList& layerKeys, QWidget * parent = 0, Qt::WindowFlags f = 0 ); + QgsDxfExportDialog( const QList& layerKeys, QWidget * parent = 0, Qt::WindowFlags f = 0 ); ~QgsDxfExportDialog(); QList layers() const; diff --git a/src/ui/qgsdxfexportdialogbase.ui b/src/ui/qgsdxfexportdialogbase.ui index 592d48d3906..283767950d3 100644 --- a/src/ui/qgsdxfexportdialogbase.ui +++ b/src/ui/qgsdxfexportdialogbase.ui @@ -6,97 +6,85 @@ 0 0 - 373 - 288 + 377 + 292 DXF export - - - - 20 - 260 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 10 - 10 - 361 - 247 - - - - - - - - - - Symbology mode - - - - - - - Symbology scale - - - - - - - Save as - - - - - - - ... - - - - - - + + + + + + + + - No symbology + Symbology mode - - + + + + - Feature symbology + Symbology scale - - + + + + - Symbol layer symbology + Save as - - - - - - - - - - - + + + + + + ... + + + + + + + + No symbology + + + + + Feature symbology + + + + + Symbol layer symbology + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + From ef3eee2daa9f568f6a10163a6a31c42d33c321f4 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 5 Dec 2013 09:34:18 +0100 Subject: [PATCH 32/38] Linestyles for Qt pen styles --- src/core/dxf/qgsdxfexport.cpp | 149 +++++++++++++++++++++++++++++----- src/core/dxf/qgsdxfexport.h | 11 ++- 2 files changed, 137 insertions(+), 23 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index e14f6fd790d..8c3be2f42ea 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -20,6 +20,7 @@ #include "qgspoint.h" #include "qgsrendererv2.h" #include "qgssymbollayerv2.h" +#include "qgsfillsymbollayerv2.h" #include "qgslinesymbollayerv2.h" #include "qgsvectorlayer.h" #include @@ -427,18 +428,10 @@ void QgsDxfExport::writeTables() mLineStyles.clear(); writeGroup( 0, "TABLE" ); writeGroup( 2, "LTYPE" ); - writeGroup( 70, nLineTypes( slList ) + 1 ); + writeGroup( 70, nLineTypes( slList ) + 5 ); - //add continuous style as default - writeGroup( 0, "LTYPE" ); - writeGroup( 2, "CONTINUOUS" ); - writeGroup( 70, 64 ); - writeGroup( 3, "Defaultstyle" ); - writeGroup( 72, 65 ); - writeGroup( 73, 0 ); - writeGroup( 40, 0.0 ); - - //add symbol layer linestyles + writeDefaultLinestyles(); + //add custom linestyles QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >::const_iterator slIt = slList.constBegin(); for ( ; slIt != slList.constEnd(); ++slIt ) { @@ -829,15 +822,7 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, const QString& layer, cons { int c = colorFromSymbolLayer( symbolLayer ); double width = widthFromSymbolLayer( symbolLayer ); - QString lineStyleName = "CONTINUOUS"; - QHash< const QgsSymbolLayerV2*, QString >::const_iterator lineTypeIt = mLineStyles.find( symbolLayer ); - if ( lineTypeIt != mLineStyles.constEnd() ) - { - lineStyleName = lineTypeIt.value(); - } - - //todo: write point symbols as blocks - + QString lineStyleName = lineStyleFromSymbolLayer( symbolLayer ); QGis::WkbType geometryType = geom->wkbType(); //single point @@ -922,7 +907,7 @@ int QgsDxfExport::colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) return closestColorMatch( c.rgba() ); } -double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) +double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) const { //line symbol layer has width and width units if ( symbolLayer && symbolLayer->type() == QgsSymbolV2::Line ) @@ -938,6 +923,36 @@ double QgsDxfExport::widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) //mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) } +QString QgsDxfExport::lineStyleFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) +{ + QString lineStyleName = "CONTINUOUS"; + if ( !symbolLayer ) + { + return lineStyleName; + } + + QHash< const QgsSymbolLayerV2*, QString >::const_iterator lineTypeIt = mLineStyles.find( symbolLayer ); + if ( lineTypeIt != mLineStyles.constEnd() ) + { + lineStyleName = lineTypeIt.value(); + } + else + { + //simple line and simple fill have pen style member + if ( symbolLayer->layerType() == "SimpleLine" ) + { + const QgsSimpleLineSymbolLayerV2* sl = static_cast< const QgsSimpleLineSymbolLayerV2* >( symbolLayer ); + return lineNameFromPenStyle( sl->penStyle() ); + } + else if ( symbolLayer->layerType() == "SimpleFill" ) + { + const QgsSimpleFillSymbolLayerV2* sf = static_cast< const QgsSimpleFillSymbolLayerV2* >( symbolLayer ); + return lineNameFromPenStyle( sf->borderStyle() ); + } + } + return lineStyleName; +} + int QgsDxfExport::closestColorMatch( QRgb pixel ) { int idx = 0; @@ -1070,6 +1085,48 @@ QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > QgsDxfExport::symbolLayers() return symbolLayers; } +void QgsDxfExport::writeDefaultLinestyles() +{ + double das = dashSize(); + double dos = dotSize(); + double dss = dashSeparatorSize(); + + //continuous (Qt solid line) + writeGroup( 0, "LTYPE" ); + writeGroup( 2, "CONTINUOUS" ); + writeGroup( 70, 64 ); + writeGroup( 3, "Defaultstyle" ); + writeGroup( 72, 65 ); + writeGroup( 73, 0 ); + writeGroup( 40, 0.0 ); + + QVector dashVector( 2 ); + dashVector[0] = das; + dashVector[1] = dss; + writeLinestyle( "DASH", dashVector, QgsSymbolV2::MapUnit ); + + QVector dotVector( 2 ); + dotVector[0] = dos; + dotVector[1] = dss; + writeLinestyle( "DOT", dotVector, QgsSymbolV2::MapUnit ); + + QVector dashDotVector( 4 ); + dashDotVector[0] = das; + dashDotVector[1] = dss; + dashDotVector[2] = dos; + dashDotVector[3] = dss; + writeLinestyle( "DASHDOT", dashDotVector, QgsSymbolV2::MapUnit ); + + QVector dashDotDotVector( 6 ); + dashDotDotVector[0] = das; + dashDotDotVector[1] = dss; + dashDotDotVector[2] = dos; + dashDotDotVector[3] = dss; + dashDotDotVector[4] = dos; + dashDotDotVector[5] = dss; + writeLinestyle( "DASHDOTDOT", dashDotDotVector, QgsSymbolV2::MapUnit ); +} + void QgsDxfExport::writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ) { if ( !symbolLayer ) @@ -1155,6 +1212,56 @@ bool QgsDxfExport::hasDataDefinedProperties( const QgsSymbolLayerV2* sl, const Q return sl->hasDataDefinedProperties(); } +double QgsDxfExport::dashSize() const +{ + double size = mSymbologyScaleDenominator * 0.002; + return sizeToMapUnits( size ); +} + +double QgsDxfExport::dotSize() const +{ + double size = mSymbologyScaleDenominator * 0.0006; + return sizeToMapUnits( size ); +} + +double QgsDxfExport::dashSeparatorSize() const +{ + double size = mSymbologyScaleDenominator * 0.0006; + return sizeToMapUnits( size ); +} + +double QgsDxfExport::sizeToMapUnits( double s ) const +{ + double size = s; + if ( mMapUnits == QGis::Feet ) + { + size /= 0.3048; + } + else if ( mMapUnits == QGis::Degrees ) + { + size /= 111120; + } + return size; +} + +QString QgsDxfExport::lineNameFromPenStyle( Qt::PenStyle style ) +{ + switch ( style ) + { + case Qt::DashLine: + return "DASH"; + case Qt::DotLine: + return "DOT"; + case Qt::DashDotLine: + return "DASHDOT"; + case Qt::DashDotDotLine: + return "DASHDOTDOT"; + case Qt::SolidLine: + default: + return "CONTINUOUS"; + } +} + /******************************************************Test with AC_1018 methods***************************************************************/ void QgsDxfExport::writeHeaderAC1018( QTextStream& stream ) diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index 7ace900b1d8..9bebde5c7f5 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -108,6 +108,7 @@ class QgsDxfExport void writePoint( const QgsPoint& pt, const QString& layer, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ); void writeVertex( const QgsPoint& pt, const QString& layer ); + void writeDefaultLinestyles(); void writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ); void writeLinestyle( const QString& styleName, const QVector& pattern, QgsSymbolV2::OutputUnit u ); @@ -129,8 +130,9 @@ class QgsDxfExport double scaleToMapUnits( double value, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits ) const; //returns dxf palette index from symbol layer color - int colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); - double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); + static int colorFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); + double widthFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ) const; + QString lineStyleFromSymbolLayer( const QgsSymbolLayerV2* symbolLayer ); //functions for dxf palette static int color_distance( QRgb p1, int index ); @@ -144,6 +146,11 @@ class QgsDxfExport QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2* > > symbolLayers(); static int nLineTypes( const QList< QPair< QgsSymbolLayerV2*, QgsSymbolV2*> >& symbolLayers ); static bool hasDataDefinedProperties( const QgsSymbolLayerV2* sl, const QgsSymbolV2* symbol ); + double dashSize() const; + double dotSize() const; + double dashSeparatorSize() const; + double sizeToMapUnits( double s ) const; + static QString lineNameFromPenStyle( Qt::PenStyle style ); }; #endif // QGSDXFEXPORT_H From 3fed0d0755a518395d136b6a608e89cda557de2d Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 5 Dec 2013 16:12:13 +0100 Subject: [PATCH 33/38] Fix rotation for svg markers exported to dxf --- src/core/dxf/qgsdxfexport.cpp | 2 +- src/core/symbology-ng/qgsmarkersymbollayerv2.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 8c3be2f42ea..18511296f6e 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -490,7 +490,7 @@ void QgsDxfExport::writeBlocks() } writeGroup( 0, "BLOCK" ); writeGroup( 8, 0 ); - QString blockName = QString( "symbolLayer%1" ).arg( mBlockCounter ); + QString blockName = QString( "symbolLayer%1" ).arg( mBlockCounter++ ); writeGroup( 2, blockName ); writeGroup( 70, 64 ); diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index c4ba453e689..a9efca334a1 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -1285,9 +1285,14 @@ void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale QPainter p; p.begin( &pd ); - p.rotate( angle ); - pd.setShift( shift - QPointF( halfSize, halfSize ) ); - pd.setOutputSize( QRectF( 0, 0, size, size ) ); + if ( !qgsDoubleNear( angle, 0.0 ) ) + { + p.translate( r.defaultSize().width() / 2.0, r.defaultSize().height() / 2.0 ); + p.rotate( angle ); + p.translate( -r.defaultSize().width() / 2.0, -r.defaultSize().height() / 2.0 ); + } + pd.setShift( shift ); + pd.setOutputSize( QRectF( -halfSize, -halfSize, size, size ) ); pd.setLayer( layerName ); r.render( &p ); p.end(); From 642b0d5ee347b53391c2c6b182cbbb6d34ec2812 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Thu, 5 Dec 2013 16:47:48 +0100 Subject: [PATCH 34/38] Add copy constructor and assignment operator for QgsDxfExport --- python/CMakeLists.txt | 1 + src/core/dxf/qgsdxfexport.cpp | 17 +++++++++++++++++ src/core/dxf/qgsdxfexport.h | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 5bfb76a7e65..3ff27647251 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -38,6 +38,7 @@ INCLUDE_DIRECTORIES( ../src/core/pal ../src/core/composer ../src/core/diagram + ../src/core/dxf ../src/core/gps ../src/core/raster ../src/core/symbology-ng diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 18511296f6e..8ca3c32d9dc 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -291,6 +291,23 @@ QgsDxfExport::QgsDxfExport(): mSymbologyScaleDenominator( 1.0 ), mSymbologyExpor { } +QgsDxfExport::QgsDxfExport( const QgsDxfExport& dxfExport ) +{ + *this = dxfExport; +} + +QgsDxfExport& QgsDxfExport::operator=( const QgsDxfExport & dxfExport ) +{ + mLayers = dxfExport.mLayers; + mSymbologyScaleDenominator = dxfExport.mSymbologyScaleDenominator; + mSymbologyExport = dxfExport.mSymbologyExport; + mMapUnits = dxfExport.mMapUnits; + mSymbolLayerCounter = 0; //internal counter + mNextHandleId = 0; + mBlockCounter = 0; + return *this; +} + QgsDxfExport::~QgsDxfExport() { } diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index 9bebde5c7f5..e0cbc10b7da 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -40,7 +40,9 @@ class QgsDxfExport }; QgsDxfExport(); + QgsDxfExport( const QgsDxfExport& dxfExport ); ~QgsDxfExport(); + QgsDxfExport& operator=( const QgsDxfExport& dxfExport ); void addLayers( QList< QgsMapLayer* >& layers ) { mLayers = layers; } int writeToFile( QIODevice* d ); //maybe add progress dialog? //other parameters (e.g. scale, dpi)? @@ -84,8 +86,6 @@ class QgsDxfExport QTextStream mTextStream; - QVector mDxfColorPalette; - static double mDxfColors[][3]; int mSymbolLayerCounter; //internal counter From a75de2b81b8882b0d8bbb686b10707ca6bdb8758 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 6 Dec 2013 10:51:51 +0100 Subject: [PATCH 35/38] Draw default point symbol if dxf export not supported by marker symbol --- src/core/dxf/qgsdxfexport.cpp | 43 ++++++++++++++++--- src/core/dxf/qgsdxfexport.h | 4 +- .../symbology-ng/qgsmarkersymbollayerv2.cpp | 12 ++++-- .../symbology-ng/qgsmarkersymbollayerv2.h | 4 +- src/core/symbology-ng/qgssymbollayerv2.h | 4 +- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 8ca3c32d9dc..58222965488 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -700,7 +700,7 @@ void QgsDxfExport::endSection() writeGroup( 0, "ENDSEC" ); } -void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ) +void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, int color, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ) { #if 0 //debug: draw rectangle for debugging @@ -737,8 +737,12 @@ void QgsDxfExport::writePoint( const QgsPoint& pt, const QString& layer, const Q { QgsRenderContext ct; QgsSymbolV2RenderContext ctx( ct, QgsSymbolV2::MapUnit, symbol->alpha(), false, symbol->renderHints(), f ); - symbolLayer->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, msl->sizeUnit(), mMapUnits ), layer, &ctx, f, QPointF( pt.x(), pt.y() ) ); + if ( symbolLayer->writeDxf( *this, mapUnitScaleFactor( mSymbologyScaleDenominator, msl->sizeUnit(), mMapUnits ), layer, &ctx, f, QPointF( pt.x(), pt.y() ) ) ) + { + return; + } } + writePoint( layer, color, pt ); //write default point symbol } else { @@ -782,6 +786,16 @@ void QgsDxfExport::writeLine( const QgsPoint& pt1, const QgsPoint& pt2, const QS writePolyline( line, layer, lineStyleName, color, width, false ); } +void QgsDxfExport::writePoint( const QString& layer, int color, const QgsPoint& pt ) +{ + writeGroup( 0, "POINT" ); + writeGroup( 8, layer ); + writeGroup( 62, color ); + writeGroup( 10, pt.x() ); + writeGroup( 20, pt.y() ); + writeGroup( 30, 0.0 ); +} + void QgsDxfExport::writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 ) { writeGroup( 0, "SOLID" ); @@ -837,15 +851,34 @@ void QgsDxfExport::addFeature( const QgsFeature& fet, const QString& layer, cons QgsGeometry* geom = fet.geometry(); if ( geom ) { - int c = colorFromSymbolLayer( symbolLayer ); + int c = 0; + if ( mSymbologyExport != NoSymbology ) + { + c = colorFromSymbolLayer( symbolLayer ); + } double width = widthFromSymbolLayer( symbolLayer ); - QString lineStyleName = lineStyleFromSymbolLayer( symbolLayer ); + QString lineStyleName = "CONTINUOUS"; + if ( mSymbologyExport != NoSymbology ) + { + lineStyleFromSymbolLayer( symbolLayer ); + } QGis::WkbType geometryType = geom->wkbType(); //single point if ( geometryType == QGis::WKBPoint || geometryType == QGis::WKBPoint25D ) { - writePoint( geom->asPoint(), layer, &fet, symbolLayer, symbol ); + writePoint( geom->asPoint(), layer, c, &fet, symbolLayer, symbol ); + } + + //multipoint + if ( geometryType == QGis::WKBMultiPoint || geometryType == QGis::WKBMultiPoint25D ) + { + QgsMultiPoint multiPoint = geom->asMultiPoint(); + QgsMultiPoint::const_iterator it = multiPoint.constBegin(); + for ( ; it != multiPoint.constEnd(); ++it ) + { + writePoint( *it, layer, c, &fet, symbolLayer, symbol ); + } } //single line diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index e0cbc10b7da..61991975472 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -76,6 +76,8 @@ class QgsDxfExport //write line (as a polyline) void writeLine( const QgsPoint& pt1, const QgsPoint& pt2, const QString& layer, const QString& lineStyleName, int color, double width = -1 ); + void writePoint( const QString& layer, int color, const QgsPoint& pt ); + private: QList< QgsMapLayer* > mLayers; @@ -106,7 +108,7 @@ class QgsDxfExport void startSection(); void endSection(); - void writePoint( const QgsPoint& pt, const QString& layer, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ); + void writePoint( const QgsPoint& pt, const QString& layer, int color, const QgsFeature* f, const QgsSymbolLayerV2* symbolLayer, const QgsSymbolV2* symbol ); void writeVertex( const QgsPoint& pt, const QString& layer ); void writeDefaultLinestyles(); void writeSymbolLayerLinestyle( const QgsSymbolLayerV2* symbolLayer ); diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp index a9efca334a1..e6cd5f7186b 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.cpp @@ -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& shift ) const +bool 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; @@ -805,6 +805,11 @@ void QgsSimpleMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitSc 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() ) ); } + else + { + return false; + } + return true; } ////////// @@ -1212,7 +1217,7 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element return m; } -void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, +bool QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const { Q_UNUSED( layerName ); @@ -1221,7 +1226,7 @@ void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale QSvgRenderer r( mPath ); if ( !r.isValid() ) { - return; + return false; } QgsDxfPaintDevice pd( &e ); @@ -1296,6 +1301,7 @@ void QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScale pd.setLayer( layerName ); r.render( &p ); p.end(); + return true; } ////////// diff --git a/src/core/symbology-ng/qgsmarkersymbollayerv2.h b/src/core/symbology-ng/qgsmarkersymbollayerv2.h index 3f09df95aa9..d03c1c9fa05 100644 --- a/src/core/symbology-ng/qgsmarkersymbollayerv2.h +++ b/src/core/symbology-ng/qgsmarkersymbollayerv2.h @@ -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& shift = QPointF( 0.0, 0.0 ) ) const; + bool writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift = QPointF( 0.0, 0.0 ) ) const; protected: @@ -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& shift = QPointF( 0.0, 0.0 ) ) const; + bool 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; diff --git a/src/core/symbology-ng/qgssymbollayerv2.h b/src/core/symbology-ng/qgssymbollayerv2.h index 611365a3c74..c9533ee5276 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.h +++ b/src/core/symbology-ng/qgssymbollayerv2.h @@ -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& 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 ); } + virtual bool 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 ); return false; } protected: QgsSymbolLayerV2( QgsSymbolV2::SymbolType type, bool locked = false ) From ebbb976e8a1716b0e0cfa30ee51c6d24d69a87d0 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 6 Dec 2013 11:17:28 +0100 Subject: [PATCH 36/38] Show success / failure of dxf export in message bar --- src/app/qgisapp.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index c72055b5174..270ada3ec8e 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -3837,7 +3837,14 @@ void QgisApp::dxfExport() } } QFile dxfFile( d.saveFile() ); - dxfExport.writeToFile( &dxfFile ); + if ( dxfExport.writeToFile( &dxfFile ) == 0 ) + { + messageBar()->pushMessage( tr( "DXF export completed" ), QgsMessageBar::INFO, 4 ); + } + else + { + messageBar()->pushMessage( tr( "DXF export failed" ), QgsMessageBar::CRITICAL, 4 ); + } } } From 668403ace5e86f7aed9a6782a38d8e3c270180b6 Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 6 Dec 2013 13:23:52 +0100 Subject: [PATCH 37/38] Write dxf circle --- src/core/dxf/qgsdxfexport.cpp | 11 +++++++++++ src/core/dxf/qgsdxfexport.h | 4 +++- src/core/dxf/qgsdxfpaintdevice.h | 2 +- src/core/dxf/qgsdxfpaintengine.cpp | 8 +++++++- src/core/dxf/qgsdxfpaintengine.h | 2 +- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/core/dxf/qgsdxfexport.cpp b/src/core/dxf/qgsdxfexport.cpp index 58222965488..fd6b09a2817 100644 --- a/src/core/dxf/qgsdxfexport.cpp +++ b/src/core/dxf/qgsdxfexport.cpp @@ -796,6 +796,17 @@ void QgsDxfExport::writePoint( const QString& layer, int color, const QgsPoint& writeGroup( 30, 0.0 ); } +void QgsDxfExport::writeCircle( const QString& layer, int color, const QgsPoint& pt, double radius ) +{ + writeGroup( 0, "CIRCLE" ); + writeGroup( 8, layer ); + writeGroup( 62, color ); + writeGroup( 10, pt.x() ); + writeGroup( 20, pt.y() ); + writeGroup( 30, 0 ); + writeGroup( 40, radius ); +} + void QgsDxfExport::writeSolid( const QString& layer, int color, const QgsPoint& pt1, const QgsPoint& pt2, const QgsPoint& pt3, const QgsPoint& pt4 ) { writeGroup( 0, "SOLID" ); diff --git a/src/core/dxf/qgsdxfexport.h b/src/core/dxf/qgsdxfexport.h index 61991975472..36ad1105a29 100644 --- a/src/core/dxf/qgsdxfexport.h +++ b/src/core/dxf/qgsdxfexport.h @@ -29,7 +29,7 @@ class QgsPoint; class QgsSymbolLayerV2; class QIODevice; -class QgsDxfExport +class CORE_EXPORT QgsDxfExport { public: enum SymbologyExport @@ -78,6 +78,8 @@ class QgsDxfExport void writePoint( const QString& layer, int color, const QgsPoint& pt ); + void writeCircle( const QString& layer, int color, const QgsPoint& pt, double radius ); + private: QList< QgsMapLayer* > mLayers; diff --git a/src/core/dxf/qgsdxfpaintdevice.h b/src/core/dxf/qgsdxfpaintdevice.h index eb13eb6c98b..6317005b1a8 100644 --- a/src/core/dxf/qgsdxfpaintdevice.h +++ b/src/core/dxf/qgsdxfpaintdevice.h @@ -26,7 +26,7 @@ class QPaintEngine; /**A paint device for drawing into dxf files*/ -class QgsDxfPaintDevice: public QPaintDevice +class CORE_EXPORT QgsDxfPaintDevice: public QPaintDevice { public: QgsDxfPaintDevice( QgsDxfExport* dxf ); diff --git a/src/core/dxf/qgsdxfpaintengine.cpp b/src/core/dxf/qgsdxfpaintengine.cpp index 3433d19ec61..ede4c67b7ad 100644 --- a/src/core/dxf/qgsdxfpaintengine.cpp +++ b/src/core/dxf/qgsdxfpaintengine.cpp @@ -103,7 +103,13 @@ void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount ) void QgsDxfPaintEngine::drawEllipse( const QRectF& rect ) { - //map to circle in case of square? + QPoint midPoint(( rect.left() + rect.right() ) / 2.0, ( rect.top() + rect.bottom() ) / 2.0 ); + + //a circle + if ( qgsDoubleNear( rect.width(), rect.height() ) ) + { + mDxf->writeCircle( mLayer, currentPenColor(), toDxfCoordinates( midPoint ), rect.width() / 2.0 ); + } //todo: create polyline for real ellises } diff --git a/src/core/dxf/qgsdxfpaintengine.h b/src/core/dxf/qgsdxfpaintengine.h index 7374f91b2ad..ea7a6d16d23 100644 --- a/src/core/dxf/qgsdxfpaintengine.h +++ b/src/core/dxf/qgsdxfpaintengine.h @@ -24,7 +24,7 @@ class QgsDxfExport; class QgsDxfPaintDevice; class QgsPoint; -class QgsDxfPaintEngine: public QPaintEngine +class CORE_EXPORT QgsDxfPaintEngine: public QPaintEngine { public: QgsDxfPaintEngine( const QgsDxfPaintDevice* dxfDevice, QgsDxfExport* dxf ); From 0239b4d6c7a9f1ce5c070ad225250f57421ab7bd Mon Sep 17 00:00:00 2001 From: Marco Hugentobler Date: Fri, 6 Dec 2013 15:05:05 +0100 Subject: [PATCH 38/38] Dxf export for ellipse symbol layer --- .../symbology-ng/qgsellipsesymbollayerv2.cpp | 137 ++++++++++++++++++ .../symbology-ng/qgsellipsesymbollayerv2.h | 2 + 2 files changed, 139 insertions(+) diff --git a/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp b/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp index 814dfd5bd7f..a0f4bed2a18 100644 --- a/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp +++ b/src/core/symbology-ng/qgsellipsesymbollayerv2.cpp @@ -13,6 +13,7 @@ * * ***************************************************************************/ #include "qgsellipsesymbollayerv2.h" +#include "qgsdxfexport.h" #include "qgsexpression.h" #include "qgsfeature.h" #include "qgsrendercontext.h" @@ -474,3 +475,139 @@ QgsSymbolV2::OutputUnit QgsEllipseSymbolLayerV2::outputUnit() const } return unit; } + +bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const +{ + //width + double symbolWidth = mSymbolWidth; + QgsExpression* widthExpression = expression( "width" ); + if ( widthExpression ) //1. priority: data defined setting on symbol layer level + { + symbolWidth = widthExpression->evaluate( const_cast( f ) ).toDouble(); + } + else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level + { + symbolWidth = mSize; + } + if ( mSymbolWidthUnit == QgsSymbolV2::MM ) + { + symbolWidth *= mmMapUnitScaleFactor; + } + + //height + double symbolHeight = mSymbolHeight; + QgsExpression* heightExpression = expression( "height" ); + if ( heightExpression ) //1. priority: data defined setting on symbol layer level + { + symbolHeight = heightExpression->evaluate( const_cast( f ) ).toDouble(); + } + else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level + { + symbolHeight = mSize; + } + if ( mSymbolHeightUnit == QgsSymbolV2::MM ) + { + symbolHeight *= mmMapUnitScaleFactor; + } + + //outline width + double outlineWidth = mOutlineWidth; + QgsExpression* outlineWidthExpression = expression( "outline_width" ); + if ( outlineWidthExpression ) + { + outlineWidth = outlineWidthExpression->evaluate( const_cast( context->feature() ) ).toDouble(); + } + if ( mOutlineWidthUnit == QgsSymbolV2::MM ) + { + outlineWidth *= outlineWidth; + } + + //color + QColor c = mFillColor; + QgsExpression* fillColorExpression = expression( "fill_color" ); + if ( fillColorExpression ) + { + c = QColor( fillColorExpression->evaluate( const_cast( context->feature() ) ).toString() ); + } + int colorIndex = e.closestColorMatch( c.rgb() ); + + //symbol name + QString symbolName = mSymbolName; + QgsExpression* symbolNameExpression = expression( "symbol_name" ); + if ( symbolNameExpression ) + { + QgsExpression* symbolNameExpression = expression( "symbol_name" ); + symbolName = symbolNameExpression->evaluate( const_cast( context->feature() ) ).toString(); + } + + //offset + double offsetX = 0; + double offsetY = 0; + markerOffset( *context, offsetX, offsetY ); + QPointF off( offsetX, offsetY ); + + //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) + double rotation = 0.0; + QgsExpression* rotationExpression = expression( "rotation" ); + if ( rotationExpression ) + { + rotation = rotationExpression->evaluate( const_cast( context->feature() ) ).toDouble(); + } + else if ( !qgsDoubleNear( mAngle, 0.0 ) ) + { + rotation = mAngle; + } + rotation = -rotation; //rotation in Qt is counterclockwise + if ( rotation ) + off = _rotatedOffset( off, rotation ); + + QTransform t; + t.translate( shift.x() + offsetX, shift.y() + offsetY ); + + if ( rotation != 0 ) + t.rotate( rotation ); + + double halfWidth = symbolWidth / 2.0; + double halfHeight = symbolHeight / 2.0; + + if ( symbolName == "circle" ) + { + //soon... + } + else if ( symbolName == "rectangle" ) + { + QPointF pt1( t.map( QPointF( -halfWidth, -halfHeight ) ) ); + QPointF pt2( t.map( QPointF( halfWidth, -halfHeight ) ) ); + QPointF pt3( t.map( QPointF( -halfWidth, halfHeight ) ) ); + QPointF pt4( t.map( QPointF( halfWidth, halfHeight ) ) ); + e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) ); + return true; + } + else if ( symbolName == "cross" ) + { + QgsPolyline line1( 2 ); + QPointF pt1( t.map( QPointF( -halfWidth, 0 ) ) ); + QPointF pt2( t.map( QPointF( halfWidth, 0 ) ) ); + line1[0] = QgsPoint( pt1.x(), pt1.y() ); + line1[1] = QgsPoint( pt2.x(), pt2.y() ); + e.writePolyline( line1, layerName, "CONTINUOUS", colorIndex, outlineWidth, false ); + QgsPolyline line2( 2 ); + QPointF pt3( t.map( QPointF( 0, halfHeight ) ) ); + QPointF pt4( t.map( QPointF( 0, -halfHeight ) ) ); + line2[0] = QgsPoint( pt3.x(), pt3.y() ); + line2[1] = QgsPoint( pt3.x(), pt3.y() ); + e.writePolyline( line2, layerName, "CONTINUOUS", colorIndex, outlineWidth, false ); + return true; + } + else if ( symbolName == "triangle" ) + { + QPointF pt1( t.map( QPointF( -halfWidth, -halfHeight ) ) ); + QPointF pt2( t.map( QPointF( halfWidth, -halfHeight ) ) ); + QPointF pt3( t.map( QPointF( 0, halfHeight ) ) ); + QPointF pt4( t.map( QPointF( 0, halfHeight ) ) ); + e.writeSolid( layerName, colorIndex, QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ), QgsPoint( pt4.x(), pt4.y() ) ); + return true; + } + + return false; //soon... +} diff --git a/src/core/symbology-ng/qgsellipsesymbollayerv2.h b/src/core/symbology-ng/qgsellipsesymbollayerv2.h index c6ff8b20483..78c2755b6c5 100644 --- a/src/core/symbology-ng/qgsellipsesymbollayerv2.h +++ b/src/core/symbology-ng/qgsellipsesymbollayerv2.h @@ -40,6 +40,8 @@ class CORE_EXPORT QgsEllipseSymbolLayerV2: public QgsMarkerSymbolLayerV2 void toSld( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const; void writeSldMarker( QDomDocument& doc, QDomElement &element, QgsStringMap props ) const; + bool writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift = QPointF( 0.0, 0.0 ) ) const; + void setSymbolName( const QString& name ) { mSymbolName = name; } QString symbolName() const { return mSymbolName; }