Merge pull request #13749 from ahocevar/gml-polygon-ring-curve

Support GML polygons with ring curves instead of linear rings
This commit is contained in:
Andreas Hocevar
2022-06-12 13:35:41 +02:00
committed by GitHub
3 changed files with 118 additions and 10 deletions

View File

@@ -13,6 +13,7 @@ import {
XML_SCHEMA_INSTANCE_URI, XML_SCHEMA_INSTANCE_URI,
createElementNS, createElementNS,
getAllTextContent, getAllTextContent,
makeArrayExtender,
makeArrayPusher, makeArrayPusher,
makeChildAppender, makeChildAppender,
makeReplacer, makeReplacer,
@@ -133,6 +134,27 @@ class GML3 extends GMLBase {
} }
} }
/**
* @param {Element} node Node.
* @param {Array<*>} objectStack Object stack.
* @return {Array<number>|undefined} Polygon.
*/
readFlatCurveRing(node, objectStack) {
/** @type {Array<LineString>} */
const lineStrings = pushParseAndPop(
[],
this.MULTICURVE_PARSERS,
node,
objectStack,
this
);
const flatCoordinates = [];
for (let i = 0, ii = lineStrings.length; i < ii; ++i) {
extend(flatCoordinates, lineStrings[i].getFlatCoordinates());
}
return flatCoordinates;
}
/** /**
* @param {Element} node Node. * @param {Element} node Node.
* @param {Array<*>} objectStack Object stack. * @param {Array<*>} objectStack Object stack.
@@ -189,13 +211,7 @@ class GML3 extends GMLBase {
* @return {Array<number>|undefined} flat coordinates. * @return {Array<number>|undefined} flat coordinates.
*/ */
readSegment(node, objectStack) { readSegment(node, objectStack) {
return pushParseAndPop( return pushParseAndPop([], this.SEGMENTS_PARSERS, node, objectStack, this);
[null],
this.SEGMENTS_PARSERS,
node,
objectStack,
this
);
} }
/** /**
@@ -1161,7 +1177,20 @@ GML3.prototype.PATCHES_PARSERS = {
*/ */
GML3.prototype.SEGMENTS_PARSERS = { GML3.prototype.SEGMENTS_PARSERS = {
'http://www.opengis.net/gml': { 'http://www.opengis.net/gml': {
'LineStringSegment': makeReplacer(GML3.prototype.readLineStringSegment), 'LineStringSegment': makeArrayExtender(
GML3.prototype.readLineStringSegment
),
},
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
*/
GMLBase.prototype.RING_PARSERS = {
'http://www.opengis.net/gml': {
'LinearRing': makeReplacer(GMLBase.prototype.readFlatLinearRing),
'Ring': makeReplacer(GML3.prototype.readFlatCurveRing),
}, },
}; };

View File

@@ -4,7 +4,12 @@
import GML2 from './GML2.js'; import GML2 from './GML2.js';
import GML3 from './GML3.js'; import GML3 from './GML3.js';
import GMLBase from './GMLBase.js'; import GMLBase from './GMLBase.js';
import {makeArrayPusher, makeChildAppender, makeReplacer} from '../xml.js'; import {
makeArrayExtender,
makeArrayPusher,
makeChildAppender,
makeReplacer,
} from '../xml.js';
import {writeStringTextNode} from '../format/xsd.js'; import {writeStringTextNode} from '../format/xsd.js';
/** /**
@@ -169,7 +174,9 @@ GML32.prototype.PATCHES_PARSERS = {
*/ */
GML32.prototype.SEGMENTS_PARSERS = { GML32.prototype.SEGMENTS_PARSERS = {
'http://www.opengis.net/gml/3.2': { 'http://www.opengis.net/gml/3.2': {
'LineStringSegment': makeReplacer(GML3.prototype.readLineStringSegment), 'LineStringSegment': makeArrayExtender(
GML3.prototype.readLineStringSegment
),
}, },
}; };
@@ -247,6 +254,7 @@ GML32.prototype.POLYGONMEMBER_PARSERS = {
GML32.prototype.RING_PARSERS = { GML32.prototype.RING_PARSERS = {
'http://www.opengis.net/gml/3.2': { 'http://www.opengis.net/gml/3.2': {
'LinearRing': makeReplacer(GMLBase.prototype.readFlatLinearRing), 'LinearRing': makeReplacer(GMLBase.prototype.readFlatLinearRing),
'Ring': makeReplacer(GML32.prototype.readFlatCurveRing),
}, },
}; };

View File

@@ -2252,6 +2252,77 @@ describe('ol.format.GML32', function () {
const serialized = format.writeGeometryNode(g); const serialized = format.writeGeometryNode(g);
expect(serialized.firstElementChild).to.xmleql(parse(text)); expect(serialized.firstElementChild).to.xmleql(parse(text));
}); });
it('can read and write a curve geometry', function () {
const text =
'<gml:Curve xmlns:gml="http://www.opengis.net/gml/3.2" ' +
' srsName="CRS:84">' +
' <gml:segments>' +
' <gml:LineStringSegment>' +
' <gml:posList srsDimension="2">1 2 3 4</gml:posList>' +
' </gml:LineStringSegment>' +
' <gml:LineStringSegment>' +
' <gml:posList srsDimension="2">5 6 7 8</gml:posList>' +
' </gml:LineStringSegment>' +
' </gml:segments>' +
'</gml:Curve>';
const g = readGeometry(format, text);
expect(g).to.be.an(LineString);
expect(g.getCoordinates()).to.eql([
[1, 2, 0],
[3, 4, 0],
[5, 6, 0],
[7, 8, 0],
]);
format = new GML32({srsName: 'CRS:84', curve: true});
const serialized = format.writeGeometryNode(g);
// Conversion back to GML is not lossless, because we don't know
// the mapping of original LineString segements to the OpenLayers
// LineString geometry's coordinates.
const expected =
'<gml:Curve xmlns:gml="http://www.opengis.net/gml/3.2" ' +
' srsName="CRS:84">' +
' <gml:segments>' +
' <gml:LineStringSegment>' +
' <gml:posList srsDimension="2">1 2 3 4 5 6 7 8</gml:posList>' +
' </gml:LineStringSegment>' +
' </gml:segments>' +
'</gml:Curve>';
expect(serialized.firstElementChild).to.xmleql(parse(expected));
});
it('can read a polygon with a ring of curves', function () {
const text = `
<gml:Polygon xmlns:gml="http://www.opengis.net/gml/3.2" srsName="CRS:84">
<gml:exterior>
<gml:Ring>
<gml:curveMember>
<gml:Curve>
<gml:segments>
<gml:LineStringSegment interpolation="linear">
<gml:posList>1 2 3 4</gml:posList>
</gml:LineStringSegment>
<gml:LineStringSegment interpolation="linear">
<gml:posList>5 6 7 8</gml:posList>
</gml:LineStringSegment>
</gml:segments>
</gml:Curve>
</gml:curveMember>
</gml:Ring>
</gml:exterior>
</gml:Polygon>
`;
const g = readGeometry(format, text);
expect(g).to.be.an(Polygon);
expect(g.getCoordinates()).to.eql([
[
[1, 2, 0],
[3, 4, 0],
[5, 6, 0],
[7, 8, 0],
],
]);
});
}); });
describe('envelope', function () { describe('envelope', function () {