Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE]: Add WFS support for QGIS server. Provided by René-Luc D'Hont
  • Loading branch information
mhugent committed Mar 20, 2012
1 parent a2ee769 commit c27c890
Show file tree
Hide file tree
Showing 15 changed files with 1,676 additions and 9 deletions.
48 changes: 46 additions & 2 deletions src/app/qgsprojectproperties.cpp
Expand Up @@ -175,7 +175,7 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
twIdentifyLayers->setCellWidget( i, 2, cb );
}

grpWMSServiceCapabilities->setChecked( QgsProject::instance()->readBoolEntry( "WMSServiceCapabilities", "/", false ) );
grpOWSServiceCapabilities->setChecked( QgsProject::instance()->readBoolEntry( "WMSServiceCapabilities", "/", false ) );
mWMSTitle->setText( QgsProject::instance()->readEntry( "WMSServiceTitle", "/" ) );
mWMSContactOrganization->setText( QgsProject::instance()->readEntry( "WMSContactOrganization", "/", "" ) );
mWMSContactPerson->setText( QgsProject::instance()->readEntry( "WMSContactPerson", "/", "" ) );
Expand Down Expand Up @@ -229,6 +229,38 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
bool addWktGeometry = QgsProject::instance()->readBoolEntry( "WMSAddWktGeometry", "/" );
mAddWktGeometryCheckBox->setChecked( addWktGeometry );

QStringList wfsLayerIdList = QgsProject::instance()->readListEntry( "WFSLayers", "/" );

twWFSLayers->setColumnCount( 2 );
twWFSLayers->horizontalHeader()->setVisible( true );
twWFSLayers->setRowCount( mapLayers.size() );

i = 0;
int j = 0;
for ( QMap<QString, QgsMapLayer*>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); it++, i++ )
{
currentLayer = it.value();
if ( currentLayer->type() == QgsMapLayer::VectorLayer )
{

QTableWidgetItem *twi = new QTableWidgetItem( QString::number( j ) );
twWFSLayers->setVerticalHeaderItem( j, twi );

twi = new QTableWidgetItem( currentLayer->name() );
twi->setData( Qt::UserRole, it.key() );
twi->setFlags( twi->flags() & ~Qt::ItemIsEditable );
twWFSLayers->setItem( j, 0, twi );

QCheckBox *cb = new QCheckBox();
cb->setChecked( wfsLayerIdList.contains( currentLayer->id() ) );
twWFSLayers->setCellWidget( j, 1, cb );
j++;

}
}
twWFSLayers->setRowCount( j );
twWFSLayers->verticalHeader()->setResizeMode( QHeaderView::ResizeToContents );

restoreState();
}

Expand Down Expand Up @@ -380,7 +412,7 @@ void QgsProjectProperties::apply()

QgsProject::instance()->writeEntry( "Identify", "/disabledLayers", noIdentifyLayerList );

QgsProject::instance()->writeEntry( "WMSServiceCapabilities", "/", grpWMSServiceCapabilities->isChecked() );
QgsProject::instance()->writeEntry( "WMSServiceCapabilities", "/", grpOWSServiceCapabilities->isChecked() );
QgsProject::instance()->writeEntry( "WMSServiceTitle", "/", mWMSTitle->text() );
QgsProject::instance()->writeEntry( "WMSContactOrganization", "/", mWMSContactOrganization->text() );
QgsProject::instance()->writeEntry( "WMSContactPerson", "/", mWMSContactPerson->text() );
Expand Down Expand Up @@ -428,6 +460,18 @@ void QgsProjectProperties::apply()

QgsProject::instance()->writeEntry( "WMSAddWktGeometry", "/", mAddWktGeometryCheckBox->isChecked() );

QStringList wfsLayerList;
for ( int i = 0; i < twWFSLayers->rowCount(); i++ )
{
QCheckBox *cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( i, 1 ) );
if ( cb && cb->isChecked() )
{
QString id = twWFSLayers->item( i, 0 )->data( Qt::UserRole ).toString();
wfsLayerList << id;
}
}
QgsProject::instance()->writeEntry( "WFSLayers", "/", wfsLayerList );

//todo XXX set canvas color
emit refresh();
}
Expand Down
290 changes: 290 additions & 0 deletions src/core/qgsgeometry.cpp
Expand Up @@ -4185,6 +4185,296 @@ QString QgsGeometry::exportToWkt()
}
}

