Use scale for symbology export (if symbol measures are defined in map units)

This commit is contained in:
Marco Hugentobler 2012-12-21 16:28:34 +01:00
parent 3a63b7baba
commit 1a79041af2
18 changed files with 184 additions and 127 deletions

View File

@ -168,9 +168,9 @@ class QgsSymbolLayerV2Utils
static QColor parseColor( QString colorStr );
/**Returns the line width scale factor depending on the unit and the paint device*/
static double lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
static double lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Creates a render context for a pixel based device*/
static QgsRenderContext createRenderContext( QPainter* p );

View File

@ -82,6 +82,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/../core/
${CMAKE_CURRENT_SOURCE_DIR}/../core/renderer
${CMAKE_CURRENT_SOURCE_DIR}/../core/raster
${CMAKE_CURRENT_SOURCE_DIR}/../core/symbology-ng
interpolation
${PROJ_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}

View File

@ -200,3 +200,8 @@ int QgsVectorLayerSaveAsDialog::symbologyExport() const
{
return mSymbologyExportComboBox->itemData( mSymbologyExportComboBox->currentIndex() ).toInt();
}
double QgsVectorLayerSaveAsDialog::scaleDenominator() const
{
return mScaleSpinBox->value();
}

View File

@ -46,6 +46,7 @@ class QgsVectorLayerSaveAsDialog : public QDialog, private Ui::QgsVectorLayerSav
1: Feature symbology
2: Symbol level symbology*/
int symbologyExport() const;
double scaleDenominator() const;
private slots:
void on_mFormatComboBox_currentIndexChanged( int idx );

View File

@ -4205,7 +4205,8 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection )
datasourceOptions, dialog->layerOptions(),
dialog->skipAttributeCreation(),
&newFilename,
( QgsVectorFileWriter::SymbologyExport )( dialog->symbologyExport() ) );
( QgsVectorFileWriter::SymbologyExport )( dialog->symbologyExport() ),
dialog->scaleDenominator() );
QApplication::restoreOverrideCursor();

View File

