@@ -331,7 +331,37 @@ QDomDocument QgsWFSServer::describeFeatureType()
331
331
// xsd:element
332
332
QDomElement geomElem = doc.createElement ( " element" /* xsd:element*/ );
333
333
geomElem.setAttribute ( " name" , " geometry" );
334
- geomElem.setAttribute ( " type" , " gml:GeometryPropertyType" );
334
+ QGis::WkbType wkbType = layer->wkbType ();
335
+ switch ( wkbType )
336
+ {
337
+ case QGis::WKBPoint25D:
338
+ case QGis::WKBPoint:
339
+ geomElem.setAttribute ( " type" , " gml:PointPropertyType" );
340
+ break ;
341
+ case QGis::WKBLineString25D:
342
+ case QGis::WKBLineString:
343
+ geomElem.setAttribute ( " type" , " gml:LineStringPropertyType" );
344
+ break ;
345
+ case QGis::WKBPolygon25D:
346
+ case QGis::WKBPolygon:
347
+ geomElem.setAttribute ( " type" , " gml:PolygonPropertyType" );
348
+ break ;
349
+ case QGis::WKBMultiPoint25D:
350
+ case QGis::WKBMultiPoint:
351
+ geomElem.setAttribute ( " type" , " gml:MultiPointPropertyType" );
352
+ break ;
353
+ case QGis::WKBMultiLineString25D:
354
+ case QGis::WKBMultiLineString:
355
+ geomElem.setAttribute ( " type" , " gml:MultiLineStringPropertyType" );
356
+ break ;
357
+ case QGis::WKBMultiPolygon25D:
358
+ case QGis::WKBMultiPolygon:
359
+ geomElem.setAttribute ( " type" , " gml:MultiPolygonPropertyType" );
360
+ break ;
361
+ default :
362
+ geomElem.setAttribute ( " type" , " gml:GeometryPropertyType" );
363
+ break ;
364
+ }
335
365
geomElem.setAttribute ( " minOccurs" , " 0" );
336
366
geomElem.setAttribute ( " maxOccurs" , " 1" );
337
367
sequenceElem.appendChild ( geomElem );
@@ -543,9 +573,11 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
543
573
}
544
574
}
545
575
576
+ if ( bboxOk )
577
+ searchRect.set ( minx, miny, maxx, maxy );
546
578
QgsCoordinateReferenceSystem layerCrs = layer->crs ();
547
579
548
- startGetFeature ( request, format );
580
+ startGetFeature ( request, format, layerCrs, &searchRect );
549
581
550
582
if ( fidOk )
551
583
{
@@ -589,8 +621,6 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
589
621
}
590
622
else
591
623
{
592
- if ( bboxOk )
593
- searchRect.set ( minx, miny, maxx, maxy );
594
624
provider->select ( attrIndexes, searchRect, mWithGeom , true );
595
625
while ( provider->nextFeature ( feature ) && featureCounter < maxFeat )
596
626
{
@@ -608,25 +638,102 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
608
638
return 0 ;
609
639
}
610
640
611
- void QgsWFSServer::startGetFeature ( QgsRequestHandler& request, const QString& format )
641
+ void QgsWFSServer::startGetFeature ( QgsRequestHandler& request, const QString& format, QgsCoordinateReferenceSystem& crs, QgsRectangle* rect )
612
642
{
613
643
QByteArray result;
614
644
QString fcString;
615
645
if ( format == " GeoJSON" )
616
646
{
617
647
fcString = " {\" type\" : \" FeatureCollection\" ,\n " ;
648
+ fcString += " \" bbox\" : [ " + QString::number ( rect->xMinimum (), ' f' ) +" , " + QString::number ( rect->yMinimum (), ' f' ) +" , " + QString::number ( rect->xMaximum (), ' f' ) +" , " + QString::number ( rect->yMaximum (), ' f' ) +" ],\n " ;
618
649
fcString += " \" features\" : [\n " ;
619
650
result = fcString.toUtf8 ();
620
651
request.startGetFeatureResponse ( &result, format );
621
652
}
622
653
else
623
654
{
655
+ // Prepare url
656
+ // Some client requests already have http://<SERVER_NAME> in the REQUEST_URI variable
657
+ QString hrefString;
658
+ QString requestUrl = getenv ( " REQUEST_URI" );
659
+ QUrl mapUrl ( requestUrl );
660
+ mapUrl.setHost ( QString ( getenv ( " SERVER_NAME" ) ) );
661
+
662
+ // Add non-default ports to url
663
+ QString portString = getenv ( " SERVER_PORT" );
664
+ if ( !portString.isEmpty () )
665
+ {
666
+ bool portOk;
667
+ int portNumber = portString.toInt ( &portOk );
668
+ if ( portOk )
669
+ {
670
+ if ( portNumber != 80 )
671
+ {
672
+ mapUrl.setPort ( portNumber );
673
+ }
674
+ }
675
+ }
676
+
677
+ if ( QString ( getenv ( " HTTPS" ) ).compare ( " on" , Qt::CaseInsensitive ) == 0 )
678
+ {
679
+ mapUrl.setScheme ( " https" );
680
+ }
681
+ else
682
+ {
683
+ mapUrl.setScheme ( " http" );
684
+ }
685
+
686
+ QList<QPair<QString, QString> > queryItems = mapUrl.queryItems ();
687
+ QList<QPair<QString, QString> >::const_iterator queryIt = queryItems.constBegin ();
688
+ for ( ; queryIt != queryItems.constEnd (); ++queryIt )
689
+ {
690
+ if ( queryIt->first .compare ( " REQUEST" , Qt::CaseInsensitive ) == 0 )
691
+ {
692
+ mapUrl.removeQueryItem ( queryIt->first );
693
+ mapUrl.addQueryItem ( queryIt->first , " DescribeFeatureType" );
694
+ }
695
+ else if ( queryIt->first .compare ( " FORMAT" , Qt::CaseInsensitive ) == 0 )
696
+ {
697
+ mapUrl.removeQueryItem ( queryIt->first );
698
+ }
699
+ else if ( queryIt->first .compare ( " OUTPUTFORMAT" , Qt::CaseInsensitive ) == 0 )
700
+ {
701
+ mapUrl.removeQueryItem ( queryIt->first );
702
+ }
703
+ else if ( queryIt->first .compare ( " BBOX" , Qt::CaseInsensitive ) == 0 )
704
+ {
705
+ mapUrl.removeQueryItem ( queryIt->first );
706
+ }
707
+ else if ( queryIt->first .compare ( " FEATUREID" , Qt::CaseInsensitive ) == 0 )
708
+ {
709
+ mapUrl.removeQueryItem ( queryIt->first );
710
+ }
711
+ else if ( queryIt->first .compare ( " FILTER" , Qt::CaseInsensitive ) == 0 )
712
+ {
713
+ mapUrl.removeQueryItem ( queryIt->first );
714
+ }
715
+ else if ( queryIt->first .compare ( " MAXFEATURES" , Qt::CaseInsensitive ) == 0 )
716
+ {
717
+ mapUrl.removeQueryItem ( queryIt->first );
718
+ }
719
+ else if ( queryIt->first .compare ( " PROPERTYNAME" , Qt::CaseInsensitive ) == 0 )
720
+ {
721
+ mapUrl.removeQueryItem ( queryIt->first );
722
+ }
723
+ else if ( queryIt->first .compare ( " _DC" , Qt::CaseInsensitive ) == 0 )
724
+ {
725
+ mapUrl.removeQueryItem ( queryIt->first );
726
+ }
727
+ }
728
+ mapUrl.addQueryItem ( " OUTPUTFORMAT" , " XMLSCHEMA" );
729
+ hrefString = mapUrl.toString ();
730
+
624
731
// wfs:FeatureCollection
625
732
fcString = " <wfs:FeatureCollection" ;
626
733
fcString += " xmlns=\" http://www.opengis.net/wfs\" " ;
627
734
fcString += " xmlns:wfs=\" http://www.opengis.net/wfs\" " ;
628
735
fcString += " xmlns:xsi=\" http://www.w3.org/2001/XMLSchema-instance\" " ;
629
- fcString += " xsi:schemaLocation=\" http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd\" " ;
736
+ fcString += " xsi:schemaLocation=\" http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd http://www.opengis.net/gml " + hrefString. replace ( " & " , " & " ) + " \" " ;
630
737
fcString += " xmlns:ogc=\" http://www.opengis.net/ogc\" " ;
631
738
fcString += " xmlns:gml=\" http://www.opengis.net/gml\" " ;
632
739
fcString += " xmlns:ows=\" http://www.opengis.net/ows\" " ;
@@ -635,6 +742,21 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
635
742
fcString += " >" ;
636
743
result = fcString.toUtf8 ();
637
744
request.startGetFeatureResponse ( &result, format );
745
+
746
+ QDomDocument doc;
747
+ QDomElement bbElem = doc.createElement ( " gml:boundedBy" );
748
+ QDomElement boxElem = createBoxElem ( rect, doc );
749
+ if ( !boxElem.isNull () )
750
+ {
751
+ if ( crs.isValid () )
752
+ {
753
+ boxElem.setAttribute ( " srsName" , crs.authid () );
754
+ }
755
+ bbElem.appendChild ( boxElem );
756
+ doc.appendChild ( bbElem );
757
+ }
758
+ result = doc.toByteArray ();
759
+ request.sendGetFeatureResponse ( &result );
638
760
}
639
761
fcString = " " ;
640
762
}
@@ -701,6 +823,10 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, QgsCoordinateRefer
701
823
QgsGeometry* geom = feat->geometry ();
702
824
if ( geom && mWithGeom )
703
825
{
826
+ QgsRectangle box = geom->boundingBox ();
827
+
828
+ fStr += " \" bbox\" : [ " + QString::number ( box.xMinimum (), ' f' ) +" , " + QString::number ( box.yMinimum (), ' f' ) +" , " + QString::number ( box.xMaximum (), ' f' ) +" , " + QString::number ( box.yMaximum (), ' f' ) +" ],\n " ;
829
+
704
830
fStr += " \" geometry\" : " ;
705
831
fStr += geom->exportToGeoJSON ();
706
832
fStr += " ,\n " ;
@@ -759,14 +885,25 @@ QDomElement QgsWFSServer::createFeatureElem( QgsFeature* feat, QDomDocument& doc
759
885
if ( mWithGeom )
760
886
{
761
887
// add geometry column (as gml)
888
+ QgsGeometry* geom = feat->geometry ();
889
+
762
890
QDomElement geomElem = doc.createElement ( " qgs:geometry" );
763
- QDomElement gmlElem = createGeometryElem ( feat-> geometry () , doc );
891
+ QDomElement gmlElem = createGeometryElem ( geom , doc );
764
892
if ( !gmlElem.isNull () )
765
893
{
894
+ QgsRectangle box = geom->boundingBox ();
895
+ QDomElement bbElem = doc.createElement ( " gml:boundedBy" );
896
+ QDomElement boxElem = createBoxElem ( &box, doc );
897
+
766
898
if ( crs.isValid () )
767
899
{
900
+ boxElem.setAttribute ( " srsName" , crs.authid () );
768
901
gmlElem.setAttribute ( " srsName" , crs.authid () );
769
902
}
903
+
904
+ bbElem.appendChild ( boxElem );
905
+ typeNameElement.appendChild ( bbElem );
906
+
770
907
geomElem.appendChild ( gmlElem );
771
908
typeNameElement.appendChild ( geomElem );
772
909
}
@@ -793,6 +930,27 @@ QDomElement QgsWFSServer::createFeatureElem( QgsFeature* feat, QDomDocument& doc
793
930
return featureElement;
794
931
}
795
932
933
+ QDomElement QgsWFSServer::createBoxElem ( QgsRectangle* box, QDomDocument& doc ) /* const*/
934
+ {
935
+ if ( !box )
936
+ {
937
+ return QDomElement ();
938
+ }
939
+
940
+ QDomElement boxElem = doc.createElement ( " gml:Box" );
941
+ QVector<QgsPoint> v;
942
+ QgsPoint p1;
943
+ p1.set ( box->xMinimum (), box->yMinimum () );
944
+ v.append ( p1 );
945
+ QgsPoint p2;
946
+ p2.set ( box->xMaximum (), box->yMaximum () );
947
+ v.append ( p2 );
948
+ QDomElement coordElem = createCoordinateElem ( v, doc );
949
+ boxElem.appendChild ( coordElem );
950
+
951
+ return boxElem;
952
+ }
953
+
796
954
QDomElement QgsWFSServer::createGeometryElem ( QgsGeometry* geom, QDomDocument& doc ) /* const*/
797
955
{
798
956
if ( !geom )
@@ -931,13 +1089,13 @@ QDomElement QgsWFSServer::createPolygonElem( QgsGeometry* geom, QDomDocument& do
931
1089
QString boundaryName;
932
1090
if ( i == 0 )
933
1091
{
934
- boundaryName = " outerBoundaryIs" ;
1092
+ boundaryName = " gml: outerBoundaryIs" ;
935
1093
}
936
1094
else
937
1095
{
938
- boundaryName = " innerBoundaryIs" ;
1096
+ boundaryName = " gml: innerBoundaryIs" ;
939
1097
}
940
- QDomElement boundaryElem = doc.createElementNS ( " http://www.opengis.net/gml " , boundaryName );
1098
+ QDomElement boundaryElem = doc.createElement ( boundaryName );
941
1099
QDomElement ringElem = doc.createElement ( " gml:LinearRing" );
942
1100
QDomElement coordElem = createCoordinateElem ( poly.at ( i ), doc );
943
1101
ringElem.appendChild ( coordElem );
@@ -979,7 +1137,7 @@ QDomElement QgsWFSServer::createCoordinateElem( const QVector<QgsPoint> points,
979
1137
coordElem.setAttribute ( " ts" , " " );
980
1138
981
1139
// precision 4 for meters / feet, precision 8 for degrees
982
- int precision = 8 ;
1140
+ int precision = 6 ;
983
1141
/*
984
1142
if ( mSourceCRS.mapUnits() == QGis::Meters
985
1143
|| mSourceCRS.mapUnits() == QGis::Feet )
@@ -996,9 +1154,9 @@ QDomElement QgsWFSServer::createCoordinateElem( const QVector<QgsPoint> points,
996
1154
{
997
1155
coordString += " " ;
998
1156
}
999
- coordString += QString::number ( pointIt->x (), ' f' , precision );
1157
+ coordString += QString::number ( pointIt->x (), ' f' );
1000
1158
coordString += " ," ;
1001
- coordString += QString::number ( pointIt->y (), ' f' , precision );
1159
+ coordString += QString::number ( pointIt->y (), ' f' );
1002
1160
}
1003
1161
1004
1162
QDomText coordText = doc.createTextNode ( coordString );
0 commit comments