isoxml-angular
Version:
JavaScript library to parse and generate ISOXML (ISO11783-10) files
149 lines (148 loc) • 7.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtendedPolygon = void 0;
const turf_1 = require("@turf/turf");
const polygon_clipping_1 = require("polygon-clipping");
const baseEntities_1 = require("../baseEntities");
const classRegistry_1 = require("../classRegistry");
const LineString_1 = require("./LineString");
class ExtendedPolygon extends baseEntities_1.Polygon {
constructor(attributes, isoxmlManager) {
super(attributes, isoxmlManager);
this.tag = "PLN" /* TAGS.Polygon */;
}
static fromXML(xml, isoxmlManager, internalId) {
return baseEntities_1.Polygon.fromXML(xml, isoxmlManager, internalId, ExtendedPolygon);
}
static fromGeoJSON(geoJSON, polygonType, isoxmlManager) {
if (geoJSON.type === 'Polygon') {
geoJSON = {
type: 'MultiPolygon',
coordinates: [geoJSON.coordinates]
};
}
if (isoxmlManager.options.version === 3) {
const lineStrings = [].concat(...geoJSON.coordinates.map(component => component.map((ring, idx) => LineString_1.ExtendedLineString.fromGeoJSONCoordinates(ring, isoxmlManager, idx
? "2" /* LineStringLineStringTypeEnum.PolygonInterior */
: "1" /* LineStringLineStringTypeEnum.PolygonExterior */))));
return [new ExtendedPolygon({
PolygonType: polygonType,
LineString: lineStrings
}, isoxmlManager)];
}
else {
return geoJSON.coordinates.map(component => new ExtendedPolygon({
PolygonType: polygonType,
LineString: component.map((ring, idx) => LineString_1.ExtendedLineString.fromGeoJSONCoordinates(ring, isoxmlManager, idx
? "2" /* LineStringLineStringTypeEnum.PolygonInterior */
: "1" /* LineStringLineStringTypeEnum.PolygonExterior */))
}, isoxmlManager));
}
}
// converts polygons to fits format of the target ISOXML version (taken from the first Polygon)
static normalizePolygons(polygons) {
if (!polygons || polygons.length === 0) {
return [];
}
const isoxmlManager = polygons[0].isoxmlManager;
if (isoxmlManager.options.version === 3) {
if (polygons.length === 1) {
return polygons;
}
const allLineStrings = [].concat(...polygons.map(poly => poly.attributes.LineString));
const combinedPolygon = new ExtendedPolygon(Object.assign(Object.assign({}, polygons[0].attributes), { LineString: allLineStrings }), isoxmlManager);
delete combinedPolygon.attributes.PolygonArea; // area recalculation is not implemented
return [combinedPolygon];
}
else {
const splittedPolygons = [];
polygons.forEach(polygon => {
const outerRings = polygon.attributes.LineString
.filter((ring) => ring.attributes.LineStringType === "1" /* LineStringLineStringTypeEnum.PolygonExterior */);
if (outerRings.length <= 1) {
splittedPolygons.push(polygon);
return;
}
const innerRings = polygon.attributes.LineString
.filter((ring) => ring.attributes.LineStringType === "2" /* LineStringLineStringTypeEnum.PolygonInterior */);
const outerRingIdxs = innerRings.map((ring) => {
let maxArea = 0;
let bestIdx = -1;
outerRings.forEach((outerRing, idx) => {
const intersectionRes = (0, polygon_clipping_1.intersection)([outerRing.toCoordinatesArray()], [ring.toCoordinatesArray()]);
if (intersectionRes) {
const areaRes = (0, turf_1.area)({ type: 'MultiPolygon', coordinates: intersectionRes });
if (areaRes > maxArea) {
maxArea = areaRes;
bestIdx = idx;
}
}
});
return bestIdx;
});
outerRings.forEach((outerRing, outerIdx) => {
const splittedPolygon = new ExtendedPolygon(Object.assign(Object.assign({}, polygon.attributes), { LineString: [
outerRing,
...innerRings.filter((_, innerIdx) => outerRingIdxs[innerIdx] === outerIdx)
] }), isoxmlManager);
delete splittedPolygon.attributes.PolygonArea; // area recalculation is not implemented
splittedPolygons.push(splittedPolygon);
});
});
return splittedPolygons;
}
}
static toGeoJSON(polygons) {
if (!polygons || polygons.length === 0) {
return null;
}
const geoJSONCoordinates = [];
polygons.forEach(polygon => {
const outerRings = polygon.attributes.LineString
.filter((ring) => ring.attributes.LineStringType === "1" /* LineStringLineStringTypeEnum.PolygonExterior */)
.map((ring) => ring.toCoordinatesArray());
const innerRings = polygon.attributes.LineString
.filter((ring) => ring.attributes.LineStringType === "2" /* LineStringLineStringTypeEnum.PolygonInterior */)
.map((ring) => ring.toCoordinatesArray());
if (outerRings.length === 0) {
return;
}
else if (outerRings.length === 1) {
geoJSONCoordinates.push([
outerRings[0],
...innerRings
]);
return;
}
const outerRingIdxs = innerRings.map((ring) => {
let maxArea = 0;
let bestIdx = -1;
outerRings.forEach((outerRing, idx) => {
const intersectionRes = (0, polygon_clipping_1.intersection)([outerRing], [ring]);
if (intersectionRes) {
const areaRes = (0, turf_1.area)({ type: 'MultiPolygon', coordinates: intersectionRes });
if (areaRes > maxArea) {
maxArea = areaRes;
bestIdx = idx;
}
}
});
return bestIdx;
});
outerRings.forEach((outerRing, outerIdx) => {
geoJSONCoordinates.push([
outerRing,
...innerRings.filter((_, innerIdx) => outerRingIdxs[innerIdx] === outerIdx)
]);
});
});
const geoJSON = {
type: 'MultiPolygon',
coordinates: geoJSONCoordinates
};
geoJSON.bbox = (0, turf_1.bbox)(geoJSON);
return geoJSON;
}
}
exports.ExtendedPolygon = ExtendedPolygon;
(0, classRegistry_1.registerEntityClass)('main', "PLN" /* TAGS.Polygon */, ExtendedPolygon);