Skip to content

Commit a9c830e

Browse files
committedJun 30, 2015
[FEATURE]: getMap in dxf format
1 parent 7b31f8a commit a9c830e

File tree

6 files changed

+282
-2
lines changed

6 files changed

+282
-2
lines changed
 

‎src/server/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ SET ( qgis_mapserv_SRCS
4545
qgswmsconfigparser.cpp
4646
qgswmsprojectparser.cpp
4747
qgsserverprojectparser.cpp
48+
qgsserverstreamingdevice.cpp
4849
qgssldconfigparser.cpp
4950
qgsconfigparserutils.cpp
5051
)
@@ -160,6 +161,7 @@ INCLUDE_DIRECTORIES(
160161
${QT_INCLUDE_DIR}
161162
${QGIS_INCLUDE_DIR}
162163
../core
164+
../core/dxf
163165
../core/geometry
164166
../core/raster
165167
../core/symbology-ng

‎src/server/qgshttprequesthandler.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ void QgsHttpRequestHandler::sendHeaders()
131131
printf( it.value().toLocal8Bit() );
132132
printf( "\n" );
133133
}
134-
printf( "\n" );
135134
}
136135
printf( "\n" );
137136
mHeaders.clear();
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/***************************************************************************
2+
qgsserverstreamingdevice.cpp
3+
-------------------------------------------------------------------
4+
Date : 25 May 2015
5+
Copyright : (C) 2015 by Marco Hugentobler
6+
email : marco.hugentobler at sourcepole dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsserverstreamingdevice.h"
17+
#include "qgsrequesthandler.h"
18+
19+
QgsServerStreamingDevice::QgsServerStreamingDevice( const QString& formatName, QgsRequestHandler* rh, QObject* parent ): QIODevice( parent ), mFormatName( formatName ), mRequestHandler( rh )
20+
{
21+
}
22+
23+
QgsServerStreamingDevice::QgsServerStreamingDevice(): QIODevice( 0 ), mRequestHandler( 0 )
24+
{
25+
26+
}
27+
28+
QgsServerStreamingDevice::~QgsServerStreamingDevice()
29+
{
30+
}
31+
32+
bool QgsServerStreamingDevice::open( OpenMode mode )
33+
{
34+
if( !mRequestHandler || mode != QIODevice::WriteOnly )
35+
{
36+
return false;
37+
}
38+
39+
mRequestHandler->setHeader( "Content-Type", mFormatName );
40+
mRequestHandler->sendResponse();
41+
return QIODevice::open( mode );
42+
}
43+
44+
void QgsServerStreamingDevice::close()
45+
{
46+
QIODevice::close();
47+
}
48+
49+
qint64 QgsServerStreamingDevice::writeData( const char * data, qint64 maxSize )
50+
{
51+
QByteArray ba( data, maxSize );
52+
mRequestHandler->setGetFeatureResponse( &ba );
53+
return maxSize;
54+
}
55+
56+
qint64 QgsServerStreamingDevice::readData( char * data, qint64 maxSize )
57+
{
58+
return -1; //reading not supported
59+
}

‎src/server/qgsserverstreamingdevice.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/***************************************************************************
2+
qgsserverstreamingdevice.h
3+
-------------------------------------------------------------------
4+
Date : 25 May 2015
5+
Copyright : (C) 2015 by Marco Hugentobler
6+
email : marco.hugentobler at sourcepole dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSSERVERSTREAMINGDEVICE_H
17+
#define QGSSERVERSTREAMINGDEVICE_H
18+
19+
#include <QIODevice>
20+
21+
class QgsRequestHandler;
22+
23+
class QgsServerStreamingDevice: public QIODevice
24+
{
25+
public:
26+
QgsServerStreamingDevice( const QString& formatName, QgsRequestHandler* rh, QObject* parent = 0 );
27+
~QgsServerStreamingDevice();
28+
29+
bool isSequential() const { return false; }
30+
31+
bool open( OpenMode mode );
32+
void close();
33+
34+
protected:
35+
QString mFormatName;
36+
QgsRequestHandler* mRequestHandler;
37+
38+
QgsServerStreamingDevice(); //default constructor forbidden
39+
40+
qint64 writeData( const char * data, qint64 maxSize );
41+
qint64 readData ( char * data, qint64 maxSize );
42+
};
43+
44+
#endif // QGSSERVERSTREAMINGDEVICE_H

‎src/server/qgswmsserver.cpp

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgswmsserver.h"
1919
#include "qgscapabilitiescache.h"
2020
#include "qgscrscache.h"
21+
#include "qgsdxfexport.h"
2122
#include "qgsfield.h"
2223
#include "qgsgeometry.h"
2324
#include "qgslayertree.h"
@@ -46,6 +47,7 @@
4647
#include "qgsogcutils.h"
4748
#include "qgsfeature.h"
4849
#include "qgseditorwidgetregistry.h"
50+
#include "qgsserverstreamingdevice.h"
4951

5052
#include <QImage>
5153
#include <QPainter>
@@ -158,6 +160,25 @@ void QgsWMSServer::executeRequest()
158160
//GetMap
159161
else if ( request.compare( "GetMap", Qt::CaseInsensitive ) == 0 )
160162
{
163+
//export as dxf
164+
QString format = mParameters.value( "FORMAT" );
165+
if ( format.compare( "application/dxf", Qt::CaseInsensitive ) == 0 )
166+
{
167+
try
168+
{
169+
getMapAsDxf();
170+
cleanupAfterRequest();
171+
return;
172+
}
173+
catch ( QgsMapServiceException& ex )
174+
{
175+
QgsDebugMsg( "Caught exception during GetMap request" );
176+
mRequestHandler->setServiceException( ex );
177+
cleanupAfterRequest();
178+
return;
179+
}
180+
}
181+
161182
QImage* result = 0;
162183
try
163184
{
@@ -446,7 +467,7 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf
446467

447468
//wms:GetMap
448469
elem = doc.createElement( "GetMap"/*wms:GetMap*/ );
449-
appendFormats( doc, elem, QStringList() << "image/jpeg" << "image/png" << "image/png; mode=16bit" << "image/png; mode=8bit" << "image/png; mode=1bit" );
470+
appendFormats( doc, elem, QStringList() << "image/jpeg" << "image/png" << "image/png; mode=16bit" << "image/png; mode=8bit" << "image/png; mode=1bit" << "application/dxf" );
450471
elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities'
451472
requestElement.appendChild( elem );
452473

