openlayermap
Version:
openlayer Map Component for Vue 2.0
829 lines (777 loc) • 32.5 kB
JavaScript
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