Skip to content

Commit 8ebfc01

Browse files
Add source projection information to map-sources
Add a `src-proj` property to WFS sources to make configuring the projection information more explicit.
1 parent 73cb88f commit 8ebfc01

File tree

3 files changed

+53
-43
lines changed

3 files changed

+53
-43
lines changed

src/gm3/actions/mapSource.js

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ import {
3636
} from "../components/map/layers/wfs";
3737
import { EDIT_LAYER_NAME } from "../defaults";
3838

39-
import * as util from "../util";
39+
import {
40+
parseBoolean,
41+
getTagContents,
42+
getXmlTextContents,
43+
getMapSourceName,
44+
getLayerName,
45+
} from "../util";
4046

4147
let MS_Z_INDEX = 100000;
4248

@@ -135,7 +141,7 @@ function parseProperties(msXml) {
135141
for (let x = 0, xx = options.length; x < xx; x++) {
136142
propDef.options.push({
137143
value: options[x].getAttribute("value"),
138-
label: util.getXmlTextContents(options[x]),
144+
label: getXmlTextContents(options[x]),
139145
});
140146
}
141147
}
@@ -174,8 +180,8 @@ export const favoriteLayer = createAction(
174180
* @returns Object defining the map source
175181
*/
176182
function mapServerToDestType(msXml, conf, destType) {
177-
let urls = util.getTagContents(msXml, "url", true);
178-
const mapfile = util.getTagContents(msXml, "file", true)[0];
183+
let urls = getTagContents(msXml, "url", true);
184+
const mapfile = getTagContents(msXml, "file", true)[0];
179185

180186
// if the url is null then default to the
181187
// mapserver url.
@@ -220,11 +226,13 @@ function mapServerToWFS(msXml, conf) {
220226

221227
/* MapServer has a pretty major bug, it will not properly
222228
* reproject bounding boxes for non-WGS84 layers when doing
223-
* WFS queries. This tells the query engine in the map component,
224-
* to use an internal work-around ... aka ... "hack".
229+
* WFS queries.
230+
* This forces using a query of projection of 4326 if it
231+
* otherwise not set
225232
*/
226-
wfsConf.wgs84Hack = true;
227-
233+
if (!wfsConf.srcProj) {
234+
wfsConf.srcProj = "EPSG:4326";
235+
}
228236
return wfsConf;
229237
}
230238

@@ -235,21 +243,22 @@ export function addFromXml(xml, config) {
235243
// initialize the map source object.
236244
const mapSource = {
237245
name: xml.getAttribute("name"),
238-
urls: util.getTagContents(xml, "url", true),
246+
urls: getTagContents(xml, "url", true),
239247
type: xml.getAttribute("type"),
240248
label: xml.getAttribute("title"),
241249
opacity: xml.getAttribute("opacity"),
242250
zIndex: xml.getAttribute("z-index"),
243-
queryable: util.parseBoolean(xml.getAttribute("queryable"), true),
251+
queryable: parseBoolean(xml.getAttribute("queryable"), true),
244252
// assume layers are printable
245-
printable: util.parseBoolean(xml.getAttribute("printable"), true),
253+
printable: parseBoolean(xml.getAttribute("printable"), true),
246254
refresh: null,
247255
layers: [],
248256
transforms: {},
249257
params: {},
250258
config: {},
251259
properties: [],
252260
idProperty: "_uuid",
261+
srcProj: xml.getAttribute("src-proj"),
253262
};
254263

255264
// handle setting up the zIndex
@@ -315,9 +324,9 @@ export function addFromXml(xml, config) {
315324

316325
const layer = {
317326
name: layerXml.getAttribute("name"),
318-
on: util.parseBoolean(layerXml.getAttribute("status")),
319-
favorite: util.parseBoolean(layerXml.getAttribute("favorite")),
320-
selectable: util.parseBoolean(layerXml.getAttribute("selectable")),
327+
on: parseBoolean(layerXml.getAttribute("status")),
328+
favorite: parseBoolean(layerXml.getAttribute("favorite")),
329+
selectable: parseBoolean(layerXml.getAttribute("selectable")),
321330
label: layerTitle ? layerTitle : mapSource.label,
322331
templates: {},
323332
legend: null,
@@ -332,14 +341,14 @@ export function addFromXml(xml, config) {
332341
if (legends.length > 0) {
333342
layer.legend = {
334343
type: legends[0].getAttribute("type"),
335-
contents: util.getXmlTextContents(legends[0]),
344+
contents: getXmlTextContents(legends[0]),
336345
};
337346
}
338347

339348
// pull in an HTML attribution as available.
340349
const attribution = layerXml.getElementsByTagName("attribution");
341350
if (attribution.length > 0) {
342-
layer.attribution = util.getXmlTextContents(attribution[0]);
351+
layer.attribution = getXmlTextContents(attribution[0]);
343352
}
344353

345354
const templates = layerXml.getElementsByTagName("template");
@@ -351,7 +360,7 @@ export function addFromXml(xml, config) {
351360

352361
const templateSrc = templateXml.getAttribute("src");
353362
const templateAlias = templateXml.getAttribute("alias");
354-
const autoTemplate = util.parseBoolean(templateXml.getAttribute("auto"));
363+
const autoTemplate = parseBoolean(templateXml.getAttribute("auto"));
355364
if (templateAlias) {
356365
templateDef = {
357366
type: "alias",
@@ -369,17 +378,16 @@ export function addFromXml(xml, config) {
369378
} else {
370379
templateDef = {
371380
type: "local",
372-
contents: util.getXmlTextContents(templateXml),
381+
contents: getXmlTextContents(templateXml),
373382
};
374383
}
375384
templateDef.highlight =
376-
util.parseBoolean(templateXml.getAttribute("highlight"), true) !==
377-
false;
385+
parseBoolean(templateXml.getAttribute("highlight"), true) !== false;
378386
layer.templates[templateName] = templateDef;
379387
}
380388

381389
// check to see if there are any style definitions
382-
const style = util.getTagContents(layerXml, "style", false);
390+
const style = getTagContents(layerXml, "style", false);
383391
if (style && style.length > 0) {
384392
// convert to JSON
385393
try {
@@ -394,7 +402,7 @@ export function addFromXml(xml, config) {
394402
}
395403

396404
// check to see if there are any filter definitions
397-
const filter = util.getTagContents(layerXml, "filter", false);
405+
const filter = getTagContents(layerXml, "filter", false);
398406
if (filter && filter.length > 0) {
399407
// convert to JSON
400408
try {
@@ -526,8 +534,8 @@ export function getActiveMapSources(mapSources, onlyPrintable = false) {
526534
}
527535

528536
export function getLayerFromPath(mapSources, path) {
529-
const mapSourceName = util.getMapSourceName(path);
530-
const layerName = util.getLayerName(path);
537+
const mapSourceName = getMapSourceName(path);
538+
const layerName = getLayerName(path);
531539

532540
return getLayer(mapSources, {
533541
mapSourceName: mapSourceName,
@@ -754,11 +762,11 @@ export function removeFeature(path, feature) {
754762
return (dispatch, getState) => {
755763
const mapSources = getState().mapSources;
756764
const layer = getLayerFromPath(mapSources, path);
757-
const layerSrcName = util.getMapSourceName(path);
765+
const layerSrcName = getMapSourceName(path);
758766

759767
let mapSourceName = layerSrcName;
760768
if (layer && layer.queryAs && layer.queryAs.length > 0) {
761-
mapSourceName = util.getMapSourceName(layer.queryAs[0]);
769+
mapSourceName = getMapSourceName(layer.queryAs[0]);
762770
}
763771

764772
const mapSource = getState().mapSources[mapSourceName];
@@ -945,11 +953,11 @@ export function saveFeature(path, feature) {
945953
return (dispatch, getState) => {
946954
const mapSources = getState().mapSources;
947955
const layer = getLayerFromPath(mapSources, path);
948-
const layerSrcName = util.getMapSourceName(path);
956+
const layerSrcName = getMapSourceName(path);
949957

950958
let mapSourceName = layerSrcName;
951959
if (layer && layer.queryAs && layer.queryAs.length > 0) {
952-
mapSourceName = util.getMapSourceName(layer.queryAs[0]);
960+
mapSourceName = getMapSourceName(layer.queryAs[0]);
953961
}
954962

955963
const mapSource = getState().mapSources[mapSourceName];

src/gm3/components/map/layers/wfs.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ import * as proj from "ol/proj";
3131

3232
import { featureToJson, transformFeatures } from "../../../util";
3333

34+
export function getQueryProjection(mapSource, mapProjection) {
35+
return mapSource.config?.srs || mapSource.srcProj || mapProjection;
36+
}
37+
3438
function chainFilters(operator, filters) {
3539
let chainedFilters = null;
3640
if (filters.length > 1) {
@@ -99,13 +103,10 @@ export function buildWfsQuery(
99103
) {
100104
const geomField = getGeometryName(mapSource);
101105

102-
// the internal storage mechanism requires features
103-
// returned from the query be stored in 4326 and then
104-
// reprojected on render.
105-
let queryProjection = mapProjection;
106-
if (mapSource.wgs84Hack) {
107-
queryProjection = new proj.get("EPSG:4326");
108-
}
106+
// The WFS source may be in a different projection than the map
107+
const queryProjection = new proj.get(
108+
getQueryProjection(mapSource, mapProjection)
109+
);
109110

110111
const filters = [];
111112
if (query.selection && query.selection.length > 0) {
@@ -169,6 +170,7 @@ export function wfsGetFeatures(
169170
mapProjection,
170171
outputFormat
171172
);
173+
const queryProjection = getQueryProjection(mapSource, mapProjection);
172174

173175
// TODO: check for params and properly join to URL!
174176

@@ -181,6 +183,8 @@ export function wfsGetFeatures(
181183
const gmlFormat = new GML2Format();
182184

183185
let features = gmlFormat.readFeatures(response).map((feature) => {
186+
feature.getGeometry().transform(queryProjection, "EPSG:4326");
187+
184188
const jsonFeature = featureToJson(feature);
185189
jsonFeature.properties = {
186190
...jsonFeature.properties,
@@ -202,7 +206,7 @@ function wfsTransact(mapSource, mapProjection, inFeatures) {
202206
const options = {
203207
featurePrefix: typeParts[0],
204208
featureType: typeParts[1],
205-
srsName: config.srs || "EPSG:3857",
209+
srsName: getQueryProjection(mapSource, mapProjection),
206210
};
207211

208212
if (config["namespace-uri"]) {

src/gm3/query/wfs.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@ import GML2Format from "ol/format/GML2";
55
import { applyPixelTolerance } from "./util";
66
import { transformFeatures, formatUrlParameters } from "../util";
77

8-
import { buildWfsQuery } from "../components/map/layers/wfs";
8+
import {
9+
buildWfsQuery,
10+
getQueryProjection,
11+
} from "../components/map/layers/wfs";
912

1013
export const wfsGetFeatureQuery = (layer, mapState, mapSource, query) => {
11-
// the internal storage mechanism requires features
12-
// returned from the query be stored in 4326 and then
13-
// reprojected on render.
14-
const queryProjection = mapSource.wgs84Hack
15-
? "EPSG:4326"
16-
: mapState.projection;
14+
const queryProjection = getQueryProjection(mapSource, mapState.projection);
1715

1816
// check for the outputFormat based on the params
1917
let outputFormat = "text/xml; subtype=gml/2.1.2";

0 commit comments

Comments
 (0)