Skip to content

Commit

Permalink
Merge pull request #5125 from adube/gsgmf-1047-4-query-polygon
Browse files Browse the repository at this point in the history
Introduce polygon query
  • Loading branch information
adube authored Sep 26, 2019
2 parents 2203381 + 895dc19 commit e05262c
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 32 deletions.
25 changes: 16 additions & 9 deletions src/datasource/OGC.js
Original file line number Diff line number Diff line change
Expand Up @@ -595,20 +595,27 @@ class OGC extends ngeoDatasourceDataSource {
}

/**
* @param {?string} layer The layer name.
* @param {string=} layer The layer name.
* @return {?string} Geometry name
*/
geometryName(layer) {
if (!this.ogcAttributes_ || !layer) {
return this.geometryName_;
}
const attributes = this.ogcAttributes_[layer];
for (const attribute in attributes) {
if (attributes[attribute].namespace == 'http://www.opengis.net/gml') {
return attribute;
let geometryName = null;

if (layer && this.ogcAttributes_) {
const attributes = this.ogcAttributes_[layer];
for (const attribute in attributes) {
if (attributes[attribute].namespace == 'http://www.opengis.net/gml') {
geometryName = attribute;
break;
}
}
}
return this.geometryName_;

if (!geometryName) {
geometryName = this.geometryName_;
}

return geometryName;
}

/**
Expand Down
55 changes: 35 additions & 20 deletions src/filter/RuleHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -446,30 +446,12 @@ export class RuleHelper {

if (options.incTime) {
const timeFilter = this.createTimeFilterFromDataSource_(dataSource);
if (timeFilter) {
if (mainFilter) {
mainFilter = olFormatFilter.and.apply(
null,
[
mainFilter,
timeFilter
]
);
} else {
mainFilter = timeFilter;
}
}
mainFilter = this.joinFilters(mainFilter, timeFilter);
}

if (options.incDimensions) {
const dimensionsFilter = this.createDimensionsFilterFromDataSource_(dataSource);
if (dimensionsFilter) {
if (mainFilter) {
mainFilter = olFormatFilter.and.apply(null, [mainFilter, dimensionsFilter]);
} else {
mainFilter = dimensionsFilter;
}
}
mainFilter = this.joinFilters(mainFilter, dimensionsFilter);
}

return mainFilter;
Expand All @@ -490,6 +472,39 @@ export class RuleHelper {
return filterString;
}

/**
* Join 2 filters together in an "And" filter, if both are set.
*
* If only one is set, then no need to create an "And"
* filter. Simply return the one that is set.
*
* If none are set, return null.
*
* @param {?import("ol/format/filter/Filter.js").default} filterA
* First filter.
* @param {?import("ol/format/filter/Filter.js").default} filterB
* Second filter.
* @return {?import("ol/format/filter/Filter.js").default} Filters
* joined together.
*/
joinFilters(filterA, filterB) {
let filter = null;
if (filterA && filterB) {
filter = olFormatFilter.and.apply(
null,
[
filterA,
filterB
]
);
} else if (filterA) {
filter = filterA;
} else if (filterB) {
filter = filterB;
}
return filter;
}

/**
* @param {import("ngeo/rule/Rule.js").default} rule Rule.
* @param {import("ngeo/datasource/OGC.js").default} dataSource Data source.
Expand Down
19 changes: 18 additions & 1 deletion src/query/Querent.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import angular from 'angular';
import ngeoDatasourceOGC from 'ngeo/datasource/OGC.js';
import ngeoFilterRuleHelper from 'ngeo/filter/RuleHelper.js';
import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js';
import * as olFormatFilter from 'ol/format/filter.js';
import olFormatWFS from 'ol/format/WFS.js';
import ngeoWFSDescribeFeatureType from 'ngeo/WFSDescribeFeatureType.js';
import olFormatWMSCapabilities from 'ol/format/WMSCapabilities.js';
Expand Down Expand Up @@ -49,6 +50,8 @@ import olSourceImageWMS from 'ol/source/ImageWMS.js';
* - `replace`: newly queried features are used as result
* - `add`: newly queried features are added to the existing ones
* - `remove`: newly queried features are removed from the existing ones
* @property {import("ol/extent.js").Extent} [bbox] The bbox to issue the requests with,
* which will end up with a WFS request.
* @property {import("ol/coordinate.js").Coordinate} [coordinate] The coordinate to issue the requests with,
* which can end up with either WMS or WFS requests.
* @property {Array<import('ngeo/datasource/DataSource.js').default>} [dataSources] list of data sources to
Expand All @@ -59,6 +62,8 @@ import olSourceImageWMS from 'ol/source/ImageWMS.js';
* @property {import("ol/format/filter/Filter.js").default} [filter] A filter to additionally use with the
* query. Only used by WFS requests.
* If a filter is defined, then it is used instead of the data source's filter rules.
* @property {import("ol/geom/Geometry.js").default} [geometry] The geometry to use as filter for the
* requests, which can end up with WFS requests only.
* @property {number} [limit] The maximum number of features to get per request.
* @property {import("ol/Map.js").default} map The ol3 map object. Used to fill some parameters of the
* queries, such as 'srs' and filter the queryable layers within the data sources.
Expand Down Expand Up @@ -610,7 +615,7 @@ export class Querent {

// (c) Add filter, if any. If the case, then only one data source
// is expected to be used for this request.
let filter;
let filter = null;
if (options.filter) {
filter = this.ngeoRuleHelper_.createFilter({
dataSource: dataSource,
Expand Down Expand Up @@ -638,6 +643,18 @@ export class Querent {
});
}

// (d) If a 'geometry' is set in the query options, then
// create and add a spatial filter it to the existing filter
// as well.
if (options.geometry) {
const spatialFilter = olFormatFilter.intersects(
dataSource.geometryName(),
options.geometry,
srsName
);
filter = this.ngeoRuleHelper_.joinFilters(filter, spatialFilter);
}

if (filter) {
getFeatureCommonOptions.filter = filter;
}
Expand Down
61 changes: 59 additions & 2 deletions src/query/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ class QueryController {
type: 'Circle'
});

/**
* @type {olInteractionDraw}
* @private
*/
this.drawPolygonInteraction_ = new olInteractionDraw({
condition: olEventsConditionAlways,
source: this.vectorSource_,
type: 'Polygon'
});

/**
* The event keys of the currently active "mode".
*
Expand Down Expand Up @@ -229,6 +239,19 @@ class QueryController {
);
break;

case ngeoQueryMode.DRAW_POLYGON:
this.map.addLayer(this.vectorLayer_);
this.map.addInteraction(this.drawPolygonInteraction_);
this.listenerKeys_.push(
olEventsListen(
this.drawPolygonInteraction_,
'drawend',
this.handleDrawPolygonInteractionDrawEnd_,
this
)
);
break;

default:
break;
}
Expand Down Expand Up @@ -263,6 +286,11 @@ class QueryController {
this.map.removeInteraction(this.drawBoxInteraction_);
break;

case ngeoQueryMode.DRAW_POLYGON:
this.map.removeLayer(this.vectorLayer_);
this.map.removeInteraction(this.drawPolygonInteraction_);
break;

default:
break;
}
Expand Down Expand Up @@ -308,7 +336,7 @@ class QueryController {
* @private
*/
handleDrawBoxInteractionDrawEnd_(evt) {
// @ts-ignore: evt should be of type {import('ol/interaction/Draw.js').DrawEvent but he is private
// @ts-ignore: evt should be of type {import('ol/interaction/Draw.js').DrawEvent but it is private
const feature = evt.feature;

const action = this.ngeoQueryModeSelector_.action;
Expand All @@ -330,6 +358,35 @@ class QueryController {
});
}

/**
* Called when a polygon is drawn on the map. Use it to issue a query.
* @param {Event|import("ol/events/Event.js").default} evt The draw
* interaction drawend event being fired.
* @private
*/
handleDrawPolygonInteractionDrawEnd_(evt) {
// @ts-ignore: evt should be of type {import('ol/interaction/Draw.js').DrawEvent but it is private
const feature = evt.feature;

const action = this.ngeoQueryModeSelector_.action;
const geometry = feature.getGeometry();
const limit = this.getLimitOption_();
const map = this.map;

this.ngeoMapQuerent_.issue({
action,
geometry,
limit,
map
})
.then(() => {})
.catch(() => {})
.then(() => {
// "finally"
this.vectorSource_.clear();
});
}

/**
* Called when the map is clicked while this component is active and
* the mode is "click". Issue a request to the query service using
Expand Down Expand Up @@ -392,7 +449,7 @@ class QueryController {
module.component('ngeoQuery', {
bindings: {
'active': '=',
'autoclear': '<?',
'autoclear': '=?',
'map': '<'
},
controller: QueryController
Expand Down
9 changes: 9 additions & 0 deletions src/query/panelComponent.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
>
<%=require('ngeo/icons/rectangle.svg?viewbox&height=1em')%>
</button>
<button
data-toggle="tooltip"
title="{{'While active, click on the map multiple times to draw a polygon, which will issue a query using it' | translate}}"
class="btn btn-default"
ng-class="{active: qpCtrl.ngeoQueryModeSelector.mode === 'drawpolygon'}"
ng-click="qpCtrl.ngeoQueryModeSelector.mode = 'drawpolygon'"
>
<%=require('ngeo/icons/polygon.svg?viewbox&height=1em')%>
</button>
</div>

<div class="ngeo-query-panel-actions">
Expand Down

0 comments on commit e05262c

Please sign in to comment.