kmap-ui
Version:
A components of zmap base on vue2.X
350 lines (333 loc) • 11.7 kB
JavaScript
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
import ol_format_GeoJSON from 'ol/format/GeoJSON'
import ol_ext_inherits from '../util/ext'
/** Feature format for reading and writing data in the GeoJSONX format.
* @constructor
* @extends {ol_format_GeoJSON}
* @param {*} options options.
* @param {number} options.decimals number of decimals to save, default 7 for EPSG:4326, 2 for other projections
* @param {boolean|Array<*>} options.deleteNullProperties An array of property values to remove, if false, keep all properties, default [null,undefined,""]
* @param {boolean|Array<*>} options.extended Decode/encode extended GeoJSON with foreign members (id, bbox, title, etc.), default false
* @param {Array<string>|function} options.whiteList A list of properties to keep on features when encoding or a function that takes a property name and retrun true if the property is whitelisted
* @param {Array<string>|function} options.blackList A list of properties to remove from features when encoding or a function that takes a property name and retrun true if the property is blacklisted
* @param {ol.ProjectionLike} options.dataProjection Projection of the data we are reading. If not provided `EPSG:4326`
* @param {ol.ProjectionLike} options.featureProjection Projection of the feature geometries created by the format reader. If not provided, features will be returned in the dataProjection.
*/
var ol_format_GeoJSONX = function(options) {
options = options || {};
ol_format_GeoJSON.call (this, options);
this._hash = {};
this._count = 0;
this._extended = options.extended;
if (typeof(options.whiteList)==='function') {
this._whiteList = options.whiteList;
} else if (options.whiteList && options.whiteList.indexOf) {
this._whiteList = function (k) { return options.whiteList.indexOf(k) > -1 };
} else {
this._whiteList = function() { return true };
}
if (typeof(options.blackList)==='function') {
this._blackList = options.blackList;
} else if (options.blackList && options.blackList.indexOf) {
this._blackList = function (k) { return options.blackList.indexOf(k) > -1 };
} else {
this._blackList = function() { return false };
}
this._deleteNull = options.deleteNullProperties===false ? false : [null,undefined,""];
var decimals = 2;
if (!options.dataProjection || options.dataProjection === 'EPSG:4326') decimals = 7;
if (!isNaN(parseInt(options.decimals))) decimals = parseInt(options.decimals);
this._decimals = decimals;
};
ol_ext_inherits(ol_format_GeoJSONX, ol_format_GeoJSON);
/** Radix */
ol_format_GeoJSONX.prototype._radix =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ !#$%&\'()*-.:<=>?@[]^_`{|}~';
/** Radix size */
ol_format_GeoJSONX.prototype._size = ol_format_GeoJSONX.prototype._radix.length;
/** GeoSJON types */
ol_format_GeoJSONX.prototype._type = {
"Point": 0,
"LineString": 1,
"Polygon": 2,
"MultiPoint": 3,
"MultiLineString": 4,
"MultiPolygon": 5,
"GeometryCollection": null // Not supported
};
/** GeoSJONX types */
ol_format_GeoJSONX.prototype._toType = [
"Point",
"LineString",
"Polygon",
"MultiPoint",
"MultiLineString",
"MultiPolygon"
];
/** Encode a number
* @param {number} number Number to encode
* @private {number} decimals Number of decimals
* @param {string}
*/
ol_format_GeoJSONX.prototype.encodeNumber = function(number, decimals) {
if (isNaN(Number(number)) || number === null || !isFinite(number)) {
number = 0;
}
if (!decimals && decimals!==0) decimals = this._decimals;
// Round number
number = Math.round(number * Math.pow(10, decimals));
// Zigzag encoding (get positive number)
if (number<0) number = -2*number - 1;
else number = 2*number;
// Encode
var result = '';
var modulo, residual = number;
while (true) {
modulo = residual % this._size
result = this._radix.charAt(modulo) + result;
residual = Math.floor(residual / this._size);
if (residual == 0) break;
}
return result;
};
/** Decode a number
* @param {string} s
* @private {number} decimals Number of decimals
* @return {number}
*/
ol_format_GeoJSONX.prototype.decodeNumber = function(s, decimals) {
if (!decimals && decimals!==0) decimals = this._decimals;
var decode = 0;
s.split('').forEach(function (c) {
decode = (decode * this._size) + this._radix.indexOf(c);
}.bind(this));
// Zigzag encoding
var result = Math.floor(decode/2)
if (result !== decode/2) result = -1-result;
return result / Math.pow(10, decimals);
};
/** Encode coordinates
* @param {ol.coordinate|Array<ol.coordinate>} v
* @param {number} decimal
* @return {string|Array<string>}
* @api
*/
ol_format_GeoJSONX.prototype.encodeCoordinates = function(v, decimal) {
var i;
if (typeof(v[0]) === 'number') {
return this.encodeNumber(v[0], decimal) +','+ this.encodeNumber(v[1], decimal);
} else if (v.length && v[0]) {
if (typeof(v[0][0]) === 'number') {
var dxy=[0,0];
var xy = [];
for (i=0; i<v.length; i++) {
v[i] = [
Math.round( v[i][0] * Math.pow(10, decimal)),
Math.round( v[i][1] * Math.pow(10, decimal))
];
var dx = v[i][0]-dxy[0];
var dy = v[i][1]-dxy[1];
if (i==0 || (dx!==0 || dy!==0)) {
xy.push(this.encodeNumber(dx, 0) +','+ this.encodeNumber(dy, 0));
dxy = v[i];
}
}
// Almost 2 points...
if (xy.length<2) xy.push('A,A');
return xy.join(';');
} else {
for (i=0; i<v.length; i++) {
v[i] = this.encodeCoordinates(v[i], decimal);
}
return v;
}
} else {
return this.encodeCoordinates([0,0], decimal);
}
};
/** Decode coordinates
* @param {string|Array<string>}
* @param {number} decimal Number of decimals
* @return {ol.coordinate|Array<ol.coordinate>} v
* @api
*/
ol_format_GeoJSONX.prototype.decodeCoordinates = function(v, decimals) {
var i;
if (typeof(v) === 'string') {
v = v.split(';');
if (v.length>1) {
var dxy=[0,0];
v.forEach(function(vi, i) {
v[i] = vi.split(',');
v[i][0] = this.decodeNumber(v[i][0], decimals) + dxy[0];
v[i][1] = this.decodeNumber(v[i][1], decimals) + dxy[1];
dxy = v[i];
}.bind(this));
return v;
} else {
v = v[0].split(',');
return [ this.decodeNumber(v[0], decimals), this.decodeNumber(v[1], decimals) ];
}
} else if (v.length) {
var r = [];
for (i=0; i<v.length; i++) {
r[i] = this.decodeCoordinates(v[i], decimals);
}
return r;
} else {
return [0,0];
}
};
/** Encode an array of features as a GeoJSONX object.
* @param {Array<ol.Feature>} features Features.
* @param {*} options Write options.
* @return {*} GeoJSONX Object.
* @override
* @api
*/
ol_format_GeoJSONX.prototype.writeFeaturesObject = function (features, options) {
options = options || {};
this._count = 0;
this._hash = {};
var geojson = ol_format_GeoJSON.prototype.writeFeaturesObject.call(this, features, options);
geojson.decimals = this._decimals;
geojson.hashProperties = [];
Object.keys(this._hash).forEach(function(k) {
geojson.hashProperties.push(k);
}.bind(this));
this._count = 0;
this._hash = {};
// Push features at the end of the object
var temp = geojson.features;
delete geojson.features;
geojson.features = temp;
return geojson;
};
/** Encode a set of features as a GeoJSONX object.
* @param {ol.Feature} feature Feature
* @param {*} options Write options.
* @return {*} GeoJSONX Object.
* @override
* @api
*/
ol_format_GeoJSONX.prototype.writeFeatureObject = function(source, options) {
var f0 = ol_format_GeoJSON.prototype.writeFeatureObject.call(this, source, options);
// Only features supported yet
if (f0.type !== 'Feature') throw 'GeoJSONX doesn\'t support '+f0.type+'.';
var f = [];
// Encode geometry
if (f0.geometry.type==='Point') {
f.push(this.encodeCoordinates(f0.geometry.coordinates, this._decimals));
} else {
if (!this._type[f0.geometry.type]) {
throw 'GeoJSONX doesn\'t support '+f0.geometry.type+'.';
}
f.push ([
this._type[f0.geometry.type],
this.encodeCoordinates(f0.geometry.coordinates, this._decimals)
]);
}
// Encode properties
var k;
var prop = [];
for (k in f0.properties) {
if (!this._whiteList(k) || this._blackList(k)) continue;
if (!this._hash.hasOwnProperty(k)) {
this._hash[k] = this._count;
this._count++;
}
if (!this._deleteNull || this._deleteNull.indexOf(f0.properties[k])<0) {
prop.push (this._hash[k], f0.properties[k]);
}
}
// Create prop table
if (prop.length || this._extended) {
f.push(prop);
}
// Other properties (id, title, bbox, centerline...
if (this._extended) {
var found = false;
prop = {};
for (k in f0) {
if (!/^type$|^geometry$|^properties$/.test(k)) {
prop[k] = f0[k];
found = true;
}
}
if (found) f.push(prop);
}
return f;
};
/** Encode a geometry as a GeoJSONX object.
* @param {ol.geom.Geometry} geometry Geometry.
* @param {*} options Write options.
* @return {*} Object.
* @override
* @api
*/
ol_format_GeoJSONX.prototype.writeGeometryObject = function(source, options) {
var g = ol_format_GeoJSON.prototype.writeGeometryObject.call(this, source, options);
// Encode geometry
if (g.type==='Point') {
return this.encodeCoordinates(g.coordinates, this._decimals)
} else {
return [
this._type[g.type],
this.encodeCoordinates(g.coordinates, this._decimals)
];
}
};
/** Decode a GeoJSONX object.
* @param {*} object GeoJSONX
* @param {*} options Read options.
* @return {Array<ol.Feature>}
* @override
* @api
*/
ol_format_GeoJSONX.prototype.readFeaturesFromObject = function (object, options) {
this._hashProperties = object.hashProperties || [];
options = options || {};
options.decimals = parseInt(object.decimals);
if (!options.decimals && options.decimals!==0) throw 'Bad file format...';
var features = ol_format_GeoJSON.prototype.readFeaturesFromObject.call(this, object, options);
return features;
};
/** Decode GeoJSONX Feature object.
* @param {*} object GeoJSONX
* @param {*} options Read options.
* @return {ol.Feature}
*/
ol_format_GeoJSONX.prototype.readFeatureFromObject = function (f0, options) {
var f = {
type: 'Feature'
}
if (typeof(f0[0]) === 'string') {
f.geometry = {
type: 'Point',
coordinates: this.decodeCoordinates(f0[0], typeof(options.decimals) === 'number' ? options.decimals : this.decimals)
}
} else {
f.geometry = {
type: this._toType[f0[0][0]],
coordinates: this.decodeCoordinates(f0[0][1], typeof(options.decimals) === 'number' ? options.decimals : this.decimals)
}
}
if (this._hashProperties && f0[1]) {
f.properties = {};
var t = f0[1];
for (var i=0; i<t.length; i+=2) {
f.properties[this._hashProperties[t[i]]] = t[i+1];
}
} else {
f.properties = f0[1];
}
// Extended properties
if (f0[2]) {
for (var k in f0[2]) {
f[k] = f0[2][k];
}
}
var feature = ol_format_GeoJSON.prototype.readFeatureFromObject.call(this, f, options);
return feature;
};
export default ol_format_GeoJSONX