kmap-ui
Version:
A components of zmap base on vue2.X
222 lines (202 loc) • 7.08 kB
JavaScript
/* Copyright (c) 2019 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*/
import ol_Feature from 'ol/Feature'
import ol_geom_Polygon from 'ol/geom/Polygon'
import ol_source_Vector from 'ol/source/Vector'
import { ol_coordinate_getFeatureCenter } from "../geom/GeomUtils";
import './Vector'
import {ol_ext_inherits} from '../util/ext'
/** Abstract base class; normally only used for creating subclasses. Bin collector for data
* @constructor
* @extends {ol.source.Vector}
* @param {Object} options ol_source_VectorOptions + grid option
* @param {ol.source.Vector} options.source Source
* @param {boolean} options.listenChange listen changes (move) on source features to recalculate the bin, default true
* @param {fucntion} [options.geometryFunction] Function that takes an ol.Feature as argument and returns an ol.geom.Point as feature's center.
* @param {function} [options.flatAttributes] Function takes a bin and the features it contains and aggragate the features in the bin attributes when saving
*/
var ol_source_BinBase = function (options) {
options = options || {};
this._bindModify = this._onModifyFeature.bind(this);
this._watch = true;
ol_source_Vector.call(this, options);
this._origin = options.source;
this._listen = (options.listenChange !== false);
// Geometry function
this._geomFn = options.geometryFunction || ol_coordinate_getFeatureCenter || function (f) { return f.getGeometry().getFirstCoordinate(); };
// Existing features
this.reset();
// Future features
this._origin.on('addfeature', this._onAddFeature.bind(this));
this._origin.on('removefeature', this._onRemoveFeature.bind(this));
this._origin.on('clearstart', this._onClearFeature.bind(this));
this._origin.on('clearend', this._onClearFeature.bind(this));
if (typeof (options.flatAttributes) === 'function') this._flatAttributes = options.flatAttributes;
};
ol_ext_inherits(ol_source_BinBase, ol_source_Vector);
/**
* On add feature
* @param {ol.events.Event} e
* @param {ol.Feature} bin
* @private
*/
ol_source_BinBase.prototype._onAddFeature = function (e, bin, listen) {
var f = e.feature || e.target;
bin = bin || this.getBinAt(this._geomFn(f), true);
if (bin) bin.get('features').push(f);
if (this._listen && listen!==false) f.on('change', this._bindModify);
};
/**
* On remove feature
* @param {ol.events.Event} e
* @param {ol.Feature} bin
* @private
*/
ol_source_BinBase.prototype._onRemoveFeature = function (e, bin, listen) {
if (!this._watch) return;
var f = e.feature || e.target;
bin = bin || this.getBinAt(this._geomFn(f));
if (bin) {
// Remove feature from bin
var features = bin.get('features');
for (var i=0, fi; fi=features[i]; i++) {
if (fi===f) {
features.splice(i, 1);
break;
}
}
// Remove bin if no features
if (!features.length) {
this.removeFeature(bin);
}
} else {
// console.log("[ERROR:Bin] remove feature: feature doesn't exists anymore.");
}
if (this._listen && listen!==false) f.un('change', this._bindModify);
};
/** When clearing features remove the listener
* @private
*/
ol_source_BinBase.prototype._onClearFeature = function (e) {
if (e.type==='clearstart') {
if (this._listen) {
this._origin.getFeatures().forEach(function (f) {
f.un('change', this._bindModify);
}.bind(this));
}
this.clear();
this._watch = false;
} else {
this._watch = true;
}
};
/**
* Get the bin that contains a feature
* @param {ol.Feature} f the feature
* @return {ol.Feature} the bin or null it doesn't exit
*/
ol_source_BinBase.prototype.getBin = function (feature) {
var bins = this.getFeatures();
for (var i=0, b; b = bins[i]; i++) {
var features = b.get('features');
for (var j=0, f; f=features[j]; j++) {
if (f===feature) return b;
}
}
return null;
}
/** Get the grid geometry at the coord
* @param {ol.Coordinate} coord
* @param {Object} attributes add key/value to this object to add properties to the grid feature
* @returns {ol.geom.Polygon}
* @api
*/
ol_source_BinBase.prototype.getGridGeomAt = function (coord /*, attributes */) {
return new ol_geom_Polygon([coord]);
};
/** Get the bean at a coord
* @param {ol.Coordinate} coord
* @param {boolean} create true to create if doesn't exit
* @return {ol.Feature} the bin or null it doesn't exit
*/
ol_source_BinBase.prototype.getBinAt = function (coord, create) {
var attributes = {};
var g = this.getGridGeomAt(coord, attributes);
if (!g) return null;
var center = g.getInteriorPoint ? g.getInteriorPoint().getCoordinates() : g.getInteriorPoints().getCoordinates()[0];// ol_extent_getCenter(g.getExtent());
var features = this.getFeaturesAtCoordinate( center );
var bin = features[0];
if (!bin && create) {
attributes.geometry = g;
attributes.features = [];
attributes.center = center;
bin = new ol_Feature(attributes);
this.addFeature(bin);
}
return bin || null;
};
/**
* A feature has been modified
* @param {ol.events.Event} e
* @private
*/
ol_source_BinBase.prototype._onModifyFeature = function (e) {
var bin = this.getBin(e.target);
var bin2 = this.getBinAt(this._geomFn(e.target), 'create');
if (bin !== bin2) {
// remove from the bin
if (bin) {
this._onRemoveFeature(e, bin, false);
}
// insert in the new bin
if (bin2) {
this._onAddFeature(e, bin2, false);
}
}
this.changed();
};
/** Clear all bins and generate a new one.
*/
ol_source_BinBase.prototype.reset = function () {
this.clear();
var features = this._origin.getFeatures();
for (var i = 0, f; f = features[i]; i++) {
this._onAddFeature({ feature: f });
}
this.changed();
};
/**
* Get features without circular dependencies (vs. getFeatures)
* @return {Array<ol.Feature>}
*/
ol_source_BinBase.prototype.getGridFeatures = function () {
var features = [];
this.getFeatures().forEach(function (f) {
var bin = new ol_Feature(f.getGeometry().clone());
for (var i in f.getProperties()) {
if (i!=='features' && i!=='geometry') {
bin.set(i, f.get(i));
}
}
bin.set('nb', f.get('features').length);
this._flatAttributes(bin, f.get('features'));
features.push(bin);
}.bind(this));
return features;
};
/** Create bin attributes using the features it contains when exporting
* @param {ol.Feature} bin the bin to export
* @param {Array<ol.Features>} features the features it contains
*/
ol_source_BinBase.prototype._flatAttributes = function(/*bin, features*/) {
};
/**
* Get the orginal source
* @return {ol_source_Vector}
*/
ol_source_BinBase.prototype.getSource = function () {
return this._origin;
};
export default ol_source_BinBase