import {Zondy} from '../../service/common/Base';
import {ThemeSource} from './ThemeSource';
import {copyAttributesWithClip} from '../../service/common/Util';
import {ShapeFactory} from '../../common/overlay/feature/ShapeFactory';
import {ThemeVector} from '../../common/overlay/ThemeVector';
import {FeatureSet} from '../../service/common/FeatureSet';
import {Rectangle} from '../../service/common/Rectangle';
/**
* @class Zondy.Source.GeoFeatureSource
* @classdesc 地理几何专题要素型专题图层基类。
* @param {string} name - 图层名称。
* @param {Object} options - 参数。
* @param {ol.Map} options.map - 当前 OpenLayers Map 对象。
* @param {string} [options.id] - 专题图层 ID
* @param {number} [options.opacity=1] - 图层透明度。
* @param {ol.proj.Projection} [options.projection] - 投影信息。
* @param {number} [options.ratio=1.5] - 视图比,1 表示画布是地图视口的大小,2 表示地图视口的宽度和高度的两倍,依此类推。 必须是 1 或更高。
* @param {Array} [options.resolutions] - 分辨率数组。
* @param {ol.source.State} [option.state] - 资源状态。
* @param {Object} [options.style] - 专题图样式。
* @param {Object} [options.styleGroups] - 各专题类型样式组。
* @param {boolean} [options.isHoverAble=false] - 是否开启 hover 事件。
* @param {Object} [options.highlightStyle] - 开启 hover 事件后,触发的样式风格。
* @extends {Zondy.Source.ThemeSource}
*/
class GeoFeatureSource extends ThemeSource {
constructor(name, options) {
super(name, options);
this.cache = options.cache || {};
this.cacheFields = options.cacheFields || [];
this.style = options.style || {};
this.maxCacheCount = options.maxCacheCount || 0;
this.isCustomSetMaxCacheCount = options.isCustomSetMaxCacheCount || false;
this.nodesClipPixel = options.nodesClipPixel || 2;
this.isHoverAble = options.isHoverAble || false;
this.isMultiHover = options.isMultiHover || false;
this.isClickAble = options.isClickAble || true;
this.highlightStyle = options.highlightStyle || null;
this.isAllowFeatureStyle = options.isAllowFeatureStyle || false;
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.destroy
* @description 释放资源,将引用资源的属性置空。
*/
destroy() {
this.maxCacheCount = null;
this.isCustomSetMaxCacheCount = null;
this.nodesClipPixel = null;
this.isHoverAble = null;
this.isMultiHover = null;
this.isClickAble = null;
this.cache = null;
this.cacheFields = null;
this.style = null;
this.highlightStyle = null;
this.isAllowFeatureStyle = null;
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.addFeatures
* @description 添加要素。
* @param {Object} features - 要素对象。
*/
addFeatures(features) {
var me = this;
this.dispatchEvent({
type: 'beforefeaturesadded',
value: {features: features}
});
if (features instanceof FeatureSet) {
var attrs = null;
var attstruct = features.AttStruct;
var feaArr = features.SFEleArray;
if (feaArr != null && feaArr.length > 0) {
for (var j = 0; j < feaArr.length; j++) {
var feature = feaArr[j];
if (feature.AttValue != null && feature.AttValue.length > 0) {
var attrs = {};
for (var i = 0; i < feature.AttValue.length; i++) {
attrs[(attstruct.FldName)[i]] = (feature.AttValue)[i];
}
attrs['FID'] = feature.FID;
}
feature.attributes = attrs;
me.features.push(feature);
}
}
}
if (!this.isCustomSetMaxCacheCount) {
this.maxCacheCount = this.features.length * 5;
}
//绘制专题要素
if (this.renderer) {
this.changed();
}
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.removeFeatures
* @description 从专题图中删除 feature。这个函数删除所有传递进来的矢量要素。
* @param {Zondy.Feature.Vector} features - 要删除的要素对象。
*/
removeFeatures(features) { // eslint-disable-line no-unused-vars
this.clearCache();
ThemeSource.prototype.removeFeatures.apply(this, arguments);
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.removeAllFeatures
* @description 清除当前图层所有的矢量要素。
*/
removeAllFeatures() {
this.clearCache();
ThemeSource.prototype.removeAllFeatures.apply(this, arguments);
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.redrawThematicFeatures
* @description 重绘所有专题要素。
* @param {Object} extent - 视图范围数据。
*/
redrawThematicFeatures(extent) {
//获取高亮专题要素对应的用户 id
var hoverone = this.renderer.getHoverOne();
var hoverFid = null;
if (hoverone && hoverone.refDataID) {
hoverFid = hoverone.refDataID;
}
//清除当前所有可视元素
this.renderer.clearAll();
var features = this.features;
var cache = this.cache;
var cacheFields = this.cacheFields;
var cmZoom = this.map.getView().getZoom();
var maxCC = this.maxCacheCount;
var bounds = new Rectangle(extent[0], extent[1], extent[2], extent[3]);
for (var i = 0, len = features.length; i < len; i++) {
var feature = features[i];
var feaBounds = feature.bound;
//剔除当前视图(地理)范围以外的数据
if (bounds && !bounds.intersectsBounds(feaBounds)) {
continue;
}
//缓存字段
var fields = feature.FID + "_zoom_" + cmZoom.toString();
var thematicFeature;
//判断专题要素缓存是否存在
if (cache[fields]) {
cache[fields].updateAndAddShapes();
} else {
//如果专题要素缓存不存在,创建专题要素
thematicFeature = this.createThematicFeature(features[i]);
//检查 thematicFeature 是否有可视化图形
if (thematicFeature.getShapesCount() < 1) {
continue;
}
//加入缓存
cache[fields] = thematicFeature;
cacheFields.push(fields);
//缓存数量限制
if (cacheFields.length > maxCC) {
var fieldsTemp = cacheFields[0];
cacheFields.splice(0, 1);
delete cache[fieldsTemp];
}
}
}
this.renderer.render();
//地图漫游后,重新高亮图形
if (hoverFid && this.isHoverAble && this.isMultiHover) {
var hShapes = this.getShapesByFeatureID(hoverFid);
this.renderer.updateHoverShapes(hShapes);
}
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.createThematicFeature
* @description 创建专题要素。
* @param {Object} feature - 要素对象。
*/
createThematicFeature(feature) {
var style = copyAttributesWithClip(this.style);
//创建专题要素时的可选参数
var options = {};
options.nodesClipPixel = this.nodesClipPixel;
options.isHoverAble = this.isHoverAble;
options.isMultiHover = this.isMultiHover;
options.isClickAble = this.isClickAble;
options.highlightStyle = ShapeFactory.transformStyle(this.highlightStyle);
//将数据转为专题要素(Vector)
var thematicFeature = new ThemeVector(feature, this, ShapeFactory.transformStyle(style), options);
//直接添加图形到渲染器
for (var m = 0; m < thematicFeature.shapes.length; m++) {
this.renderer.addShape(thematicFeature.shapes[m]);
}
return thematicFeature;
}
canvasFunctionInternal_(extent, resolution, pixelRatio, size, projection) { // eslint-disable-line no-unused-vars
return ThemeSource.prototype.canvasFunctionInternal_.apply(this, arguments);
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.clearCache
* @description 清除缓存。
*/
clearCache() {
this.cache = {};
this.cacheFields = [];
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.clear
* @description 清除的内容包括数据(features)、专题要素、缓存。
*/
clear() {
this.renderer.clearAll();
this.renderer.refresh();
this.removeAllFeatures();
this.clearCache();
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.getCacheCount
* @description 获取当前缓存数量。
* @returns {number} 返回当前缓存数量。
*/
getCacheCount() {
return this.cacheFields.length;
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.setMaxCacheCount
* @param {number} cacheCount - 缓存总数。
* @description 设置最大缓存条数。
*/
setMaxCacheCount(cacheCount) {
if (!isNaN(cacheCount)) {
this.maxCacheCount = cacheCount;
this.isCustomSetMaxCacheCount = true;
}
}
/**
* @function Zondy.Source.GeoFeatureSource.prototype.setMaxCacheCount
* @param {number} featureID - 要素 ID。
* @description 通过 FeatureID 获取 feature 关联的所有图形。如果不传入此参数,函数将返回所有图形。
*/
getShapesByFeatureID(featureID) {
var list = [];
var shapeList = this.renderer.getAllShapes();
if (!featureID) {
return shapeList
}
for (var i = 0, len = shapeList.length; i < len; i++) {
var si = shapeList[i];
if (si.refDataID && featureID === si.refDataID) {
list.push(si);
}
}
return list;
}
}
export {GeoFeatureSource};
Zondy.Source.GeoFeatureSource = GeoFeatureSource;