UNPKG

openlayermap

Version:

openlayer Map Component for Vue 2.0

829 lines (777 loc) 32.5 kB
import {SuperMap} from '../SuperMap' import {Vector} from '../commontypes/Vector' import {Util} from '../commontypes/Util' import {Bounds} from '../commontypes/Bounds' import {Collection} from '../commontypes/geometry/Collection' import {JSONFormat} from './JSON' import {Point} from '../commontypes/geometry/Point' import {MultiPoint} from '../commontypes/geometry/MultiPoint' import {LineString} from '../commontypes/geometry/LineString' import {MultiLineString} from '../commontypes/geometry/MultiLineString' import {LinearRing} from '../commontypes/geometry/LinearRing' import {Polygon} from '../commontypes/geometry/Polygon' import {MultiPolygon} from '../commontypes/geometry/MultiPolygon' import {GeometryType} from '../REST' /** * @class SuperMap.Format.GeoJSON * @classdesc GeoJSON 的读和写。使用 <SuperMap.Format.GeoJSON> 构造器创建一个GeoJSON解析器。 * @category Format * @extends SuperMap.Format.JSON。 */ export class GeoJSON extends JSONFormat { constructor(options) { super(options) /** * @member SuperMap.Format.GeoJSON.prototype.ignoreExtraDims - {boolean} * @description 忽略维度超过2的几何要素。 */ this.ignoreExtraDims = false this.CLASS_NAME = "SuperMap.Format.GeoJSON" /** * @member SuperMap.Format.GeoJSON.prototype.parseCoords - {Object} * @description 一个属性名对应着GeoJSON对象的几何类型的对象。每个属性其实都是一个实际上做解析用的方法。 */ this.parseCoords = { /** * @function SuperMap.Format.GeoJSON.parseCoords.point * @description 将一组坐标成一个<SuperMap.Geometry>对象。 * @param array - {Object} GeoJSON片段中的一组坐标。 * @return {SuperMap.Geometry} 一个几何对象。 */ "point": function (array) { if (this.ignoreExtraDims == false && array.length != 2) { throw "Only 2D points are supported: " + array } return new Point(array[0], array[1]) }, /** * @function SuperMap.Format.GeoJSON.parseCoords.multipoint * @description 将坐标组数组转化成为一个<SuperMap.Geometry>对象。 * @param array - {Object} GeoJSON片段中的坐标组数组。 * @return {SuperMap.Geometry} 一个几何对象。 */ "multipoint": function (array) { var points = [] var p = null for (var i = 0, len = array.length; i < len; ++i) { try { p = this.parseCoords["point"].apply(this, [array[i]]) } catch (err) { throw err } points.push(p) } return new MultiPoint(points) }, /** * @function SuperMap.Format.GeoJSON.parseCoords.linestring * @description 将坐标组数组转化成为一个<SuperMap.Geometry>对象。 * @param array - {Object} GeoJSON片段中的坐标组数组。 * @return {SuperMap.Geometry} 一个几何对象。 */ "linestring": function (array) { var points = [] var p = null for (var i = 0, len = array.length; i < len; ++i) { try { p = this.parseCoords["point"].apply(this, [array[i]]) } catch (err) { throw err } points.push(p) } return new LineString(points) }, /** * @function SuperMap.Format.GeoJSON.parseCoords.multilinestring * @description 将坐标组数组转化成为一个<SuperMap.Geometry>对象。 * @param array - {Object} GeoJSON片段中的坐标组数组。 * @return {SuperMap.Geometry} 一个几何对象。 */ "multilinestring": function (array) { var lines = [] var l = null for (var i = 0, len = array.length; i < len; ++i) { try { l = this.parseCoords["linestring"].apply(this, [array[i]]) } catch (err) { throw err } lines.push(l) } return new MultiLineString(lines) }, /** * @function SuperMap.Format.GeoJSON.parseCoords.polygon * @description 将坐标组数组转化成为一个<SuperMap.Geometry>对象。 * @return {SuperMap.Geometry} 一个几何对象。 */ "polygon": function (array) { var rings = [] var r, l for (var i = 0, len = array.length; i < len; ++i) { try { l = this.parseCoords["linestring"].apply(this, [array[i]]) } catch (err) { throw err } r = new LinearRing(l.components) rings.push(r) } return new Polygon(rings) }, /** * @function SuperMap.Format.GeoJSON.parseCoords.multipolygon * @description 将坐标组数组转化成为一个<SuperMap.Geometry>对象。 * @param array - {Object} GeoJSON片段中的坐标组数组。 * @return {SuperMap.Geometry} 一个几何对象。 */ "multipolygon": function (array) { var polys = [] var p = null for (var i = 0, len = array.length; i < len; ++i) { try { p = this.parseCoords["polygon"].apply(this, [array[i]]) } catch (err) { throw err } polys.push(p) } return new MultiPolygon(polys) }, /** * @function SuperMap.Format.GeoJSON.parseCoords.box * @description 将坐标组数组转化成为一个<SuperMap.Geometry>对象。 * @param array - {Object} GeoJSON片段中的坐标组数组。 * @return {SuperMap.Geometry} 一个几何对象。 */ "box": function (array) { if (array.length != 2) { throw "GeoJSON box coordinates must have 2 elements" } return new Polygon([ new LinearRing([ new Point(array[0][0], array[0][1]), new Point(array[1][0], array[0][1]), new Point(array[1][0], array[1][1]), new Point(array[0][0], array[1][1]), new Point(array[0][0], array[0][1]) ]) ]) } } /** * Property: extract * 一个属性名对应着GeoJSON类型的对象。其值为相应的实际的解析方法。 */ this.extract = { /** * @function SuperMap.Format.GeoJSON.extract.feature * @description 返回一个表示单个要素对象的GeoJSON的一部分。 * @param feature - iServer要素对象 * @return {Object} 一个表示点的对象。 */ 'feature': function (feature) { var geom = this.extract.geometry.apply(this, [feature.geometry]) var json = { "type": "Feature", "properties": this.createAttributes(feature), "geometry": geom } if (feature.geometry && feature.geometry.type === 'TEXT') { json.properties.texts = feature.geometry.texts json.properties.textStyle = feature.geometry.textStyle } if (feature.fid !== null) { json.id = feature.fid } if (feature.ID !== null) { json.id = feature.ID } return json }, /** * @function SuperMap.Format.GeoJSON.extract.geometry * @description 返回一个表示单个几何对象的GeoJSON的一部分。 * @param geometry -iServer 几何对象 * @return {Object} 一个表示几何体的对象。 */ 'geometry': function (geometry) { if (geometry == null) { return null } var geo = this.toGeometry(geometry) var geometryType = geo.type var data = this.extract[geometryType.toLowerCase()].apply(this, [geo]) geometryType = geometryType === 'TEXT' ? 'Point' : geometryType var json if (geometryType === "Collection") { json = { "type": "GeometryCollection", "geometries": data } } else { json = { "type": geometryType, "coordinates": data } } return json }, /** * @function SuperMap.Format.GeoJSON.extract.point * @description 从一个点对象中返回一个坐标组。 * @param point - {SuperMap.Geometry.Point} 一个点对象。 * @return {Array} 一个表示一个点的坐标组。 */ 'point': function (point) { var p = [point.x, point.y] for (var name in point) { if (name !== "x" && name !== "y" && !isNaN(point[name])) { p.push(point[name]) } } return p }, /** * @function SuperMap.Format.GeoJSON.extract.point * @description 从一个文本对象中返回一个坐标组。 * @param geo 一个文本对象。 * @return {Array} 一个表示一个点的坐标组。 */ 'text': function (geo) { return [geo.points[0].x, geo.points[0].y] }, /** * @function SuperMap.Format.GeoJSON.extract.multipoint * @description 从一个多点对象中返一个坐标组数组。 * @param multipoint - {SuperMap.Geometry.MultiPoint} 多点对象。 * @return {Array} 一个表示多点的坐标组数组。 */ 'multipoint': function (multipoint) { var array = [] for (var i = 0, len = multipoint.components.length; i < len; ++i) { array.push(this.extract.point.apply(this, [multipoint.components[i]])) } return array }, /** * @function SuperMap.Format.GeoJSON.extract.linestring * @description 从一个线对象中返回一个坐标组数组。 * @param linestring - {SuperMap.Geometry.Linestring} 线对象。 * @return {Array} 一个表示线对象的坐标组数组。 */ 'linestring': function (linestring) { var array = [] for (var i = 0, len = linestring.components.length; i < len; ++i) { array.push(this.extract.point.apply(this, [linestring.components[i]])) } return array }, /** * @function SuperMap.Format.GeoJSON.extract.multilinestring * @description 从一个多线对象中返回一个线数组。 * @param multilinestring - {SuperMap.Geometry.MultiLinestring} 多线对象 * * @return {Array} 一个表示多线的线数组。 */ 'multilinestring': function (multilinestring) { var array = [] for (var i = 0, len = multilinestring.components.length; i < len; ++i) { array.push(this.extract.linestring.apply(this, [{components: multilinestring.components[i]}])) } return array }, /** * @function SuperMap.Format.GeoJSON.extract.polygon * @description 从一个面对象中返回一组线环。 * @polygon - {SuperMap.Geometry.Polygon} 面对象。 * @return {Array} 一组表示面的线环。 */ 'polygon': function (polygon) { var array = [] for (var i = 0, len = polygon.components.length; i < len; ++i) { array.push(this.extract.linestring.apply(this, [{components: polygon.components[i]}])) } return array }, /** * @function SuperMap.Format.GeoJSON.extract.multipolygon * @description 从一个多面对象中返回一组面。 * @param multipolygon - {SuperMap.Geometry.MultiPolygon} 多面对象。 * @return {Array} 一组表示多面的面。 */ 'multipolygon': function (multipolygon) { var array = [] for (var i = 0, len = multipolygon.components.length; i < len; ++i) { array.push(this.extract.polygon.apply(this, [{components: multipolygon.components[i]}])) } return array }, /** * @function SuperMap.Format.GeoJSON.extract.collection * @description 从一个几何要素集合中一组几何要素数组。 * @param collection - {SuperMap.Geometry.Collection} 几何要素集合。 * @return {Array} 一组表示几何要素集合的几何要素数组。 */ 'collection': function (collection) { var len = collection.components.length var array = new Array(len) for (var i = 0; i < len; ++i) { array[i] = this.extract.geometry.apply(this, [{ type: "Collection", components: collection.components[i] }]) } return array } } } /** * @function SuperMap.Format.GeoJSON.prototype.read * @description 反序列化一个 GeoJSON 字符串。 * @param json - {string} GeoJSON 字符串 * @param type - {string} 可选的字符串,它决定了输出的格式。 * 支持的值有:"Geometry","Feature",和"FeatureCollection", * 如果此值为null,则会使用默认值"FeaureCollection"。 * @param filter - {function} 对象中每个层次每个键值对都会调用此函数得出一个结果。 * 每个值都会被filter函数的结果所替换掉。这个函数可被用来将某些对象转化成 * 某个类相应的对象,或者将日期字符串转化成Date对象。 * * @return {Object} 返回值依赖于type参数的值。<br> * 如果type等于"FeatureCollection"(默认值),返回值将会是 <SuperMap.Feature.Vector> 数组。<br> * 如果type为"Geometry",输入的json对象必须表示一个唯一的几何体,然后返回值就会是 <SuperMap.Feature.Geometry>。 <br> * 如果type为"Feature",输入的json对象也必须表示的一个要素,这样返回值才会是<SuperMap.Feature.Vector> 。 */ read(json, type, filter) { type = (type) ? type : "FeatureCollection" var results = null var obj = null if (typeof json === "string") { obj = super.read(json, filter) } else { obj = json } if (!obj) { //SuperMap.Console.error("Bad JSON: " + json) } else if (typeof(obj.type) !== "string") { //SuperMap.Console.error("Bad GeoJSON - no type: " + json) } else if (this.isValidType(obj, type)) { switch (type) { case "Geometry": try { results = this.parseGeometry(obj) } catch (err) { //SuperMap.Console.error(err) } break case "Feature": try { results = this.parseFeature(obj) results.type = "Feature" } catch (err) { //SuperMap.Console.error(err) } break case "FeatureCollection": // for type FeatureCollection, we allow input to be any type results = [] switch (obj.type) { case "Feature": try { results.push(this.parseFeature(obj)) } catch (err) { results = null //SuperMap.Console.error(err) } break case "FeatureCollection": for (var i = 0, len = obj.features.length; i < len; ++i) { try { results.push(this.parseFeature(obj.features[i])) } catch (err) { results = null // SuperMap.Console.error(err) } } break default: try { var geom = this.parseGeometry(obj) results.push(new Vector(geom)) } catch (err) { results = null //SuperMap.Console.error(err) } } break default: break } } return results } /** * @function SuperMap.Format.GeoJSON.prototype.isValidType * @description 检查一个GeoJSON对象是否和给定的类型相符的合法的对象。 * @return {boolean} GeoJSON是否是给定类型的合法对象。 */ isValidType(obj, type) { var valid = false switch (type) { case "Geometry": if (Util.indexOf( ["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", "Box", "GeometryCollection"], obj.type) == -1) { // unsupported geometry type //SuperMap.Console.error("Unsupported geometry type: " + // obj.type) } else { valid = true } break case "FeatureCollection": // allow for any type to be converted to a feature collection valid = true break default: // for Feature types must match if (obj.type == type) { valid = true } else { //SuperMap.Console.error("Cannot convert types from " + //obj.type + " to " + type) } } return valid } /** * @function SuperMap.Format.GeoJSON.prototype.parseFeature * @description 将一个GeoJSON中的feature转化成<SuperMap.Feature.Vector>对象。 * @param obj - {Object} 从GeoJSON对象中创建一个对象。 * @return {SuperMap.Feature.Vector} 一个要素。 */ parseFeature(obj) { var feature, geometry, attributes, bbox attributes = (obj.properties) ? obj.properties : {} bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox try { geometry = this.parseGeometry(obj.geometry) } catch (err) { // deal with bad geometries throw err } feature = new Vector(geometry, attributes) if (bbox) { feature.bounds = Bounds.fromArray(bbox) } if (obj.id) { feature.fid = obj.id } return feature } /** * @function SuperMap.Format.GeoJSON.prototype.parseGeometry * @description 将一个GeoJSON中的几何要素转化成<SuperMap.Geometry>对象。 * @param obj - {Object} 从GeoJSON对象中创建一个对象。 * @return {SuperMap.Geometry} 一个几何要素。 */ parseGeometry(obj) { if (obj === null) { return null } var geometry if (obj.type === "GeometryCollection") { if (!(Util.isArray(obj.geometries))) { throw "GeometryCollection must have geometries array: " + obj } var numGeom = obj.geometries.length var components = new Array(numGeom) for (var i = 0; i < numGeom; ++i) { components[i] = this.parseGeometry.apply( this, [obj.geometries[i]] ) } geometry = new Collection(components) } else { if (!(Util.isArray(obj.coordinates))) { throw "Geometry must have coordinates array: " + obj } if (!this.parseCoords[obj.type.toLowerCase()]) { throw "Unsupported geometry type: " + obj.type } try { geometry = this.parseCoords[obj.type.toLowerCase()].apply( this, [obj.coordinates] ) } catch (err) { // deal with bad coordinates throw err } } return geometry } /** * @function SuperMap.Format.GeoJSON.write * @description 序列化一个要素对象,几何对象,要素对象数组为一个GeoJSON字符串。 * @param obj - {Object} 一个 <SuperMap.Feature.Vector> 对象,一个 <SuperMap.Geometry> 对象或者一个要素对象数组。 * @param pretty - {boolean} 是否使用换行和缩进来控制输出。默认值为false。 * @return {string} 一个GeoJSON字符串,它表示了输入的几何对象,要素对象,或者要素对象数组。 */ write(obj, pretty) { var geojson = { "type": null } if (Util.isArray(obj)) { geojson.type = "FeatureCollection" var numFeatures = obj.length geojson.features = new Array(numFeatures) for (var i = 0; i < numFeatures; ++i) { var element = obj[i] if (isGeometry(element)) { let feature = {} feature.geometry = element geojson.features[i] = this.extract.feature.apply(this, [feature]) } else { geojson.features[i] = this.extract.feature.apply(this, [element]) } } } else if (isGeometry(obj)) { let feature = {} feature.geometry = obj geojson = this.extract.feature.apply(this, [feature]) } function isGeometry(input) { return input.hasOwnProperty("parts") && input.hasOwnProperty("points") } return super.write(geojson, pretty) } /** * @function SuperMap.Format.GeoJSON.createCRSObject * @description 从一个要素对象中创建一个坐标参考系对象。 * @param object - {SuperMap.Feature.Vector} 要素对象 * @return {Object} 一个可作为GeoJSON对象的crs属性使用的对象。 */ createCRSObject(object) { var proj = object.layer.projection.toString() var crs = {} if (proj.match(/epsg:/i)) { var code = parseInt(proj.substring(proj.indexOf(":") + 1)) if (code == 4326) { crs = { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } } } else { crs = { "type": "name", "properties": { "name": "EPSG:" + code } } } } return crs } createAttributes(feature) { if (!feature) { return null } var attr = {} processFieldsAttributes(feature, attr) var exceptKeys = ["fieldNames", "fieldValues", "geometry"] for (var key in feature) { if (exceptKeys.indexOf(key) > -1) { continue } attr[key] = feature[key] } function processFieldsAttributes(feature, attributes) { if (!(feature.hasOwnProperty("fieldNames") && feature.hasOwnProperty("fieldValues"))) { return } var names = feature.fieldNames, values = feature.fieldValues for (var i in names) { attributes[names[i]] = values[i] } } return attr } toGeometry(geometry) { var me = this var geoType = geometry.type if (geoType === 'polygon') { geoType = GeometryType.REGION } switch (geoType.toUpperCase()) { case GeometryType.POINT: return me.toGeoPoint(geometry) case GeometryType.LINE: return me.toGeoLine(geometry) case GeometryType.LINEM: return me.toGeoLinem(geometry) case GeometryType.REGION: return me.toGeoRegion(geometry) case GeometryType.POINTEPS: return me.toGeoPoint(geometry) // case GeometryType.LINEEPS: // return me.toGeoLineEPS() // case GeometryType.REGIONEPS: // return me.toGeoRegionEPS() default: return geometry } } /** * @function SuperMap.Format.GeoJSON.toGeoPoint * @description 将服务端的点几何对象转换为几何对象 */ toGeoPoint(geometry) { var geoPoints = geometry.points || [{x: geometry.x, y: geometry.y}] var geoParts = geometry.parts || [geoPoints.length] var len = geoParts.length if (len < 1) { return null } if (len === 1) { return {type: "Point", x: parseFloat(geoPoints[0].x), y: parseFloat(geoPoints[0].y)} } else { for (var i = 0, pointList = []; i < len; i++) { pointList.push({x: parseFloat(geoPoints[i].x), y: parseFloat(geoPoints[i].y)}) } return {type: "MultiPoint", components: pointList} } } /** * * @function SuperMap.Format.GeoJSON.toGeoPoint * @description 将服务端的线几何对象转换为几何对象。 */ toGeoLine(geometry) { var me = this var geoPoints = geometry.points || [] var geoParts = geometry.parts || [geoPoints.length] var len = geoParts.length if (len < 1) { return null } if (len === 1) { for (var i = 0, pointList = []; i < geoParts[0]; i++) { pointList.push({x: parseFloat(geoPoints[i].x), y: parseFloat(geoPoints[i].y)}) } //判断线是否闭合,如果闭合,则返回LinearRing,否则返回LineString if (me.isPointsEquals(pointList[0], pointList[geoParts[0] - 1])) { pointList.pop() pointList.push(pointList[0]) } return {type: "LineString", components: pointList} } else { for (var k = 0, lineList = []; k < len; k++) { for (var j = 0, pointArr = []; j < geoParts[k]; j++) { pointArr.push({x: parseFloat(geoPoints[j].x), y: parseFloat(geoPoints[j].y)}) } lineList.push(pointArr) geoPoints.splice(0, geoParts[k]) } return {type: "MultiLineString", components: lineList} } } /** * * @function SuperMap.Format.GeoJSON.toGeoLinem * @description 将服务端的路由线几何对象转换为几何对象。 */ toGeoLinem(geometry) { var me = this, geoPoints = geometry.points || [], geoParts = geometry.parts || [geoPoints.length], len = geoParts.length, lineList = [] if (len < 1) { return null } for (var i = 0, pointIndex = 0, pointList = []; i < len; i++) { for (var j = 0; j < geoParts[i]; j++) { pointList.push({ x: parseFloat(geoPoints[pointIndex + j].x), y: parseFloat(geoPoints[pointIndex + j].y), measure: parseFloat(geoPoints[pointIndex + j].measure) }) } pointIndex += geoParts[i] //判断线是否闭合,如果闭合,则返回LinearRing,否则返回LineString if (me.isPointsEquals(pointList[0], pointList[geoParts[0] - 1])) { pointList.pop() pointList.push(pointList[0]) } lineList.push(pointList) pointList = [] } return {type: "MultiLineString", components: lineList} } /** * * @function SuperMap.Format.GeoJSON.toGeoRegion * @description 将服务端的面几何对象转换为几何对象。 */ toGeoRegion(geometry) { var CCWArray = [], geoPoints = geometry.points || [], geoParts = geometry.parts || [geoPoints.length], len = geoParts.length if (len < 1) { return null } var polygonArray = new Array() for (var i = 0, pointIndex = 0, pointList = []; i < len; i++) { for (var j = 0; j < geoParts[i]; j++) { pointList.push({ x: parseFloat(geoPoints[pointIndex + j].x), y: parseFloat(geoPoints[pointIndex + j].y) }) } pointIndex += geoParts[i] var linearRing = pointList.concat() linearRing.pop() linearRing.push(linearRing[0]) if (this.isClockWise(linearRing) > 0) { CCWArray.push(linearRing) } else { polygonArray.push([linearRing]) } if (i === len - 1) { var polyLength = polygonArray.length if (polyLength) { polygonArray[polyLength - 1] = polygonArray[polyLength - 1].concat(CCWArray) } else { for (var k = 0, length = CCWArray.length; k < length; k++) { polygonArray.push([CCWArray[k]].concat()) } } } pointList = [] } return {type: "MultiPolygon", components: polygonArray} } isClockWise(points) { var length = points.length if (length < 3) { return 0.0 } var s = points[0].y * (points[length - 1].x - points[1].x) points.push(points[0]) for (var i = 1; i < length; i++) { s += points[i].y * (points[i - 1].x - points[i + 1].x) } return s * 0.5 } isPointsEquals(point1, point2) { return (point1.x === point2.x && point1.y === point2.y) } } SuperMap.Format.GeoJSON = GeoJSON