/**
* @constructor
* @param {cercaliax.FeatureOptions} options Feature options
*/
cercalia.Feature = function(options) {
/**
* @private
* @type {string}
*/
this.id_ = options.id ? options.id : 'CercaliaFeature_id_' + Date.now() + (Math.random() * 0xffffffff | 0);
/**
* @private
* @type {cercalia.Map}
*/
this.map_ = null;
/**
* @private
* @type {ol.Feature}
*/
this.feature_ = null;
/**
* @private
* @type {Array.<ol.Feature>}
*/
this.arrowsFeatures_ = null;
/**
* @private
* @type {string}
*/
this.srs_ = options.srs ? options.srs : 'EPSG:4326';
/**
* @private
* @type {ol.geom.Geometry}
*/
this.geometry_ = options.geometry ? options.geometry : null;
/**
* @private
* @type {number}
*/
this.zIndex_ = options.zIndex ? options.zIndex : 100;
/**
* @private
* @type {string}
*/
this.strokeColor_ = options.strokeColor ? options.strokeColor : '#ffffff';
/**
* @private
* @type {number}
*/
this.strokeOpacity_ = options.strokeOpacity !== undefined ? options.strokeOpacity : 0.7;
/**
* @private
* @type {number}
*/
this.strokeWidth_ = options.strokeWidth !== undefined ? options.strokeWidth : 5;
/**
* @private
* @type {boolean}
*/
this.outline_ = options.outline ? options.outlineColor : 1;
/**
* @private
* @type {string}
*/
this.outlineColor_ = options.outlineColor ? options.outlineColor : '#009BFF';
/**
* @private
* @type {number}
*/
this.outlineOpacity_ = options.outlineOpacity !== undefined ? options.outlineOpacity : 0.9;
/**
* @private
* @type {number}
*/
this.outlineWidth_ = options.outlineWidth !== undefined ? options.outlineWidth : 7;
/**
* @private
* @type {string}
*/
this.fillColor_ = options.fillColor ? options.fillColor : '#B5E2FF';
/**
* @private
* @type {number}
*/
this.fillOpacity_ = options.fillOpacity !== undefined ? options.fillOpacity : 0.75;
/**
* @private
* @type {string}
*/
this.pointEditableColor_ = options.pointEditableColor ? options.pointEditableColor : '#009BFF';
/**
* @private
* @type {number}
*/
this.radius_ = options.radius ? options.radius : 5;
/**
* @type {Function}
*/
this.onClick = options.onClick ? options.onClick : null;
/**
* @private
* @type {Array.<number>}
*/
this.lineDash_ = options.lineDash ? options.lineDash : null;
/**
* @type {Function}
*/
this.onDoubleClick = options.onDoubleClick ? options.onDoubleClick : null;
/**
* @type {Function}
*/
this.onRightClick = options.onRightClick ? options.onRightClick : null;
/**
* @type {Function}
*/
this.onMouseOver = options.onMouseOver ? options.onMouseOver : null;
/**
* onMouseOver Function, if specified
* @type {Function}
*/
this.onMouseOut = options.onMouseOut ? options.onMouseOut : null;
/**
* @type {Function}
* @private
*/
this.onDragStartCallBack_ = options.onDragStart ? options.onDragStart : null;
/**
* @type {Function}
* @private
*/
this.onDragMoveCallBack_ = options.onDragMove ? options.onDragMove : null;
/**
* @type {Function}
* @private
*/
this.onDragEndCallBack_ = options.onDragEnd ? options.onDragEnd : null;
/**
* @type {Function}
*/
this.onDragStart = function(marker, lonlat, evt) {
if (this.onDragStartCallBack_) this.onDragStartCallBack_(marker, lonlat, evt);
};
/**
* @type {Function}
*/
this.onDragMove = function(marker, lonlat, evt) {
this.isDragging_ = true;
if (this.onDragMoveCallBack_) this.onDragMoveCallBack_(marker, lonlat, evt);
};
/**
* @type {Function}
*/
this.onDragEnd = function(marker, lonlat, evt) {
this.isDragging_ = false;
if (this.onDragEndCallBack_) this.onDragEndCallBack_(marker, lonlat, evt);
};
/**
* @private
* @type {boolean}
*/
this.isDragging_ = false;
/**
* @type {funtion}
*/
this.onDrop = options.onDrop ? options.onDrop : null;
/**
* @private
* @type {cercalia.SimpleLabel}
*/
this.simpleLabel_ = options.simpleLabel ? options.simpleLabel : null;
if (this.simpleLabel_) {
this.simpleLabel_.setFeature(this);
}
/**
* @private
* @type {boolean}
*/
this.draggable_ = undefined;
/**
* @private
* @type {boolean}
*/
this.editable_ = options.editable ? options.editable : false;
/**
* @private
* @type {string}
*/
this.wkt_ = options.wkt ? options.wkt : null;
/**
* @private
* @type {boolean}
*/
this.showDirection_ = options.showDirection ? options.showDirection : false;
/**
* @private
* @type {String}
*/
this.iconArrow_ = options.iconArrow ? options.iconArrow : cercaliaGlobals.img + '/cercalia-arrow.png';
/**
* @private
* @type {ol.style.Style}
*/
this.style_ = null;
/**
* @private
* @type {ol.style.Style}
*/
this.styleEditable_ = null;
/**
* @private
* @type {string}
*/
this.prefixLayernameArrow_ = "LayerFeatureArrows";
if (this.wkt_) {
var wktFormat = new ol.format.WKT();
this.feature_ = wktFormat.readFeature(options.wkt);
//this.feature_ = this.features_[0];
this.geometry_ = this.feature_.getGeometry();
if (this.srs_ != 'EPSG:3857') {
this.geometry_.transform(this.srs_, 'EPSG:3857'); //Per defecte EPSG:3857
}
} else if (this.geometry_) {
this.feature_ = new ol.Feature({
geometry: this.geometry_
});
}
// Atencio! Afegim Id apart perque a vegades no es guarda
this.feature_.setId(this.id_ + "_ol_feature");
//Con esta funcion inicializamos el atribut 'this.style_'
this.setStyle_();
//Si se desa pintar las flechas sobre la linea
if (this.showDirection_) {
this.createArrows_();
}
this.feature_.setStyle(this.style_);
/**
* @private
* @type {cercalia.Feature}
*/
this.feature_.feature_ = this;
/**
* Class name
* @private
* @type {string}
*/
this.CLASS_NAME_ = "cercalia.Feature";
/**
* @private
* @type {string}
*/
this.feature_.featureType_ = this.CLASS_NAME_;
/**
* @private
* @type {boolean}
*/
this.editab
// Inicialitzem estats de drag i edit
this.setDraggable(options.draggable ? options.draggable : false);
};
/**
* @return {string} Internal feature ID
*/
cercalia.Feature.prototype.getId = function() {
return this.id_;
};
/**
* @return {cercalia.Map} Map object {@link cercalia.Map}
*/
cercalia.Feature.prototype.getMap = function() {
return this.map_;
};
/**
* Assign an ID to the feature.
* @param {string} id
*/
cercalia.Feature.prototype.setId = function(id) {
this.id_ = id;
};
/**
* @return {string} Feature WKT (Well-known-text). WKT has not Circle type format.
*/
cercalia.Feature.prototype.getWKT = function() {
//return this.wkt_;
if (this.feature_) {
return this.feature_.getWKT();
} else {
return this.wkt_;
}
};
/**
* Assigns the value to the style object based on geometry
* @private
* @param {string} styleModified
*/
cercalia.Feature.prototype.setStyle_ = function(styleModified) {
switch (this.feature_.getGeometry().getType()) {
case 'Point':
case 'MultiPoint':
this.optionsStyle_ = {
text: this.simpleLabel_ ? this.simpleLabel_.getTextStyle() : null,
image: new ol.style.Circle({
radius: this.radius_,
fill: new ol.style.Fill({
color: cercalia.Util.transformColor2rgba(this.fillColor_, this.fillOpacity_)
}),
stroke: new ol.style.Stroke({
color: cercalia.Util.transformColor2rgba(this.strokeColor_, this.strokeOpacity_),
lineDash: this.lineDash_,
width: this.strokeWidth_
})
})
};
break;
case 'LineString':
case 'MultiLineString':
case 'Polygon':
case 'MultiPolygon':
case 'GeometryCollection':
case 'Circle':
this.optionsStyle_ = {
text: this.simpleLabel_ ? this.simpleLabel_.getTextStyle() : null,
stroke: new ol.style.Stroke({
color: cercalia.Util.transformColor2rgba(this.strokeColor_, this.strokeOpacity_),
lineDash: this.lineDash_,
width: this.strokeWidth_
}),
fill: new ol.style.Fill({
color: cercalia.Util.transformColor2rgba(this.fillColor_, this.fillOpacity_)
}),
zIndex: this.zIndex_
};
break;
default:
alert('Unknown geometry: ' + this.feature_.getGeometry().getType());
break;
}
this.style_ = [new ol.style.Style(this.optionsStyle_)];
if (this.outline_ != null) {
this.style_.push(new ol.style.Style({
stroke: new ol.style.Stroke({
color: cercalia.Util.transformColor2rgba(this.outlineColor_, this.outlineOpacity_),
width: this.outlineWidth_
})
}));
}
if (this.feature_) {
this.feature_.setStyle(this.style_);
}
};
/**
* Converts the feature object to `draggable`. You can drag the feature.
* @param {boolean} draggable
*/
cercalia.Feature.prototype.setDraggable = function(draggable) {
var map = this.map_;
if (this.map_) {
this.map_.removeFeatures(this);
}
this.draggable_ = draggable;
if (map) {
map.addFeature(this);
}
};
/**
* @return {boolean} Returns the drag status for feature. Values: `true` or `false`.
*/
cercalia.Feature.prototype.isDraggable = function() {
return this.draggable_;
};
/**
* @return {boolean} Returns the edit status for feature. Values: `true` or `false`.
*/
cercalia.Feature.prototype.isEditable = function() {
return this.editable_;
};
/**
* Modify the edit status for feature. Values: `true` or `false`.
*/
cercalia.Feature.prototype.setEditable = function(edit) {
this.editable_ = edit;
if (this.map_) {
this.map_.setFeatureEditable(this, edit);
}
//If style editable not initialized..
if (!this.styleEditable_) {
this.styleEditable_ = this.style_.slice(0); //clone object
var geom = this.feature_.getGeometry();
if (geom instanceof ol.geom.Polygon || geom instanceof ol.geom.LineString) {
this.styleEditable_.push(
new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: cercalia.Util.transformColor2rgba(this.pointEditableColor_, this.fillOpacity_)
})
}),
geometry: function(feature) {
// return the coordinates of the first ring of the polygon
var coordinates;
var geometry = feature.getGeometry();
if (geometry instanceof ol.geom.Polygon) {
coordinates = geometry.getCoordinates()[0];
} else {
coordinates = geometry.getCoordinates();
}
return new ol.geom.MultiPoint(coordinates);
},
zIndex: Infinity
})
);
}
}
if (edit) {
this.feature_.setStyle(this.styleEditable_);
} else {
this.feature_.setStyle(this.style_);
}
};
/**
* @return {number} zIndex Feature object
*/
cercalia.Feature.prototype.getZIndex = function() {
return this.zIndex_;
};
/**
* Assigns a zIndex to Feature object
* @param {number} zIndex zIndex CSS.
*/
cercalia.Feature.prototype.setZIndex = function(zIndex) {
this.zIndex_ = zIndex;
this.setStyle_();
};
/**
* @return {number} circle Radius (in pixels).
*/
cercalia.Feature.prototype.getRadius = function() {
return this.radius_;
};
/**
* Assigns the feature object outline opacity.
* @param {number} radius
*/
cercalia.Feature.prototype.setRadius = function(radius) {
this.radius_ = radius;
this.setStyle_();
};
/**
* @return {number} Feature opacity. Values: `[0..1]`.
*/
cercalia.Feature.prototype.getStrokeOpacity = function() {
return this.strokeOpacity_;
};
/**
* Assigns the feature object outline opacity. Feature.
* @param {number} strokeOpacity Opacity, values between 0 y 1. -> `[0..1]`
*/
cercalia.Feature.prototype.setStrokeOpacity = function(strokeOpacity) {
this.strokeOpacity_ = strokeOpacity;
this.setStyle_();
};
/**
* @return {string} Outline color.
*/
cercalia.Feature.prototype.getStrokeColor = function() {
return this.strokeColor_;
};
/**
* Assign the object outiline color.
* @param {string} strokeColor Object Color
*/
cercalia.Feature.prototype.setStrokeColor = function(strokeColor) {
this.strokeColor_ = strokeColor;
this.setStyle_();
};
/**
* @return {number} Outline width
*/
cercalia.Feature.prototype.getStrokeWidth = function() {
return this.strokeWidth_;
};
/**
* @param {number} strokeWidth Outline width
*/
cercalia.Feature.prototype.setStrokeWidth = function(strokeWidth) {
this.strokeWidth_ = strokeWidth;
this.setStyle_();
};
/**
* @return {number} Feature object outline opacity.
*/
cercalia.Feature.prototype.getOutlineOpacity = function() {
return this.outlineOpacity_;
};
/**
* Assigns the object outline opacity. Feature.
* @param {number} outlineOpacity feature outline opacity.
*/
cercalia.Feature.prototype.setOutlineOpacity = function(outlineOpacity) {
this.outlineOpacity_ = outlineOpacity;
this.setStyle_();
};
/**
* @return {string} Outline color.
*/
cercalia.Feature.prototype.getOutlineColor = function() {
return this.outlineColor_;
};
/**
* Asign the outline color.
* @param {string} outlineColor object color
*/
cercalia.Feature.prototype.setOutlineColor = function(outlineColor) {
this.outlineColor_ = outlineColor;
this.setStyle_();
};
/**
* @return {number} Outline width
*/
cercalia.Feature.prototype.getOutlineWidth = function() {
return this.outlineWidth_;
};
/**
* @param {number} outlineWidth outiline width
*/
cercalia.Feature.prototype.setOutlineWidth = function(outlineWidth) {
this.outlineWidth_ = outlineWidth;
this.setStyle_();
};
/**
* @return {string} Fill color
*/
cercalia.Feature.prototype.getFillColor = function() {
return this.fillColor_;
};
/**
* Assign the fillcolor.
* @param {string} Fill color Hexadecimal color. Ex: '#ff0000'
*/
cercalia.Feature.prototype.setFillColor = function(fillColor) {
this.fillColor_ = fillColor;
this.setStyle_();
};
/**
* @return {number} Fill opacity. Values between 0 and 1.
*/
cercalia.Feature.prototype.getFillOpacity = function() {
return this.fillOpacity_;
};
/**
* Assign Fill opacity. Values between 0 and 1.
* @param {number} fillOpacity Fill opacity. Values between 0 and 1.
*/
cercalia.Feature.prototype.setFillOpacity = function(fillOpacity) {
this.fillOpacity_ = fillOpacity;
this.setStyle_();
};
/**
* Assign Line dash.
* @param {Array.<number>} lineDash Line dash.
*/
cercalia.Feature.prototype.setLineDash = function(lineDash) {
this.lineDash_ = lineDash;
this.setStyle_();
};
/**
* @return {Array.<number>} Line dash.
*/
cercalia.Feature.prototype.getLineDash = function() {
return this.lineDash_;
};
/**
* True if feature is dragging, otherwise false.
* @return {boolean}
*/
cercalia.Feature.prototype.isDragging = function() {
return this.isDragging_;
}
/**
* @return {ol.Feature} Object <a href="http://openlayers.org/en/v3.0.0/apidoc/ol.Feature.html">`ol.Feature`</a> Openlayers3
*/
cercalia.Feature.prototype.getFeature = function() {
return this.feature_;
};
/**
* SimpleLabel to add/modify related to the marker
* @param {cercalia.SimpleLabel} simpleLabel
*/
cercalia.Feature.prototype.setSimpleLabel = function(simpleLabel) {
this.simpleLabel_ = simpleLabel;
this.simpleLabel_.setFeature(this);
this.optionsStyle_.text = simpleLabel.getTextStyle();
this.setStyle_();
};
/**
* @return {cercalia.SimpleLabel} Returns {@link cercalia.SimpleLabel} if it's created. If not, returns `null`.
*/
cercalia.Feature.prototype.getSimpleLabel = function() {
return this.simpleLabel_;
};
/**
* Add or remove map reference. For add a feature, use the class {@link cercalia.Map}
* function `addFeature` or `addFeatures`
* @param {cercalia.Map} map Cercalia Map.
*/
cercalia.Feature.prototype.setMap = function(map) {
if (map) {
if (this.map_ == null) {
this.map_ = map;
var projectionCode = map.getProjectionCode();
//Si té una altra projecció que no és la original
if (projectionCode != 'EPSG:3857') {
this.getFeature().getGeometry().transform('EPSG:3857', projectionCode);
}
//Arrows si en té..
if (this.arrowsFeatures_) {
this.addArrowsToMap_();
}
this.setEditable(this.editable_);
} else {
alert('cercalia.feature: Ya existía el Feature');
}
} else {
this.removeArrowsFromMap_();
this.map_ = null;
}
};
/**
* @private
*/
cercalia.Feature.prototype.removeArrowsFromMap_ = function() {
if (this.map_ && this.clusterArrowLayer_) {
this.map_.removeLayer(this.clusterArrowLayer_);
this.clusterArrowLayer_ = null;
this.arrowsFeatures_ = null;
}
};
/**
* @private
*/
cercalia.Feature.prototype.addArrowsToMap_ = function() {
var sourceFeatures = new ol.source.Vector({});
this.clusterArrowLayer_ = new ol.layer.Vector({
name: this.prefixLayernameArrow_ + this.id_,
source: new ol.source.Cluster({
distance: 40,
source: new ol.source.Vector({
features: this.arrowsFeatures_
})
})
});
// Afegim el layer sota el layer de markers per que aquests apareguin per sobre les fletxes
var indexToPut = this.map_.getLayerIndexByName(cercalia.LayerEnumeration.MarkerLayer);
this.map_.addLayer(this.clusterArrowLayer_, indexToPut);
var self = this;
sourceFeatures.addFeatures(this.arrowsFeatures_);
var onchangeSourceFunction = function() {
var clusterFeatures = self.clusterArrowLayer_.getSource().getFeatures();
if (clusterFeatures.length > 0) {
for (var i = 0; i < clusterFeatures.length; i++) {
//Por cada Cluster (feature) buscamos el elemento de los de dentro más cercano
var clusterInnerFeatures = clusterFeatures[i].getProperties().features;
if (clusterInnerFeatures.length == 1) {
//Solo tiene una feature. Usaremos esta como flecha
clusterFeatures[i].setGeometry(clusterInnerFeatures[0].getGeometry());
clusterFeatures[i].setStyle(clusterInnerFeatures[0].getStyle());
} else {
//Buscamos la feature mas cercana al cluster para usar su estilo y su posicion
var coordReferencia = clusterFeatures[i].getGeometry().getCoordinates();
var minDist = 9999999;
var featureNearest = null;
for (var k = 0; k < clusterInnerFeatures.length; k++) {
var coordAct = clusterInnerFeatures[k].getGeometry().getCoordinates();
var dist = Math.sqrt(Math.pow((coordReferencia[0] - coordAct[0]), 2) + Math.pow((coordReferencia[1] - coordAct[1]), 2));
if (dist < minDist) {
minDist = dist;
featureNearest = clusterInnerFeatures[k];
}
}
//Feature más cercana
clusterFeatures[i].setGeometry(featureNearest.getGeometry());
clusterFeatures[i].setStyle(featureNearest.getStyle());
}
}
}
self.clusterArrowLayer_.getSource().once('change', onchangeSourceFunction);
};
this.clusterArrowLayer_.getSource().once('change', onchangeSourceFunction);
};
/**
* Destroy object and related atributes to free up memory
*/
cercalia.Feature.prototype.destroy = function() {
if (this.map_ != null) {
this.removeArrowsFromMap_();
this.map_.removeFeatures(this);
for (var key in this) {
delete this[key];
}
}
};
/**
* @return {cercalia.Bounds} Returns the feature limits
*/
cercalia.Feature.prototype.getBounds = function() {
var extentOL = this.feature_.getGeometry().getExtent();
var projectionCode = this.map_ ? this.map_.getProjectionCode() : 'EPSG:3857';
var extent = ol.proj.transformExtent(extentOL, projectionCode, 'EPSG:4326');
return new cercalia.Bounds(extent);
};
/**
* Returns the object type.
* @return {string}
*/
cercalia.Feature.prototype.getClass = function() {
return this.CLASS_NAME_;
};
/**
* @private
*/
cercalia.Feature.prototype.createArrows_ = function() {
var geometry = this.feature_.getGeometry();
var position = 'middle';
var forEachSegment = true;
if (geometry instanceof ol.geom.LineString) {
this.arrowsFeatures_ = this.createLineStringDirection_(geometry, position, forEachSegment);
} else if (geometry instanceof ol.geom.MultiLineString) {
//Convertimos multilinestring a linestring
var linestrings = geometry.getLineStrings();
var linestringGeometry = linestrings[0];
for (var i = 1; i < linestrings.length; i++) {
linestrings[i].getCoordinates().forEach(function(coord, index) {
linestringGeometry.appendCoordinate(coord);
});
}
this.arrowsFeatures_ = this.createLineStringDirection_(linestringGeometry, position, forEachSegment);
}
};
/**
* @private
* @param {ol.geom.LineString} line
* @param {String} position
* @param {boolean} forEachSegment
* @return {Array.<ol.Feature>}
*/
cercalia.Feature.prototype.createLineStringDirection_ = function(line, position, forEachSegment) {
if (position == undefined) {
position = "end";
}
if (forEachSegment == undefined) {
forEachSegment = false;
}
var points = [];
var allSegs = this.getSegments_(line);
var segs = [];
if (forEachSegment) {
segs = allSegs;
} else {
if (position == "start") {
segs.push(allSegs[0]);
} else if (position == "end") {
segs.push(allSegs[allSegs.length - 1]);
} else if (position == "middle") {
return [this.getPointOnLine_(line, .5)];
} else {
return [];
}
}
for (var i = 0; i < segs.length; i++) {
points = points.concat(this.createSegDirection_(segs[i], position));
}
return points;
};
/**
* @private
* @param {ol.geom.LineString} line
* @return {Array.<Object>}
*/
cercalia.Feature.prototype.getSegments_ = function(line) {
var numSeg = line.getCoordinates().length - 1;
var components = line.getCoordinates();
var segments = new Array(numSeg),
point1, point2;
for (var i = 0; i < numSeg; ++i) {
point1 = components[i];
point2 = components[i + 1];
segments[i] = {
x1: point1[0],
y1: point1[1],
x2: point2[0],
y2: point2[1]
};
}
return segments;
};
/**
* @private
* @param {ol.Coord} seg
* @param {String} position
* @return {Array.<ol.Feature>}
*/
cercalia.Feature.prototype.createSegDirection_ = function(seg, position) {
var segBearing = this.bearing_(seg);
var positions = [];
var points = [];
if (position == "start") {
positions.push([seg.x1, seg.y1]);
} else if (position == "end") {
positions.push([seg.x2, seg.y2]);
} else if (position == "middle") {
positions.push([(seg.x1 + seg.x2) / 2, (seg.y1 + seg.y2) / 2]);
} else {
return null;
}
for (var i = 0; i < positions.length; i++) {
var idFeature = this.id_ + "_arrow_" + new Date().getTime() + "" + Math.random() * 10000;
var pt = new ol.geom.Point([positions[i][0], positions[i][1]]);
var ptFeature = new ol.Feature({
geometry: pt
});
ptFeature.setId(idFeature);
ptFeature.setStyle(new ol.style.Style({
image: new ol.style.Icon({
src: this.iconArrow_,
rotation: (Math.PI * segBearing / 180),
rotateWithView: true
}),
zIndex: this.zIndex_ + 1
}));
points.push(ptFeature);
}
return points;
};
/**
* @private
* @param {ol.Coord} seg
* @return {number}
*/
cercalia.Feature.prototype.bearing_ = function(seg) {
var b_x = 0;
var b_y = 1;
var a_x = seg.x2 - seg.x1;
var a_y = seg.y2 - seg.y1;
var angle_rad = Math.acos((a_x * b_x + a_y * b_y) / Math.sqrt(a_x * a_x + a_y * a_y));
var angle = 360 / (2 * Math.PI) * angle_rad;
if (a_x < 0) {
return 360 - angle;
} else {
return angle;
}
};
/**
* @private
* @param {ol.geom} line
* @param {number} measure
* @return {ol.Feature|boolean}
*/
cercalia.Feature.prototype.getPointOnLine_ = function(line, measure) {
var segs = this.getSegments_(line);
var lineLength = line.getLength();
var measureLength = lineLength * measure;
var length = 0;
var partLength = 0;
for (var i = 0; i < segs.length; i++) {
var segLength = this.getSegmentLength_(segs[i]);
if (measureLength < length + segLength) {
partLength = measureLength - length;
var x = segs[i].x1 + (segs[i].x2 - segs[i].x1) * partLength / segLength;
var y = segs[i].y1 + (segs[i].y2 - segs[i].y1) * partLength / segLength;
var segBearing = bearing(segs[i]);
var pt = new ol.geom.Point(x, y);
var ptFeature = new ol.Feature({
geometry: pt
});
ptFeature.setId(this.id_ + "_ol_feature" + "_p_" + i);
ptFeature.setStyle(new ol.style.Style({
image: new ol.style.Icon({
src: this.iconArrow_,
rotation: segBearing
})
}));
return ptFeature;
}
length = length + segLength;
}
return false;
};
/**
* Returns true if the feature has directions created and visibles.
*/
cercalia.Feature.prototype.hasDirections = function() {
return this.arrowsFeatures_ != null;
};
/**
* Show arrow directions of feature
*/
cercalia.Feature.prototype.showDirections = function() {
if (!this.showDirection_) {
this.showDirection_ = true;
this.createArrows_();
if (this.arrowsFeatures_) {
this.addArrowsToMap_();
}
}
};
/**
* Hide arrow directions of feature.
*/
cercalia.Feature.prototype.hideDirections = function() {
if (this.showDirection_) {
this.showDirection_ = false;
this.removeArrowsFromMap_();
}
};
/**
* @private
* @param {Object} seg
* @return {number}
*/
cercalia.Feature.prototype.getSegmentLength_ = function(seg) {
return Math.sqrt(Math.pow((seg.x2 - seg.x1), 2) + Math.pow((seg.y2 - seg.y1), 2));
};
/**
* @public
* @param onDragStart {function|undefined}
*/
cercalia.Feature.prototype.addOnDragStart = function(onDragStart) {
this.onDragStartCallBack_ = onDragStart ? onDragStart : null;
};
/**
* @public
* @param onDragMove {function|undefined}
*/
cercalia.Feature.prototype.addOnDragMove = function(onDragMove) {
this.onDragMoveCallBack_ = onDragMove ? onDragMove : null;
};
/**
* @public
* @param onDragEnd {function|undefined}
*/
cercalia.Feature.prototype.addOnDragEnd = function(onDragEnd) {
this.onDragEndCallBack_ = onDragEnd ? onDragEnd : null;
};
/**
* @public
* @param onClick {function|undefined}
*/
cercalia.Feature.prototype.addOnClick = function(onClick) {
this.onClick = onClick ? onClick : null;
};
/**
* @return {string} Change vertices color when is in editing mode.
*/
cercalia.Feature.prototype.setEditablePointColor = function(color) {
this.pointEditableColor_ = color;
};
/**
* @param {cercalia.LonLat} position Position
* @return {cercalia.LonLat} Closest position of feature respect parameter position.
*/
cercalia.Feature.prototype.getClosestCoordinate = function(position) {
var projectionCode = this.map_ ? this.map_.getProjectionCode() : 'EPSG:3857';
var olCoordinate = position.transform(projectionCode);
var closestCoordinate = this.geometry_.getClosestPoint(olCoordinate);
return new cercalia.LonLat(closestCoordinate[0], closestCoordinate[1], projectionCode);
};