@@ -1311,6 +1332,76 @@ QImage* QgsWMSServer::getMap( HitTest* hitTest )
13111332
return theImage;
13121333
}
13131334

1335+
void QgsWMSServer::getMapAsDxf()
1336+
{
1337+
QgsServerStreamingDevice d( "application/dxf" , mRequestHandler );
1338+
if ( !d.open( QIODevice::WriteOnly ) )
1339+
{
1340+
throw QgsMapServiceException( "Internal server error", "Error opening output device for writing" );
1341+
}
1342+
1343+
QgsDxfExport dxf;
1344+
1345+
//BBOX
1346+
bool bboxOk;
1347+
QgsRectangle extent = _parseBBOX( mParameters.value( "BBOX", "0,0,0,0" ), bboxOk );
1348+
if ( !bboxOk )
1349+
{
1350+
extent = QgsRectangle();
1351+
}
1352+
dxf.setExtent( extent );
1353+
1354+
//get format options (for MODE,SCALE, LAYERATTRIBUTES )
1355+
QMap<QString, QString > formatOptionsMap;
1356+
readFormatOptions( formatOptionsMap );
1357+
1358+
QList< QPair<QgsVectorLayer *, int > > layers;
1359+
readDxfLayerSettings( layers, formatOptionsMap );
1360+
dxf.addLayers( layers );
1361+
1362+
//MODE
1363+
QMap<QString, QString>::const_iterator modeIt = formatOptionsMap.find( "MODE" );
1364+
1365+
QgsDxfExport::SymbologyExport se;
1366+
if ( modeIt == formatOptionsMap.constEnd() )
1367+
{
1368+
se = QgsDxfExport::NoSymbology;
1369+
}
1370+
else
1371+
{
1372+
if ( modeIt->compare( "SymbolLayerSymbology", Qt::CaseInsensitive ) == 0 )
1373+
{
1374+
se = QgsDxfExport::SymbolLayerSymbology;
1375+
}
1376+
else if ( modeIt->compare( "FeatureSymbology", Qt::CaseInsensitive ) == 0 )
1377+
{
1378+
se = QgsDxfExport::FeatureSymbology;
1379+
}
1380+
else
1381+
{
1382+
se = QgsDxfExport::NoSymbology;
1383+
}
1384+
}
1385+
dxf.setSymbologyExport( se );
1386+
1387+
//SCALE
1388+
QMap<QString, QString>::const_iterator scaleIt = formatOptionsMap.find( "SCALE" );
1389+
if ( scaleIt != formatOptionsMap.constEnd() )
1390+
{
1391+
dxf.setSymbologyScaleDenominator( scaleIt->toDouble() );
1392+
}
1393+
1394+
QString codec = "ISO-8859-1";
1395+
QMap<QString, QString>::const_iterator codecIt = formatOptionsMap.find( "CODEC" );
1396+
if ( codecIt != formatOptionsMap.constEnd() )
1397+
{
1398+
codec = formatOptionsMap.value( "CODEC" );
1399+
}
1400+
1401+
dxf.writeToFile( &d, codec );
1402+
d.close();
1403+
}
1404+
13141405
int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
13151406
{
13161407
if ( !mMapRenderer || !mConfigParser )
@@ -3114,3 +3205,82 @@ QgsRectangle QgsWMSServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRend
31143205
infoPoint.x() + mapUnitTolerance, infoPoint.y() + mapUnitTolerance );
31153206
return( mr->mapToLayerCoordinates( ml, mapRectangle ) );
31163207
}
3208+
3209+
void QgsWMSServer::readFormatOptions( QMap<QString, QString>& formatOptions ) const
3210+
{
3211+
formatOptions.clear();
3212+
QString fo = mParameters.value( "FORMAT_OPTIONS" );
3213+
QStringList formatOptionsList = fo.split( ";" );
3214+
QStringList::const_iterator optionsIt = formatOptionsList.constBegin();
3215+
for ( ; optionsIt != formatOptionsList.constEnd(); ++optionsIt )
3216+
{
3217+
int equalIdx = optionsIt->indexOf( ":" );
3218+
if ( equalIdx > 0 && equalIdx < ( optionsIt->length() - 1 ) )
3219+
{
3220+
formatOptions.insert( optionsIt->left( equalIdx ).toUpper(), optionsIt->right( optionsIt->length() - equalIdx - 1 ).toUpper() );
3221+
}
3222+
}
3223+
}
3224+
3225+
void QgsWMSServer::readDxfLayerSettings( QList< QPair<QgsVectorLayer *, int > >& layers, const QMap<QString, QString>& formatOptionsMap ) const
3226+
{
3227+
layers.clear();
3228+
3229+
QSet<QString> wfsLayers = QSet<QString>::fromList( mConfigParser->wfsLayerNames() );
3230+
3231+
QStringList layerAttributes;
3232+
QMap<QString, QString>::const_iterator layerAttributesIt = formatOptionsMap.find( "LAYERATTRIBUTES" );
3233+
if ( layerAttributesIt != formatOptionsMap.constEnd() )
3234+
{
3235+
layerAttributes = formatOptionsMap.value( "LAYERATTRIBUTES" ).split( "," );
3236+
}
3237+
3238+
//LAYERS and STYLES
3239+
QStringList layerList, styleList;
3240+
if ( readLayersAndStyles( layerList, styleList ) != 0 )
3241+
{
3242+
return;
3243+
}
3244+
3245+
for ( int i = 0; i < layerList.size(); ++i )
3246+
{
3247+
QString layerName = layerList.at( i );
3248+
QString styleName;
3249+
if ( styleList.size() > i )
3250+
{
3251+
styleName = styleList.at( i );
3252+
}
3253+
3254+
QList<QgsMapLayer*> layerList = mConfigParser->mapLayerFromStyle( layerName, styleName );
3255+
QList<QgsMapLayer*>::const_iterator layerIt = layerList.constBegin();
3256+
for ( ; layerIt != layerList.constEnd(); ++layerIt )
3257+
{
3258+
if ( !( *layerIt ) )
3259+
{
3260+
continue;
3261+
}
3262+
3263+
//vector layer?
3264+
if (( *layerIt )->type() != QgsMapLayer::VectorLayer )
3265+
{
3266+
continue;
3267+
}
3268+
3269+
QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>( *layerIt );
3270+
3271+
int layerAttribute = -1;
3272+
if ( layerAttributes.size() > i )
3273+
{
3274+
layerAttribute = vlayer->pendingFields().indexFromName( layerAttributes.at( i ) );
3275+
}
3276+
3277+
//only wfs layers are allowed to be published
3278+
if ( !wfsLayers.contains( vlayer->name() ) )
3279+
{
3280+
continue;
3281+
}
3282+
3283+
layers.append( qMakePair( vlayer, layerAttribute ) );
3284+
}
3285+
}
3286+
}

‎src/server/qgswmsserver.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ class QgsWMSServer: public QgsOWSServer
8484
of the image object). If an instance to existing hit test structure is passed, instead of rendering
8585
it will fill the structure with symbols that would be used for rendering */
8686
QImage* getMap( HitTest* hitTest = 0 );
87+
/**GetMap request with vector format output. This output is usually symbolized (difference to WFS GetFeature)*/
88+
void getMapAsDxf();
8789
/**Returns an SLD file with the style of the requested layer. Exception is raised in case of troubles :-)*/
8890
QDomDocument getStyle();
8991
/**Returns an SLD file with the styles of the requested layers. Exception is raised in case of troubles :-)*/
@@ -254,6 +256,10 @@ class QgsWMSServer: public QgsOWSServer
254256

255257
/**Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)*/
256258
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;
259+
260+
/**Reads and extracts the different options in the FORMAT_OPTIONS parameter*/
261+
void readFormatOptions( QMap<QString, QString>& formatOptions ) const;
262+
void readDxfLayerSettings( QList< QPair<QgsVectorLayer *, int > >& layers, const QMap<QString, QString>& formatOptionsMap ) const;
257263
};
258264

259265
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.