Commit 0788fb1f authored by Pedro Eduardo Trujillo's avatar Pedro Eduardo Trujillo
Browse files

Separa partes de la lógica de capa wms

Divide la lógica presente en la implementación de la capa de mapa
destinada a representar servicios WMS para simplificar su mantenimiento.
Agrupa la funcionalidad relativa a obtener información con el método
'getFeatureInfo' en una base de código y la funcionalidad relativa a la
gestión de las dimensiones aplicadas en otra base de código.

Prepara el terreno para trabajar con la dimensión de elevación.
parent b59a72bf
Loading
Loading
Loading
Loading
+6 −247
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'leaflet'
	, 'moment'
	, 'src/component/map/layer/_LayerDimensions'
	, 'src/component/map/layer/_LayerFeatureInfo'
	, 'src/component/map/layer/_LayerProtocols'
	, 'src/component/map/layer/MapLayer'
	, 'src/component/map/StaticLayersDefinition'
@@ -10,15 +10,15 @@ define([
], function(
	declare
	, lang
	, L
	, moment
	, _LayerDimensions
	, _LayerFeatureInfo
	, _LayerProtocols
	, MapLayer
	, StaticLayersDefinition
	, ServiceOGCImage
) {

	return declare([MapLayer, _LayerProtocols], {
	return declare([MapLayer, _LayerProtocols, _LayerFeatureInfo, _LayerDimensions], {
		//	summary:
		//		Implementación de capa provista por servicio externo.
		//	description:
@@ -29,14 +29,7 @@ define([
			this.config = {
				ownChannel: 'wmsLayer',
				layerDefinition: null,
				refresh: 0,
				getFeatureInfoService: 'WMS',
				getFeatureInfoVersion: '1.1.1',
				getFeatureInfoRequest: 'GetFeatureInfo',
				getFeatureInfoSrs: 'EPSG:4326',
				getFeatureInfoFormat: 'application/json',
				getFeatureInfoMaxCount: 100,
				getFeatureInfoBuffer: 5
				refresh: 0
			};

			lang.mixin(this, this.config, args);
@@ -110,231 +103,6 @@ define([
			this._emitEvt('LAYER_LEGEND', this._getLayerLegendToPublish(legendElement));
		},

		_chkUrlAndAddParams: function(url, paramsStr) {

			var index = url.indexOf('?'),
				params = paramsStr;

			if (index >= 0) {
				params = '';

				if (index !== url.length - 1) {
					params += '&';
				}

				params += paramsStr.substr(1, paramsStr.length);
			}

			return url + params;
		},

		_requestLayerInfo: function(obj) {

			this.infoTarget = this._obtainLayerInfoTarget(obj);

			this._emitEvt('GET', {
				target: this.infoTarget,
				requesterId: this.getOwnChannel(),
				headers: {
					'X-Requested-With': ''
				}
			});
		},

		_obtainLayerInfoTarget: function(data) {

			var protocol = this.layerDefinition.protocol,
				mustUseAlternativeDefinition = protocol === 'WMTS' || protocol === 'TMS' || protocol === 'WMS-C';

			if (mustUseAlternativeDefinition) {
				return this._obtainLayerAlternativeDefinitionTarget(data);
			}

			return this._obtainLayerMainDefinitionTarget(data);
		},

		_obtainLayerMainDefinitionTarget: function(data) {

			return this._chkUrlAndAddParams(this._obtainMainGetUrl(), this._obtainMainGetParams(data));
		},

		_obtainLayerAlternativeDefinitionTarget: function(data) {

			var alternativeDefinitions = this.layerDefinition.alternativeDefinitions,
				alternativeDefinition;

			for (var i = 0; i < alternativeDefinitions.length; i++) {
				var altDef = alternativeDefinitions[i];
				if (altDef.protocol === 'WMS') {
					alternativeDefinition = altDef;
					break;
				}
			}

			if (!alternativeDefinition) {
				console.error('Alternative protocol not found for GetFeatureInfo at layer:', this.layerDefinition);
				return;
			}

			return this._chkUrlAndAddParams(this._obtainAltGetUrl(alternativeDefinition),
				this._obtainAltGetParams(alternativeDefinition, data));
		},

		_obtainCommonGetParams: function() {

			return {
				service: this.getFeatureInfoService,
				version: this.getFeatureInfoVersion,
				request: this.getFeatureInfoRequest,
				srs: this.getFeatureInfoSrs,
				info_format: this.getFeatureInfoFormat,
				feature_count: this.getFeatureInfoMaxCount,
				buffer: this.getFeatureInfoBuffer
			};
		},

		_obtainDimensionParams: function(data) {

			var dimensionParams = {};

			if (data.time) {
				dimensionParams.time = moment(data.time).toISOString();
			}

			return dimensionParams;
		},

		_obtainPositionGetParams: function(position, version) {

			var params = {},
				lngParam, latParam;

			if (version === '1.3.0') {
				lngParam = 'i';
				latParam = 'j';
			} else {
				lngParam = 'x';
				latParam = 'y';
			}

			params[lngParam] = parseInt(position.x, 10);
			params[latParam] = parseInt(position.y, 10);

			return params;
		},

		_obtainAltGetUrl: function(altDef) {

			return altDef.url + '?';
		},

		_obtainAltGetParams: function(altDef, data) {

			var commonGetParams = this._obtainCommonGetParams(),
				dimensionParams = this._obtainDimensionParams(data),
				positionParams = this._obtainPositionGetParams(data.containerPoint, commonGetParams.version),
				sizeParams = {
					width: data.size.x,
					height: data.size.y,
					bbox: data.bbox.toBBoxString()
				},
				layerProps = altDef.props,
				layerName = layerProps.layers,
				layerStyles = layerProps.styles || '';

			var getParams = this._merge([commonGetParams, dimensionParams, positionParams, sizeParams, {
				layers: layerName,
				query_layers: layerName,
				styles: layerStyles
			}]);

			return L.Util.getParamString(getParams);
		},

		_obtainMainGetUrl: function() {

			return this.layer._wmsUrl + '?';
		},

		_obtainMainGetParams: function(data) {

			var commonGetParams = this._obtainCommonGetParams(),
				dimensionParams = this._obtainDimensionParams(data),
				serviceVersion = commonGetParams.version,
				layerName = this.layer.wmsParams.layers,
				positionParams, sizeParams;

			var isTiled = this.layerDefinition.protocol === 'WMS-C';
			if (!isTiled) {
				var containerPosParams = this._obtainPositionGetParams(data.containerPoint, serviceVersion);

				positionParams = containerPosParams;

				sizeParams = {
					width: data.size.x,
					height: data.size.y,
					bbox: data.bbox.toBBoxString()
				};
			} else {
				var tile = this._getClickedTile(data.latLng, data.zoom),
					tileSize = this.layer.getTileSize(),
					tilePoint = this._getClickedTilePoint(data.containerPoint, tile),
					tilePosParams = this._obtainPositionGetParams(tilePoint, serviceVersion);

				// TODO falla el punto
				positionParams = tilePosParams;

				sizeParams = {
					width: tileSize.x,
					height: tileSize.y,
					bbox: this._getTileBbox(tile)
				};
			}

			var getParams = this._merge([commonGetParams, dimensionParams, positionParams, sizeParams, {
				layers: layerName,
				query_layers: layerName,
				styles: this.layer.wmsParams.styles
			}]);

			return L.Util.getParamString(getParams);
		},

		_getClickedTile: function(clickLatLng, currZoom) {

			var clickedTileKey = this._getTileKey(clickLatLng, currZoom);

			return this.layer._tiles[clickedTileKey];
		},

		_getTileKey: function(clickLatLng, currZoom) {

			var tileSize = this.layer.getTileSize(),
				pixelPoint = this.layer._map.project(clickLatLng, currZoom).floor(),
				coords = pixelPoint.unscaleBy(tileSize).floor();

			return coords.x + ':' + coords.y + ':' + currZoom;
		},

		_getClickedTilePoint: function(containerPoint, tile) {
			// TODO no funciona, va bien en zoom alejado solamente

			var tilePosition = tile.el._leaflet_pos,
				tileOffsetX = containerPoint.x - tilePosition.x,
				tileOffsetY = containerPoint.y - tilePosition.y;

			return { x: tileOffsetX, y: tileOffsetY };
		},

		_getTileBbox: function(tile) {

			var tileSrc = tile.el.src,
				bboxExpr = /.+bbox=([-.,\d]+).*/gi,
				exprMatches = new RegExp(bboxExpr).exec(tileSrc);

			return exprMatches[1];
		},

		_chkLayerIsMe: function(response) {

			var layerAddedId = response.layer._leaflet_id;
@@ -342,15 +110,6 @@ define([
			return layerAddedId === this.layerId;
		},

		_processLayerInfo: function(data) {

			this._emitEvt('LAYER_INFO', {
				layerId: this.layerId,
				layerLabel: this.layerLabel,
				info: data
			});
		},

		_onMapShown: function(response) {

			this._setRefreshInterval();
+106 −0
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'dojo/aspect'
	, 'moment'
], function(
	declare
	, lang
	, aspect
	, moment
) {

	return declare(null, {
		//	summary:
		//		Extensión de MapLayer para asignar valores a diferentes dimensiones de la capa, como la temporal o la de
		//		elevación.

		constructor: function(args) {

			this.config = {
				layerDimensionsActions: {
					SET_LAYER_DIMENSION: 'SET_LAYER_DIMENSION'
				},

				_currentDimensionValues: {}
			};

			lang.mixin(this, this.config, args);

			aspect.after(this, '_mixEventsAndActions', lang.hitch(this, this._mixLayerDimensionsEventsAndActions));
			aspect.after(this, '_defineSubscriptions', lang.hitch(this, this._defineLayerDimensionsSubscriptions));
		},

		_mixLayerDimensionsEventsAndActions: function () {

			lang.mixin(this.actions, this.layerDimensionsActions);
			delete this.layerDimensionsActions;
		},

		_defineLayerDimensionsSubscriptions: function () {

			this.subscriptionsConfig.push({
				channel: this.getChannel('SET_LAYER_DIMENSION'),
				callback: '_subSetLayerDimension'
			});

			this._deleteDuplicatedChannels(this.subscriptionsConfig);
		},

		_obtainDimensionParams: function(data) {

			var dimensionParams = {};

			this._obtainTimeDimensionParams(dimensionParams, data);
			this._obtainElevationDimensionParams(dimensionParams);

			return dimensionParams;
		},

		_obtainTimeDimensionParams: function(dimensionParams, data) {

			if (dimensionParams && data && data.time) {
				dimensionParams.time = moment(data.time).toISOString();
				this._currentDimensionValues.time = dimensionParams.time;
			}

			return dimensionParams;
		},

		_obtainElevationDimensionParams: function(dimensionParams) {

			if (dimensionParams && this._currentDimensionValues.elevation) {
				dimensionParams.elevation = this._currentDimensionValues.elevation;
			}

			return dimensionParams;
		},

		_subSetLayerDimension: function(req) {

			this._setElevationDimension(req);
		},

		_setElevationDimension: function(req) {

			if (!req || !req.elevation) {
				return;
			}

			var newElevation = req.elevation.value;
			this._currentDimensionValues.elevation = newElevation;

			this._applyElevationDimension();
		},

		_applyElevationDimension: function(req) {

			if (!this.layer) {
				return;
			}
			this.layer.setParams({
				elevation: this._currentDimensionValues.elevation
			});
		}
	});
});
+253 −0
Original line number Diff line number Diff line
define([
	'dojo/_base/declare'
	, 'dojo/_base/lang'
	, 'leaflet'
], function(
	declare
	, lang
	, L
) {

	return declare(null, {
		//	summary:
		//		Extensión de WmsLayerImpl para gestionar las peticiones de información mediante getFeatureInfo.

		constructor: function(args) {

			this.config = {
				getFeatureInfoService: 'WMS',
				getFeatureInfoVersion: '1.1.1',
				getFeatureInfoRequest: 'GetFeatureInfo',
				getFeatureInfoSrs: 'EPSG:4326',
				getFeatureInfoFormat: 'application/json',
				getFeatureInfoMaxCount: 100,
				getFeatureInfoBuffer: 5
			};

			lang.mixin(this, this.config, args);
		},

		_requestLayerInfo: function(obj) {

			this.infoTarget = this._obtainLayerInfoTarget(obj);

			this._emitEvt('GET', {
				target: this.infoTarget,
				requesterId: this.getOwnChannel(),
				headers: {
					'X-Requested-With': ''
				}
			});
		},

		_processLayerInfo: function(data) {

			this._emitEvt('LAYER_INFO', {
				layerId: this.layerId,
				layerLabel: this.layerLabel,
				info: data
			});
		},

		_obtainLayerInfoTarget: function(data) {

			var protocol = this.layerDefinition.protocol,
				mustUseAlternativeDefinition = protocol === 'WMTS' || protocol === 'TMS' || protocol === 'WMS-C';

			if (mustUseAlternativeDefinition) {
				return this._obtainLayerAlternativeDefinitionTarget(data);
			}

			return this._obtainLayerMainDefinitionTarget(data);
		},

		_chkUrlAndAddParams: function(url, paramsStr) {

			var index = url.indexOf('?'),
				params = paramsStr;

			if (index >= 0) {
				params = '';

				if (index !== url.length - 1) {
					params += '&';
				}

				params += paramsStr.substr(1, paramsStr.length);
			}

			return url + params;
		},

		_obtainLayerMainDefinitionTarget: function(data) {

			return this._chkUrlAndAddParams(this._obtainMainGetUrl(), this._obtainMainGetParams(data));
		},

		_obtainLayerAlternativeDefinitionTarget: function(data) {

			var alternativeDefinitions = this.layerDefinition.alternativeDefinitions,
				alternativeDefinition;

			for (var i = 0; i < alternativeDefinitions.length; i++) {
				var altDef = alternativeDefinitions[i];
				if (altDef.protocol === 'WMS') {
					alternativeDefinition = altDef;
					break;
				}
			}

			if (!alternativeDefinition) {
				console.error('Alternative protocol not found for GetFeatureInfo at layer:', this.layerDefinition);
				return;
			}

			return this._chkUrlAndAddParams(this._obtainAltGetUrl(alternativeDefinition),
				this._obtainAltGetParams(alternativeDefinition, data));
		},

		_obtainCommonGetParams: function() {

			return {
				service: this.getFeatureInfoService,
				version: this.getFeatureInfoVersion,
				request: this.getFeatureInfoRequest,
				srs: this.getFeatureInfoSrs,
				info_format: this.getFeatureInfoFormat,
				feature_count: this.getFeatureInfoMaxCount,
				buffer: this.getFeatureInfoBuffer
			};
		},

		_obtainPositionGetParams: function(position, version) {

			var params = {},
				lngParam, latParam;

			if (version === '1.3.0') {
				lngParam = 'i';
				latParam = 'j';
			} else {
				lngParam = 'x';
				latParam = 'y';
			}

			params[lngParam] = parseInt(position.x, 10);
			params[latParam] = parseInt(position.y, 10);

			return params;
		},

		_obtainAltGetUrl: function(altDef) {

			return altDef.url + '?';
		},

		_obtainAltGetParams: function(altDef, data) {

			var commonGetParams = this._obtainCommonGetParams(),
				dimensionParams = this._obtainDimensionParams(data),
				positionParams = this._obtainPositionGetParams(data.containerPoint, commonGetParams.version),
				sizeParams = {
					width: data.size.x,
					height: data.size.y,
					bbox: data.bbox.toBBoxString()
				},
				layerProps = altDef.props,
				layerName = layerProps.layers,
				layerStyles = layerProps.styles || '';

			var getParams = this._merge([commonGetParams, dimensionParams, positionParams, sizeParams, {
				layers: layerName,
				query_layers: layerName,
				styles: layerStyles
			}]);

			return L.Util.getParamString(getParams);
		},

		_obtainMainGetUrl: function() {

			return this.layer._wmsUrl + '?';
		},

		_obtainMainGetParams: function(data) {

			var commonGetParams = this._obtainCommonGetParams(),
				dimensionParams = this._obtainDimensionParams(data),
				serviceVersion = commonGetParams.version,
				layerName = this.layer.wmsParams.layers,
				positionParams, sizeParams;

			var isTiled = this.layerDefinition.protocol === 'WMS-C';
			if (!isTiled) {
				var containerPosParams = this._obtainPositionGetParams(data.containerPoint, serviceVersion);

				positionParams = containerPosParams;

				sizeParams = {
					width: data.size.x,
					height: data.size.y,
					bbox: data.bbox.toBBoxString()
				};
			} else {
				var tile = this._getClickedTile(data.latLng, data.zoom),
					tileSize = this.layer.getTileSize(),
					tilePoint = this._getClickedTilePoint(data.containerPoint, tile),
					tilePosParams = this._obtainPositionGetParams(tilePoint, serviceVersion);

				// TODO falla el punto
				positionParams = tilePosParams;

				sizeParams = {
					width: tileSize.x,
					height: tileSize.y,
					bbox: this._getTileBbox(tile)
				};
			}

			var getParams = this._merge([commonGetParams, dimensionParams, positionParams, sizeParams, {
				layers: layerName,
				query_layers: layerName,
				styles: this.layer.wmsParams.styles
			}]);

			return L.Util.getParamString(getParams);
		},

		_getClickedTile: function(clickLatLng, currZoom) {

			var clickedTileKey = this._getTileKey(clickLatLng, currZoom);

			return this.layer._tiles[clickedTileKey];
		},

		_getTileKey: function(clickLatLng, currZoom) {

			var tileSize = this.layer.getTileSize(),
				pixelPoint = this.layer._map.project(clickLatLng, currZoom).floor(),
				coords = pixelPoint.unscaleBy(tileSize).floor();

			return coords.x + ':' + coords.y + ':' + currZoom;
		},

		_getClickedTilePoint: function(containerPoint, tile) {
			// TODO no funciona, va bien en zoom alejado solamente

			var tilePosition = tile.el._leaflet_pos,
				tileOffsetX = containerPoint.x - tilePosition.x,
				tileOffsetY = containerPoint.y - tilePosition.y;

			return { x: tileOffsetX, y: tileOffsetY };
		},

		_getTileBbox: function(tile) {

			var tileSrc = tile.el.src,
				bboxExpr = /.+bbox=([-.,\d]+).*/gi,
				exprMatches = new RegExp(bboxExpr).exec(tileSrc);

			return exprMatches[1];
		}
	});
});