@ -25,7 +25,6 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsvectorfilewriter.h"
#include "qgsrendererv2.h"
#include "qgssymbolv2.h"
#include "qgssymbollayerv2.h"
#include <QFile>
@ -435,7 +434,7 @@ QString QgsVectorFileWriter::errorMessage()
return mErrorMessage;
}
bool QgsVectorFileWriter::addFeature( QgsFeature& feature, QgsFeatureRendererV2* renderer )
bool QgsVectorFileWriter::addFeature( QgsFeature& feature, QgsFeatureRendererV2* renderer, QGis::UnitType outputUnit )
{
// create the feature
OGRFeatureH poFeature = createFeature( feature );
@ -459,7 +458,8 @@ bool QgsVectorFileWriter::addFeature( QgsFeature& feature, QgsFeatureRendererV2*
{
continue;
}*/
currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle();//"@" + it.value();
double wScaleFactor = widthScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( wScaleFactor );//"@" + it.value();
if ( mSymbologyExport == FeatureSymbology )
{
@ -683,7 +683,8 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
const QStringList &layerOptions,
bool skipAttributeCreation,
QString *newFilename,
SymbologyExport symbologyExport )
SymbologyExport symbologyExport,
double symbologyScale )
{
QgsDebugMsg( "fileName = " + fileName );
const QgsCoordinateReferenceSystem* outputCRS;
@ -709,6 +710,7 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
QgsVectorFileWriter* writer =
new QgsVectorFileWriter( fileName, fileEncoding, skipAttributeCreation ? QgsFieldMap() : layer->pendingFields(), layer->wkbType(),
outputCRS, driverName, datasourceOptions, layerOptions, newFilename, symbologyExport );
writer->setSymbologyScaleDenominator( symbologyScale );
if ( newFilename )
{
@ -750,10 +752,10 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
}
//create symbol table if needed
/*if( writer->symbologyExport() != NoSymbology )
if ( writer->symbologyExport() != NoSymbology )
{
writer->createSymbolLayerTable( layer, writer->mDS );
}*/
//writer->createSymbolLayerTable( layer, writer->mDS );
}
if ( writer->symbologyExport() == SymbolLayerSymbology && layer->isUsingRendererV2() )
{
@ -770,6 +772,13 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
int n = 0, errors = 0;
//unit type
QGis::UnitType mapUnits = layer->crs().mapUnits();
if ( ct )
{
mapUnits = ct->destCRS().mapUnits();
}
// write all features
while ( layer->nextFeature( fet ) )
{
@ -803,7 +812,7 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
{
fet.clearAttributeMap();
}
if ( !writer->addFeature( fet, layer->rendererV2() ) )
if ( !writer->addFeature( fet, layer->rendererV2(), mapUnits ) )
{
WriterError err = writer->hasError();
if ( err != NoError && errorMessage )
@ -1165,7 +1174,7 @@ bool QgsVectorFileWriter::driverMetadata( QString driverName, QString &longName,
return true;
}
void QgsVectorFileWriter::createSymbolLayerTable( QgsVectorLayer* vl, OGRDataSourceH ds )
void QgsVectorFileWriter::createSymbolLayerTable( QgsVectorLayer* vl, const QgsCoordinateTransform* ct, OGRDataSourceH ds )
{
if ( !vl || !ds )
{
@ -1183,6 +1192,13 @@ void QgsVectorFileWriter::createSymbolLayerTable( QgsVectorLayer* vl, OGRDataSo
return;
}
//unit type
QGis::UnitType mapUnits = vl->crs().mapUnits();
if ( ct )
{
mapUnits = ct->destCRS().mapUnits();
}
mSymbolLayerTable.clear();
OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
@ -1197,7 +1213,8 @@ void QgsVectorFileWriter::createSymbolLayerTable( QgsVectorLayer* vl, OGRDataSo
for ( int i = 0; i < nLevels; ++i )
{
mSymbolLayerTable.insert(( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(), ( *symbolIt )->ogrFeatureStyle().toLocal8Bit() );
OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( widthScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits ) ).toLocal8Bit() );
++nTotalLevels;
}
}
@ -1217,6 +1234,13 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::exportFeaturesSymbolLevels
}
QHash< QgsSymbolV2*, QList<QgsFeature> > features;
//unit type
QGis::UnitType mapUnits = layer->crs().mapUnits();
if ( ct )
{
mapUnits = ct->destCRS().mapUnits();
}
//fetch features
QgsFeature fet;
QgsSymbolV2* featureSymbol = 0;
@ -1307,7 +1331,8 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::exportFeaturesSymbolLevels
continue;
}
QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle();
QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( widthScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(),
mapUnits ) );
if ( !styleString.isEmpty() )
{
OGR_F_SetStyleString( ogrFeature, styleString.toLocal8Bit().data() );
@ -1328,3 +1353,21 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::exportFeaturesSymbolLevels
return ( nErrors > 0 ) ? QgsVectorFileWriter::ErrFeatureWriteFailed : QgsVectorFileWriter::NoError;
}
double QgsVectorFileWriter::widthScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
{
if ( symbolUnits == QgsSymbolV2::MM )
{
return 1.0;
}
else
{
//conversion factor map units -> mm
if ( mapUnits == QGis::Meters )
{
return 1000 / scaleDenominator;
}
}
return 1.0; //todo: map units
}

View File

@ -21,6 +21,7 @@
#include "qgsvectorlayer.h"
#include "qgsfield.h"
#include "qgssymbolv2.h"
#include <QPair>
@ -104,7 +105,8 @@ class CORE_EXPORT QgsVectorFileWriter
const QStringList &layerOptions = QStringList(), // added in 1.6
bool skipAttributeCreation = false, // added in 1.6
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology //added in 2.0
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
double symbologyScale = 1.0 // added in 2.0
);
/** create shapefile and initialize it */
@ -144,7 +146,7 @@ class CORE_EXPORT QgsVectorFileWriter
QString errorMessage();
/** add feature to the currently opened shapefile */
bool addFeature( QgsFeature& feature, QgsFeatureRendererV2* renderer = 0 );
bool addFeature( QgsFeature& feature, QgsFeatureRendererV2* renderer = 0, QGis::UnitType outputUnit = QGis::Meters );
//! @note not available in python bindings
QMap<int, int> attrIdxToOgrIdx() { return mAttrIdxToOgrIdx; }
@ -161,6 +163,9 @@ class CORE_EXPORT QgsVectorFileWriter
SymbologyExport symbologyExport() const { return mSymbologyExport; }
void setSymbologyExport( SymbologyExport symExport ) { mSymbologyExport = symExport; }
double symbologyScaleDenominator() const { return mSymbologyScaleDenominator; }
void setSymbologyScaleDenominator( double d ) { mSymbologyScaleDenominator = d; }
protected:
//! @note not available in python bindings
OGRGeometryH createEmptyGeometry( QGis::WkbType wkbType );
@ -187,14 +192,18 @@ class CORE_EXPORT QgsVectorFileWriter
QMap< QgsSymbolLayerV2*, QString > mSymbolLayerTable;
/**Scale for symbology export (e.g. for symbols units in map units)*/
double mSymbologyScaleDenominator;
private:
static bool driverMetadata( QString driverName, QString &longName, QString &trLongName, QString &glob, QString &ext );
void createSymbolLayerTable( QgsVectorLayer* vl, OGRDataSourceH ds );
void createSymbolLayerTable( QgsVectorLayer* vl, const QgsCoordinateTransform* ct, OGRDataSourceH ds );
OGRFeatureH createFeature( QgsFeature& feature );
bool writeFeature( OGRLayerH layer, OGRFeatureH feature );
/**Writes features considering symbol level order*/
WriterError exportFeaturesSymbolLevels( QgsVectorLayer* layer, const QgsCoordinateTransform* ct, QString* errorMessage = 0 );
double widthScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits );
};
#endif

