mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[FEATURE]: merge dxf_export branch
This commit is contained in:
commit
561f01c0c2
@ -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
|
||||
|
@ -27,6 +27,7 @@
|
||||
%Include qgsdatasourceuri.sip
|
||||
%Include qgsdbfilterproxymodel.sip
|
||||
%Include qgsdistancearea.sip
|
||||
%Include qgsdxfexport.sip
|
||||
%Include qgseditorwidgetconfig.sip
|
||||
%Include qgserror.sip
|
||||
%Include qgsexpression.sip
|
||||
|
29
python/core/qgsdxfexport.sip
Normal file
29
python/core/qgsdxfexport.sip
Normal file
@ -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 <qgsdxfexport.h>
|
||||
%End
|
||||
public:
|
||||
QgsDxfExport();
|
||||
~QgsDxfExport();
|
||||
|
||||
void addLayers( QList< QgsMapLayer* >& layers );
|
||||
int writeToFile( QIODevice* d );
|
||||
};
|
@ -157,7 +157,7 @@ class QgsMarkerSymbolLayerV2 : 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 );
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,7 @@ SET(QGIS_APP_SRCS
|
||||
qgsdecorationscalebardialog.cpp
|
||||
qgsdecorationgrid.cpp
|
||||
qgsdecorationgriddialog.cpp
|
||||
qgsdxfexportdialog.cpp
|
||||
qgsformannotationdialog.cpp
|
||||
qgshtmlannotationdialog.cpp
|
||||
qgsdelattrdialog.cpp
|
||||
@ -190,6 +191,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
qgsdelattrdialog.h
|
||||
qgsdiagramproperties.h
|
||||
qgsdisplayangle.h
|
||||
qgsdxfexportdialog.h
|
||||
qgsfeatureaction.h
|
||||
qgsfieldcalculator.h
|
||||
qgsfieldsproperties.h
|
||||
@ -423,7 +425,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 ../gui/editorwidgets ../gui/editorwidgets/core
|
||||
../plugins
|
||||
../python
|
||||
|
@ -116,6 +116,8 @@
|
||||
#include "qgscustomprojectiondialog.h"
|
||||
#include "qgsdatasourceuri.h"
|
||||
#include "qgsdatumtransformdialog.h"
|
||||
#include "qgsdxfexport.h"
|
||||
#include "qgsdxfexportdialog.h"
|
||||
#include "qgsdecorationcopyright.h"
|
||||
#include "qgsdecorationnortharrow.h"
|
||||
#include "qgsdecorationscalebar.h"
|
||||
@ -958,6 +960,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
|
||||
|
||||
@ -3808,6 +3811,54 @@ void QgisApp::fileSaveAs()
|
||||
}
|
||||
} // QgisApp::fileSaveAs
|
||||
|
||||
void QgisApp::dxfExport()
|
||||
{
|
||||
QgsLegend* mapLegend = legend();
|
||||
if ( !mapLegend )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsDxfExportDialog d( mapLegend->layers() );
|
||||
if ( d.exec() == QDialog::Accepted )
|
||||
{
|
||||
QgsDxfExport dxfExport;
|
||||
|
||||
QList<QgsMapLayer*> layerList;
|
||||
QList<QString> layerIdList = d.layers();
|
||||
QList<QString>::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() );
|
||||
if ( mapCanvas() )
|
||||
{
|
||||
QgsMapRenderer* r = mapCanvas()->mapRenderer();
|
||||
if ( r )
|
||||
{
|
||||
dxfExport.setMapUnits( r->mapUnits() );
|
||||
}
|
||||
}
|
||||
QFile dxfFile( d.saveFile() );
|
||||
if ( dxfExport.writeToFile( &dxfFile ) == 0 )
|
||||
{
|
||||
messageBar()->pushMessage( tr( "DXF export completed" ), QgsMessageBar::INFO, 4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
messageBar()->pushMessage( tr( "DXF export failed" ), QgsMessageBar::CRITICAL, 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Open the project file corresponding to the
|
||||
// path at the given index in mRecentProjectPaths
|
||||
void QgisApp::openProject( QAction *action )
|
||||
@ -7430,7 +7481,7 @@ QMenu* QgisApp::getPluginMenu( QString menuName )
|
||||
}
|
||||
// It doesn't exist, so create
|
||||
QMenu *menu = new QMenu( menuName, this );
|
||||
menu->setObjectName( menuName.normalized(QString::NormalizationForm_KD).remove(QRegExp("[^a-zA-Z]")) );
|
||||
menu->setObjectName( menuName.normalized( QString::NormalizationForm_KD ).remove( QRegExp( "[^a-zA-Z]" ) ) );
|
||||
// Where to put it? - we worked that out above...
|
||||
mPluginMenu->insertMenu( before, menu );
|
||||
|
||||
|
@ -838,6 +838,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 );
|
||||
|
119
src/app/qgsdxfexportdialog.cpp
Normal file
119
src/app/qgsdxfexportdialog.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "qgsdxfexportdialog.h"
|
||||
#include "qgsmaplayer.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgis.h"
|
||||
#include <QFileDialog>
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
|
||||
QgsDxfExportDialog::QgsDxfExportDialog( const QList<QgsMapLayer*>& 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<QgsMapLayer*>::const_iterator layerIt = layerKeys.constBegin();
|
||||
for ( ; layerIt != layerKeys.constEnd(); ++layerIt )
|
||||
{
|
||||
QgsMapLayer* layer = *layerIt;
|
||||
if ( layer )
|
||||
{
|
||||
if ( layer->type() == QgsMapLayer::VectorLayer )
|
||||
{
|
||||
QListWidgetItem* layerItem = new QListWidgetItem( layer->name() );
|
||||
layerItem->setData( Qt::UserRole, layer->id() );
|
||||
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<QString> QgsDxfExportDialog::layers() const
|
||||
{
|
||||
QList<QString> layerKeyList;
|
||||
int nItems = mLayersListWidget->count();
|
||||
for ( int i = 0; i < nItems; ++i )
|
||||
{
|
||||
QListWidgetItem* currentItem = mLayersListWidget->item( i );
|
||||
if ( currentItem->checkState() == Qt::Checked )
|
||||
{
|
||||
layerKeyList.prepend( 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() );
|
||||
}
|
25
src/app/qgsdxfexportdialog.h
Normal file
25
src/app/qgsdxfexportdialog.h
Normal file
@ -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<QgsMapLayer*>& layerKeys, QWidget * parent = 0, Qt::WindowFlags f = 0 );
|
||||
~QgsDxfExportDialog();
|
||||
|
||||
QList<QString> 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
|
@ -162,6 +162,10 @@ SET(QGIS_CORE_SRCS
|
||||
composer/qgscomposerhtml.cpp
|
||||
composer/qgscomposermultiframe.cpp
|
||||
composer/qgscomposition.cpp
|
||||
|
||||
dxf/qgsdxfexport.cpp
|
||||
dxf/qgsdxfpaintdevice.cpp
|
||||
dxf/qgsdxfpaintengine.cpp
|
||||
|
||||
pal/costcalculator.cpp
|
||||
pal/feature.cpp
|
||||
@ -556,6 +560,7 @@ ENDIF (QT_MOBILITY_LOCATION_FOUND)
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
composer
|
||||
dxf
|
||||
pal
|
||||
raster
|
||||
renderer
|
||||
|
1724
src/core/dxf/qgsdxfexport.cpp
Normal file
1724
src/core/dxf/qgsdxfexport.cpp
Normal file
File diff suppressed because it is too large
Load Diff
160
src/core/dxf/qgsdxfexport.h
Normal file
160
src/core/dxf/qgsdxfexport.h
Normal file
@ -0,0 +1,160 @@
|
||||
/***************************************************************************
|
||||
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 "qgsgeometry.h"
|
||||
#include "qgssymbolv2.h"
|
||||
#include <QColor>
|
||||
#include <QList>
|
||||
#include <QTextStream>
|
||||
|
||||
class QgsMapLayer;
|
||||
class QgsPoint;
|
||||
class QgsSymbolLayerV2;
|
||||
class QIODevice;
|
||||
|
||||
class CORE_EXPORT QgsDxfExport
|
||||
{
|
||||
public:
|
||||
enum SymbologyExport
|
||||
{
|
||||
NoSymbology = 0, //export only data
|
||||
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)
|
||||
};
|
||||
|
||||
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)?
|
||||
|
||||
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; }
|
||||
|
||||
//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 );
|
||||
|
||||
//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 );
|
||||
|
||||
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;
|
||||
/**Scale for symbology export (used if symbols units are mm)*/
|
||||
double mSymbologyScaleDenominator;
|
||||
SymbologyExport mSymbologyExport;
|
||||
QGis::UnitType mMapUnits;
|
||||
|
||||
QTextStream mTextStream;
|
||||
|
||||
static double mDxfColors[][3];
|
||||
|
||||
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();
|
||||
void writeTables();
|
||||
void writeBlocks();
|
||||
void writeEntities();
|
||||
void writeEntitiesSymbolLevels( QgsVectorLayer* layer );
|
||||
void writeEndFile();
|
||||
|
||||
void startSection();
|
||||
void endSection();
|
||||
|
||||
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 );
|
||||
void writeLinestyle( const QString& styleName, const QVector<qreal>& 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<qreal>& 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;
|
||||
|
||||
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
|
||||
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 );
|
||||
static QRgb createRgbEntry( qreal r, qreal g, qreal b );
|
||||
|
||||
//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 );
|
||||
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
|
100
src/core/dxf/qgsdxfpaintdevice.cpp
Normal file
100
src/core/dxf/qgsdxfpaintdevice.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/***************************************************************************
|
||||
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 ) const
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
void QgsDxfPaintDevice::setLayer( const QString& layer )
|
||||
{
|
||||
if ( mPaintEngine )
|
||||
{
|
||||
mPaintEngine->setLayer( layer );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDxfPaintDevice::setShift( const QPointF& shift )
|
||||
{
|
||||
if ( mPaintEngine )
|
||||
{
|
||||
mPaintEngine->setShift( shift );
|
||||
}
|
||||
}
|
||||
|
||||
|
63
src/core/dxf/qgsdxfpaintdevice.h
Normal file
63
src/core/dxf/qgsdxfpaintdevice.h
Normal file
@ -0,0 +1,63 @@
|
||||
/***************************************************************************
|
||||
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 <QPaintDevice>
|
||||
#include "qgsdxfpaintengine.h"
|
||||
|
||||
class QgsDxfExport;
|
||||
class QPaintEngine;
|
||||
|
||||
/**A paint device for drawing into dxf files*/
|
||||
|
||||
class CORE_EXPORT 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 ) const;
|
||||
|
||||
/*int height() const { return mDrawingSize.height(); }
|
||||
int width() const { return mDrawingSize.width(); }*/
|
||||
|
||||
int metric( PaintDeviceMetric metric ) const;
|
||||
|
||||
void setLayer( const QString& layer );
|
||||
|
||||
void setShift( const QPointF& shift );
|
||||
|
||||
|
||||
private:
|
||||
QgsDxfPaintEngine* mPaintEngine;
|
||||
|
||||
QSizeF mDrawingSize; //size (in source coordinates)
|
||||
QRectF mRectangle; //size (in dxf coordinates)
|
||||
};
|
||||
|
||||
#endif // QGSDXFPAINTDEVICE_H
|
171
src/core/dxf/qgsdxfpaintengine.cpp
Normal file
171
src/core/dxf/qgsdxfpaintengine.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
/***************************************************************************
|
||||
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 "qgsdxfpaintdevice.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 )
|
||||
{
|
||||
if ( !mDxf || !mPaintDevice )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsPolyline polyline( pointCount );
|
||||
for ( int i = 0; i < pointCount; ++i )
|
||||
{
|
||||
polyline[i] = toDxfCoordinates( points[i] );
|
||||
}
|
||||
|
||||
mDxf->writePolyline( polyline, mLayer, "CONTINUOUS", currentPenColor(), currentWidth(), mode != QPaintEngine::PolylineMode );
|
||||
}
|
||||
|
||||
void QgsDxfPaintEngine::drawRects( const QRectF* rects, int rectCount )
|
||||
{
|
||||
if ( !mDxf || !mPaintDevice || !rects )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
void QgsDxfPaintEngine::drawPath( const QPainterPath& path )
|
||||
{
|
||||
QList<QPolygonF> polygonList = path.toFillPolygons();
|
||||
QList<QPolygonF>::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 )
|
||||
{
|
||||
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
|
||||
{
|
||||
if ( !mPaintDevice || !mDxf )
|
||||
{
|
||||
return QgsPoint( pt.x(), pt.y() );
|
||||
}
|
||||
|
||||
QPointF dxfPt = mPaintDevice->dxfCoordinates( mTransform.map( pt ) ) + mShift;
|
||||
return QgsPoint( dxfPt.x(), dxfPt.y() );
|
||||
}
|
||||
|
||||
int QgsDxfPaintEngine::currentPenColor() const
|
||||
{
|
||||
if ( !mDxf )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mDxf->closestColorMatch( mPen.color().rgb() );
|
||||
}
|
||||
|
||||
double QgsDxfPaintEngine::currentWidth() const
|
||||
{
|
||||
if ( !mPaintDevice )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return mPen.widthF() * mPaintDevice->widthScaleFactor();
|
||||
}
|
66
src/core/dxf/qgsdxfpaintengine.h
Normal file
66
src/core/dxf/qgsdxfpaintengine.h
Normal file
@ -0,0 +1,66 @@
|
||||
/***************************************************************************
|
||||
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 <QPaintEngine>
|
||||
|
||||
class QgsDxfExport;
|
||||
class QgsDxfPaintDevice;
|
||||
class QgsPoint;
|
||||
|
||||
class CORE_EXPORT 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 );
|
||||
|
||||
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;
|
||||
|
||||
//painter state information
|
||||
QTransform mTransform;
|
||||
QPen mPen;
|
||||
QString mLayer;
|
||||
QPointF mShift;
|
||||
|
||||
QgsPoint toDxfCoordinates( const QPointF& pt ) const;
|
||||
int currentPenColor() const;
|
||||
double currentWidth() const;
|
||||
};
|
||||
|
||||
#endif // QGSDXFPAINTENGINE_H
|
@ -13,6 +13,7 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsellipsesymbollayerv2.h"
|
||||
#include "qgsdxfexport.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsrendercontext.h"
|
||||
@ -492,3 +493,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<QgsFeature*>( 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<QgsFeature*>( 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<QgsFeature*>( 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<QgsFeature*>( 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<QgsFeature*>( 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<QgsFeature*>( 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...
|
||||
}
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "qgsmarkersymbollayerv2.h"
|
||||
#include "qgssymbollayerv2utils.h"
|
||||
|
||||
#include "qgsdxfexport.h"
|
||||
#include "qgsdxfpaintdevice.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsrendercontext.h"
|
||||
#include "qgslogger.h"
|
||||
@ -721,6 +723,116 @@ void QgsSimpleMarkerSymbolLayerV2::drawMarker( QPainter* p, QgsSymbolV2RenderCon
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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<QgsFeature*>( 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;
|
||||
}
|
||||
double halfSize = size / 2.0;
|
||||
|
||||
|
||||
QColor c = mBrush.color();
|
||||
QgsExpression* colorExpression = expression( "color" );
|
||||
if ( colorExpression )
|
||||
{
|
||||
c = QgsSymbolLayerV2Utils::decodeColor( colorExpression->evaluate( *f ).toString() );
|
||||
}
|
||||
int colorIndex = QgsDxfExport::closestColorMatch( c.rgb() );
|
||||
|
||||
//offset
|
||||
double offsetX = 0;
|
||||
double offsetY = 0;
|
||||
markerOffset( *context, offsetX, offsetY );
|
||||
QPointF off( offsetX, offsetY );
|
||||
|
||||
//angle
|
||||
double angle = mAngle;
|
||||
QgsExpression* angleExpression = expression( "angle" );
|
||||
if ( angleExpression )
|
||||
{
|
||||
angle = angleExpression->evaluate( const_cast<QgsFeature*>( context->feature() ) ).toDouble();
|
||||
}
|
||||
angle = -angle; //rotation in Qt is counterclockwise
|
||||
if ( angle )
|
||||
off = _rotatedOffset( off, angle );
|
||||
|
||||
if ( mSizeUnit == QgsSymbolV2::MM )
|
||||
{
|
||||
off *= mmMapUnitScaleFactor;
|
||||
}
|
||||
|
||||
QTransform t;
|
||||
t.translate( shift.x() + offsetX, shift.y() + offsetY );
|
||||
|
||||
if ( angle != 0 )
|
||||
t.rotate( angle );
|
||||
|
||||
//data defined symbol name
|
||||
|
||||
if ( mName == "circle" )
|
||||
{
|
||||
e.writeGroup( 0, "CIRCLE" );
|
||||
e.writeGroup( 8, layerName );
|
||||
|
||||
e.writeGroup( 62, colorIndex );
|
||||
e.writeGroup( 10, halfSize + shift.x() );
|
||||
e.writeGroup( 20, halfSize + shift.y() );
|
||||
e.writeGroup( 30, 0.0 );
|
||||
e.writeGroup( 40, halfSize );
|
||||
}
|
||||
else if ( mName == "square" || mName == "rectangle" )
|
||||
{
|
||||
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" )
|
||||
{
|
||||
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() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////
|
||||
|
||||
|
||||
@ -1143,6 +1255,93 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::createFromSld( QDomElement &element
|
||||
return m;
|
||||
}
|
||||
|
||||
bool QgsSvgMarkerSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f,
|
||||
const QPointF& shift ) const
|
||||
{
|
||||
Q_UNUSED( layerName );
|
||||
Q_UNUSED( shift ); //todo...
|
||||
|
||||
QSvgRenderer r( mPath );
|
||||
if ( !r.isValid() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsDxfPaintDevice pd( &e );
|
||||
pd.setDrawingSize( QSizeF( r.defaultSize() ) );
|
||||
|
||||
//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 );
|
||||
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();
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////
|
||||
|
||||
QgsFontMarkerSymbolLayerV2::QgsFontMarkerSymbolLayerV2( QString fontFamily, QChar chr, double pointSize, QColor color, double angle )
|
||||
|
@ -76,6 +76,8 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
|
||||
QgsSymbolV2::OutputUnit outlineWidthUnit() const { return mOutlineWidthUnit; }
|
||||
void setOutlineWidthUnit( QgsSymbolV2::OutputUnit u ) { mOutlineWidthUnit = u; }
|
||||
|
||||
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:
|
||||
|
||||
void drawMarker( QPainter* p, QgsSymbolV2RenderContext& context );
|
||||
@ -157,6 +159,8 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
|
||||
void setOutputUnit( QgsSymbolV2::OutputUnit unit );
|
||||
QgsSymbolV2::OutputUnit outputUnit() 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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
@ -180,14 +180,14 @@ 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
|
||||
{
|
||||
markerOffset( context, mSize, mSize, mSizeUnit, mSizeUnit, offsetX, offsetY );
|
||||
}
|
||||
|
||||
void QgsMarkerSymbolLayerV2::markerOffset( QgsSymbolV2RenderContext& context, double width, double height,
|
||||
void QgsMarkerSymbolLayerV2::markerOffset( const QgsSymbolV2RenderContext& context, double width, double height,
|
||||
QgsSymbolV2::OutputUnit widthUnit, QgsSymbolV2::OutputUnit heightUnit,
|
||||
double& offsetX, double& offsetY )
|
||||
double& offsetX, double& offsetY ) const
|
||||
{
|
||||
offsetX = mOffset.x();
|
||||
offsetY = mOffset.y();
|
||||
|
@ -38,6 +38,7 @@ class QPainter;
|
||||
class QSize;
|
||||
class QPolygonF;
|
||||
|
||||
class QgsDxfExport;
|
||||
class QgsExpression;
|
||||
class QgsRenderContext;
|
||||
|
||||
@ -91,6 +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 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 )
|
||||
@ -109,7 +114,8 @@ class CORE_EXPORT QgsSymbolLayerV2
|
||||
static const bool selectFillStyle = false; // Fill symbol uses symbol layer style..
|
||||
|
||||
virtual void prepareExpressions( const QgsVectorLayer* vl, double scale = -1 );
|
||||
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*/
|
||||
@ -174,11 +180,13 @@ class CORE_EXPORT QgsMarkerSymbolLayerV2 : public QgsSymbolLayerV2
|
||||
|
||||
protected:
|
||||
QgsMarkerSymbolLayerV2( bool locked = false );
|
||||
|
||||
//handles marker offset and anchor point shift together
|
||||
void markerOffset( QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY );
|
||||
void markerOffset( QgsSymbolV2RenderContext& context, double width, double height,
|
||||
void markerOffset( const QgsSymbolV2RenderContext& context, double& offsetX, double& offsetY ) const;
|
||||
void markerOffset( const QgsSymbolV2RenderContext& context, double width, double height,
|
||||
QgsSymbolV2::OutputUnit widthUnit, QgsSymbolV2::OutputUnit heightUnit,
|
||||
double& offsetX, double& offsetY );
|
||||
double& offsetX, double& offsetY ) const;
|
||||
|
||||
static QPointF _rotatedOffset( const QPointF& offset, double angle );
|
||||
|
||||
double mAngle;
|
||||
|
@ -17,7 +17,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1050</width>
|
||||
<height>31</height>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="mProjectMenu">
|
||||
@ -47,6 +47,7 @@
|
||||
<addaction name="mActionSaveProject"/>
|
||||
<addaction name="mActionSaveProjectAs"/>
|
||||
<addaction name="mActionSaveMapAsImage"/>
|
||||
<addaction name="mActionDxfExport"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="mActionNewPrintComposer"/>
|
||||
<addaction name="mActionShowComposerManager"/>
|
||||
@ -2136,6 +2137,11 @@ Acts on currently active editable layer</string>
|
||||
<string>Paste features in clipboard into a new memory vector layer.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionDxfExport">
|
||||
<property name="text">
|
||||
<string>DXF Export...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
|
124
src/ui/qgsdxfexportdialogbase.ui
Normal file
124
src/ui/qgsdxfexportdialogbase.ui
Normal file
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsDxfExportDialogBase</class>
|
||||
<widget class="QDialog" name="QgsDxfExportDialogBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>377</width>
|
||||
<height>292</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>DXF export</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="mFileLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="mSymbologyModeLabel">
|
||||
<property name="text">
|
||||
<string>Symbology mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="mSymbologyScaleLabel">
|
||||
<property name="text">
|
||||
<string>Symbology scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mSaveAsLabel">
|
||||
<property name="text">
|
||||
<string>Save as</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="mFileSelectionButton">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="mSymbologyModeComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>No symbology</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Feature symbology</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Symbol layer symbology</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="mSymbologyScaleLineEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QListWidget" name="mLayersListWidget"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>QgsDxfExportDialogBase</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>QgsDxfExportDialogBase</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user