import Zondy from '../Zondy'
import Evented from '../Evented'
import { getGUID, defaultValue, Log, defined } from '../../util'
import { Geometry } from '../geometry'
import {
SimpleFillSymbol,
SimpleLineSymbol,
SimpleMarkerSymbol,
Symbol
} from '../symbol'
import { GeometryType, SymbolType } from '../enum'
import ElevationInfo from '../ElevationInfo'
/**
* 要素对象,示例如下:<a id='add-Feature'>[初始化要素对象]</a>
* <br><br>[ES5引入方式]:<br/>
* Zondy.Feature() <br/>
* [ES6引入方式]:<br/>
* import { Feature } from "@mapgis/webclient-common" <br/>
* <br/>
* @class Feature
* @moduleEX FeatureModule
* @param {Object} options 构造参数
* @param {String} [options.id] 要素的id,不给则给一个随机的默认id
* @param {Object} [options.attributes = {}] 要素的属性
* @param {Geometry} [options.geometry] 要素的几何对象,支持如下:<br/>
* [圆]{@link Circle}、[矩形范围]{@link Extent}、[线]{@link LineString}、
* [多线]{@link MultiLineString}、[点]{@link Point}、[多点]{@link MultiPoint}、[区]{@link Polygon}、
* [多区]{@link MultiPolygon}
* @param {Symbol} [options.symbol = {}] 要素的样式,支持如下:<br/>
* [图片Marker符号]{@link PictureMarkerSymbol}、[简单Marker符号]{@link SimpleMarkerSymbol}、
* [简单填充符号]{@link SimpleFillSymbol}、[简单线符号]{@link SimpleLineSymbol}、[文本符号]{@link TextSymbol}
* @param {Boolean} [options.visible = true] 要素是否可见
* @param {ElevationInfo} [options.elevationInfo] 高程信息
*
* @summary <h5>支持如下方法:</h5>
* <a href='#fromGeoJSON'>[1、从geoJSON对象中导入数据]</a><br/>
* <a href='#toGeoJSON'>[2、导出为GeoJSON数据]</a><br/>
* <a href='#fromJSON'>[3、通过传入的json构造并返回一个新的几何对象]</a><br/>
* <a href='#toJSON'>[4、导出一个JSON对像]</a><br/>
* <a href='#clone'>[5、克隆并返回新要素]</a><br/>
* <a href='#toIGSFeature'>[6、导出为igs服务接口的要素对象]</a><br/>
* <a href='#toOldIGSFeature'>[7、出为igs1.0服务接口的要素对象]</a><br/>
* <a href='#toGraphicInfo'>[8、导出为igs1.0的要素的图形信息]</a><br/>
* <a href='#toAttValue'>[9、导出为igs1.0的要素的属性值]</a><br/>
* <a href='#toFType'>[10、导出为igs1.0的要素的几何类型]</a><br/>
*
* @example <caption><h7 id='add-Feature'>创建几何对象</h7></caption>
* // ES5引入方式
* const { Feature, Color } = Zondy
* const { LineString } = Zondy.Geometry
* const { SimpleLineSymbol } = Zondy.Symbol
* // ES6引入方式
* import { Feature, Color, LineString, SimpleLineSymbol } from "@mapgis/webclient-common"
* let feature = new Feature({
* //不填则创建一个随机的guid
* id: "你的id",
* //设置属性
* attributes: {},
* //构建几何
* geometry: new LineString({
* coordinates: [[112.0, 30.0], [113.0, 30.0], [113.0, 31.0]]
* }),
* //设置样式
* symbol: new SimpleLineSymbol({
* //设置颜色
* color: new Color(255, 0, 0, 1),
* //设置线宽
* width: 2
* })
* })
*/
class Feature extends Evented {
constructor(options) {
super(options)
options = defaultValue(options, {})
/**
* 要素id
* default 随机id
* @member {String} Feature.prototype.id
*/
this.id = defaultValue(options.id, getGUID())
/**
* 要素的属性
* default {}
* @member {Object} Feature.prototype.attributes
*/
this.attributes = defaultValue(options.attributes, {})
/**
* 要素的几何对象
* @member {Geometry} Feature.prototype.geometry
*/
this.geometry = this._decorate(
'geometry',
options.geometry,
Geometry,
Geometry.fromJSON
)
if (!this.geometry) {
Log.error('要素几何信息缺失')
}
/**
* 要素的样式
* @member {Symbol} Feature.prototype.symbol
*/
this.symbol = this._decorate(
'symbol',
options.symbol,
Symbol,
this._getSymbol.bind(this)
)
/**
* 要素是否可见
* default = true
* @member {Boolean} Feature.prototype.visible
*/
this.visible = defaultValue(options.visible, true)
/**
* 对象类型
* @readonly
* @member {String} Feature.prototype.type
*/
this.type = 'Feature'
/**
* 高程信息
* @member {ElevationInfo} Feature.prototype.elevationInfo
*/
this.elevationInfo = defaultValue(
options.elevationInfo,
new ElevationInfo()
)
/**
* 额外属性,其中的arc3表示三点弧的信息
* @member {additional} Feature.prototype.additional
*/
this.additional = defaultValue(options.additional, {})
}
/**
* @description: 根据几何类型支持程度重设符号
* @param {*} symbol
* @return symbol
*/
_getSymbol(symbol) {
const symbolType = symbol ? symbol.type : 'undefine'
const geometryType = this.geometry.type
let instance = symbol instanceof Symbol ? symbol : Symbol.fromJSON(symbol)
switch (geometryType) {
case GeometryType.multiPoint:
case GeometryType.point: {
const limits = [
SymbolType.simpleMarker,
SymbolType.text,
SymbolType.mapgisText,
SymbolType.pictureMarker,
SymbolType.point3D,
SymbolType.label3D
]
if (!defined(symbol)) {
instance = new SimpleMarkerSymbol()
}
if (!limits.some((v) => v === symbolType)) {
Log.info('图元几何和符号不匹配')
const json = instance.toJSON()
instance = new SimpleMarkerSymbol({
color: json.color
})
}
break
}
case GeometryType.multiLineString:
case GeometryType.lineString: {
const limits = [SymbolType.simpleLine, SymbolType.line3D]
if (!defined(symbol)) {
instance = new SimpleLineSymbol()
}
if (!limits.some((v) => v === symbolType)) {
Log.info('图元几何和符号不匹配')
const json = instance.toJSON()
instance = new SimpleLineSymbol({
color: json.color
})
}
break
}
case GeometryType.polygon:
case GeometryType.extent:
case GeometryType.circle:
case GeometryType.multiPolygon: {
const limits = [
SymbolType.simpleFill,
SymbolType.simpleMarker,
SymbolType.text,
SymbolType.mapgisText,
SymbolType.pictureMarker,
SymbolType.pictureFill,
SymbolType.polygon3D
]
if (!defined(symbol)) {
instance = new SimpleFillSymbol()
}
if (!limits.some((v) => v === symbolType)) {
Log.info('图元几何和符号不匹配')
const json = instance.toJSON()
instance = new SimpleFillSymbol({
color: json.color
})
}
break
}
default: {
break
}
}
return instance
}
/**
* 克隆并返回新要素<a id='clone'></a>
* @return {Feature} 克隆后的新要素
*/
clone() {
return new Feature(this.toJSON())
}
/**
* 导出一个JSON对像<a id='toJSON'></a>
* @return {Object} JSON对像
*/
toJSON() {
const json = {}
json.id = this.id
json.attributes = JSON.parse(JSON.stringify(this.attributes))
json.geometry = this.geometry.toJSON()
json.symbol = this.symbol.toJSON()
json.visible = this.visible
json.type = this.type
json.elevationInfo = this.elevationInfo
return json
}
/**
* 通过传入的json构造并返回一个新的几何对象<a id='fromJSON'></a>
* @param {Object} json JSON对象
* @example <caption><h7>通过传入的json构造并返回一个新的几何对象</h7></caption>\
* // ES5引入方式
* const { LineString } = Zondy.Geometry
* const { Feature } = Zondy
* // ES6引入方式
* import { LineString, Feature } from "@mapgis/webclient-common"
* const json = {
* //设置属性
* attributes: {},
* //构建几何
* geometry: new LineString({
* coordinates: [[112.0, 30.0], [113.0, 30.0], [113.0, 31.0]]
* })
* }
* const feature = new Feature.fromJSON(json)
*/
static fromJSON(json) {
json = defaultValue(json, {})
return new Feature(json)
}
/**
* 从geoJSON对象中导入数据<a id='fromGeoJSON'></a>
* @param geoJSON geoJSON数据
* @example <caption><h7 id='fromJSON'>从geoJSON对象中导入数据</h7></caption>
* // ES5引入方式
* const { Feature } = Zondy
* // ES6引入方式
* import { Feature } from "@mapgis/webclient-common"
* //数据格式参考https://geojson.org/
* const feature = new Feature();
* feature.fromGeoJSON({
* type: "Feature",
* geometry: {
* type: "LineString",
* coordinates: [
* [114.329481, 30.711953],
* [114.342372, 30.684553],
* [114.341474, 30.674527],
* [114.338273, 30.665863],
* [114.334533, 30.655893],
* [114.330017, 30.643386],
* [114.322936, 30.631171],
* [114.318749, 30.625032],
* [114.313923, 30.617818],
* [114.308156, 30.608404],
* [114.301348, 30.598718],
* [114.295038, 30.592581],
* [114.285992, 30.585234],
* [114.278415, 30.580865],
* [114.270119, 30.577433],
* [114.261901, 30.573909],
* [114.250444, 30.571547],
* [114.240741, 30.574025],
* [114.224975, 30.580306],
* [114.218822, 30.585491],
* [114.211532, 30.589347],
* [114.20474, 30.593382],
* [114.196667, 30.597536],
* [114.183062, 30.604521],
* [114.169464, 30.609907],
* [114.163868, 30.615064],
* [114.155941, 30.61846],
* [114.138907, 30.617699],
* [114.128567, 30.624968],
* [114.123644, 30.631684],
* [114.120804, 30.649056],
* [114.120828, 30.659055],
* ],
* },
* properties: {
* ln: "1号线",
* su: "1",
* kn: "轨道交通1号线",
* ls: "420100034364",
* cl: "3080B7",
* la: "",
* x: 1,
* li: "420100034364|420100034365",
* color: "#3080B7",
* },
* });
*/
fromGeoJSON(geoJSON) {
geoJSON = defaultValue(geoJSON, {})
const that = this
// 从geometry中获取几何
const geometry = defaultValue(geoJSON.geometry, {})
that.geometry = Geometry.fromGeoJSON(geometry)
// 从properties中获取属性
const properties = defaultValue(geoJSON.properties, {})
Object.keys(properties).forEach(function (key) {
if (properties.hasOwnProperty(key)) {
that.attributes[key] = properties[key]
}
})
}
/**
* 导出为GeoJSON数据<a id='toGeoJSON'></a>
* @return geoJSON geoJSON数据
* @example <caption><h7 id='toGeoJSON'>导出为GeoJSON数据</h7></caption>
* //导出为GeoJSON数据
* let geojson = feature.toGeoJSON();
*/
toGeoJSON() {
return {
type: 'Feature',
geometry: this.geometry.toGeoJSON(),
properties: JSON.parse(JSON.stringify(this.attributes)),
style: this.symbol.toJSON()
}
}
/**
* 导出为igs服务接口的要素对象<a id='toIGSFeature'></a>
* @return igs传输要素
*/
toIGSFeature() {
const geometry = this.geometry.toJSON()
return {
type: 'Feature',
geometry: {
type: geometry.type,
coordinates: geometry.coordinates
},
attributes: JSON.parse(JSON.stringify(this.attributes)),
styleInfo: null
}
}
/**
* 出为igs1.0服务接口的要素对象<a id='toOldIGSFeature'></a>
* @return igs1.0的要素
*/
toOldIGSFeature() {
return {
fGeom: this.geometry.toOldIGSGeometry(),
GraphicInfo: this.toGraphicInfo(),
AttValue: this.toAttValue(),
FID: this.id,
bound: null,
ftype: this.toFType()
}
}
/**
* 导出为igs1.0的要素的图形信息<a id='toGraphicInfo'></a>
* @return {Object} igs1.0的要素的图形信息
*/
toGraphicInfo() {
let graphicInfo
switch (this.geometry.type) {
case 'Point':
case 'MultiPoint':
graphicInfo = {
InfoType: 1,
PntInfo: this.symbol
}
break
case 'LineString':
case 'MultiLineString':
graphicInfo = {
InfoType: 2,
LinInfo: this.symbol
}
break
case 'Polygon':
case 'MultiPolygon':
default:
graphicInfo = {
InfoType: 3,
RegInfo: this.symbol
}
break
}
return graphicInfo
}
/**
* 导出为igs1.0的要素的属性值<a id='toAttValue'></a>
* @return {Array} igs1.0的要素的属性值
*/
toAttValue() {
const attValue = []
const self = this
Object.keys(this.attributes).forEach((key) => {
if (self.attributes.hasOwnProperty(key)) {
attValue.push(self.attributes[key])
}
})
return attValue
}
/**
* 导出为igs1.0的要素的几何类型<a id='toFType'></a>
* @return {Number} igs1.0的要素的几何类型
*/
toFType() {
let ftype
switch (this.geometry.type) {
case 'Point':
case 'MultiPoint':
ftype = 1
break
case 'LineString':
case 'MultiLineString':
ftype = 2
break
case 'Polygon':
case 'MultiPolygon':
default:
ftype = 3
break
}
return ftype
}
}
Zondy.Feature = Feature
export default Feature