1 /** 2 * @fileOverview 3 * Copyright (c) 2013 Regione Autonoma della Sardegna 4 * Published under the GPL license.<br> 5 * See <a href="https://sardegnageoportale.it/webgis/license.txt">https://sardegnageoportale.it/webgis/license.txt</a> 6 * for the full text of the license. 7 * @version 0.1 8 */ 9 10 /** 11 * @require framework/plugins/ClickableAttribution.js 12 * @require framework/plugins/InfoMetaPopup.js 13 */ 14 15 /** 16 * @namespace framework.plugins 17 */ 18 Ext.namespace("framework.plugins"); 19 20 /** 21 * Provides control for link to info application. 22 * @name_ InfoAerialPhotos 23 * @class Provides control for link to info aerial photo. 24 * @constructor 25 * @extends <a target="_blank" href="http://gxp.opengeo.org/master/doc/lib/plugins/Tool.html">gxp.plugins.Tool</a> 26 */ 27 framework.plugins.InfoAerialPhotos = Ext.extend(gxp.plugins.Tool, 28 /** 29 * @lends framework.plugins.InfoAerialPhotos.prototype 30 */ 31 { 32 /** 33 * plugin type. 34 * @public 35 * @type String 36 */ 37 ptype: "framework_infoaerialphotos", 38 /** 39 * Menu text. 40 * @public 41 * @type String 42 */ 43 menuText: "Seleziona immagini aeree", 44 /** 45 * Tooltip text. 46 * @public 47 * @type String 48 */ 49 tooltip: "Selezione immagini aeree", 50 /** 51 * Css class for icon. 52 * @public 53 * @type String 54 */ 55 iconCls: "gxp-icon-getfeatureinfo", 56 /** 57 * ID Double Map component. 58 * @public 59 * @type String 60 */ 61 idDoubleMapComp: null, 62 /** 63 * 64 * @public 65 * @type Object 66 */ 67 popupWindowDefaults: { 68 // Eddy 69 title: 'Feature Info', 70 width: 360, 71 height: 200, 72 anchored: false, 73 hideonmove: false 74 }, 75 /** 76 * 77 * @public 78 * @type Object 79 */ 80 controlDefaults: { 81 maxFeatures: 8, 82 hover: false, 83 drillDown: false, 84 infoFormat: "application/vnd.ogc.gml", 85 queryVisible: true 86 }, 87 /** 88 * 89 * @public 90 * @type String 91 */ 92 filexml: 'tilemapresource.xml', 93 /** 94 * Extent of the tile map 95 * @public 96 * @type {OpenLayers.Bounds} 97 */ 98 extent: null, 99 /** 100 * Origin of the tile map 101 * @public 102 * @type {OpenLayers.LonLat} 103 */ 104 tileOrigin: null, 105 /** 106 * Max resolution of the zero level 107 * @public 108 * @type {float} 109 */ 110 maxResolution: null, 111 /** 112 * Zooom of the tilemap 113 * @public 114 * @type {int} 115 */ 116 typeImg: null, 117 /** 118 * Num levels of the tile map 119 * @public 120 * @type {int} 121 */ 122 numLevels: 0, 123 /** 124 * Resolutions of the tile map 125 * @public 126 * @type {Array} 127 */ 128 resolutions: null, 129 /** 130 * Service url TMS of the tile map 131 * @public 132 * @type {String} 133 */ 134 tmsUrl: null, 135 /** 136 * @private 137 * @type {String} 138 */ 139 strisciata: null, 140 /** 141 * @private 142 * @type {String} 143 */ 144 foto: null, 145 /** 146 * Layer WMS that show selected fotogramma 147 * @public 148 * @type {OpenLayers.Layer.WMS} 149 */ 150 fotoLayer: null, 151 /** 152 * List aerial photos 153 * @public 154 * @type {JSON} 155 */ 156 mappingVoli: null, 157 /** 158 * Configured double map with aerial Photos 159 * @public 160 * @type {OpenLayers.Map} 161 */ 162 mapVoli: null, 163 /** 164 * Number volo 165 * @public 166 * @type {String} 167 */ 168 volo: null, 169 /** 170 * Image icon button. 171 * @public 172 * @type String 173 */ 174 iconButton: 'theme/app/img/camera16x16.png', 175 /** 176 * @private 177 * @param {Object} config configuration object 178 */ 179 constructor: function(config) { 180 framework.plugins.InfoAerialPhotos.superclass.constructor.apply(this, arguments); 181 }, 182 /** 183 * Create and append info action 184 * @public 185 * @returns {framework.plugins.InfoAerialPhotos} Object with info control inside 186 */ 187 addActions: function() { 188 189 190 if (this.getfeatureControl) { 191 this.controlDefaults = Ext.apply(this.controlDefaults, this.getfeatureControl); 192 } 193 194 this.control = new OpenLayers.Control.WMSGetFeatureInfo(this.controlDefaults); 195 196 // FeatureInfoPanel via Popup 197 if (this.popupWindow) { 198 var self = this; 199 200 //The control will be added to the map in constuctor of GeoExt.Action 201 var popupWindowProps = Ext.apply(this.popupWindowDefaults, this.popupWindow); 202 203 //Add the control to the popupWindow. 204 popupWindowProps.olControl = this.control; 205 206 //Apply the featureinfopanel-options to the popupWindow. 207 popupWindowProps.featureInfoPanel = this.popupWindow ? this.popupWindow.featureInfoPanel : null; 208 209 popupWindowProps.map = this.target.mapPanel.map; 210 211 popupWindowProps.iconButton = this.iconButton; 212 213 //se ha dei listeners definiti da fuori vengono appesi dopo per essere prioritari rispetto a quelli interni 214 var popupWindowListeners = popupWindowProps.listeners; 215 216 popupWindowProps.listeners = { 217 showAerialPhoto: function(record) { 218 this.openAerialPhoto(record); 219 //we add to record a method for self representation in json 220 var volo = this.mappingVoli[record.data.feature.layer.name]; 221 record.toJSON = function() { 222 var obj = { 223 idVolo: this.data.feature.layer.name, 224 volo: volo, 225 strisciata: this.data.feature.attributes[volo.strisciata].replace(/ /g, "_"), 226 foto: this.data.feature.attributes[volo.fotogramma] 227 }; 228 return JSON.stringify(obj); 229 } 230 self.fireEvent('aerialPhotoOpened', record); 231 }, 232 scope: this 233 } 234 235 if(popupWindowListeners){ 236 for (var attrname in popupWindowListeners) { 237 popupWindowProps.listeners[attrname] = popupWindowListeners[attrname]; 238 } 239 } 240 241 242 var createPopupWindow = function() { 243 // Create only once, show only when features found 244 if (!self.featurePopupWindow) { 245 self.featurePopupWindow = new framework.widgets.search.FeatureInfoPopup(popupWindowProps); 246 } 247 }; 248 249 // If enabled already create the window. 250 // if (this.pressed) { 251 createPopupWindow(); 252 // } 253 254 this.handler = function() { 255 createPopupWindow(); 256 self.featurePopupWindow.hide(); 257 }; 258 259 260 } 261 262 var actions = []; 263 264 actions.unshift(new GeoExt.Action({ 265 menuText: this.menuText, 266 id: this.idBtn, 267 hidden: this.hiddenBtn, 268 iconCls: this.iconCls, 269 tooltip: this.tooltipText, 270 enableToggle: true, 271 toggleGroup: this.toggleGroup, 272 pressed: this.pressed, 273 control: this.control, 274 map: this.target.mapPanel.map, 275 handler: this.handler 276 })); 277 278 return framework.plugins.InfoAerialPhotos.superclass.addActions.apply(this, [actions]); 279 }, 280 /** 281 * Opens an aerialphoto 282 * @param {Object} photo Photogram to open 283 * @public 284 */ 285 openAerialPhoto: function(photo) { 286 if (this.mappingVoli) { 287 if (this.idDoubleMapComp) { 288 Ext.getCmp(this.idDoubleMapComp).checkToggleColumnButton(true); 289 this.mapVoli = Ext.getCmp(this.idDoubleMapComp).app2.mapPanel.map; 290 } 291 else 292 this.mapVoli = this.target.mapPanel.map; 293 this.idVolo = photo.data.feature.layer.name; 294 this.volo = this.mappingVoli[photo.data.feature.layer.name]; 295 this.tmsUrl = this.volo.tmsUrl; 296 this.strisciata = photo.data.feature.attributes[this.volo.strisciata].replace(/ /g, "_"); 297 this.foto = photo.data.feature.attributes[this.volo.fotogramma]; 298 var url = this.tmsUrl + '/' + this.strisciata + '_' + this.foto + '/' + this.filexml; 299 300 Ext.Ajax.request({ 301 url: url, 302 success: this.fillTileMap, 303 failure: this.fillTileMapFailure, 304 scope: this 305 }); 306 } 307 }, 308 /** 309 * Opens an aerialphoto but using its json representation 310 * @param {String} json json representation of the photogram 311 * @param {int} scale scale level 312 * @public 313 */ 314 openFromJSON: function(json, scale) { 315 if (json) { 316 var record = JSON.parse(json); 317 if (this.mappingVoli) { 318 if (this.idDoubleMapComp) { 319 Ext.getCmp(this.idDoubleMapComp).checkToggleColumnButton(true); 320 this.mapVoli = Ext.getCmp(this.idDoubleMapComp).app2.mapPanel.map; 321 } 322 else 323 this.mapVoli = this.target.mapPanel.map; 324 this.idVolo = record.idVolo; 325 this.volo = record.volo; 326 this.tmsUrl = this.volo.tmsUrl; 327 this.strisciata = record.strisciata; 328 this.foto = record.foto; 329 var url = this.tmsUrl + '/' + this.strisciata + '_' + this.foto + '/' + this.filexml; 330 331 Ext.Ajax.request({ 332 url: url, 333 success: function(data) { 334 this.fillTileMap(data, scale); 335 }, 336 failure: this.fillTileMapFailure, 337 scope: this 338 }); 339 } 340 } 341 }, 342 /** 343 * Method: fillTileMap 344 * 345 * fill this object tile map with the information of the tile map 346 * 347 * @param data string of the file xml 348 * 349 */ 350 fillTileMap: function(data, scale) { 351 352 var doc = data.responseXML; 353 if (!doc || !doc.documentElement) { 354 doc = data.responseText; 355 } 356 357 var xml = new OpenLayers.Format.XML(); 358 if (typeof doc == "string") { 359 doc = xml.read(doc); 360 } 361 362 var boundingBoxNode = doc.getElementsByTagName('BoundingBox'); 363 if (boundingBoxNode != null && boundingBoxNode[0] != null) { 364 var boundingBox = boundingBoxNode[0]; 365 var minx = boundingBox.getAttribute('miny'); 366 var miny = boundingBox.getAttribute('minx'); 367 var maxx = boundingBox.getAttribute('maxy'); 368 var maxy = boundingBox.getAttribute('maxx'); 369 if (minx != null && minx != '' && miny != null && miny != '' && maxx != null && maxx != '' && maxy != null && maxy != '') { 370 this.extent = new OpenLayers.Bounds(minx, miny, maxx, maxy); 371 } 372 } 373 var tileOriginNode = doc.getElementsByTagName('Origin'); 374 if (tileOriginNode != null && tileOriginNode[0] != null) { 375 var origin = tileOriginNode[0]; 376 var x = origin.getAttribute('y'); 377 var y = origin.getAttribute('x'); 378 if (x != null && x != '' && y != null && y != '') { 379 this.tileOrigin = new OpenLayers.LonLat(x, y); 380 } 381 } 382 var tileFormat = doc.getElementsByTagName('TileFormat'); 383 if (tileFormat != null && tileFormat[0] != null) { 384 var tileType = tileFormat[0]; 385 this.typeImg = tileType.getAttribute('extension'); 386 } 387 var tileSet = doc.getElementsByTagName('TileSet'); 388 if (tileSet != null && tileSet.length > 0) { 389 this.numLevels = tileSet.length; 390 this.resolutions = []; 391 for (var i = 0; i < tileSet.length; i++) { 392 var firstTileSet = tileSet[i]; 393 var order = firstTileSet.getAttribute('order'); 394 if (order != null && order == '0') { 395 var unitsperpixel = firstTileSet.getAttribute('units-per-pixel'); 396 if (unitsperpixel != null) { 397 this.maxResolution = unitsperpixel; 398 } 399 //break; 400 } 401 this.resolutions.push(parseFloat(firstTileSet.getAttribute('units-per-pixel'))); 402 } 403 this.resolutions = this.resolutions.reverse(); 404 } 405 406 this.updateFotogrammiLayer(); 407 /*if (scale) { 408 this.mapVoli.zoomToScale(scale); 409 }*/ 410 411 }, 412 /** 413 * Method: fillTileMapFailure 414 * on failure load url 415 * 416 * @param data string of the file xml 417 * 418 */ 419 fillTileMapFailure: function(data) { 420 alert('Fotogramma non esistente.'); 421 }, 422 /** 423 * Method: updateFotogrammiLayer 424 * 425 * Update Fotogrammi Layer to show selected fotogramma 426 * 427 */ 428 updateFotogrammiLayer: function() { 429 430 var options = { 431 projection: "EPSG:3003", 432 id: "mymap", 433 units: 'm', 434 resolutions: this.resolutions, 435 maxResolution: this.maxResolution, 436 maxExtent: this.extent, 437 restrictedExtent: this.extent, 438 numZoomLevels: this.numLevels, 439 panMethod: "null", 440 zoom: 1 441 }; 442 443 this.mapVoli.setOptions(options); 444 445 446 var layerOld = this.fotoLayer; 447 var layerName = this.strisciata + '_' + this.foto; 448 this.fotoLayer = new OpenLayers.Layer.TMS( 449 this.volo.title, 450 this.tmsUrl, 451 { 452 layername: layerName, 453 type: this.typeImg, 454 background: "#000000", 455 maxExtent: this.extent, 456 tileOrigin: this.tileOrigin, 457 candidateBaseLayer: true, 458 displayInLayerSwitcher: false, 459 serviceVersion: '' 460 }); 461 462 new framework.plugins.ClickableAttribution({ 463 layer: this.fotoLayer, 464 params: { 465 idVolo: this.idVolo, 466 strisciata: this.strisciata, 467 foto: this.foto 468 }, 469 text: Ext.isDefined(this.volo.attribution) ? this.volo.attribution : 'no info provided', 470 listeners: { 471 click: function(layer, params) { 472 var volo = this.mappingVoli[params.idVolo]; 473 var popup = new framework.plugins.InfoMetaPopup({ 474 titolo: volo.title, 475 strisciata: params.strisciata, 476 fotogramma: params.foto, 477 copyright: volo.attribution, 478 metadata: volo.metadata 479 }); 480 popup.show(); 481 }, scope: this 482 } 483 }); 484 this.fotoLayer.setIsBaseLayer(true); 485 486 this.mapVoli.addLayer(this.fotoLayer); 487 488 if (layerOld !== null) 489 { 490 layerOld.destroy(); 491 } 492 493 this.mapVoli.setBaseLayer(this.fotoLayer); 494 this.mapVoli.zoomToExtent(this.extent); 495 } 496 497 498 }); 499 500 Ext.preg(framework.plugins.InfoAerialPhotos.prototype.ptype, framework.plugins.InfoAerialPhotos); 501