View File

@ -195,7 +195,7 @@ void QgsSimpleLineSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
}
}
QString QgsSimpleLineSymbolLayerV2::ogrFeatureStyle() const
QString QgsSimpleLineSymbolLayerV2::ogrFeatureStyle( double widthScaleFactor ) const
{
QString symbolStyle;
@ -205,7 +205,7 @@ QString QgsSimpleLineSymbolLayerV2::ogrFeatureStyle() const
symbolStyle.append( mPen.color().name() );
symbolStyle.append( ",w:" );
//dxf driver writes ground units as mm? Should probably be changed in ogr
symbolStyle.append( QString::number( mWidth ) );
symbolStyle.append( QString::number( mWidth * widthScaleFactor ) );
symbolStyle.append( "g" );
symbolStyle.append( ")" );

View File

@ -56,7 +56,7 @@ class CORE_EXPORT QgsSimpleLineSymbolLayerV2 : public QgsLineSymbolLayerV2
void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;
QString ogrFeatureStyle() const;
QString ogrFeatureStyle( double widthScaleFactor ) const;
// new stuff

View File

@ -480,7 +480,7 @@ void QgsSimpleMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElemen
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, mOffset );
}
QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle() const
QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle( double widthScaleFactor ) const
{
#if 0
QString ogrType = "3"; //default is circle

View File

@ -62,7 +62,7 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
void writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;
QString ogrFeatureStyle() const;
QString ogrFeatureStyle( double widthScaleFactor ) const;
QString name() const { return mName; }
void setName( QString name ) { mName = name; }

View File

@ -54,7 +54,7 @@ class CORE_EXPORT QgsSymbolLayerV2
virtual void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
{ Q_UNUSED( props ); element.appendChild( doc.createComment( QString( "SymbolLayerV2 %1 not implemented yet" ).arg( layerType() ) ) ); }
virtual QString ogrFeatureStyle() const { return QString(); }
virtual QString ogrFeatureStyle( double widthScaleFactor ) const { Q_UNUSED( widthScaleFactor ); return QString(); }
virtual QgsStringMap properties() const = 0;

View File

@ -2455,7 +2455,7 @@ QColor QgsSymbolLayerV2Utils::parseColor( QString colorStr )
return QColor( p[0].toInt(), p[1].toInt(), p[2].toInt() );
}
double QgsSymbolLayerV2Utils::lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
double QgsSymbolLayerV2Utils::lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
{
if ( u == QgsSymbolV2::MM )
@ -2476,7 +2476,7 @@ double QgsSymbolLayerV2Utils::lineWidthScaleFactor( QgsRenderContext& c, QgsSymb
}
}
double QgsSymbolLayerV2Utils::pixelSizeScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
double QgsSymbolLayerV2Utils::pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
{
if ( u == QgsSymbolV2::MM )
{

View File

@ -203,9 +203,9 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
static QColor parseColor( QString colorStr );
/**Returns the line width scale factor depending on the unit and the paint device*/
static double lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
static double lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Creates a render context for a pixel based device*/
static QgsRenderContext createRenderContext( QPainter* p );

View File

@ -314,27 +314,6 @@ void QgsSymbolV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap p
}
}
QString QgsSymbolV2::ogrFeatureStyle() const
{
QString styleString;
QString currentStyleString;
for ( QgsSymbolLayerV2List::const_iterator it = mLayers.constBegin(); it != mLayers.constEnd(); ++it )
{
currentStyleString = ( *it )->ogrFeatureStyle();
if ( currentStyleString.isEmpty() )
{
continue;
}
if ( it != mLayers.constBegin() )
{
styleString.append( ";" );
}
styleString.append( currentStyleString );
}
return styleString;
}
QgsSymbolLayerV2List QgsSymbolV2::cloneLayers() const
{
QgsSymbolLayerV2List lst;

View File

@ -113,9 +113,6 @@ class CORE_EXPORT QgsSymbolV2
void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;
/**Returns the OGR feature style string for the symbol*/
QString ogrFeatureStyle() const;
OutputUnit outputUnit() const { return mOutputUnit; }
void setOutputUnit( OutputUnit u ) { mOutputUnit = u; }

View File

@ -11,6 +11,7 @@ QT4_WRAP_CPP(OGR_MOC_SRCS ${OGR_MOC_HDRS})
INCLUDE_DIRECTORIES(
.
../../core
${CMAKE_CURRENT_SOURCE_DIR}/../../core/symbology-ng
${GDAL_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
)

View File

@ -14,8 +14,85 @@
<string>Save vector layer as...</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mFormatComboBox"/>
<item row="1" column="1">
<widget class="QLineEdit" name="leFilename">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="browseCRS">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Encoding</string>
</property>
<property name="buddy">
<cstring>mEncodingComboBox</cstring>
</property>
</widget>
</item>
<item row="5" column="0" rowspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRS</string>
</property>
<property name="buddy">
<cstring>leCRS</cstring>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mEncodingComboBox"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="mSymbologyExportLabel">
<property name="text">
<string>Symbology export</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Save as</string>
</property>
<property name="buddy">
<cstring>leFilename</cstring>
</property>
</widget>
</item>
<item row="7" column="1" colspan="2">
<widget class="QComboBox" name="mSymbologyExportComboBox"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="browseFilename">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="leCRS">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="mCRSSelection"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
@ -27,7 +104,7 @@
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<item row="10" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -37,7 +114,10 @@
</property>
</widget>
</item>
<item row="8" column="0" colspan="3">
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mFormatComboBox"/>
</item>
<item row="9" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>OGR creation options</string>
@ -89,83 +169,23 @@
</layout>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="mCRSSelection"/>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="leCRS">
<property name="enabled">
<bool>false</bool>
<item row="8" column="1" colspan="2">
<widget class="QSpinBox" name="mScaleSpinBox">
<property name="prefix">
<string>1:</string>
</property>
<property name="readOnly">
<bool>true</bool>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>50000</number>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mEncodingComboBox"/>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="browseCRS">
<item row="8" column="0">
<widget class="QLabel" name="mScaleLabel">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="browseFilename">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Save as</string>
</property>
<property name="buddy">
<cstring>leFilename</cstring>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Encoding</string>
</property>
<property name="buddy">
<cstring>mEncodingComboBox</cstring>
</property>
</widget>
</item>
<item row="5" column="0" rowspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRS</string>
</property>
<property name="buddy">
<cstring>leCRS</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leFilename">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="7" column="1" colspan="2">
<widget class="QComboBox" name="mSymbologyExportComboBox"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="mSymbologyExportLabel">
<property name="text">
<string>Symbology export</string>
<string>Scale</string>
</property>
</widget>
</item>