import { FeatureLayer } from '../baseLayer'
import { Zondy } from '../../../base'
import { LayerType, LoadStatus } from '../../../base/enum'
import {Log, defaultValue, isNull, toJSON} from '../../../util'
import { FeatureServer, ResourceServer } from '../../../service'
import { Extent, SpatialReference } from '../../../base/geometry'
import epsg from '../../../base/EPSG'
import {getBaseUrl, jsonClone} from '../../../util/Utils'
import LabelClass from '../../support/LabelClass'
/**
* IGS要素图层,<br>
* 目前二维和三维上支持4326(包括4490,4214以及4610),3857以及EPSG支持的自定义坐标系,要素服务会自动读取元信息上的坐标系,不需要用户指定
* <br><br>[ES5引入方式]:<br/>
* Zondy.Layer.IGSFeatureLayer() <br/>
* [ES6引入方式]:<br/>
* import { IGSFeatureLayer } from "@mapgis/webclient-common" <br/>
* <br/>
* 针对图层的操作请在图层加载完毕事件中进行<br/>
* Layer.on('layerview-created', function (result) {<br/>
* console.log("加载完毕:", result.layer)<br/>
* });<br/>
* 如果不想在该事件中放入业务代码,则请确认图层资源已加载完毕后再进行操作<br/>
* if(layer.loadStatus === 'loaded') {<br/>
* // 你的业务逻辑<br/>
* }
* @class IGSFeatureLayer
* @moduleEX LayerModule
* @classdesc IGS地图图层
* @extends FeatureLayer
* @fires Layer#图层加载完毕事件
* @fires Layer#图层销毁完毕事件
* @fires Layer#图层更新完毕事件
* @fires Layer#图层显隐更新完毕事件
* @fires Layer#图层透明度更新完毕事件
* @fires Layer#图层刷新完毕事件
* @fires IGSFeatureLayer#图层样式更新完毕事件
* @param {Object} options 构造参数
* @param {String} [options.url] 服务基地址,<br/>
* 1、IGS2.0服务:http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer<br/>
* 示例如下:<br/>
* <a href='#add-IGSFeatureLayer'>[1、添加IGS要素图层-不指定图层]</a><br/>
* <a href='#IGSFeatureLayer-id'>[2、添加IGS要素图层-指定图层id]</a><br/>
* <a href='#IGSFeatureLayer-url'>[3、添加IGS要素图层-在基地址中指定图层id]</a><br/>
* 2、IGS1.0服务:http://{ip}:{port}/igs/rest/mrfs/docs/{ServiceName}<br/>
* 示例如下:<br/>
* <a href='#IGSFeatureLayer-IGS1.0'>[1、添加IGS要素图层-IGS1.0]</a><br/>
* 3、GDBP服务,注意该服务不支持注记:http://{ip}:{port}/igs/rest/mrfs/layer<br/>
* 示例如下:<br/>
* <a href='#IGSFeatureLayer-gdbp'>[1、指定一个gdbp地址来渲染要素]</a><br/>
* 4、删除图层方法:<a href='#remove-layer'>[删除图层]</a>
* @param {Number|String} [options.sublayerId = 0] 要素服务的子图层id,不指定则查询第0个图层,指定时,则查询指定layerId的图层
* @param {String} [options.gdbp] 指定一个gdbp数据源来加载图形,格式如下:gdbp://MapGisLocal/武汉市/ds/4326矢量/sfcls/武汉市区划4326
* @param {String} [options.id] 图层id,图层的唯一标识,不指定则给一个随机id
* @param {Number} [options.opacity = 1] 图层透明度,0到1之间的值,0为完全透明,1为不透明,参考示例:<a href='#opacity'>[设置图层透明度]</a>
* @param {Boolean} [options.visible = true] 图层显示或隐藏,true则显示,false则隐藏,参考示例:<a href='#visible'>[设置图层显示或隐藏]</a>
* @param {String} [options.renderMode = 'client'] 渲染模式,分为客户端渲染'client'和服务器端渲染'server'
* @param {Renderer} [options.renderer] 渲染样式,<br>
* 目前支持如下样式:<br/>
* [1、单值专题图]{@link UniqueValueRenderer}<br/>
* [2、分段专题图]{@link ClassBreakRenderer}<br/>
* [3、统一专题图]{@link SimpleRenderer}<br/>
* 参考示例:<br/>
* <a href='#UniqueValueRenderer'>[1、单值专题图]</a><br/>
* <a href='#ClassBreakRenderer'>[2、分段专题图]</a><br/>
* <a href='#SimpleRenderer'>[3、统一专题图]</a><br/>
* @param {String} [options.definitionExpression = ''] sql语句查询,例如name='中国'
* @param {Boolean} [options.labelsVisible = false] 是否开启动态注记,仅支持三维场景
* @param {Array<LabelClass>} [options.labelingInfo = []] 注记样式数组,可以和renderer同时启用,默认取数组的第一个样式,
* 仅支持三维场景,参考示例:<a href='#add-labelingInfo'>[注记样式]</a><br/>
* @param {Number} [options.minScale = null] 最小比例尺,只有当地图视图的比例尺大于最小比例尺时显示要素图层
* @param {Number} [options.maxScale = null] 最大比例尺,只有当地图视图的比例尺小于最大比例尺时显示要素图层
* @param {String} [options.tokenKey = 'token'] token名
* @param {String} [options.tokenValue] token值,只有当tokenValue存在时,才会绑定token
* @param {Boolean} [options.supportArc3 = true] 是否返回三点弧段数据,为true则返回三个点代表三点弧段,否则返回离散的点
*
* @summary <h5>支持如下方法:</h5>
* <a href='#load'>[1、加载图层资源]</a><br/>
* <a href='#queryFeatures'>[2、指定图层的要素查询]</a><br/>
* <a href='#queryFeaturesCount'>[3、查询要素数量]</a><br/>
* <a href='#fromJSON'>[4、通过传入的json构造并返回一个新的几何对象]</a><br/>
* [5、导出为json对象]{@link OGCLayer#toJSON}<br/>
* [6、克隆几何对象]{@link OGCLayer#clone}
*
* @example <caption><h7 id='add-IGSFeatureLayer'>添加IGS要素图层-不指定图层</h7></caption>
* // ES5引入方式
* const { Map , MapView } = Zondy
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { Map , MapView, IGSFeatureLayer} from "@mapgis/webclient-common"
* // 初始化图层管理容器
* const map = new Map();
* // 初始化地图视图对象
* const mapView = new MapView({
* // 视图id
* viewId: "viewer-id",
* // 图层管理容器
* map: map
* });
* // 添加图层
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer'
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='IGSFeatureLayer-id'>添加IGS要素图层-指定图层id</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { IGSFeatureLayer} from "@mapgis/webclient-common"
* // 添加图层
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
* // 指定图层id
* sublayerId: 2
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='IGSFeatureLayer-url'>添加IGS要素图层-在基地址中指定图层id</h7></caption
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { IGSFeatureLayer} from "@mapgis/webclient-common"
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,再基地址上指定图层id
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer/1'
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='IGSFeatureLayer-IGS1.0'>添加IGS要素图层-IGS1.0</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { IGSFeatureLayer} from "@mapgis/webclient-common"
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,再基地址上指定图层id
* url: 'http://{ip}:{port}/igs/rest/mrfs/docs/{ServiceName}',
* // 图层id
sublayerId: '1'
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='remove-layer'>删除图层</h7></caption>
* map.remove(igsFeatureLayer)
*
* @example <caption><h7 id='opacity'>设置图层透明度</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { IGSFeatureLayer} from "@mapgis/webclient-common"
* // 在初始化时设置
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,再基地址上指定图层id
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer/1',
* // 设置透明度
* opacity: 1
* })
* map.add(igsFeatureLayer)
*
* // 在图层加载完毕后设置
* igsFeatureLayer.opacity = 0.5
*
* @example <caption><h7 id='visible'>设置图层可见性</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { IGSFeatureLayer} from "@mapgis/webclient-common"
* // 在初始化时设置
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,再基地址上指定图层id
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer/1',
* // 设置图层可见性
* visible: true
* })
* map.add(igsFeatureLayer)
*
* // 在图层加载完毕后设置
* igsFeatureLayer.visible = !igsFeatureLayer.visible
*
* @example <caption><h7 id='index'>图层顺序</h7></caption>
* // 加载完毕后,更改图层顺序
* map.reorder(igsFeatureLayer, '要移动到的index');
*
* @example <caption><h7 id='UniqueValueRenderer'>单值专题图</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* const { UniqueValueRenderer } = Zondy.Renderer
* const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
* const { Color } = Zondy
* // ES6引入方式
* import { IGSFeatureLayer,UniqueValueRenderer,SimpleFillSymbol,SimpleLineSymbol,Color } from "@mapgis/webclient-common"
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,当不指定图层名称时,默认查询第一个子图层
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
* // 设置渲染样式-单值专题图
* renderer: renderer: new UniqueValueRenderer({
* // 专题图过滤字段名
* field: '字段名',
* // 默认样式,当没有匹配到指定值时,会使用默认样式
* // 因为该数据的几何类型为区,因此设置区样式
* defaultSymbol: new SimpleFillSymbol({
* // 填充颜色
* color: new Color(255, 0, 0),
* // 外边线样式
* outline: new SimpleLineSymbol({
* // 线颜色
* color: new Color(0, 0, 0),
* // 线宽
* width: 1
* })
* }),
* // 单值专题图过滤条件数组
* uniqueValueInfos: [
* {
* //指定字段值
* value: '过滤字段值1',
* //匹配到该值后的样式
* // 因为该数据的几何类型为区,因此设置区样式
* symbol: new SimpleFillSymbol({
* // 填充颜色
* color: new Color(255, 0, 0)
* })
* },
* {
* //指定字段值
* // 因为该数据的几何类型为区,因此设置区样式
* value: '过滤字段值2',
* //匹配到该值后的样式
* // 因为该数据的几何类型为区,因此设置区样式
* symbol: new SimpleFillSymbol({
* // 填充颜色
* color: 'rgb(255, 123, 220)'
* })
* }
* ]
* })
* })
* map.add(igsFeatureLayer3)
*
* @example <caption><h7 id='ClassBreakRenderer'>分段专题图</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* const { ClassBreakRenderer } = Zondy.Renderer
* const { SimpleLineSymbol } = Zondy.Symbol
* const { Color } = Zondy
* // ES6引入方式
* import { IGSFeatureLayer,ClassBreakRenderer,SimpleLineSymbol,Color } from "@mapgis/webclient-common"
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,当不指定图层名称时,默认查询第一个子图层
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
* // 设置渲染样式-分段专题图
* renderer: new ClassBreakRenderer({
* // 专题图过滤字段名
* field: '字段名',
* // 默认样式,当没有匹配到指定值时,会使用默认样式
* // 因为该数据的几何类型为线,因此设置线样式
* defaultSymbol: new SimpleLineSymbol({
* // 线符号颜色
* color: new Color(1, 244, 0),
* // 线宽
* width: 3
* }),
* // 分段专题图过滤条件数组
* classBreakInfos: [
* {
* // 最小过滤范围,field对应的值大于等于minValue
* minValue: 0,
* // 最大过滤范围,field对应的值小于maxValue
* maxValue: 2,
* // 匹配到该值后的样式
* // 因为该数据的几何类型为线,因此设置线样式
* symbol: new SimpleLineSymbol({
* // 线符号颜色
* color: new Color(1, 244, 0),
* // 线宽
* width: 3
* })
* },
* {
* // 最小过滤范围,field对应的值大于等于minValue
* minValue: 3,
* // 最大过滤范围,field对应的值小于maxValue
* maxValue: 5,
* // 匹配到该值后的样式
* // 因为该数据的几何类型为线,因此设置线样式
* symbol: new SimpleLineSymbol({
* // 线符号颜色
* color: new Color(111, 144, 10),
* // 线宽
* width: 3
* })
* },
* {
* // 最小过滤范围,field对应的值大于等于minValue
* minValue: 5,
* // 最大过滤范围,field对应的值小于maxValue
* maxValue: 7,
* // 匹配到该值后的样式
* // 因为该数据的几何类型为线,因此设置线样式
* symbol: new SimpleLineSymbol({
* // 线符号颜色
* color: new Color(22, 244, 10),
* // 线宽
* width: 3
* })
* },
* {
* // 最小过滤范围,field对应的值大于等于minValue
* minValue: 7,
* // 最大过滤范围,field对应的值小于maxValue
* maxValue: 9,
* // 匹配到该值后的样式
* // 因为该数据的几何类型为线,因此设置线样式
* symbol: new SimpleLineSymbol({
* // 线符号颜色
* color: new Color(33, 44, 10),
* // 线宽
* width: 3
* })
* },
* {
* // 最小过滤范围,field对应的值大于等于minValue
* minValue: 9,
* // 最大过滤范围,field对应的值小于maxValue
* maxValue: 20,
* // 匹配到该值后的样式
* // 因为该数据的几何类型为线,因此设置线样式
* symbol: new SimpleLineSymbol({
* // 线符号颜色
* color: new ZColor(123, 124, 110),
* // 线宽
* width: 3
* })
* }
* ]
* })
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='SimpleRenderer'>统一专题图</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* const { SimpleRenderer } = Zondy.Renderer
* const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
* const { Color } = Zondy
* // ES6引入方式
* import { IGSFeatureLayer,SimpleRenderer,SimpleFillSymbol,SimpleLineSymbol,Color } from "@mapgis/webclient-common"
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,当不指定图层名称时,默认查询第一个子图层
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
* // 设置渲染样式-统一专题图
* renderer: new SimpleRenderer({
* // 因为该数据的几何类型为区,因此设置区样式
* symbol: new SimpleFillSymbol({
* // 填充颜色
* color: new Color(255, 0, 0),
* // 外边线样式
* outline: new SimpleLineSymbol({
* // 线颜色
* color: new Color(0, 0, 0),
* // 线宽度
* width: 1
* })
* })
* })
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='IGSFeatureLayer-gdbp'>指定一个gdbp地址来渲染要素</h7></caption>
* // ES5引入方式
* const { IGSFeatureLayer } = Zondy.Layer
* // ES6引入方式
* import { IGSFeatureLayer } from "@mapgis/webclient-common"
* const igsFeatureLayer = new IGSFeatureLayer({
* // 服务基地址,该地址为要素服务1.0地址
* url: "http://{ip}:{port}/igs/rest/mrfs/layer",
* // gdbp地址,在桌面的数据库中右键简单要素类,来获取该地址
* gdbp: "gdbp://MapGisLocal/武汉市/ds/4326矢量/sfcls/武汉市区划4326"
* })
* map.add(igsFeatureLayer)
*
* @example <caption><h7 id='add-labelingInfo'>启用注记</h7></caption>
* // ES5引入方式
* const { igsFeatureLayer } = Zondy.Layer
* const { LabelClass ,Font} = Zondy
* const { TextSymbol } = Zondy.Symbol
* // ES6引入方式
* import { igsFeatureLayer,LabelClass,Font,TextSymbol } from "@mapgis/webclient-common"
* // 初始化LabelClass
* const labelClass = new LabelClass({
* // 指定文本符号样式
* symbol: new TextSymbol({
* // 文字颜色
* color: new Color(252, 100, 22, 1),
* // 文字样式
* font: new Font({
* // 字体
* family: "微软雅黑",
* // 文字大小,单位像素
* size: 30,
* // 文字是否为斜体,正常模式
* style: "normal",
* // 文字粗细
* weight: "normal"
* })
* })
* })
* // 初始化IGS要素图层
* const igsFeatureLayer = new igsFeatureLayer({
* // 服务基地址,当不指定图层名称时,默认查询第一个子图层
* url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
* // 可在此处设置渲染样式
* renderer: {},
* // 启用注记
* labelsVisible: true,
* // 设置注记样式
* labelingInfo: [labelClass]
* })
* // 添加到容器中
* map.add(igsFeatureLayer)
* */
/**
* 图层样式更新完毕事件,请注意该事件是图层更新事件(layerview-update)的子事件
* @event IGSFeatureLayer#图层样式更新完毕事件
* @property {Object} event 事件对象
* @property {String} [event.type = 'layerview-update'] 图层更新完毕事件
* @property {String} [event.message = null] 更新描述
* @property {Array<UpdateContent>} [event.updateContent = null] 更新详情对象
* @property {Layer} [event.layer = null] 地图图层对象
* @property {MapView} [event.layerView = null] 图层的视图对象
* @property {Layer} [event.sourceTarget = null] 事件发起对象
* @property {Map} [event.target = null] 事件接收对象
* @example <caption><h5>图层样式更新完毕事件</h5></caption>
* Layer.on('layerview-update', function (event) {
* // 获取更新事件对象
* console.log("更新完毕:", event)
* // 获取更新详情数组
* const updateContent = event.updateContent
* // 循环数组,根据事件名进行后续操作
* for (let i = 0; i < updateContent.length; i++) {
* // 图层样式更新完毕事件
* if(updateContent[i].name === 'renderer'){
* console.log("图层样式更新完毕事件:", event);
* }
* }
* });
*/
class IGSFeatureLayer extends FeatureLayer {
constructor(options) {
super(options)
options = defaultValue(options, {})
this.url = defaultValue(options.url, undefined)
this.type = LayerType.igsFeature
/**
* gdbp数据源
* @member {String} IGSFeatureLayer.prototype.gdbp
*/
this.gdbp = defaultValue(options.gdbp, '')
/**
* 服务返回的要素字段名数组
* @member {Array<String>} IGSFeatureLayer.prototype.outFields
*/
this.outFields = []
/**
* 服务支持的能力
* @member {Array<String>} IGSFeatureLayer.prototype.capabilities
*/
this.capabilities = []
/**
* 要素图层index
* @member {Number|String} IGSFeatureLayer.prototype.sublayerId
*/
this.sublayerId = defaultValue(options.sublayerId, 0)
/**
* 是否开启动态注记,仅支持三维动态注记渲染
* @member {Boolean} IGSFeatureLayer.prototype.labelsVisible
*/
this.labelsVisible = defaultValue(options.labelsVisible, false)
/**
* 是否返回三点弧段数据,为true则返回三个点代表三点弧段,否则返回离散的点
* @member {Boolean} IGSFeatureLayer.prototype.supportArc3
*/
this.supportArc3 = defaultValue(options.supportArc3, true)
/**
* 注记样式数组,默认取数组的第一个样式,仅支持三维动态注记渲染
* @member {Array<LabelClass>} IGSFeatureLayer.prototype.labelingInfo
*/
const _labelingInfo = []
const _optLabelingInfo = defaultValue(options.labelingInfo, [])
for (let i = 0; i < _optLabelingInfo.length; i++) {
_labelingInfo.push(new LabelClass(_optLabelingInfo[i]))
}
this.labelingInfo = _labelingInfo
/**
* 渲染模式,分为客户端渲染'client'和服务器端渲染'server'
* @member {String} IGSFeatureLayer.prototype.renderMode
*/
this.renderMode = defaultValue(options.renderMode, 'client')
this._definitionExpression = defaultValue(options.definitionExpression)
// 处理外部图层id
const processSublayerId = () => {
const reg = /^.*FeatureServer/
const reg1 = /^.*\/igs\/rest\/mrfs\/docs\//
const matchResult = this.url.match(reg)
const matchResult1 = this.url.match(reg1)
if (matchResult) {
const url = matchResult[0]
// 解析图层id
if (this.url.length !== url.length) {
const len = this.url.length - url.length
const substr = this.url.substr(url.length + 1, len - 1)
this.sublayerId = substr
this.url = url
}
} else if (matchResult1) {
const url = matchResult1[0]
const str = this.url.replace(url, '')
if (str) {
const splitArr = str.split('/')
if (splitArr.length > 1) {
this.url = url + splitArr[0]
this.sublayerId = splitArr[1]
}
}
}
}
// igs服务版本
this._igsVersion = '2.0'
// 渲染模式区分
if (this.renderMode === 'client') {
const baseUrl = getBaseUrl(this.url)
if (this.url.indexOf('/igs/rest/mrfs/layer') > -1) {
this._igsVersion = '1.0'
this._resourceServer = new ResourceServer({
url: `${baseUrl}/igs/rest/mrcs`
})
this._featureServer = new FeatureServer({
url: this.url
})
} else {
if (this.url.indexOf('/igs/rest/mrfs/docs') > -1) {
this._igsVersion = '1.0'
}
// 分离url
processSublayerId()
// 构造服务server
this._featureServer = new FeatureServer({
url: this.url
})
}
} else {
const baseUrl = getBaseUrl(this.url)
// 1.0
if (this.url.indexOf('/igs/rest/mrfs/layer') > -1) {
this._igsVersion = '1.0'
this._resourceServer = new ResourceServer({
url: `${baseUrl}/igs/rest/mrcs`
})
} else {
// 分离url
processSublayerId()
// 构造服务server
this._featureServer = new FeatureServer({
url: this.url
})
// 2.0
this._igsVersion = '2.0'
this._resourceServer = new ResourceServer({
url: `${baseUrl}/igs/rest/services/system/ResourceServer`
})
}
}
}
/**
* 加载图层资源
* @example <caption><h7 id='load'>不加载图层,仅获取图层信息</h7></caption>
* // 初始化图层
* const igsFeatureLayer = new Zondy.Layer.IGSFeatureLayer({
* // 服务基地址
* url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/FeatureServer',
* });
* igsFeatureLayer.load().then((result) => {
* // 获取完图层信息
* console.log(result)
* })
* @return {Promise<IGSFeatureLayer>}
*/
load() {
return super.load()
}
/**
* 子类加载服务端元信息的方法
* @private
* */
_load() {
const self = this
// 客户端渲染
if (self.renderMode === 'client') {
if (self.url.indexOf('/igs/rest/mrfs/layer') > -1) {
// 1.0 gdbp
return this._resourceServer
.queryGDBPInfo({
gdbpUrl: this.gdbp
})
.then((res) => {
// 解析信息无效
return new Promise((resolve) => {
self.loadStatus = LoadStatus.loaded
self.loaded = true
resolve(self)
})
})
} else {
return self._featureServer
.queryLayerInfo({
layerId: `${self.sublayerId}`
})
.then((result) => {
const data = result.data
// 解析元数据
self._processDataInfo(self, data)
return new Promise((resolve) => {
self.loadStatus = LoadStatus.loaded
self.loaded = true
resolve(self)
})
})
.catch((result) => {
Log.error('要素服务图层信息获取失败:', result)
})
}
}
// 服务器端渲染
else if (self.renderMode === 'server') {
if (this._igsVersion === '1.0') {
// 1.0 gdbp
return this._resourceServer
.queryGDBPInfo({
gdbpUrl: this.gdbp
})
.then((res) => {
// 解析信息无效
return new Promise((resolve) => {
self.loadStatus = LoadStatus.loaded
self.loaded = true
resolve(self)
})
})
} else {
// 2.0 gdbp
// 目前igs2.0上取图时,无法从要素服务查询到gdbp地址
return this._resourceServer
.queryTempDataInfo({
method: Zondy.Enum.FetchMethod.get,
url: self.gdbp
})
.then((result) => {
const data = result.data
// 解析元数据
self._processDataInfo(self, data)
return new Promise((resolve) => {
self.loadStatus = LoadStatus.loaded
self.loaded = true
resolve(self)
})
})
.catch((result) => {
Log.error('要素服务图层信息获取失败:', result)
})
}
} else {
Log.error('无法解析渲染模式')
}
}
/**
* 指定图层的要素查询
* @param {Object} queryOptions 参考此接口的入参{@link FeatureServer#queryFeatures}
* @return {Promise<FeatureSet>}
* @example <caption><h7 id='queryFeatures'>指定图层的要素查询</h7></caption>
* igsFeatureLayer.queryFeatures({
* // 图层id
* sublayerId: '0',
* // where语句
* where: "NAME='天门市'"
* }).then((result) => {
* console.log('查询结果:', result)
* })
*/
queryFeatures(queryOptions) {
const query = this._createQueryOption(queryOptions)
let promise
if (this.url.indexOf('/igs/rest/mrfs/layer') > -1) {
query.gdbp = this.gdbp
promise = this._featureServer.queryFeaturesInLayers(query)
} else {
promise = this._featureServer.queryFeatures(query)
}
return promise.then((res) => {
const data = res.data
if (!data) Log.error('添加图层视图失败,未获取到请求数据')
const featureSet = data.featureSet
// 设置要素
this._setFeatureSetSpatialReference(featureSet)
if (!featureSet) Log.error('添加图层视图失败,未获取到几何要素信息')
return featureSet
})
}
/**
* 查询要素数量,仅支持igs2.0
* @param {Object} queryOptions 参考此接口的入参{@link FeatureServer#queryFeatures}
* @return {Promise<Number>}
* @example <caption><h7 id='queryFeaturesCount'>查询要素数量</h7></caption>
* igsFeatureLayer.queryFeaturesCount({
* // 图层id
* sublayerId: '0',
* // where语句
* where: "NAME='天门市'"
* }).then((result) => {
* console.log('查询结果:', result)
* })
*/
queryFeaturesCount(queryOptions) {
if (this.gdbp) {
Log.error('gdbp模式不支持查询要素条数,igs1.0不支持此操作')
return
}
const query = this._createQueryOption(queryOptions)
query.returnCountOnly = true
return this._featureServer.queryFeatures(query).then((res) => {
const data = res.data
if (!data) Log.error('添加图层视图失败,未获取到请求数据')
return data.count
})
}
/**
* 通过传入的json构造并返回一个新的几何对象<a id='fromJSON'></a>
* @param {Object} [json] JSON对象
* @example <caption><h7>通过传入的json构造并返回一个新的几何对象</h7></caption>
* const json = {
* // 服务基地址
* url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/FeatureServer',
* }
* const igsFeatureLayer = new Zondy.Layer.IGSFeatureLayer.fromJSON(json)
*/
static fromJSON(json) {
json = jsonClone(json)
const _layer = new IGSFeatureLayer(json)
const _labelingInfo = []
for (let i = 0; i < json.labelingInfo.length; i++) {
_labelingInfo.push(new LabelClass(json.labelingInfo[i]))
}
_layer.labelingInfo = _labelingInfo
return _layer
}
/**
* @description 转换为json对象
* @return {Object} json对象
*/
toJSON() {
const json = super.toJSON()
json.url = this.url
json.gdbp = this.gdbp
json.outFields = this.outFields
json.capabilities = this.capabilities
json.sublayerId = this.sublayerId
json.labelsVisible = this.labelsVisible
json.renderMode = this.renderMode
json.definitionExpression = this.definitionExpression
const _labelingInfo = []
for (let i = 0; i < this.labelingInfo.length; i++) {
_labelingInfo.push(toJSON(this.labelingInfo[i], LabelClass))
}
json.labelingInfo = _labelingInfo
return json
}
_createQueryOption(queryOptions) {
let query = defaultValue(queryOptions, {})
// eslint-disable-next-line prefer-object-spread
query = Object.assign(
{
layerId: `${this.sublayerId}`,
where: this.definitionExpression || '',
supportArc3: this.supportArc3
},
query
)
return query
}
_processDataInfo(self, data) {
// 解析要素字段
if (!data) throw new Error('要素服务源数据请求失败')
// 解析要素坐标系
if (!self._spatialReference) {
const srsName = data.srsName || data.SRSName
// 2.0 数据坐标系
if (data.spatialReference) {
self._spatialReference = SpatialReference.fromJSON(
data.spatialReference
)
// 1.0 数据坐标系
} else if (srsName && epsg.find((v) => v.name === srsName)) {
const epsgObject = epsg.find((v) => v.name === srsName)
self._spatialReference = new SpatialReference({
wkid: epsgObject.id,
wkt: epsgObject.strProject
})
} else {
self._spatialReference = new SpatialReference('EPSG:4326')
}
}
if (isNull(self.extent)) {
const extent = self.extent || data.extent || data.Range
if (extent) {
// 2.0 extent
self.extent = new Extent({
xmin: extent.xmin,
ymin: extent.ymin,
xmax: extent.xmax,
ymax: extent.ymax,
spatialReference: self._spatialReference
})
}
}
// 解析服务器提供的能力
if (data.capabilities) {
self.capabilities = Array.isArray(data.capabilities)
? data.capabilities
: [data.capabilities]
}
// 解析要素字段
if (data.fields && Array.isArray(data.fields)) {
data.fields.forEach((field) => {
self.outFields.push(field.name)
})
}
// 解析要素集类型
if (data.geometryType) {
self.geometryType = data.geometryType
} else if (data.GeomType) {
self.geometryType = data.GeomType
}
// 解析渲染器
// if (data.drawingInfo) {
// data.drawingInfo.renderer.field = data.drawingInfo.renderer.field1
// self.renderer = formatIGSRenderer(data.drawingInfo.renderer)
// }
}
/**
* @private
* @description: 解决要素集不存在坐标系或服务未返回坐标系问题
* @return {*}
*/
_setFeatureSetSpatialReference(featureSet) {
if (!featureSet) {
Log.error('服务器请求错误,未返回FeatureSet数据,请检查服务状态')
}
const self = this
if (
!featureSet.spatialReference ||
(featureSet.spatialReference && featureSet.spatialReference.wkid === 0)
) {
featureSet.spatialReference = self._spatialReference
featureSet.features.forEach((feature) => {
if (feature && feature.geometry) {
feature.geometry.spatialReference = self._spatialReference
}
})
}
}
}
Object.defineProperties(IGSFeatureLayer.prototype, {
/**
* 要素过滤条件,类似sql语句
* @member {String} IGSFeatureLayer.prototype.definitionExpression
*/
definitionExpression: {
get() {
return this._definitionExpression
},
set(value) {
this._definitionExpression = value
if (this.loaded) {
this.refresh()
}
}
}
})
Zondy.Layer.IGSFeatureLayer = IGSFeatureLayer
export default IGSFeatureLayer