Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce polygon query #5125

Merged
merged 3 commits into from
Sep 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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