Skip to content

Commit

Permalink
[FEATURE]: getMap in dxf format
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Jul 2, 2015
2 parents 738260a + a9c830e commit cce6c8b
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ SET ( qgis_mapserv_SRCS
qgswmsconfigparser.cpp
qgswmsprojectparser.cpp
qgsserverprojectparser.cpp
qgsserverstreamingdevice.cpp
qgssldconfigparser.cpp
qgsconfigparserutils.cpp
qgsserver.cpp
Expand Down Expand Up @@ -169,6 +170,7 @@ INCLUDE_DIRECTORIES(
${QT_INCLUDE_DIR}
${QGIS_INCLUDE_DIR}
../core
../core/dxf
../core/geometry
../core/raster
../core/symbology-ng
Expand Down
1 change: 0 additions & 1 deletion src/server/qgshttprequesthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ void QgsHttpRequestHandler::sendHeaders()
addToResponseHeader( it.value().toUtf8() );
addToResponseHeader( "\n" );
}
addToResponseHeader( "\n" );
}
addToResponseHeader( "\n" );
mHeaders.clear();
Expand Down
59 changes: 59 additions & 0 deletions src/server/qgsserverstreamingdevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/***************************************************************************
qgsserverstreamingdevice.cpp
-------------------------------------------------------------------
Date : 25 May 2015
Copyright : (C) 2015 by Marco Hugentobler
email : marco.hugentobler at sourcepole dot com
***************************************************************************
* *
* 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 "qgsserverstreamingdevice.h"
#include "qgsrequesthandler.h"

QgsServerStreamingDevice::QgsServerStreamingDevice( const QString& formatName, QgsRequestHandler* rh, QObject* parent ): QIODevice( parent ), mFormatName( formatName ), mRequestHandler( rh )
{
}

QgsServerStreamingDevice::QgsServerStreamingDevice(): QIODevice( 0 ), mRequestHandler( 0 )
{

}

QgsServerStreamingDevice::~QgsServerStreamingDevice()
{
}

bool QgsServerStreamingDevice::open( OpenMode mode )
{
if( !mRequestHandler || mode != QIODevice::WriteOnly )
{
return false;
}

mRequestHandler->setHeader( "Content-Type", mFormatName );
mRequestHandler->sendResponse();
return QIODevice::open( mode );
}

void QgsServerStreamingDevice::close()
{
QIODevice::close();
}

qint64 QgsServerStreamingDevice::writeData( const char * data, qint64 maxSize )
{
QByteArray ba( data, maxSize );
mRequestHandler->setGetFeatureResponse( &ba );
return maxSize;
}

qint64 QgsServerStreamingDevice::readData( char * data, qint64 maxSize )
{
return -1; //reading not supported
}
44 changes: 44 additions & 0 deletions src/server/qgsserverstreamingdevice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/***************************************************************************
qgsserverstreamingdevice.h
-------------------------------------------------------------------
Date : 25 May 2015
Copyright : (C) 2015 by Marco Hugentobler
email : marco.hugentobler at sourcepole dot com
***************************************************************************
* *
* 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 QGSSERVERSTREAMINGDEVICE_H
#define QGSSERVERSTREAMINGDEVICE_H

#include <QIODevice>

class QgsRequestHandler;

class QgsServerStreamingDevice: public QIODevice
{
public:
QgsServerStreamingDevice( const QString& formatName, QgsRequestHandler* rh, QObject* parent = 0 );
~QgsServerStreamingDevice();

bool isSequential() const { return false; }

bool open( OpenMode mode );
void close();

protected:
QString mFormatName;
QgsRequestHandler* mRequestHandler;

QgsServerStreamingDevice(); //default constructor forbidden

qint64 writeData( const char * data, qint64 maxSize );
qint64 readData ( char * data, qint64 maxSize );
};

#endif // QGSSERVERSTREAMINGDEVICE_H
172 changes: 171 additions & 1 deletion src/server/qgswmsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "qgswmsserver.h"
#include "qgscapabilitiescache.h"
#include "qgscrscache.h"
#include "qgsdxfexport.h"
#include "qgsfield.h"
#include "qgsgeometry.h"
#include "qgslayertree.h"
Expand Down Expand Up @@ -46,6 +47,7 @@
#include "qgsogcutils.h"
#include "qgsfeature.h"
#include "qgseditorwidgetregistry.h"
#include "qgsserverstreamingdevice.h"

#include <QImage>
#include <QPainter>
Expand Down Expand Up @@ -158,6 +160,25 @@ void QgsWMSServer::executeRequest()
//GetMap
else if ( request.compare( "GetMap", Qt::CaseInsensitive ) == 0 )
{
//export as dxf
QString format = mParameters.value( "FORMAT" );
if ( format.compare( "application/dxf", Qt::CaseInsensitive ) == 0 )
{
try
{
getMapAsDxf();
cleanupAfterRequest();
return;
}
catch ( QgsMapServiceException& ex )
{
QgsDebugMsg( "Caught exception during GetMap request" );
mRequestHandler->setServiceException( ex );
cleanupAfterRequest();
return;
}
}

QImage* result = 0;
try
{
Expand Down Expand Up @@ -446,7 +467,7 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf

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

Expand Down Expand Up @@ -1311,6 +1332,76 @@ QImage* QgsWMSServer::getMap( HitTest* hitTest )
return theImage;
}

void QgsWMSServer::getMapAsDxf()
{
QgsServerStreamingDevice d( "application/dxf" , mRequestHandler );
if ( !d.open( QIODevice::WriteOnly ) )
{
throw QgsMapServiceException( "Internal server error", "Error opening output device for writing" );
}

QgsDxfExport dxf;

//BBOX
bool bboxOk;
QgsRectangle extent = _parseBBOX( mParameters.value( "BBOX", "0,0,0,0" ), bboxOk );
if ( !bboxOk )
{
extent = QgsRectangle();
}
dxf.setExtent( extent );

//get format options (for MODE,SCALE, LAYERATTRIBUTES )
QMap<QString, QString > formatOptionsMap;
readFormatOptions( formatOptionsMap );

QList< QPair<QgsVectorLayer *, int > > layers;
readDxfLayerSettings( layers, formatOptionsMap );
dxf.addLayers( layers );

//MODE
QMap<QString, QString>::const_iterator modeIt = formatOptionsMap.find( "MODE" );

QgsDxfExport::SymbologyExport se;
if ( modeIt == formatOptionsMap.constEnd() )
{
se = QgsDxfExport::NoSymbology;
}
else
{
if ( modeIt->compare( "SymbolLayerSymbology", Qt::CaseInsensitive ) == 0 )
{
se = QgsDxfExport::SymbolLayerSymbology;
}
else if ( modeIt->compare( "FeatureSymbology", Qt::CaseInsensitive ) == 0 )
{
se = QgsDxfExport::FeatureSymbology;
}
else
{
se = QgsDxfExport::NoSymbology;
}
}
dxf.setSymbologyExport( se );

//SCALE
QMap<QString, QString>::const_iterator scaleIt = formatOptionsMap.find( "SCALE" );
if ( scaleIt != formatOptionsMap.constEnd() )
{
dxf.setSymbologyScaleDenominator( scaleIt->toDouble() );
}

QString codec = "ISO-8859-1";
QMap<QString, QString>::const_iterator codecIt = formatOptionsMap.find( "CODEC" );
if ( codecIt != formatOptionsMap.constEnd() )
{
codec = formatOptionsMap.value( "CODEC" );
}

dxf.writeToFile( &d, codec );
d.close();
}

int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
{
if ( !mMapRenderer || !mConfigParser )
Expand Down Expand Up @@ -3114,3 +3205,82 @@ QgsRectangle QgsWMSServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRend
infoPoint.x() + mapUnitTolerance, infoPoint.y() + mapUnitTolerance );
return( mr->mapToLayerCoordinates( ml, mapRectangle ) );
}

void QgsWMSServer::readFormatOptions( QMap<QString, QString>& formatOptions ) const
{
formatOptions.clear();
QString fo = mParameters.value( "FORMAT_OPTIONS" );
QStringList formatOptionsList = fo.split( ";" );
QStringList::const_iterator optionsIt = formatOptionsList.constBegin();
for ( ; optionsIt != formatOptionsList.constEnd(); ++optionsIt )
{
int equalIdx = optionsIt->indexOf( ":" );
if ( equalIdx > 0 && equalIdx < ( optionsIt->length() - 1 ) )
{
formatOptions.insert( optionsIt->left( equalIdx ).toUpper(), optionsIt->right( optionsIt->length() - equalIdx - 1 ).toUpper() );
}
}
}

void QgsWMSServer::readDxfLayerSettings( QList< QPair<QgsVectorLayer *, int > >& layers, const QMap<QString, QString>& formatOptionsMap ) const
{
layers.clear();

QSet<QString> wfsLayers = QSet<QString>::fromList( mConfigParser->wfsLayerNames() );

QStringList layerAttributes;
QMap<QString, QString>::const_iterator layerAttributesIt = formatOptionsMap.find( "LAYERATTRIBUTES" );
if ( layerAttributesIt != formatOptionsMap.constEnd() )
{
layerAttributes = formatOptionsMap.value( "LAYERATTRIBUTES" ).split( "," );
}

//LAYERS and STYLES
QStringList layerList, styleList;
if ( readLayersAndStyles( layerList, styleList ) != 0 )
{
return;
}

for ( int i = 0; i < layerList.size(); ++i )
{
QString layerName = layerList.at( i );
QString styleName;
if ( styleList.size() > i )
{
styleName = styleList.at( i );
}

QList<QgsMapLayer*> layerList = mConfigParser->mapLayerFromStyle( layerName, styleName );
QList<QgsMapLayer*>::const_iterator layerIt = layerList.constBegin();
for ( ; layerIt != layerList.constEnd(); ++layerIt )
{
if ( !( *layerIt ) )
{
continue;
}

//vector layer?
if (( *layerIt )->type() != QgsMapLayer::VectorLayer )
{
continue;
}

QgsVectorLayer* vlayer = static_cast<QgsVectorLayer*>( *layerIt );

int layerAttribute = -1;
if ( layerAttributes.size() > i )
{
layerAttribute = vlayer->pendingFields().indexFromName( layerAttributes.at( i ) );
}

//only wfs layers are allowed to be published
if ( !wfsLayers.contains( vlayer->name() ) )
{
continue;
}

layers.append( qMakePair( vlayer, layerAttribute ) );
}
}
}
6 changes: 6 additions & 0 deletions src/server/qgswmsserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class QgsWMSServer: public QgsOWSServer
of the image object). If an instance to existing hit test structure is passed, instead of rendering
it will fill the structure with symbols that would be used for rendering */
QImage* getMap( HitTest* hitTest = 0 );
/**GetMap request with vector format output. This output is usually symbolized (difference to WFS GetFeature)*/
void getMapAsDxf();
/**Returns an SLD file with the style of the requested layer. Exception is raised in case of troubles :-)*/
QDomDocument getStyle();
/**Returns an SLD file with the styles of the requested layers. Exception is raised in case of troubles :-)*/
Expand Down Expand Up @@ -254,6 +256,10 @@ class QgsWMSServer: public QgsOWSServer

/**Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)*/
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;

/**Reads and extracts the different options in the FORMAT_OPTIONS parameter*/
void readFormatOptions( QMap<QString, QString>& formatOptions ) const;
void readDxfLayerSettings( QList< QPair<QgsVectorLayer *, int > >& layers, const QMap<QString, QString>& formatOptionsMap ) const;
};

#endif

0 comments on commit cce6c8b

Please sign in to comment.