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/widgets/control/Compass.js
 12  * @require framework/widgets/control/ViewDirection.js
 13  */
 14 
 15 /**
 16  * @namespace framework.plugins
 17  */
 18 Ext.namespace("framework.plugins");
 19 
 20 /**
 21  * Constant for nearest algorithm type
 22  */
 23 var OBLIQUEPHOTOS_ALGORITHMTYPE = {CENTROID_BASED: {value: 0, name: 'Centroid'}, EXTENT_BASED: {value: 1, name: 'Extent'}};
 24 
 25 /** 
 26  *  Provides control for link to info application.
 27  *  @name_ ActiveObliquePhotos
 28  *  @class Provides control for link to info application.
 29  *  @constructor
 30  *  @extends <a target="_blank" href="http://gxp.opengeo.org/master/doc/lib/plugins/Tool.html">gxp.plugins.Tool</a>
 31  */
 32 framework.plugins.ActiveObliquePhotos = Ext.extend(gxp.plugins.Tool,
 33     /** 
 34      * @lends framework.plugins.ActiveObliquePhotos.prototype 
 35      */
 36         {
 37           /**
 38            * plugin type.
 39            * @public
 40            * @type String
 41            */
 42           ptype: "framework_activeobliquephotos",
 43           /**
 44            * Menu text.
 45            * @public
 46            * @type String
 47            */
 48           menuText: "Attiva modalità foto oblique",
 49           /**
 50            * Msg no photo.
 51            * @public
 52            * @type String
 53            */
 54           noPhoto: "Foto oblique non presenti in questa zona",
 55           /**
 56            * Msg no CSV.
 57            * @public
 58            * @type String
 59            */
 60           noCSV: "Foto oblique in fase di elaborazione",
 61           /**
 62            * Tooltip text.
 63            * @public
 64            * @type String
 65            */
 66           tooltip: "Attiva la modalità foto oblique",
 67           /**
 68            * Msg tooltip deactivate.
 69            * @public
 70            * @type String
 71            */
 72           tooltipDeactivate: "Disattiva la modalità foto oblique",
 73           /**
 74            * Class with button is pressed.
 75            * @public
 76            * @type String
 77            */
 78           pressedCls: 'oblBtnPressed',
 79           /**
 80            * Class with button is unpressed.
 81            * @public
 82            * @type String
 83            */
 84           unpressedCls: 'oblBtn',
 85           /**
 86            * Css class for icon.
 87            * @public
 88            * @type String
 89            */
 90           iconCls: "gxp-icon-obliquephotos",
 91           /**
 92            * Compass used for changing direction and switching to orthophone mode
 93            * @private
 94            * @type framework.widgets.control.Compass
 95            */
 96           compass: null,
 97           /**
 98            * Type of algorithm to use for nearest photogram search
 99            * @public
100            * @type ALGORITHMTYPE
101            */
102           algorithmType: null,
103           /**
104            *  Configured map
105            * 
106            * @public
107            * @type {Object} OpenLayers.Map
108            */
109           map: null,
110           /**
111            *  Baselayer map
112            * 
113            * @public
114            * @type {Object} OpenLayers.Layer
115            */
116           lastBaseLayer: null,
117            /**
118            *  Type of Spatial Reference used for the computation. Per default: 'EPSG:4326'
119            * 
120            * @public
121            * @type String
122            */
123           srs: 'EPSG:3003',
124           /**
125             *  Proxy to make the search request. default null.
126             * 
127             * @public
128             * @type string
129             */
130           proxy: null,
131           
132           /**
133           *  Store for toring the routing results
134           * 
135           * @public
136           * @type {Object} Ext.data.Storw
137           */
138           store: null,
139           /**
140           * Base URL service WMS used for the computation. Per default: ''
141           * 
142           * @public
143           * @type string
144           */
145           baseUrl: '',
146           /**
147           * Type of service WFS used for the computation. Per default: 'http://localhost:8080/geoserver/wfs?'
148           * 
149           * @public
150           * @type string
151           */
152           url: 'http://localhost:8080/geoserver/wfs?',
153           /**
154           * Type of service TMS used for the oblique Photos. Per default: 'http://webgis.regione.sardegna.it/tms/fotooblique/'
155           * 
156           * @public
157           * @type string
158           */
159           tmsUrl: 'http://webgis.regione.sardegna.it/tms/fotooblique/',
160           /**
161           * Type of service for calculate oblique Photos. If is null: dinamic url generated
162           * 
163           * @public
164           * @type string
165           */
166           urlServOPDedicated: false,
167           /**
168           * File name of tilemap source 'http://localhost:8080/geoserver/wfs?'
169           * 
170           * @public
171           * @type string
172           */
173           tilemapResource: 'tilemapresource.xml',
174           /**
175           * Nome del layer che contiene l'inviluppo delle foto oblique'
176           * 
177           * @public
178           * @type string
179           */
180           typename: 'inviluppo_orto_roma40_tot',
181           workspace: 'dbu:',
182           /**
183           * Parametro del servizio WFS. ID del layer che indica la zona delle foto oblique'
184           * 
185           * @public
186           * @type string
187           */
188           propertyName: 'id',
189           /**
190           * Parametro del servizio WFS. Campo per l'ordinamento dei risultati di ricerca'
191           * 
192           * @public
193           * @type string
194           */
195           sortby: 'id',
196           /**
197           * Parametro del servizio WFS. Bounding box della ricerca'
198           * 
199           * @public
200           * @type string
201           */
202           BBOX: null,
203           /**
204           * Tolleranza del boundingbox per la ricerca'
205           * 
206           * @public
207           * @type Number
208           */
209           tollerance: 0,
210           /**
211           * Scala di visualizzazione minima in cui viene attivato il pulsante di
212           * attivazione delle foto oblique'
213           * 
214           * @public
215           * @type Number
216           */
217           minScaleActivate: 100000,
218           /**
219           * Livello di zoom minimo della visualizzazione delle foto oblique'
220           * 
221           * @public
222           * @type Number
223           */
224           minZoomObliquePhoto: 4,
225           /**
226           * Layer dei TMS delle fotooblique visualizzato'
227           * 
228           * @public
229           * @type {Object} OpenLayers.Layer.TMS
230           */
231           tmsLayer: null,
232           /**
233           * Foto Oblique visualizzata in mappa'
234           * 
235           * @public
236           * @type {Object} JSON
237           */
238           obliquePhoto: {
239             /** 
240              * Property: extent
241              * {OpenLayers.Bounds} extent of the tile map
242              */
243             extent: null,
244             /** 
245              * Property: extent
246              * {OpenLayers.Bounds} Maximum extent of the tile map
247              */
248             maxExtent: null,
249             /** 
250              * Property: tileOrigin
251              * {OpenLayers.LonLat} origin of the tile map
252              */
253             tileOrigin: null,
254             /** 
255              * Property: maxResolution
256              * {float} max resolution of the zero level
257              */
258             maxResolution: null,
259             /**
260              * Property: zoom
261              * {int} zooom of the tilemap   
262              */
263             typeImg: null,
264             /** 
265              * Property: numLevels
266              * {int} num levels of the tile map
267              */
268             numLevels: 0,
269             /** 
270              * Property: resolutions
271              * {int} resolution of the tile map
272              */
273             resolutions: null,
274             /** 
275              * Property: area
276              * {int} area of the tile map
277              */
278             projection: 'EPSG:32632',
279             /** 
280              * Property: area
281              * {int} area of the tile map
282              */
283             area: null,
284             /** 
285              * Property: initcoordRect
286              * {OpenLayers.LonLat} coordinata "fittizzia" del centro della mappa (rettangolo)
287              */
288             initcoordRect: null,
289              /** 
290              * Property: initcoordTrap
291              * {OpenLayers.LonLat} coordinata "reale" del centro della mappa (trapezio)
292              */
293             initcoordTrap: null,
294             /** 
295              * Property: scale
296              * {string} actual scale of the tile map
297              */
298             scale: null,
299             /** 
300              * Flag to remember if obliquephoto is opened or not
301              * {boolean} flag for opened status
302              */
303             opened: false,
304             /**
305             * Start direction: fixed North (N)
306             * 
307             * @public
308             * @type String
309             */
310             initDirection: 'N'     
311           },
312           /**
313           * Livello di zoom minimo della visualizzazione dell'ortofoto
314           * 
315           * @public
316           * @type Number
317           */
318           minZoomOrtoPhoto: 4,
319           /**
320           * Layer dei TMS del'ortofoto visualizzata
321           * 
322           * @public
323           * @type {Object} OpenLayers.Layer.TMS
324           */
325           tmsOrtoLayer: null,
326           /**
327           * Ortofoto visualizzata in mappa'
328           * 
329           * @public
330           * @type {Object} JSON
331           */
332           ortoPhoto: {
333             /** 
334              * Property: extent
335              * {OpenLayers.Bounds} extent of the tile map
336              */
337             extent: null,
338             /** 
339              * Property: tileOrigin
340              * {OpenLayers.LonLat} origin of the tile map
341              */
342             tileOrigin: null,
343             /** 
344              * Property: maxResolution
345              * {float} max resolution of the zero level
346              */
347             maxResolution: null,
348             /**
349              * Property: zoom
350              * {int} zooom of the tilemap   
351              */
352             typeImg: null,
353             /** 
354              * Property: numLevels
355              * {int} num levels of the tile map
356              */
357             numLevels: 0,
358             /** 
359              * Property: resolutions
360              * {int} resolution of the tile map
361              */
362             resolutions: null,
363             /** 
364              * Property: projection
365              * {string} projection of the tile map
366              */
367             projection: 'EPSG:32632',
368             /** 
369              * Property: area
370              * {int} area of the tile map
371              */
372             area: null, 
373             /** 
374              * Property: idmap
375              * {string} type map (map1 or map2)
376              */
377             idmap: null,
378             /** 
379              * Property: scale
380              * {string} actual scale of the tile map
381              */
382             scale: null
383           },
384           /**
385           * Classe della mappa doppia'
386           * 
387           * @public
388           * @type String
389           */
390           idDoubleMapComp: null,
391           /**
392            *  Configured doublemap
393            * 
394            * @public
395            * @type {Object} OpenLayers.Map
396            */
397           map2: null,
398           /**
399           * Layer dei TMS del'ortofoto visualizzata nella mappa singola
400           * 
401           * @public
402           * @type {Object} OpenLayers.Layer.TMS
403           */
404           tmsOrtoLayer2: null,
405           /**
406           * Indica la direzione della vista nella mappa doppia
407           * 
408           * @public
409           * @type string
410           */
411           viewdirection: null,
412           /** api: config[onlyShowOnFirstLoad]
413             * ``Boolean`` Set this to true to only show the loading indicator on the 
414             * first load of the map. Default is false.
415             * 
416             * @public
417             * @type boolean
418             */
419            onlyShowOnFirstLoad: false,
420            /** api: config[loadingMapMessage]
421             *  ``String`` Message to show when the map is loading (i18n)
422             *  
423             * @public
424             * @type String
425             */
426            loadingMapMessage: "Loading Map...",
427 
428            /** private: property[layerCount]
429             * ``Integer`` The number of layers currently loading.
430             * 
431             * @public
432             * @type integer
433             */ 
434            layerCount: 0,
435 
436            /**
437             * private: property[busyMask]
438             * ``Ext.LoadMask`` The Ext load mask to show when busy.
439             * 
440             * @public
441             * @type {Object} Ext.LoadMask
442             */
443            busyMask: null,
444            
445            /**
446             * private: property[busyMask2]
447             * ``Ext.LoadMask`` The Ext load mask to show when busy.
448             *  
449             * @public
450             * @type {Object} Ext.LoadMask
451             */
452            busyMask2: null, 
453            
454            layer_envelope: null,
455 
456             /**
457             * Modalità debug. Visualizzazione estensione e ingombri delle fotooblique 
458             * nella mappa doppia.
459             *  
460             * @public
461             * @type Boolean
462             */
463            debug: false,
464            /**
465             * Modalità debug. Layer Vector for extent rectangle
466             *  
467             * @public
468             * @type {Object} OpenLayers.Layer.Vector
469             */
470            debug_rectangle: new OpenLayers.Layer.Vector( "Rectangle", { style: {stroke: true, strokeWidth: 2, strokeColor: '#FFFF00', strokeOpacity: 0.4, fillColor: '#000', fillOpacity: 0}} ), 
471            /**
472             * Modalità debug. Feature Vectore for extent rectangle
473             *  
474             * @public
475             * @type {Object} OpenLayers.Feature.Vector
476             */
477            debug_rect: null,        
478            /**
479             * Modalità debug. Layer Vector for trapezoid oblique photo
480             *  
481             * @public
482             * @type {Object} OpenLayers.Layer.Vector
483             */
484            debug_trapezoid: new OpenLayers.Layer.Vector( "Trapezoid", { style: {stroke: true, strokeWidth: 2, strokeColor: '#0000FF', fillColor: '#000', fillOpacity: 0}} ), 
485            /**
486             * Modalità debug. Feature Vector for trapezoid oblique photo
487             *  
488             * @public
489             * @type {Object} OpenLayers.Feature.Vector
490             */
491            debug_trap: null,        
492            /**
493             * Modalità debug. Layer Vector for extent view
494             *  
495             * @public
496             * @type {Object} OpenLayers.Layer.Vector
497             */
498            debug_boxes: new OpenLayers.Layer.Vector( "Boxes", { style: {stroke: true, strokeWidth: 2, strokeColor: '#FF0000', fillColor: '#000', fillOpacity: 0.1}} ), 
499            /**
500             * Modalità debug. Feature Vector for extent view
501             *  
502             * @public
503             * @type {Object} OpenLayers.Feature.Vector
504             */
505            debug_box: null, 
506            /**
507             * Modalità debug. Inviluppo foto oblique.
508             *  
509             * @public
510             * @type {Object} OpenLayers.Layer.WMS
511             */
512            debug_layer: null,
513            /**
514             * Modalità debug. DSM.
515             *  
516             * @public
517             * @type {Object} OpenLayers.Layer.WMS
518             */
519            debug_layer_dsm: null,
520                
521           /**
522            * @private
523            * @param {Object} config configuration object
524            */
525           constructor: function(config) {
526             if (Ext.isEmpty(config.algorithmType)) {
527               //default value
528               config.algorithmType = OBLIQUEPHOTOS_ALGORITHMTYPE.CENTROID_BASED;
529             }
530             framework.plugins.ActiveObliquePhotos.superclass.constructor.apply(this, arguments);
531           },
532           /**
533            * Create and append info action
534            * @public
535            * @returns {framework.plugins.ActiveObliquePhotos} Object with info control inside
536            */
537           addActions: function() {
538                       
539             if (!this.map) {
540               this.map = this.target.mapPanel.map;
541             }
542             if (this.idDoubleMapComp && !this.map2) {
543               this.map2 = Ext.getCmp(this.idDoubleMapComp).app2.mapPanel.map;
544             }          
545             
546             if (!this.layer_envelope) {
547                 this.layer_envelope = new OpenLayers.Layer.WMS(
548                     this.typename, this.baseUrl+"/geoserver/wms",
549                     {
550                         LAYERS: this.workspace+this.typename,
551                         STYLES: '',
552                         format: "image/png",
553                         transparent: true,
554                         tiled: true
555                     },
556                     {
557                        buffer: 0,
558                        displayInLayerSwitcher: false,
559                        singleTile: true, 
560                        ratio: 1, 
561                        visibility: true,
562                        isBaseLayer: false,
563                        yx : {'EPSG:3003' : false}
564                     } 
565                 );
566             }
567             
568           
569             var self = this;
570             this.map.events.register('zoomend', this, this.enableButton);
571             this.map.events.register('zoom', this, this.verifyMinZoomObliquePhoto);
572             
573             //registrazione evento spostamento mappa
574             this.dragcontrol = new OpenLayers.Control.DragPan({'map': this.map,
575               'panMapDone': function(xy) {
576                 this.userdragged = true;
577                 self.refreshPhotogram(false);
578               }});
579 
580             this.dragcontrol.draw();
581             this.map.addControl(this.dragcontrol);
582             var sUrl = "";
583             if (this.proxy)
584               sUrl = this.proxy + escape(this.url);
585             else
586               sUrl = this.url;
587 
588             if (!this.store) {
589               this.store = new Ext.data.Store({
590                 proxy: new Ext.data.HttpProxy({
591                   url: sUrl,
592                   method: 'POST'
593                 }),
594                 fields: [this.propertyName],
595                 reader: new framework.data.EnvelopesObliquePhotos_XLSReader({
596                   propertyName: this.propertyName
597                 }),
598                 listeners: {
599                   datachanged: function(store) {
600                     var center = this.target.mapPanel.map.getCenter();
601                     // trasformazione coordinate in UTM 32N
602                     Proj4js.defs["EPSG:32632"] = "+title=UTM 32N +proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
603                     new Proj4js.Proj('EPSG:32632');
604 
605                     var fromProjection = new OpenLayers.Projection(this.srs);   // Transform from ROMA40
606                     var toProjection = new OpenLayers.Projection("EPSG:32632"); // to Spherical Mercator Projection
607                     var position = new OpenLayers.LonLat(center.lon, center.lat).transform(fromProjection, toProjection);
608                     
609                     if (store.data.items[0].data.msg_error === 1) {
610                       this.msgAlert(this.mapInfoText, this.noPhoto, false);
611                     } else {
612                       var areaId = store.data.items[0].data.id;
613                       //verificare la foto obliqua più vicina alla coordinata
614                       this.loadPhotogram(areaId, position, true);
615                     }
616                   },
617                   beforeload: function(store, operation) {
618 
619                     var center = this.target.mapPanel.map.getCenter();
620 
621                     store.baseParams['BBOX'] = (center.lon - this.tollerance) + "," + (center.lat - this.tollerance) + "," + (center.lon + this.tollerance) + "," + (center.lat + this.tollerance);
622 
623                   },
624                   scope: this
625                 },
626                 baseParams: {
627                   'typename': this.typename,
628                   'SERVICE': 'WFS',
629                   'VERSION': '1.0.0',
630                   'REQUEST': 'GetFeature',
631                   'propertyName': this.propertyName,
632                   'SRS': this.srs,
633                   'sortby': this.sortby,
634                   'BBOX': this.BBOX
635                 },
636                 scope: this
637               });
638 
639             }
640 
641             this.button = new Ext.Button({
642               iconCls: this.iconCls,
643               tooltip: this.tooltip,
644               pressedCls: this.pressedCls,
645               enableToggle: true,
646               handler: function() {
647                 if (this.button.pressed) {
648                   this.store.load();
649                 }
650                 else {
651                   this.button.addClass(this.unpressedCls);
652                   this.button.removeClass(this.pressedCls);
653                   this.button.setTooltip(this.tooltip);
654 
655                   this.closePhotogram();
656                 }
657               },
658               listeners: {
659                 mouseover: function () {
660                     this.scope.map.addLayer(this.scope.layer_envelope);
661                     self.centroidActiveObliquePhoto(this.scope.map,true);
662                 },
663                 mouseout: function () {
664                     this.scope.map.removeLayer(this.scope.layer_envelope);
665                     self.centroidActiveObliquePhoto(this.scope.map,false);                  
666                 },
667                 beforeshow: function() {
668                   this.enableButton();
669                   if (this.button.pressed) {
670                     this.button.removeClass('x-btn-pressed');
671                     this.button.removeClass(this.unpressedCls);
672                     this.button.addClass(this.pressedCls);
673                     this.button.setTooltip(this.button.tooltipDeactivate);
674                   }
675                   else {
676                     this.button.addClass(this.unpressedCls);
677                     this.button.setTooltip(this.button.tooltip);
678                   }
679                 }
680               },
681               scope: this
682             });
683 
684             this.button.addClass(this.unpressedCls);
685 
686             return framework.plugins.ActiveObliquePhotos.superclass.addActions.apply(this, [this.button]);
687           },
688           
689           centroidActiveObliquePhoto: function(map,over) {
690               
691               console.log("mouseover");
692               console.log(over);
693               
694                 if(!this.layer){
695                  this.layer = new OpenLayers.Layer.Vector('centroidActiveObliquePhoto', {
696                      displayInLayerSwitcher: false,
697                      visibility: true,
698                      styleMap: new OpenLayers.StyleMap({
699                             'default': new OpenLayers.Style({
700                                 graphicZIndex: 100,
701                                 pointRadius: 5,
702                                 fillColor: "#f29f1e",
703                                 fillOpacity: 0.5, 
704                                 strokeWidth: 2,
705                                 strokeColor: "white",
706                                 graphicName: "circle"
707                        })})
708                     });
709                 }    
710                 var center = map.getCenter();
711                 var point = new OpenLayers.Geometry.Point(center.lon, center.lat);
712                 this.layer.removeAllFeatures();
713                 this.layer.addFeatures([new OpenLayers.Feature.Vector(point)]);
714                 if (map.getLayersByName("centroidActiveObliquePhoto").length !== 0) {
715                     map.removeLayer(this.layer);
716                 };
717                 if (over)
718                     map.addLayer(this.layer);
719           },
720           /** 
721            * Enable button for activate oblique photos.
722            * @public
723            */
724           enableButton: function() {
725 
726             if (this.map.getScale() <= this.minScaleActivate) {
727               this.actions[0].enable();
728             }
729             else {
730               this.actions[0].disable();
731             }
732 
733           },
734           /** 
735            * Verifica il livello di zoom durante la navigazione.
736            * @private
737            */
738           verifyMinZoomObliquePhoto: function() {
739 
740             if (this.button) {
741                 
742                 if (this.button.pressed) {
743 
744                     var x = this.map.getZoom();
745 
746                     if (x < this.minZoomObliquePhoto)
747                     {
748                       //this.closePhotogram();
749                       //this.button.toggle(false);
750                      // this.map.zoomTo(this.minZoomObliquePhoto);
751                       this.map.setCenter(null,this.minZoomObliquePhoto);
752                     }
753                     if (this.idDoubleMapComp) {      
754                       if (!this.debug) this.map2.zoomToScale(this.map.getScale());
755                       this.map2.setCenter(this.obliquePhoto.initcoordTrap);
756                     }
757 
758                     //this.obliquePhoto.scale = this.map.getScale();
759                 }
760             }
761           },
762           /** 
763            * Chiude il fotogramma della fotoobliqua visualizzata.
764            * @private
765            */
766           closePhotogram: function() {
767 
768             var center = this.target.mapPanel.map.getCenter();
769 
770             // trasformazione coordinate in UTM 32N
771             Proj4js.defs["EPSG:32632"] = "+title=UTM 32N +proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
772             new Proj4js.Proj('EPSG:32632');
773 
774             var fromProjection = new OpenLayers.Projection("EPSG:32632"); // to Spherical Mercator Projection
775             var toProjection = new OpenLayers.Projection(this.srs);   // Transform from ROMA40
776             var position = new OpenLayers.LonLat(center.lon, center.lat).transform(fromProjection, toProjection);
777 
778             if (this.tmsLayer !== null)
779             {
780               this.tmsLayer.destroy();
781             }
782 
783             this.fireEvent('obliquePhotoClosed');
784 
785             this.map.setCenter(position);
786 
787             if (this.idDoubleMapComp)
788               this.map2.setCenter(position);
789 
790             this.lastBaseLayer = null;
791             this.dragcontrol.deactivate();
792             this.hideCompass();
793             
794             this.obliquePhoto.initcoordRect = undefined;
795             this.obliquePhoto.initcoordTrap = undefined;
796           },
797           /**
798            * Finds a photogram using area id and current coordinate and loads it
799            * @param {String} area id of the area of the photogram to find
800            * @param {OpenLayers.LonLat} coord current coordinate (used to find nearest photogram)
801            * @private
802            */
803           loadPhotogram: function(area, coord, transform) {
804             this.obliquePhoto.initDirection = "N"
805             this.obliquePhoto.area = area;
806             this.obliquePhoto.initcoordTrap = coord;
807             this.obliquePhoto.initcoordRect = coord;
808             Ext.Ajax.request({
809               url: this.getObliqueServletUrl(),
810               method: 'POST',
811               params: {
812                 method: 'nearest',
813                 area: area,
814                 algorithmType: this.algorithmType.value,
815                 photoId: Ext.isEmpty(this.obliquePhoto) ? null : this.obliquePhoto.id,
816                 coordinate: Ext.util.JSON.encode(coord),
817                 extent: Ext.util.JSON.encode(this.getCurrentExtent(transform)),
818                 direction: Ext.isEmpty(this.compass) ? this.obliquePhoto.initDirection : this.compass.getDirection()
819               },
820               success: function(data) {
821                 if (data.responseText) {
822                   var record = Ext.util.JSON.decode(data.responseText);
823             
824                   if (!Ext.isEmpty(record.error)) {
825                     if (record.error.indexOf("java.io.FileNotFoundException") != -1) {
826                         this.msgAlert(this.mapInfoText, this.noCSV, false);  
827                     }
828                     else
829                         Ext.MessageBox.alert('Errore caricamento foto obliqua', record.error);
830                   } else {
831                       
832                     // GB: HACK CASO INIZIALE CON NE, SE, NW, SW
833                     if (record.direction != this.obliquePhoto.initDirection)
834                         this.obliquePhoto.initDirection = record.direction;
835                         
836                     if (this.idDoubleMapComp) {
837                         this.openOrtoPhoto(this.obliquePhoto.area, "map2");
838                     }
839                     this.openObliquePhoto(record);
840                     this.dragcontrol.activate();
841                     if (!this.compass) {
842                       this.showCompass();
843                       this.compass.refreshCssClass();
844                     }
845                   }
846                 } else {
847                   Ext.MessageBox.alert('Errore caricamento fotogramma', 'Risposta da servlet errata');
848                 }
849               }, scope: this
850             });
851           },
852           /**
853            * Shows Compass control
854            * @public
855            */
856           showCompass: function() {
857             this.compass = new framework.widgets.control.Compass({
858               id: this.id + '_pcompass',
859               displayClass: 'panelCompass',
860               initDirection: this.obliquePhoto.initDirection         
861             });
862             this.map.addControl(this.compass);
863             this.compass.activate();
864             this.compass.events.register('rotateLeft', this, function(evt) {
865               this.refreshPhotogram(true);
866               if (this.viewdirection)
867                 this.viewdirection.rotateLeft();
868             });
869             this.compass.events.register('rotateRight', this, function(evt) {
870               this.refreshPhotogram(true);
871               if (this.viewdirection) 
872                 this.viewdirection.rotateRight();
873             });
874             this.compass.events.register('modeSwitched', this, function(evt) {
875               if (this.compass.mode === this.compass.MODES.ORTHO) {
876                 this.openOrtoPhoto(this.obliquePhoto.area, "map1");
877                 if (this.tmsLayer) this.tmsLayer.destroy();
878                 this.dragcontrol.deactivate();  
879                 if (this.viewdirection) 
880                     this.viewdirection.hide();
881               } else {
882                 var position = this.target.mapPanel.map.getCenter();
883                 if (this.tmsOrtoLayer) this.tmsOrtoLayer.destroy();
884                 this.loadPhotogram(this.obliquePhoto.area,position,false);
885                 if (this.viewdirection)
886                     this.viewdirection.show();
887               }
888 
889             });
890             
891             if (this.idDoubleMapComp) {
892                 this.createViewDirection(0);
893                 this.viewdirection.refreshCssClass();
894             }
895           },
896           /** 
897            * Crea il controllo sulla mappa doppia che indica la vista rispetto alla direzione della foto obliqua
898            * visualizzata in mappa singola
899            * @private
900            */    
901           createViewDirection: function() {
902                 this.viewdirection = new framework.widgets.control.ViewDirection({
903                     id: this.id + '_pviewdirection',
904                     displayClass: 'panelViewDirection',
905                     initDirection: this.obliquePhoto.initDirection
906                   });
907                 this.map2.addControl(this.viewdirection);
908                   
909           },
910           /**
911            * Hides Compass control
912            * @public
913            */
914           hideCompass: function() {
915             this.compass.deactivate();
916             this.map.removeControl(this.compass);
917             this.compass.destroy();
918             this.compass = null;
919             if (this.viewdirection) {
920                 this.viewdirection.destroy();
921             }
922           },
923           /**
924            * Method: fillTileMapFailure 
925            * on failure load url
926            * 
927            * @private
928            * @param data string of the file xml
929            *
930            */
931           fillCSVFailure: function(data) {
932             Ext.MessageBox.alert('Errore', 'Foto oblique non ancora disponibili. La zona è in fase di elaborazione.');
933             this.button.toggle(false);
934           },
935            /**
936            * Method: openObliquePhoto 
937            * Apre la foto obliqua
938            * 
939            * @private
940            * @param {String } json representation of the file xml
941            *
942            */
943           openObliquePhoto: function(data) {
944             this.obliquePhoto.id = data.photogramId;
945             this.obliquePhoto.tmsUrl = data.tmsUrl;
946             this.obliquePhoto.direction = data.direction;
947             this.obliquePhoto.maxExtent = new OpenLayers.Bounds(
948                 data.areaExtent.minx,
949                 data.areaExtent.miny,
950                 data.areaExtent.maxx,
951                 data.areaExtent.maxy);
952             var deltaX = this.obliquePhoto.maxExtent.getWidth()/14;
953             var deltaY = this.obliquePhoto.maxExtent.getHeight()/14;
954             //computes an extent incremented by deltaX and deltaY (and the same center)
955             this.obliquePhoto.restrictedExtent = new OpenLayers.Bounds(
956                 data.viewPort.minx - deltaX,
957                 data.viewPort.miny - deltaY,
958                 data.viewPort.maxx + deltaX,
959                 data.viewPort.maxy + deltaY);
960             this.obliquePhoto.viewPort = new OpenLayers.Bounds(
961                 data.viewPort.minx,
962                 data.viewPort.miny,
963                 data.viewPort.maxx,
964                 data.viewPort.maxy);
965             Ext.Ajax.request({
966               url: data.tmsUrl + '/' + this.tilemapResource,
967               success: function(obj) {
968                 if (!Ext.isEmpty(data.coordinate)) {
969                   obj.coordinate = data.coordinate;
970                 }
971                 if (!Ext.isEmpty(data.zoom)) {
972                   obj.zoom = data.zoom;
973                 }
974                 if (!Ext.isEmpty(data.viewPort)) {
975                   obj.viewPort = data.viewPort;
976                 }
977                 this.fillTileMap(obj);
978               },
979               failure: this.fillTileMapFailure,
980               scope: this
981             });
982           },
983           /**
984            * Method: fillTileMap 
985            * 
986            * fill this object tile map with the information of the tile map
987            * 
988            * @private
989            * @param data string of the file xml
990            *
991            */
992           fillTileMap: function(data) {
993             var doc = data.responseXML;
994             if (!doc || !doc.documentElement) {
995               doc = data.responseText;
996             }
997 
998             var xml = new OpenLayers.Format.XML();
999             if (typeof doc == "string") {
1000               doc = xml.read(doc);
1001             }
1002 
1003             var boundingBoxNode = doc.getElementsByTagName('BoundingBox');
1004             if (boundingBoxNode !== null && boundingBoxNode[0] != null) {
1005               var boundingBox = boundingBoxNode[0];
1006               var minx = boundingBox.getAttribute('miny');
1007               var miny = boundingBox.getAttribute('minx');
1008               var maxx = boundingBox.getAttribute('maxy');
1009               var maxy = boundingBox.getAttribute('maxx');
1010               if (minx != null && minx != '' && miny != null && miny != '' && maxx != null && maxx != '' && maxy != null && maxy != '') {
1011                 this.obliquePhoto.extent = new OpenLayers.Bounds(minx, miny, maxx, maxy);
1012               }
1013             }
1014             var tileOriginNode = doc.getElementsByTagName('Origin');
1015             if (tileOriginNode != null && tileOriginNode[0] != null) {
1016               var origin = tileOriginNode[0];
1017               var x = origin.getAttribute('y');
1018               var y = origin.getAttribute('x');
1019               if (x != null && x != '' && y != null && y != '') {
1020                 this.obliquePhoto.tileOrigin = new OpenLayers.LonLat(x, y);
1021               }
1022             }
1023             var tileFormat = doc.getElementsByTagName('TileFormat');
1024             if (tileFormat != null && tileFormat[0] != null) {
1025               var tileType = tileFormat[0];
1026               this.obliquePhoto.typeImg = tileType.getAttribute('extension');
1027             }
1028             var tileSet = doc.getElementsByTagName('TileSet');
1029             if (tileSet != null && tileSet.length > 0) {
1030               this.obliquePhoto.numLevels = tileSet.length;
1031               this.obliquePhoto.resolutions = [];
1032               for (var i = 0; i < tileSet.length; i++) {
1033                 var firstTileSet = tileSet[i];
1034                 var order = firstTileSet.getAttribute('order');
1035                 if (order != null && order == '0') {
1036                   var unitsperpixel = firstTileSet.getAttribute('units-per-pixel');
1037                   if (unitsperpixel != null) {
1038                     this.obliquePhoto.maxResolution = unitsperpixel;
1039                   }
1040                   //break;
1041                 }
1042                 this.obliquePhoto.resolutions.push(parseFloat(firstTileSet.getAttribute('units-per-pixel')));
1043               }
1044               this.obliquePhoto.resolutions = this.obliquePhoto.resolutions.reverse();
1045             }
1046             this.obliquePhoto.opened = true;
1047             this.updateObliquePhotoLayer(data);
1048           },
1049           /**
1050            * Method: fillTileMapFailure 
1051            * on failure load url
1052            * 
1053            * @private
1054            * @param data string of the file xml
1055            *
1056            */
1057           fillTileMapFailure: function(data) {
1058             Ext.MessageBox.alert('Errore', 'Foto obliqua non esistente.');
1059             this.button.toggle(false);
1060           },
1061           /**
1062            * Method: updateFotogrammiLayer 
1063            * Update Fotogrammi Layer to show selected fotogramma
1064            * 
1065            * @private
1066            * @param data string of the file xml
1067            *
1068            */
1069           updateObliquePhotoLayer: function(data) {
1070 
1071             this.map.events.unregister('zoomend', this, this.verifyMinZoomObliquePhoto);
1072 
1073             if (!this.lastBaseLayer) {
1074               this.lastBaseLayer = this.map.baseLayer;
1075             }
1076 
1077             var options = {
1078               projection: this.obliquePhoto.projection,
1079               id: "mymap",
1080               units: 'm',
1081               resolutions: this.obliquePhoto.resolutions,
1082               maxResolution: this.obliquePhoto.maxResolution,
1083               maxExtent: this.obliquePhoto.maxExtent,
1084               restrictedExtent: this.obliquePhoto.restrictedExtent,
1085               numZoomLevels: this.obliquePhoto.numLevels,
1086               panMethod: "null",
1087               zoom: this.minZoomObliquePhoto
1088             };
1089             this.map.setOptions(options);
1090             this.changePhotogram();
1091             this.map.setBaseLayer(this.tmsLayer);
1092             var zoom = (Ext.isEmpty(data.zoom)) ? 4 : data.zoom;
1093             var center;
1094             if (Ext.isEmpty(data.viewPort)) {
1095               center = data.coordinate;
1096               this.map.setCenter(center, zoom);
1097             } else {
1098               var x = data.viewPort.minx + (data.viewPort.maxx - data.viewPort.minx) / 2;
1099               var y = data.viewPort.miny + (data.viewPort.maxy - data.viewPort.miny) / 2;
1100               center = new OpenLayers.LonLat(x, y);
1101               this.map.setCenter(center, zoom);       
1102             }
1103             
1104             //per zoomare sul punt corretto della mappa all'apertura delle fotooblique      
1105             if (this.obliquePhoto.initcoordRect) {
1106                 this.map.setCenter(this.obliquePhoto.initcoordRect, zoom);
1107             }
1108             
1109             this.obliquePhoto.scale = this.map.getScale();
1110             
1111             this.fireEvent('obliquePhotoOpened', this.tmsLayer, this.obliquePhoto);
1112 
1113             this.map.events.register('zoomend', this, this.verifyMinZoomObliquePhoto);
1114             
1115             if (this.button) {
1116                 this.button.removeClass('x-btn-pressed');
1117                 this.button.removeClass(this.unpressedCls);
1118                 this.button.addClass(this.pressedCls);
1119                 this.button.setTooltip(this.tooltipDeactivate);
1120             }
1121 
1122           },
1123           /**
1124            * Method: changePhotogram 
1125            * Cambio fotogramma 
1126            * 
1127            * @private
1128            *
1129            */
1130           changePhotogram: function() {
1131             this.oldTmsLayer = this.tmsLayer;
1132             var layerName = this.obliquePhoto.id;
1133             if (Ext.isEmpty(this.obliquePhoto.id) || Ext.isEmpty(this.obliquePhoto.area)) {
1134               return;
1135             }
1136             this.tmsLayer = new OpenLayers.Layer.TMS(
1137                 this.obliquePhoto.id,
1138                 this.tmsUrl + this.obliquePhoto.area,
1139                 {
1140                   layername: layerName,
1141                   type: this.obliquePhoto.typeImg,
1142                   format: 'image/png',
1143                   maxExtent: this.obliquePhoto.extent,
1144                   tileOrigin: this.obliquePhoto.tileOrigin,
1145                   candidateBaseLayer: true,
1146                   displayInLayerSwitcher: false,
1147                   serviceVersion: ''
1148                 });
1149             this.tmsLayer.setIsBaseLayer(true);
1150             this.map.addLayer(this.tmsLayer);
1151             
1152             this.tmsLayer.events.register('loadstart', this, this.onloadstart);
1153             this.tmsLayer.events.register('loadend', this, this.onloadend);
1154             
1155             var oldLayer = this.oldTmsLayer;
1156           //  var destroyTask = new Ext.util.DelayedTask(function() {
1157               if (!Ext.isEmpty(oldLayer)) {
1158                 //console.log('Trying to destroy old layer');
1159                 try {
1160                   oldLayer.destroy();
1161                   //console.log('Old layer destroyed');
1162                 } catch (err) {
1163                   //l'errore può essere solo x oggetto non inizializzato => lo ignoro
1164                   console.log('error destroying old layer ' + err);
1165                 }
1166               }
1167          //   });
1168          //   destroyTask.delay(1000);
1169           },
1170           /**
1171            * Event handling on map move.
1172            * Here the program will change photogram, if necessary.
1173            * @private
1174            */
1175           refreshPhotogram: function(compass) {
1176             if (this.obliquePhoto.opened) {
1177               var currentExtent = this.getCurrentExtent(false);
1178               //if (this.obliquePhoto.viewPort.containsBounds(currentExtent) && !compass) {
1179                 // continuare perché non la prende!
1180                 //return; //skip elaboration 'cause we don't need to change photogram
1181               //}
1182               //console.log(Ext.util.JSON.encode(this.obliquePhoto.viewPort));
1183               var center = this.target.mapPanel.map.getCenter(); //fittizia
1184              // console.log("center da rettangolo (fittizio)");
1185              // console.log(center);
1186               this.obliquePhoto.initcoordRect = center;
1187               var zoom = this.target.mapPanel.map.getZoom();
1188               Ext.Ajax.request({
1189                 url: this.getObliqueServletUrl(),
1190                 method: 'POST',
1191                 params: {
1192                   method: 'convert',
1193                   area: this.obliquePhoto.area,
1194                   coordinate: Ext.util.JSON.encode(center),
1195                   extent: Ext.util.JSON.encode(currentExtent),
1196                   photoId: this.obliquePhoto.id
1197                 },
1198                 success: function(data) {
1199                   if (data.responseText) {
1200                     var record = Ext.util.JSON.decode(data.responseText);
1201                     if (!Ext.isEmpty(record.coordinate)) {
1202                       center = this.toLonLat(record.coordinate);
1203                       //console.log("center convertito sul trapezio (reale)");
1204                       //console.log(center);
1205                       this.obliquePhoto.initcoordTrap = center;
1206                       var viewPort = this.toBounds(record.viewPort);
1207                       if (this.idDoubleMapComp && this.debug) this.debugPolygon(viewPort,record.rectangle._coords,record.trapezoid._coords);
1208                       this.coordinateConverted(center, viewPort, zoom);
1209                     } else {
1210                       Ext.MessageBox.alert('Errore conversione', record.error);
1211                     }
1212                   } else {
1213                     Ext.MessageBox.alert('Errore conversione', 'Risposta da servlet errata');
1214                   }
1215                 },
1216                 failure: function() {
1217                   Ext.MessageBox.alert('Errore conversione', 'Errore in chiamata servizio conversione coordinata.');
1218                 },
1219                 scope: this
1220               });
1221             }
1222           },
1223           /**
1224            * Converts a JTS coordinate in a OpenLayers Coordinate
1225            * @param {Object} coordinate JTS coordinate
1226            * @return {OpenLayers.LonLat} LonLat corresponding coordinate
1227            * @private
1228            */
1229           toLonLat: function(coordinate) {
1230             return new OpenLayers.LonLat(coordinate.x, coordinate.y);
1231           },
1232           /**
1233            * Converts a JTS envelope to a OpenLayers Bounds
1234            * @param {Object} env JTS envelope
1235            * @return {OpenLayers.Bounds} Bounds corresponding to input envelope
1236            * @private
1237            */
1238           toBounds: function(env) {           
1239             return new OpenLayers.Bounds(env.minx, env.miny, env.maxx, env.maxy);
1240           },
1241            /**
1242            * Search nearest oblique photos before converting coordinate with extent view
1243            * 
1244            * @private
1245            * @param {OpenLayers.LatLon} center
1246            * @param {OpenLayers.Bounds} viewPort
1247            * @param {Integer} zoom
1248            */     
1249           coordinateConverted: function(center, viewPort, zoom) {
1250             var self = this;
1251             Ext.Ajax.request({
1252               url: self.getObliqueServletUrl(),
1253               method: 'POST',
1254               params: {
1255                 method: 'nearest',
1256                 area: self.obliquePhoto.area,
1257                 extent: Ext.util.JSON.encode(viewPort),
1258                 algorithmType: self.algorithmType.value,
1259                 photoId: Ext.isEmpty(this.obliquePhoto) ? null : this.obliquePhoto.id,
1260                 coordinate: Ext.util.JSON.encode(center),
1261                 direction: self.getDirection()
1262               },
1263               success: function(data) {
1264                 if (data.responseText) {
1265                   var record = Ext.util.JSON.decode(data.responseText);
1266                   if (!Ext.isEmpty(record.error)) {
1267                     Ext.MessageBox.alert('Errore cambio mappa', record.error);
1268                     //chiusura foto oblique
1269                     self.closePhotogram();
1270                     self.button.toggle(false);
1271                   } else {
1272                     if (self.idDoubleMapComp)
1273                       self.onMapObliqueMove(record);
1274                     if (Ext.isDefined(record.photogramId) && record.photogramId !== self.obliquePhoto.id) { //otherwise we will use the same photogram
1275                       self.obliquePhoto.id = data.photogramId;
1276                       self.obliquePhoto.tmsUrl = data.tmsUrl;
1277                       self.obliquePhoto.initcoordRect = self.toLonLat(record.coordinate);
1278                       //calcolare nuovo extent fotogramma
1279                       self.changePhotogram();
1280                       record.zoom = zoom;
1281                       self.openObliquePhoto(record);
1282                     }
1283                   }
1284                 } else {
1285                   Ext.MessageBox.alert('Errore cambio mappa', 'Risposta da servlet errata');
1286                 }
1287               }
1288             });
1289           },
1290           /**
1291            * Returns oblique servlet url
1292            * @private
1293            * @return url servelt obliquephotos
1294            */
1295           getObliqueServletUrl: function() {
1296             if (this.urlServOPDedicated) {
1297                 return this.urlServOPDedicated
1298             }
1299             else {
1300                 var current = String(window.location);
1301                 current = current.replace("print.jsp", ""); //removes print modality
1302                 current = current.replace(/\?.*/g, ""); //removes possible querystring
1303                 if (!current.match(/.*\/$/)) {
1304                   current += '/';
1305                 }
1306                 return current + 'ObliquePhotos';
1307             }
1308           },
1309           /**
1310            * Returns current direction
1311            * 
1312            * @public
1313            * @return {String} direction
1314            */
1315           getDirection: function() {
1316             return (Ext.isEmpty(this.compass)) ? this.obliquePhoto.initDirection : this.compass.getDirection();
1317           },
1318           /**
1319            * Returns current extent as a coordinate array (of four coordinates)
1320            * 
1321            * @private
1322            * @param {Boolean} if trasform coordinate
1323            * @return {OpenLayers.Bounds} extent view optimized
1324            */
1325           getCurrentExtent: function(trasform) {
1326             var fromProjection = new OpenLayers.Projection(this.srs);   // Transform from ROMA40
1327             var toProjection = new OpenLayers.Projection("EPSG:32632"); // to Spherical Mercator Projection
1328             var e = (trasform) ? this.target.mapPanel.map.getExtent().transform(fromProjection, toProjection) :
1329                 this.target.mapPanel.map.getExtent();
1330             var deltaX = e.getWidth()/12;
1331             var deltaY = e.getHeight()/12;
1332             //computes an extent incremented by deltaX and deltaY (and the same center)
1333             var ext_small = new OpenLayers.Bounds(
1334                 e.left + deltaX,
1335                 e.bottom + deltaY,
1336                 e.right - deltaX,
1337                 e.top - deltaY);
1338             return ext_small;
1339           },
1340           /**
1341            * Event handling on map move.
1342            * 
1343            * @private
1344            * @param {String} json representation of record coordinate
1345            * 
1346            */
1347           onMapObliqueMove: function(record) {
1348             var map1 = this.map;
1349             var map2 = this.map2;          
1350             
1351             if (this.idDoubleMapComp) {
1352                 map2.setCenter(this.obliquePhoto.initcoordTrap);
1353             }
1354             else {
1355                 // per trasformazione coordinate in UTM 32N
1356                 Proj4js.defs["EPSG:32632"] = "+title=UTM 32N +proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs ";
1357                 new Proj4js.Proj('EPSG:32632');
1358 
1359                 var fromProjection = map1.getProjectionObject();
1360                 var toProjection = map2.getProjectionObject();
1361 
1362                 map2.setCenter(new OpenLayers.LonLat(record.coordinate.x, record.coordinate.y).transform(fromProjection, toProjection))         
1363             }
1364             
1365             if (!this.debug) map2.zoomToScale(map1.getScale());
1366         },
1367 
1368           openOrtoPhoto: function(area,map) {  
1369             
1370             this.ortoPhoto.area = area;
1371             this.ortoPhoto.idmap = map;
1372             this.ortoPhoto.scale = this.map.getScale();
1373             //this.ortoPhoto.position = this.map.getCenter();
1374  
1375                 
1376                 var urlOrto = this.tmsUrl + '/'+ area + '/ORTO/' + this.tilemapResource; 
1377            
1378                 Ext.Ajax.request({
1379                     url: urlOrto,
1380                     success: this.fillTileMapOrto,
1381                     failure: this.fillTileMapOrtoFailure,
1382                     scope: this
1383                 });
1384                 
1385           },
1386                 
1387          /**
1388 	     * Method: fillTileMap 
1389 	     *
1390 	     * fill this object tile map with the information of the tile map
1391 	     * 
1392          * @private
1393 	     * @param data string of the file xml
1394 	     *
1395 	     */  
1396 	    fillTileMapOrto: function(data) {
1397             
1398             if (this.ortoPhoto.idmap == "map1") {
1399                 var map = this.map;
1400             }
1401             else {
1402                 var map = this.map2;
1403             }
1404                        
1405             this.ortoPhoto = this.configureMap(data,this.ortoPhoto.projection,this.ortoPhoto.area);
1406             
1407             if (this.ortoPhoto) {              
1408                 this.updateOrtoPhotoLayer(map,this.ortoPhoto,'ORTO',"Ortofoto HD");
1409                        
1410             }
1411             
1412             
1413 	    },        
1414         
1415          /**
1416 	     * Method: fillTileMapFailure 
1417 	     * on failure load url
1418          * 
1419 	     * @private
1420 	     * @param data string of the file xml
1421 	     *
1422 	     */  
1423 	    fillTileMapOrtoFailure: function(data) {
1424 	    	alert('Ortofoto associata alla foto obliqua non esistente.');
1425 	    },
1426         /**
1427 	     * Method: fillTileMap 
1428 	     * 
1429 	     * fill this object tile map with the information of the tile map
1430 	     * 
1431          * @private
1432 	     * @param data string of the file xml
1433 	     *
1434 	     */  
1435 	    configureMap: function(data,projection,area) {
1436             
1437             var tilemap = { 
1438                 extent: null,	 
1439                 tileOrigin:null, 
1440         	    maxResolution:null,  
1441                 typeImg: null,	
1442                 numLevels:0,
1443                 resolutions: null,
1444                 projection: projection,
1445                 area: area,
1446                 idmap: this.ortoPhoto.idmap
1447             };
1448 
1449             var doc = data.responseXML;
1450             if (!doc || !doc.documentElement) {
1451               doc = data.responseText;
1452             }
1453 
1454             var xml = new OpenLayers.Format.XML();
1455             if (typeof doc == "string") {
1456               doc = xml.read(doc);
1457             }
1458 
1459             var boundingBoxNode = doc.getElementsByTagName('BoundingBox');
1460             if (boundingBoxNode != null && boundingBoxNode[0] != null) {
1461               var boundingBox = boundingBoxNode[0];
1462               var minx = boundingBox.getAttribute('miny');
1463               var miny = boundingBox.getAttribute('minx');
1464               var maxx = boundingBox.getAttribute('maxy');
1465               var maxy = boundingBox.getAttribute('maxx');
1466               if (minx != null && minx != '' && miny != null && miny != '' && maxx != null && maxx != '' && maxy != null && maxy != '') {
1467                 tilemap.extent = new OpenLayers.Bounds(minx, miny, maxx, maxy);
1468               }
1469             }
1470             var tileOriginNode = doc.getElementsByTagName('Origin');
1471             if (tileOriginNode != null && tileOriginNode[0] != null) {
1472               var origin = tileOriginNode[0];
1473               var x = origin.getAttribute('y');
1474               var y = origin.getAttribute('x');
1475               if (x != null && x != '' && y != null && y != '') {
1476                 tilemap.tileOrigin = new OpenLayers.LonLat(x, y);
1477               }
1478             }
1479             var tileFormat = doc.getElementsByTagName('TileFormat');
1480             if (tileFormat != null && tileFormat[0] != null) {
1481               var tileType = tileFormat[0];
1482               tilemap.typeImg = tileType.getAttribute('extension');
1483             }
1484             var tileSet = doc.getElementsByTagName('TileSet');
1485             if (tileSet != null && tileSet.length > 0) {
1486               tilemap.numLevels = tileSet.length;
1487               tilemap.resolutions = [];
1488               for (var i = 0; i < tileSet.length; i++) {
1489                 var firstTileSet = tileSet[i];
1490                 var order = firstTileSet.getAttribute('order');
1491                 if (order != null && order == '0') {
1492                   var unitsperpixel = firstTileSet.getAttribute('units-per-pixel');
1493                   if (unitsperpixel != null) {
1494                     tilemap.maxResolution = unitsperpixel;
1495 
1496 
1497                   }
1498                   //break;
1499                 }
1500                 tilemap.resolutions.push(parseFloat(firstTileSet.getAttribute('units-per-pixel')));
1501               }
1502               tilemap.resolutions = tilemap.resolutions.reverse();
1503             }
1504 
1505             return tilemap;
1506             
1507             
1508 	    },
1509         /**
1510 	     * Method: updateFotogrammiLayer
1511 	     * 
1512 	     * Update Fotogrammi Layer to show selected fotogramma
1513          * @private
1514          * @param {OpenLayers.Map} map
1515          * @param {Object} tilemap Ortofoto corrente
1516          * @param {String} layername
1517          * @param {String} namePhoto
1518 	     *
1519 	     */  
1520 	    updateOrtoPhotoLayer: function(map,tilemap,layername,namePhoto) {
1521             
1522             var options = {    
1523                 projection: tilemap.projection,
1524                 id:"mymap",
1525                 units: 'm',
1526                 resolutions: tilemap.resolutions,
1527                 maxResolution: tilemap.maxResolution,
1528                 maxExtent: tilemap.extent,
1529                 restrictedExtent: tilemap.extent,
1530                 numZoomLevels: tilemap.numLevels,
1531                 panMethod:"null",
1532                 zoom: 1
1533             };
1534 
1535             map.setOptions(options);
1536 
1537             var layerTemp = new OpenLayers.Layer.TMS(
1538                 namePhoto,
1539                 this.tmsUrl + '/' + tilemap.area,
1540                 {
1541                   layername: layername,
1542                   type: tilemap.typeImg,
1543                   background: "#000000",
1544                   maxExtent: tilemap.extent,
1545                   tileOrigin: tilemap.tileOrigin,
1546                   candidateBaseLayer: true,
1547                   displayInLayerSwitcher: false,
1548                   serviceVersion: ''
1549                 });
1550 
1551             layerTemp.setIsBaseLayer(true);
1552 
1553             map.addLayer(layerTemp);
1554             
1555             if (this.idDoubleMapComp) {
1556             layerTemp.events.register('loadstart', this, this.onloadstart2);
1557             layerTemp.events.register('loadend', this, this.onloadend2);
1558             }
1559             
1560             map.setBaseLayer(layerTemp);
1561             
1562             if (!this.debug) map.zoomToScale(this.obliquePhoto.scale);
1563             map.setCenter(this.obliquePhoto.initcoordTrap);
1564             
1565             
1566             if (tilemap.idmap == "map1")
1567                 this.tmsOrtoLayer = layerTemp;  
1568             else
1569                 this.tmsOrtoLayer2 = layerTemp;  
1570             
1571         },
1572          /**
1573 	     * Method: onloadstart
1574 	     * 
1575 	     * Avvio esecuzione chiamate layer TMS, 
1576          * @private
1577          * @param {Event} evt
1578 	     *
1579 	     */
1580         onloadstart: function(evt) {
1581             this.layerCount++;
1582             if (!this.busyMask) {
1583                 this.busyMask = new Ext.LoadMask(
1584                     this.map.div, {
1585                         msg: this.loadingMapMessage
1586                     }
1587                 );
1588             }
1589             this.busyMask.show();
1590             if (this.onlyShowOnFirstLoad === true) {
1591                 this.tmsLayer.events.unregister("loadstart", this, arguments.callee);
1592             }
1593         },
1594         /**
1595 	     * Method: onloadend
1596 	     * 
1597 	     * Fine esecuzione chiamate layer TMS, 
1598          * @private
1599          * @param {Event} evt
1600 	     *
1601 	     */
1602         onloadend: function(evt) {
1603             this.layerCount--;
1604             if(this.layerCount === 0) {
1605                 this.busyMask.hide();
1606             }
1607             if (this.onlyShowOnFirstLoad === true) {
1608                 this.tmsLayer.events.unregister("loadend", this, arguments.callee);
1609             }
1610         },
1611         /**
1612 	     * Method: onloadstart2
1613 	     * 
1614 	     * Avvio esecuzione chiamate Ajax per i servizi
1615          * @private
1616          * @param {Event} evt
1617 	     *
1618 	     */      
1619         onloadstart2: function(evt) {
1620             if (!this.busyMask2) {
1621                 this.busyMask2 = new Ext.LoadMask(
1622                     this.map2.div, {
1623                         msg: this.loadingMapMessage
1624                     }
1625                 );
1626             }
1627             this.busyMask2.show();
1628             evt.object.events.unregister("loadstart", this, arguments.callee);
1629         },
1630         /**
1631 	     * Method: onloadend2
1632 	     * 
1633 	     * Fine esecuzione chiamate Ajax per i servizi
1634          * @private
1635          * @param {Event} evt
1636 	     *
1637 	     */ 
1638         onloadend2: function(evt) {
1639             this.busyMask2.hide();
1640             evt.object.events.unregister("loadend", this, arguments.callee);
1641         },
1642          /**
1643            * Opens an oblique photo but using its json representation
1644            * @param {String} json representation of the photogram
1645            * @param {OpenLayers.LatLon} center position
1646            * @public
1647            */
1648           openFromJSON: function(json,center) {
1649             if (json) {
1650                 
1651                 if (!this.map) {
1652                   this.map = this.target.mapPanel.map;
1653                 }
1654                 if (this.idDoubleMapComp && !this.map2) {
1655                   this.map2 = Ext.getCmp(this.idDoubleMapComp).app2.mapPanel.map;
1656                 }
1657                   
1658                 var record = json;
1659                 this.obliquePhoto.area = record.area;
1660                 var position = new OpenLayers.LonLat(record.initcoordRect.lon, record.initcoordRect.lat);
1661                 this.obliquePhoto.initcoordRect = position;
1662                 var position = new OpenLayers.LonLat(record.initcoordTrap.lon, record.initcoordTrap.lat);
1663                 this.obliquePhoto.initcoordTrap = position;
1664                 this.obliquePhoto.scale = record.scale;
1665                 this.obliquePhoto.id = record.id;
1666                 this.obliquePhoto.tmsUrl = record.tmsUrl;
1667                 this.obliquePhoto.direction = record.direction;
1668                 this.obliquePhoto.initDirection = record.initDirection; 
1669                 this.obliquePhoto.maxExtent = new OpenLayers.Bounds(
1670                     record.maxExtent.left,
1671                     record.maxExtent.bottom,
1672                     record.maxExtent.right,
1673                     record.maxExtent.top);
1674                 this.obliquePhoto.restrictedExtent = new OpenLayers.Bounds(
1675                     record.restrictedExtent.left,
1676                     record.restrictedExtent.bottom,
1677                     record.restrictedExtent.right,
1678                     record.restrictedExtent.top);
1679                 this.obliquePhoto.viewPort = new OpenLayers.Bounds(
1680                     record.viewPort.left,
1681                     record.viewPort.bottom,
1682                     record.viewPort.right,
1683                     record.viewPort.top);
1684 
1685                  Ext.Ajax.request({
1686                     url: record.tmsUrl + '/' + this.tilemapResource,
1687                     success: function(obj) {
1688                       if (!Ext.isEmpty(record.coordinate)) {
1689                         obj.coordinate = record.coordinate;
1690                       }
1691                       if (!Ext.isEmpty(record.zoom)) {
1692                         obj.zoom = record.zoom;
1693                       }
1694                       if (!Ext.isEmpty(record.viewPort)) {
1695                         obj.viewPort = record.viewPort;
1696                       }
1697                       this.fillTileMap(obj);
1698                     },
1699                     failure: this.fillTileMapFailure,
1700                     scope: this
1701                   });
1702                   
1703                   if (this.dragcontrol)
1704                       this.dragcontrol.activate();
1705                     
1706                   if (!this.compass) {
1707                       this.showCompass();
1708                       this.compass.setDirection(record.direction);
1709                       this.compass.refreshCssClass();
1710                       if (this.viewdirection) {
1711                         this.viewdirection.setDirection(record.direction);
1712                         this.viewdirection.refreshCssClass();
1713                       }
1714                     }
1715                     
1716                     if (this.idDoubleMapComp) {
1717                         this.openOrtoPhoto(this.obliquePhoto.area, "map2");
1718                       }
1719             
1720                 if (this.button) {
1721                  this.enableButton();
1722                  this.button.toggle(true);
1723                 }
1724             }
1725           },
1726           /**
1727 	     * Method: msgAlert
1728 	     * 
1729 	     * Messaggio di avviso
1730          * 
1731          * @private
1732          * @param {String} title
1733          * @param {String} text
1734          * @param {Boolean} toggle
1735 	     *
1736 	     */
1737           msgAlert: function (title, text, toggle) {
1738               var mapInfo = new Ext.Panel({
1739                         title: title,
1740                         html: '<div class="gx-info-panel">' +
1741                             '<p><b>'+text+'</b>' +
1742                             '</p></div>',
1743                         height: 'auto',
1744                         width: 'auto'
1745                       });
1746 
1747                       var win = new Ext.Window({
1748                         title: "Avviso",
1749                         modal: true,
1750                         layout: "fit",
1751                         width: 'auto',
1752                         height: 'auto',
1753                         items: [mapInfo]
1754                       });
1755                       win.show();
1756                       this.button.toggle(toggle);
1757           },
1758          /**
1759 	     * Method: debugPolygon
1760 	     * 
1761 	     * Funzione per lanciare la modalità di debug durante la navigazione
1762          * delle foto oblique
1763          * 
1764          * @private
1765          * @param {OpenLayers.Bounds} viewBounds
1766          * @param {Object} rectangle (points rectangle)
1767          * @param {Object} trapezoid (points trapezoid)
1768 	     *
1769 	     */          
1770           debugPolygon: function(viewBounds,rectangle,trapezoid) {
1771       
1772             if (this.debug_box) {
1773                 
1774                 //extent schermo
1775                 this.debug_boxes.removeFeatures([this.debug_box]);
1776                 this.debug_box = new OpenLayers.Feature.Vector(viewBounds.toGeometry());
1777                 this.debug_boxes.addFeatures(this.debug_box);
1778                 
1779                 //rettangolo
1780                 this.debug_rectangle.removeFeatures([this.debug_rect]);
1781                 var pointList = [];
1782                  var num_point = rectangle.length;
1783                  var newPoint = null;
1784                  for (var i = 0; i < num_point; i++) {
1785                     newPoint = new OpenLayers.Geometry.Point(rectangle[i].x,rectangle[i].y);
1786                     pointList.push(newPoint);
1787                  }
1788                  var ring = new OpenLayers.Geometry.LinearRing(pointList);
1789                  var polygon = new OpenLayers.Geometry.Polygon([ring]);
1790                 this.debug_rect = new OpenLayers.Feature.Vector(polygon);
1791                 this.debug_rectangle.addFeatures(this.debug_rect);
1792                 
1793                 //trapezio
1794                 this.debug_trapezoid.removeFeatures([this.debug_trap]);
1795                  pointList = [];
1796                  num_point = trapezoid.length;
1797                  newPoint = null;
1798                  for (var i = 0; i < num_point; i++) {
1799                     newPoint = new OpenLayers.Geometry.Point(trapezoid[i].x,trapezoid[i].y);
1800                     pointList.push(newPoint);
1801                  }
1802                  ring = new OpenLayers.Geometry.LinearRing(pointList);
1803                  polygon = new OpenLayers.Geometry.Polygon([ring]);
1804                 this.debug_trap = new OpenLayers.Feature.Vector(polygon);
1805                 this.debug_trapezoid.addFeatures(this.debug_trap);
1806             }
1807             else {
1808                      
1809                  if (this.debug_layer) this.map2.addLayer(this.debug_layer);
1810                  if (this.debug_layer_dsm) this.map2.addLayer(this.debug_layer_dsm);
1811                          
1812                  // extent schermo
1813                  this.debug_box = new OpenLayers.Feature.Vector(viewBounds.toGeometry());
1814                  this.debug_boxes.addFeatures(this.debug_box);
1815                  this.map2.addLayer(this.debug_boxes);
1816                  
1817                  //rettangolo
1818                  var pointList = [];
1819                  var num_point = rectangle.length;
1820                  var newPoint = null;
1821                  for (var i = 0; i < num_point; i++) {
1822                     newPoint = new OpenLayers.Geometry.Point(rectangle[i].x,rectangle[i].y);
1823                     pointList.push(newPoint);
1824                  }
1825                  var ring = new OpenLayers.Geometry.LinearRing(pointList);
1826                  var polygon = new OpenLayers.Geometry.Polygon([ring]);
1827                  this.debug_rect = new OpenLayers.Feature.Vector(polygon);
1828                 // var layer = new OpenLayers.Layer.Vector("Test");
1829                  this.debug_rectangle.addFeatures([this.debug_rect]);
1830                  this.map2.addLayer(this.debug_rectangle);
1831                  
1832                  // trapezio
1833                  pointList = [];
1834                  var num_point = trapezoid.length;
1835                  var newPoint = null;
1836                  for (var i = 0; i < num_point; i++) {
1837                     newPoint = new OpenLayers.Geometry.Point(trapezoid[i].x,trapezoid[i].y);
1838                     pointList.push(newPoint);
1839                  }
1840                  ring = new OpenLayers.Geometry.LinearRing(pointList);
1841                  polygon = new OpenLayers.Geometry.Polygon([ring]);
1842                  this.debug_trap = new OpenLayers.Feature.Vector(polygon);
1843                 // var layer = new OpenLayers.Layer.Vector("Test");
1844                  this.debug_trapezoid.addFeatures([this.debug_trap]);
1845                  this.map2.addLayer(this.debug_trapezoid);
1846                  
1847                 // console.log(polygon);
1848                 
1849                 
1850             }
1851  
1852           }
1853 
1854         });
1855 
1856     Ext.preg(framework.plugins.ActiveObliquePhotos.prototype.ptype, framework.plugins.ActiveObliquePhotos);
1857