Project

General

Profile

1
/*
2
Author:       Olivier Terral olivier.terralATgeomatys.fr
3
License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
4

    
5
$Id: Graticule.js 3879 2008-02-27 14:20:29Z gjvoosten $
6
*/
7
// Ensure this object's dependancies are loaded.
8
mapbuilder.loadScript(baseDir+"/widget/ButtonBase.js");
9

    
10

    
11
/**
12
 * Render a Graticule.
13
 * @constructor
14
 * @base ButtonBase
15
 * @param widgetNode  The widget's XML object node from the configuration document.
16
 * @param model       The model object that this widget belongs to.
17
 */
18
function Graticule(widgetNode, model) {
19

    
20
	ButtonBase.apply(this, new Array(widgetNode, model));
21

    
22
	this.display=false;
23
	this.color=this.getProperty("mb:color");
24
	
25
	/**
26
   * Interactive ZoomOut control.
27
   * @param objRef reference to this object.
28
   * @return {OpenLayers.Control} class of the OL control.
29
   */
30
  this.createControl = function(objRef) {
31
    var Control = OpenLayers.Class( OpenLayers.Control, {
32
      CLASS_NAME: 'mbControl.Graticule',
33
      type: OpenLayers.Control.TYPE_TOGGLE,
34
	  destroy : function() {
35
	    OpenLayers.Control.prototype.destroy.apply(this, arguments);
36
	    if (this.divs) {
37
	      for(i = this.divs.length; i > 0; --i) {
38
		this.divs[i] = null;
39
	      }
40
	    }
41
	    this.div = null;
42
	    this.mapContainer = null;
43
	  },
44
	    
45
////////////////////////////ancien/////////////////////	
46
/**
47
   * Remove divs
48
   * @param objRef Pointer to this object.
49
   */
50
	removeGraticules : function() {
51
	
52
	  try{
53
			  var i = 0;
54
			  var div = this.mapContainer;
55
		
56
		      if (this.divs) {
57
		  	for(i=0; i< this.divs.length; i++)
58
		  	{
59
				div.removeChild(this.divs[i]);
60
			}
61
		      }
62
	  }
63
	  catch(e){
64
	  }
65
	
66
	},
67

    
68
	/**
69
   * Get bbox of MapPane with the right projection
70
   * Return an object
71
   * @param this Pointer to this object.
72
   */
73
	getBbox : function() {
74
	
75
			var bbox=new Object();
76
			bbox.ll=new Object();
77
			bbox.ur=new Object();
78
			///CSCS
79
    		var ll=new OpenLayers.Geometry.Point(this.bbox[0], this.bbox[1]);
80
    		var ur=new OpenLayers.Geometry.Point(this.bbox[2], this.bbox[3]);
81
    		var wgs84 = new OpenLayers.Projection("EPSG:4326");
82
    		
83
    		ll.transform(this.proj, wgs84);
84
    		ur.transform(this.proj, wgs84);
85
		
86
			
87
			bbox.ll.lon=ll.x;		//minx
88
			bbox.ll.lat=ll.y;		//miny
89
			bbox.ur.lon=ur.x;		//maxx
90
			bbox.ur.lat=ur.y;		//maxy
91
		
92
			return bbox;
93
		
94
	},
95

    
96
	/**
97
   * Calculate rounded graticule interval for supplied lat/lon span
98
   * 
99
   * @param dDeg difference in degrees.
100
   */
101
	//
102
	//return is in minutes
103
	gridIntervalMins : function(dDeg) {  
104
	
105
	  var dDeg = dDeg/10;				//want around 10 lines in the graticule
106
	  dDeg *= 6000;						//to minutes*100
107
	  dDeg = Math.ceil(dDeg)/100;		//minutes and hundredths of mins
108
	
109
	  if(dDeg <= 0.06)
110
		dDeg = 0.06;//0.001 degrees
111
	  else if(dDeg <= 0.12)
112
		dDeg = 0.12;//0.002 degrees
113
	  else if(dDeg <= 0.3)
114
		dDeg = 0.3;//0.005 degrees
115
	  else if(dDeg <= 0.6)
116
		dDeg = 0.6;//0.01 degrees
117
	  else if (dDeg <=  1.2)
118
		dDeg = 1.2;//0.02 degrees
119
	  else if(dDeg <= 3)
120
		dDeg = 3;//0.05 degrees
121
	  else if(dDeg <= 6)
122
		dDeg = 6;//0.1 degrees
123
	  else if (dDeg <=  12)
124
		dDeg = 12;//0.2 degrees
125
	  else if (dDeg <=  30)
126
		dDeg = 30;//0.5
127
	  else if (dDeg <=  60)
128
		dDeg = 30;//1
129
	  else if (dDeg <=  (60*2))
130
		dDeg = 60*2;
131
	  else if (dDeg <=  (60*5))
132
		dDeg = 60*5;
133
	  else if (dDeg <=  (60*10))
134
		dDeg = 60*10;
135
	  else if (dDeg <=  (60*20))
136
		dDeg = 60*20;
137
	  else if (dDeg <=  (60*30))
138
		dDeg = 60*30;
139
	  else
140
		dDeg = 60*45;
141
	  
142
		
143
	  return dDeg;
144
	
145
},
146

    
147

    
148
	
149
	/* Calculate grid label precision from grid interval in degrees
150
	*
151
	*@param dDeg difference in degrees.
152
	*/
153
	gridPrecision : function(dDeg) {
154
		if(dDeg < 0.01)
155
			return 3;
156
		else if(dDeg < 0.1)
157
			return 2;
158
		else if(dDeg < 1)
159
			return 1;
160
		else return 0;
161
	},
162

    
163
	/* Draw graticules
164
	*
165
	*@param this pointer to this object.
166
	*/
167
	addGraticules : function(){
168

    
169
		//Delete old graticule
170
		this.removeGraticules();
171
		
172
		var bbox=this.getBbox();
173
		
174
		var l=bbox.ll.lon; //////ll:lower left coordinates 
175
		var b=bbox.ll.lat;		//ll:lower left ,ll.long : latitude(y) de coin en bas a gauche
176
		var r=bbox.ur.lon;			//ur:upper right ,ur.long : longitude de coin en haut a droite
177
		var t=bbox.ur.lat;		
178
		
179
		 //test if coords are valid
180
		  if (b < -90.0)
181
			b = -90.0;
182
		  if(t > 90.0)
183
			t = 90.0;
184
		  if(l < -180.0)
185
		    l = -180.0;  
186
		  if(r > 180.0)
187
		    r = 180.0;
188
		    
189
		  if(l == r){
190
			l = -180.0;
191
			r = 180.0;
192
		  }
193
		
194
		  if(t == b){
195
			b = -90.0;
196
			t = 90.0;
197
		  }
198
		 
199
		  
200
		  
201
		  //grid interval in minutes    
202
		  var dLat = this.gridIntervalMins(t-b);
203
		  var dLng; 
204
		  if(r>l)
205
			dLng = this.gridIntervalMins(r-l);
206
		  else
207
		    dLng = this.gridIntervalMins((180-l)+(r+180));
208
		
209
		  //round iteration limits to the computed grid interval
210
		  l = Math.floor(l*60/dLng)*dLng/60;
211
		  b = Math.floor(b*60/dLat)*dLat/60;
212
		  t = Math.ceil(t*60/dLat)*dLat/60;
213
		  r = Math.ceil(r*60/dLng)*dLng/60;
214
		  
215
		
216
		
217
		  //Tes if coords are valid
218
		  if (b <= -90.0)
219
			b = -90;
220
		  if(t >= 90.0)
221
			t = 90;
222
		  if(l < -180.0)
223
		    l = -180.0;  
224
		  if(r > 180.0)
225
		    r = 180.0;
226
		    
227
		  //to whole degrees
228
		  dLat /= 60;
229
		  dLng /= 60;
230

    
231
		  this.dLat=dLat;
232
		  this.dLon=dLng;
233
		  
234
		  //# digits after DP for labels
235
		  var latDecs = this.gridPrecision(dLat);
236
		  var lonDecs = this.gridPrecision(dLng);
237
		 
238
		  //array for divs used for lines and labels
239
		  this.divs = new Array();
240
		  var i=0;//count inserted divs
241
		
242
		  //min and max x and y pixel values for graticule lines
243
		  var pbl = this.fromLatLngToDivPixel(b,l);
244
		  var ptr = this.fromLatLngToDivPixel(t,r);
245
		
246
		  
247
		  this.maxX = ptr.x;
248
		  this.maxY = pbl.y;
249
		  this.minX = pbl.x;
250
		  this.minY = ptr.y;
251
		  var x;//coord for label
252
		  
253
		  //labels on second column to avoid peripheral controls
254
		  var y = this.fromLatLngToDivPixel(b+dLat+dLat,l).y + 2;//coord for label
255
		  
256
		  //pane/layer to write on
257
		  var mapDiv = this.mapContainer;//this.map_.getPane(G_MAP_MARKER_SHADOW_PANE);
258
		  
259
		  var lo = l;
260
		  
261
		  if(r<lo)
262
		      r += 360.0;
263
		
264
		  //vertical lines
265
		  while(lo<=r){
266
				
267
				 var p = this.fromLatLngToDivPixel(b,lo);
268
				 //line
269
				 this.divs[i] = this.createVLine(p.x);
270
				 this.divs[i].style.zIndex = this.div.style.zIndex;
271
				 mapDiv.insertBefore(this.divs[i],null);
272
				 i++;
273
				  	
274
				 //label	 
275
				 var d = document.createElement("DIV");
276
				 x = p.x + 3;
277
				 
278
				 d.style.position = "absolute";
279
		         d.style.left = x.toString() + "px";
280
		         d.style.top = y.toString() + "px";
281
				 d.style.color = this.color;
282
				 d.style.fontFamily='Arial';
283
				 d.style.fontSize='x-small';
284
		         
285
		         if (lo==0)
286
		         {
287
		         	d.innerHTML = (Math.abs(lo)).toFixed(lonDecs);
288
		         }
289
			     else if(lo<0)
290
				{	d.title = mbGetMessage("westWgs84");
291
					d.innerHTML = (Math.abs(lo)).toFixed(lonDecs)+" W";
292
				 }
293
				 else 
294
				{	d.title = mbGetMessage("eastWgs84");
295
					d.innerHTML = (Math.abs(lo)).toFixed(lonDecs)+" E";
296
				 }
297
				 
298
				d.style.zIndex = this.div.style.zIndex;
299
				 mapDiv.insertBefore(d,null);
300
				 this.divs[i] = d;
301
			
302
				 i++;
303
				 lo += dLng;	
304
				 if (lo > 180.0){
305
					r -= 360.0;
306
					lo -= 360.0;
307
					}		 		
308
  	}
309
  
310

    
311

    
312
	var j = 0;
313
	      
314
	  //labels on second row to avoid controls
315
	  x = this.fromLatLngToDivPixel(b,l+dLng+dLng).x + 3;
316
	  
317
	  //horizontal lines
318
	  while(b<=t){
319

    
320
			 var p = this.fromLatLngToDivPixel(b,l);
321
			 
322
			 //line
323
			 if(r < l){ //draw lines across the dateline
324
				this.divs[i] = this.createHLine3(b);
325
				this.divs[i].style.zIndex = this.div.style.zIndex;
326
				mapDiv.insertBefore(this.divs[i],null);
327
				i++;
328
			 }
329
			 else if (r == l){ //draw lines for world scale zooms
330
			
331
				this.divs[i] = this.createHLine3(b);
332
				this.divs[i].style.zIndex = this.div.style.zIndex;
333
				mapDiv.insertBefore(this.divs[i],null);
334
				i++;
335
			 }
336
			 else{
337
			 	
338
				this.divs[i] = this.createHLine(p.y);
339
				this.divs[i].style.zIndex = this.div.style.zIndex;
340
				mapDiv.insertBefore(this.divs[i],null);
341
				i++;
342
			 }
343
			 
344
			 
345
			 
346
			 
347
			 //label
348
			 var d = document.createElement("DIV");
349
			 y = p.y + 2;
350
			 d.style.position = "absolute";
351
			 d.style.left =x.toString() + "px";
352
			 d.style.top = y.toString()+ "px";
353
			 d.style.color = this.color;
354
			 d.style.fontFamily='Arial';
355
			 d.style.fontSize='x-small';
356
			 
357
			 if (b==0)
358
	         {
359
	         	d.innerHTML = (Math.abs(b)).toFixed(lonDecs);
360
	         }
361
			 else if(b<0)
362
			{	d.title = mbGetMessage("southWgs84");
363
				d.innerHTML = (Math.abs(b)).toFixed(latDecs)+" S";
364
			}
365
			 else 
366
			{	d.title = mbGetMessage("northWgs84");
367
				d.innerHTML = (Math.abs(b)).toFixed(latDecs)+" N";
368
			}
369
			 if(j != 2)//dont put two labels in the same place
370
			 {
371
			 	 
372
				 d.style.zIndex = this.div.style.zIndex;
373
				 mapDiv.insertBefore(d,null);
374
				 this.divs[i] = d;
375
				 i++;
376
			 }
377
			 j++;
378
			 b += dLat;
379
	  }
380
	 
381

    
382
	},
383
	
384
	/*Transform lat/lon coordinates in pixels coordinates
385
	* Returns an object container pixel coordinates
386
	*@param this pointer to this object.
387
	*@param lat lon  coordiantes in degrees 
388
	*/
389
	fromLatLngToDivPixel : function(lat,lon){
390
		///CSCS
391
    var pt=new OpenLayers.Geometry.Point(lon, lat);
392
    pt.transform(new OpenLayers.Projection("EPSG:4326"),this.proj);
393
    var platlon=this.map.getPixelFromLonLat(new OpenLayers.LonLat(pt.x,pt.y));
394
		return platlon;
395
	},
396
	
397
	/*Create a vertical line
398
	* Returns a div that is a vertical single pixel line
399
	*@param this pointer to this object.
400
	*@param x left style property for div element 
401
	*/
402
	
403
	createVLine : function (x) {
404

    
405
		var div = document.createElement("DIV");
406
		div.style.position = "absolute";
407
		div.style.overflow = "hidden";
408
		div.style.backgroundColor = this.color;
409
		div.style.left = x + "px";
410
		div.style.top = this.minY + "px";
411
		div.style.width = "1px";
412
		div.style.height = (this.maxY-this.minY) +"px";				
413
	    return div;
414
	
415
	},
416
 
417
	/*Create a horizontal line
418
	* Returns a div that is a horizontal single pixel line
419
	*@param this pointer to this object.
420
	*@param y top style property for div element 
421
	*/  	  
422
	createHLine : function(y) {
423

    
424
		var div = document.createElement("DIV");
425
		div.style.position = "absolute";
426
		div.style.overflow = "hidden";
427
		div.style.backgroundColor = this.color;
428
		div.style.left = this.minX + "px";
429
		div.style.top = y + "px";
430
		div.style.width = (this.maxX-this.minX) + "px";
431
		div.style.height = "1px";
432
	    return div;
433
	
434
	},
435
	/*Create a horizontal line
436
	* Returns a div that is a horizontal single pixel line, across the dateline  
437
	* we find the start and width of a 180 degree line and draw the same amount
438
	* to its left and right	
439
	*@param this pointer to this object.
440
	*@param lat latitude of  div element.
441
	*/  
442
		createHLine3 : function(lat) {
443
		
444
			var f = this.fromLatLngToDivPixel(lat,0);
445
			var t = this.fromLatLngToDivPixel(lat,180);		
446
		
447
			var div = document.createElement("DIV");
448
			div.style.position = "absolute";
449
			div.style.overflow = "hidden";
450
			div.style.backgroundColor = this.color;
451
			
452
			var x1 = f.x;
453
			var x2 = t.x;
454
			
455
			if(x2 < x1)
456
			{
457
				x2 = f.x;
458
				x1 = t.x;
459
			}
460
			div.style.left = (x1-(x2-x1)) + "px";
461
			div.style.top = f.y + "px";
462
			div.style.width = ((x2-x1)*2) + "px";
463
			div.style.height = "1px";
464
			return div;
465
			
466
			
467
}  ,
468

    
469
		/*Initialize Graticule's property 
470
		* 
471
		*@param this pointer to this object.
472
		*/ 
473
		update : function (){
474
		
475
		
476
			this.width=parseInt(this.objRef.targetModel.getWindowWidth());
477
			this.height=parseInt(this.objRef.targetModel.getWindowHeight());
478
			
479
			this.bbox=this.objRef.targetModel.getBoundingBox();
480
			this.proj=new OpenLayers.Projection( this.objRef.targetModel.getSRS());
481
		
482
			if (this.bbox[1]<0)
483
				if(this.bbox[3]<0)
484
					this.diffLat=this.bbox[1]-this.bbox[3];
485
				else
486
					this.diffLat=this.bbox[3]-this.bbox[1];
487
			else
488
				this.diffLat=this.bbox[3]+this.bbox[1];
489
				
490
			if (this.bbox[0]<0)
491
				if(this.bbox[2]<0)		
492
					this.diffLon=this.bbox[0]-this.bbox[2];
493
				else
494
					this.diffLon=this.bbox[2]-this.bbox[0];
495
			else
496
				this.diffLon=this.bbox[2]+this.bbox[0];
497
		
498
			
499
		  	this.addGraticules();
500

    
501
},
502

    
503
		/*Display graticule when click on button
504
		* 
505
		*@param this pointer to this object.
506
		*@param selected boolean true if button has been clicked , false if no
507
		*/ 
508
		activate: function() {
509
		
510
		if(OpenLayers.Control.prototype.activate.apply(this, arguments)){
511
                this.panel_div.style.backgroundImage = "url(\""+objRef.enabledImage+"\")";
512
    	//this.map.div.style.cursor = objRef.cursor;
513
			this.map.events.register('moveend', this, this.update);
514
		 	this.objRef.display=true;
515
		 	this.mapContainer = this.div;
516
		 	this.color="black";
517
			this.update();
518
		return true;
519
        } else {
520
            return false;
521
        }
522
        },
523
		deactivate: function() {
524
		if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)){
525
		    this.panel_div.style.backgroundImage = "url(\""+objRef.disabledImage+"\")";
526
			this.map.events.unregister('moveend', this, this.update);
527
			this.objRef.display=false;
528
			this.removeGraticules(); 
529
			objRef.enabled = false;
530
      		objRef.doSelect(objRef, false); 
531
       		this.active=false;
532
       		return true;
533
        } else {
534
            return false;
535
        }
536
	}
537
/////////////////////////////////////////////////////////////
538

    
539
   });
540

    
541
    return Control;
542
  }
543
}
544

    
(58-58/145)