QString QgsGeometry::exportToGeoJSON()
{
QgsDebugMsg( "entered." );

// TODO: implement with GEOS
if ( mDirtyWkb )
{
exportGeosToWkb();
}

if ( !mGeometry )
{
QgsDebugMsg( "WKB geometry not available!" );
return QString::null;
}

QGis::WkbType wkbType;
bool hasZValue = false;
double *x, *y;

QString mWkt; // TODO: rename

// Will this really work when mGeometry[0] == 0 ???? I (gavin) think not.
//wkbType = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4];
memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) );

switch ( wkbType )
{
case QGis::WKBPoint25D:
case QGis::WKBPoint:
{
mWkt += "{ \"type\": \"Point\", \"coordinates\": [";
x = ( double * )( mGeometry + 5 );
mWkt += QString::number( *x, 'f', 6 );
mWkt += ", ";
y = ( double * )( mGeometry + 5 + sizeof( double ) );
mWkt += QString::number( *y, 'f', 6 );
mWkt += "] }";
return mWkt;
}

case QGis::WKBLineString25D:
hasZValue = true;
case QGis::WKBLineString:
{
QgsDebugMsg( "LINESTRING found" );
unsigned char *ptr;
int *nPoints;
int idx;

mWkt += "{ \"type\": \"LineString\", \"coordinates\": [ ";
// get number of points in the line
ptr = mGeometry + 5;
nPoints = ( int * ) ptr;
ptr = mGeometry + 1 + 2 * sizeof( int );
for ( idx = 0; idx < *nPoints; ++idx )
{
if ( idx != 0 )
{
mWkt += ", ";
}
mWkt += "[";
x = ( double * ) ptr;
mWkt += QString::number( *x, 'f', 6 );
mWkt += ", ";
ptr += sizeof( double );
y = ( double * ) ptr;
mWkt += QString::number( *y, 'f', 6 );
ptr += sizeof( double );
if ( hasZValue )
{
ptr += sizeof( double );
}
mWkt += "]";
}
mWkt += " ] }";
return mWkt;
}

case QGis::WKBPolygon25D:
hasZValue = true;
case QGis::WKBPolygon:
{
QgsDebugMsg( "POLYGON found" );
unsigned char *ptr;
int idx, jdx;
int *numRings, *nPoints;

mWkt += "{ \"type\": \"Polygon\", \"coordinates\": [ ";
// get number of rings in the polygon
numRings = ( int * )( mGeometry + 1 + sizeof( int ) );
if ( !( *numRings ) ) // sanity check for zero rings in polygon
{
return QString();
}
int *ringStart; // index of first point for each ring
int *ringNumPoints; // number of points in each ring
ringStart = new int[*numRings];
ringNumPoints = new int[*numRings];
ptr = mGeometry + 1 + 2 * sizeof( int ); // set pointer to the first ring
for ( idx = 0; idx < *numRings; idx++ )
{
if ( idx != 0 )
{
mWkt += ", ";
}
mWkt += "[ ";
// get number of points in the ring
nPoints = ( int * ) ptr;
ringNumPoints[idx] = *nPoints;
ptr += 4;

for ( jdx = 0; jdx < *nPoints; jdx++ )
{
if ( jdx != 0 )
{
mWkt += ", ";
}
mWkt += "[";
x = ( double * ) ptr;
mWkt += QString::number( *x, 'f', 6 );
mWkt += ", ";
ptr += sizeof( double );
y = ( double * ) ptr;
mWkt += QString::number( *y, 'f', 6 );
ptr += sizeof( double );
if ( hasZValue )
{
ptr += sizeof( double );
}
mWkt += "]";
}
mWkt += " ]";
}
mWkt += " ] }";
delete [] ringStart;
delete [] ringNumPoints;
return mWkt;
}

case QGis::WKBMultiPoint25D:
hasZValue = true;
case QGis::WKBMultiPoint:
{
unsigned char *ptr;
int idx;
int *nPoints;

mWkt += "{ \"type\": \"MultiPoint\", \"coordinates\": [ ";
nPoints = ( int* )( mGeometry + 5 );
ptr = mGeometry + 5 + sizeof( int );
for ( idx = 0; idx < *nPoints; ++idx )
{
ptr += ( 1 + sizeof( int ) );
if ( idx != 0 )
{
mWkt += ", ";
}
mWkt += "[";
x = ( double * )( ptr );
mWkt += QString::number( *x, 'f', 6 );
mWkt += ", ";
ptr += sizeof( double );
y = ( double * )( ptr );
mWkt += QString::number( *y, 'f', 6 );
ptr += sizeof( double );
if ( hasZValue )
{
ptr += sizeof( double );
}
mWkt += "]";
}
mWkt += " ] }";
return mWkt;
}

case QGis::WKBMultiLineString25D:
hasZValue = true;
case QGis::WKBMultiLineString:
{
QgsDebugMsg( "MULTILINESTRING found" );
unsigned char *ptr;
int idx, jdx, numLineStrings;
int *nPoints;

mWkt += "{ \"type\": \"MultiLineString\", \"coordinates\": [ ";
numLineStrings = ( int )( mGeometry[5] );
ptr = mGeometry + 9;
for ( jdx = 0; jdx < numLineStrings; jdx++ )
{
if ( jdx != 0 )
{
mWkt += ", ";
}
mWkt += "[ ";
ptr += 5; // skip type since we know its 2
nPoints = ( int * ) ptr;
ptr += sizeof( int );
for ( idx = 0; idx < *nPoints; idx++ )
{
if ( idx != 0 )
{
mWkt += ", ";
}
mWkt += "[";
x = ( double * ) ptr;
mWkt += QString::number( *x, 'f', 6 );
ptr += sizeof( double );
mWkt += ", ";
y = ( double * ) ptr;
mWkt += QString::number( *y, 'f', 6 );
ptr += sizeof( double );
if ( hasZValue )
{
ptr += sizeof( double );
}
mWkt += "]";
}
mWkt += " ]";
}
mWkt += " ] }";
return mWkt;
}

case QGis::WKBMultiPolygon25D:
hasZValue = true;
case QGis::WKBMultiPolygon:
{
QgsDebugMsg( "MULTIPOLYGON found" );
unsigned char *ptr;
int idx, jdx, kdx;
int *numPolygons, *numRings, *nPoints;

mWkt += "{ \"type\": \"MultiPolygon\", \"coordinates\": [ ";
ptr = mGeometry + 5;
numPolygons = ( int * ) ptr;
ptr = mGeometry + 9;
for ( kdx = 0; kdx < *numPolygons; kdx++ )
{
if ( kdx != 0 )
{
mWkt += ", ";
}
mWkt += "[ ";
ptr += 5;
numRings = ( int * ) ptr;
ptr += 4;
for ( idx = 0; idx < *numRings; idx++ )
{
if ( idx != 0 )
{
mWkt += ", ";
}
mWkt += "[ ";
nPoints = ( int * ) ptr;
ptr += 4;
for ( jdx = 0; jdx < *nPoints; jdx++ )
{
if ( jdx != 0 )
{
mWkt += ", ";
}
mWkt += "[";
x = ( double * ) ptr;
mWkt += QString::number( *x, 'f', 6 );
ptr += sizeof( double );
mWkt += ", ";
y = ( double * ) ptr;
mWkt += QString::number( *y, 'f', 6 );
ptr += sizeof( double );
if ( hasZValue )
{
ptr += sizeof( double );
}
mWkt += "]";
}
mWkt += " ]";
}
mWkt += " ]";
}
mWkt += " ] }";
return mWkt;
}

default:
QgsDebugMsg( "error: mGeometry type not recognized" );
return QString::null;
}
}

bool QgsGeometry::exportWkbToGeos()
{
QgsDebugMsgLevel( "entered.", 3 );
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsgeometry.h
Expand Up @@ -361,6 +361,11 @@ class CORE_EXPORT QgsGeometry
*/
QString exportToWkt();

/** Exports the geometry to mGeoJSON
@return true in case of success and false else
*/
QString exportToGeoJSON();

/* Accessor functions for getting geometry data */

/** return contents of the geometry as a point
Expand Down
1 change: 1 addition & 0 deletions src/mapserver/CMakeLists.txt
Expand Up @@ -28,6 +28,7 @@ SET ( qgis_mapserv_SRCS
qgssldparser.cpp
qgssldrenderer.cpp
qgswmsserver.cpp
qgswfsserver.cpp
qgsmapserviceexception.cpp
qgsmslayercache.cpp
qgsfilter.cpp
Expand Down

0 comments on commit c27c890

Please sign in to comment.