Projet

Général

Profil

« Précédent | Suivant » 

Révision f60262e6

IDf60262e62ab9dbf2a5d1f0c672f9577590bd544b
Enfant 3a569aa8

Ajouté par Marc Souviron il y a plus de 12 ans

Première version enregistrée

Fichiers

  • ajouté
  • modifié
  • copié
  • renommé
  • supprimé

Voir les différences

Révisions

class/index.php
1
<!DOCTYPE html>
2
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
3
<head>
4
  <meta http-equiv="Content-type" content="text/html; charset=UTF-8"/>
5
  <title>Test des classes</title>
6
  <link rel="stylesheet" media="screen" href="css/all.css" />
7
  <script src="js/pano.js"></script>
8
</head>
9
<body>
10
  <h1>Test des classes</h1>   
11
  <?php
12
   require 'site_point.class.php';
13
   require 'sites_dir.class.php';
14

  
15
   $base_dir = '../tiles';
16
   $dir = new sites_dir($base_dir);
17

  
18
   foreach($dir->get_sites() as $pt) {
19
     printf("<h2>Nom : <em>%s</em></h2>\n", $pt->get_name());
20
     echo '<pre>';
21
     print_r($pt->get_params());
22
     print_r($pt->get_magnifications());
23
     echo '</pre>';
24
     $lat = 43.61034;
25
     $lon = 1.45553;
26
     $alt = 200;
27
     $res = $pt->coordsToCap($lat, $lon, $alt);
28
     printf("<h3>Cap vers %lf, %lf, %lf = (dist : %lf, cap : %lf, élévation : %lf)</h3>\n", $lat, $lon, $alt, $res[0], $res[1], $res[2]);
29
     $lat = 43.60698;
30
     $lon = 1.46725;
31
     $alt = 300;
32
     $res = $pt->coordsToCap($lat, $lon, $alt);
33
     printf("<h3>Cap vers %lf, %lf, %lf = (dist : %lf, cap : %lf, élévation : %lf)</h3>\n", $lat, $lon, $alt, $res[0], $res[1], $res[2]);
34
   }
35
  ?>
36
  <p><a href="http://validator.w3.org/check?uri=referer">page xHTML validé !</a></p>
37
</body>
38
</html>
class/site_point.class.php
1
<?php
2
class site_point {
3
  private $base_dir;
4
  private $name = false;
5
  private $prefix = false;
6
  private $params = false;
7
  private $zooms;
8

  
9
  public function __construct($dir) {
10
    $this->base_dir = $dir;
11
    $dir_fd = opendir($this->base_dir);
12
    while (false !== ($file = readdir($dir_fd))) {
13
       if (preg_match('/(.*)_[0-9]+_[0-9]+_[0-9]+\.jpg$/', $file, $reg)) {
14
	 $this->prefix = $reg[1];
15
	 break;
16
       }
17
    }
18
    closedir($dir_fd);
19
    if ($this->prefix === false) return false;
20
    $pfname = $this->base_dir.'/'.$this->prefix.'.params';
21
    if (is_file($pfname)) {
22
      $this->params = @parse_ini_file($pfname);
23
    }
24
  }
25
  
26
  public function get_params() {
27
    return $this->params;
28
  }
29
  
30
  public function get_name() {
31
    return basename($this->base_dir);
32
  }
33

  
34
  public function get_prefix() {
35
    return $this->prefix;
36
  }
37
  
38
  public function get_magnifications() {
39
    $dir_fd = opendir($this->base_dir);
40
    while (false !== ($file = readdir($dir_fd))) {                // extraction des paramètres de grossissement par le serveur
41
       //echo $file;
42
       if (preg_match('/(.*)_([0-9]+)_([0-9]+)_([0-9]+)\.jpg$/', $file, $reg)) {
43
	 $prefix = $reg[1];
44
	 if ($prefix == $this->prefix) {
45
	   $zoom = (int)$reg[2];
46
	   $posx = (int)$reg[3]+1;
47
	   $posy = (int)$reg[4]+1;
48
	   if (!isset($zoom_array[$zoom]['nx']) || $zoom_array[$zoom]['nx'] < $posx) $zoom_array[$zoom]['nx'] = $posx;
49
	   if (!isset($zoom_array[$zoom]['ny']) || $zoom_array[$zoom]['ny'] < $posy) $zoom_array[$zoom]['ny'] = $posy;
50
	 }
51
       }
52
    }
53
    $this->zooms = $zoom_array;
54
    return $this->zooms;
55
  }
56

  
57
  public function coordsToCap($lat, $lon, $alt) {
58
    if (!isset($this->params['latitude']) || !isset($this->params['longitude'])) return false;
59
    $rt = 6371;  // Rayon de la terre
60
    $alt1 = isset($this->params['altitude']) ? $this->params['altitude'] : $alt;
61
    $lat1 = $this->params['latitude']*M_PI/180;
62
    $lon1 = $this->params['longitude']*M_PI/180;
63
    $alt2 = $alt;
64
    $lat2 = $lat * M_PI/180;
65
    $lon2 = $lon * M_PI/180;
66

  
67
    $dLat = $lat2-$lat1;
68
    $dLon = $lon2-$lon1;
69
    
70
    $a = sin($dLat/2) * sin($dLat/2) + sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2); 
71
    $angle = 2 * atan2(sqrt($a), sqrt(1-$a));
72
    $d = $angle * $rt;                    // distance du point en Kms
73
    
74
    $y = sin($dLon)*cos($lat2);
75
    $x = cos($lat1)*sin($lat2) - sin($lat1)*cos($lat2)*cos($dLon);
76
    $cap = atan2($y, $x);                 // cap pour atteindre le point en radians
77

  
78
    $e = atan2(($alt2 - $alt1)/1000 - $d*$d/(2*$rt), $d);  // angle de l'élévation en radians
79
    //    printf("%s, %s, %s, %s\n",$lat1, $this->params['latitude'], $lat, $dLat);
80

  
81
    return array($d, $cap*180/M_PI, $e*180/M_PI);   // les résultats sont en degrés
82
  }
83
  
84
}
class/sites_dir.class.php
1
<?php
2
class sites_dir {
3
  private $base_dir;
4

  
5
  public function __construct($dir) {
6
    $this->base_dir = $dir;
7
  }
8
  
9
  public function get_sites() {
10
    $dir_fd = opendir($this->base_dir);
11
    $point_list = array();
12
    while (false !== ($point_dir = readdir($dir_fd))) {
13
      $pt = new site_point($this->base_dir.'/'.$point_dir);
14
      if ($pt->get_prefix() !== false) $point_list[] = $pt;
15
    }
16
    return $point_list;
17
  }
18

  
19
}
css/all.css
1
* {
2
    padding:0;
3
    margin:0;
4
}
5

  
6
body {
7
    overflow:hidden;
8
}
9

  
10
#mon-canvas {
11
    background-color:#44F;
12
    margin:auto;
13
    display:block;
14
}
15

  
16
#info {
17
    display:none;
18
    background-color:#FF0;
19
    border:1px red solid;
20
    position:absolute;
21
    margin:1em;
22
    padding:0.2em 0.5em;
23
    border-radius:0.5em;
24
}
25

  
26
#insert {
27
    display:none;
28
    background-color:#F88;
29
    border:1px red solid;
30
    position:absolute;
31
}
32

  
33
label {
34
    display:block;
35
    clear:both;
36
}
37

  
38
legend {
39
    opacity:1;
40
    background-color:#F88;
41
    border:solid #F00 1px;
42
    border-radius:0.5em;
43
    padding:0 1em;
44
}      
45

  
46
fieldset#control {
47
    text-shadow:2px 2px 2px #000, -2px -2px 2px #000;
48
    color:#FFF;
49
    float:left;
50
    position:absolute;
51
    top:1em;
52
    left:2em;
53
    background-color:rgba(128,128,128,0.5);
54
    border:solid #F00 1px;
55
    border-radius:0.5em;
56
    padding:0.2em 0.5em;
57
}
58

  
59
input {
60
    vertical-align:middle;
61
}
62
input[type="number"] {
63
    border-radius:1em;
64
    display:block;
65
    float:right;
66
}
67

  
68
#res>:not(ul), #control, #params, #info {
69
    user-select:none;
70
    -khtml-user-select:none;
71
    -o-user-select:none;
72
    -moz-user-select:-moz-none;
73
    -webkit-user-select:none;
74
}
75

  
76
div#params {
77
    padding:0.2em 0.5em;
78
    border-radius:0.5em;
79
    background-color:rgba(128,128,128,0.5);
80
    border:solid #00F 1px;
81
    position:absolute;
82
    top:1em;
83
    right:2em;
84
    float:right;
85
}
86

  
87
div#params em {
88
    display:block;
89
    float:right;
90
    background-color:#88F;
91
    border-radius:0.5em;
92
    padding:0 0.5em;
93
    color:#FFF;
94
}
95

  
96
div#params em:nth-child[2] {
97
    display:inline;
98
}
99

  
100
.validators {
101
    text-align:center;
102
    background-color:#CCC;
103
    border:solid 1px #F55;
104
    border-width:0 0 1px 0;
105
    display:none;
106
}
107

  
108
#res {
109
    padding:0.2em 0.4em;
110
    color:#FF8;
111
    position:absolute;
112
    bottom:1em;
113
    right:2em;
114
    background-color:rgba(0,0,0,0.3);
115
    border:solid #FFF 1px;
116
}
117

  
118
#res:empty {padding:0;}
119

  
120
#res li {
121
    list-style-type: none;
122
    color:#FFF;
123
    background-color:rgba(100,0,0,0.5);
124

  
125
}
index.php
1
<!DOCTYPE html>
2
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
3
<head>
4
  <meta http-equiv="Content-type" content="text/html; charset=UTF-8"/>
5
  <title>Liste des panoramas</title>
6
  <link rel="stylesheet" media="screen" href="css/all.css" />
7
  <script src="js/pano.js"></script>
8
</head>
9
<body>
10
  <h1>Liste des panoramas</h1>   
11
  <?php
12
   require 'class/site_point.class.php';
13
   require 'class/sites_dir.class.php';
14
   echo '<ul>';
15
   if(isset($_GET['dir']) && is_dir($_GET['dir'])) {
16
     $base_dir = $_GET['dir'];
17
   } else {
18
     $base_dir = 'tiles';
19
   }
20

  
21
   $dir = new sites_dir($base_dir);
22

  
23
   foreach($dir->get_sites() as $pt) {
24
     $params = $pt->get_params();
25
     if (isset($params['titre'])) {
26
       $cmt = $params['titre'];
27
     } else {
28
       $cmt = sprintf('fichier <samp>%s/%s</samp>', $pt->get_name(), $pt->get_prefix());
29
     }
30
     printf ('<li><a href="panorama.php?dir=%s&amp;panorama=%s">%s</a></li>'."\n", $base_dir, $pt->get_name(), $cmt);
31
   }
32
   echo '</ul>';
33
  ?>
34
  <p><a href="http://validator.w3.org/check?uri=referer">page xHTML validé !</a></p>
35
</body>
36
</html>
js/pano.js
1
if (img_prefix == undefined) var img_prefix = './tiles/ttn_mediatheque/mediatheque_70';
2
if (to_cap == undefined) var to_cap = 0;
3
if (to_ele == undefined) var to_ele = 0;
4
if (to_zoom == undefined) var to_zoom = 0;
5
if (cap == undefined) var cap = 0;
6
if (cap_min == undefined) var cap_min = cap;
7
if (cap_max == undefined) var cap_max = cap_min+360;
8
if (ref_points == undefined) var ref_points = new Array();
9
if (image_loop == undefined) var image_loop = true;
10

  
11
var debug_mode = false;
12
var canvas;
13
var cntext;
14
var point_list = new Array();
15
var zoom = 0;
16
var zooms = new Array();
17
var prev_zm;
18
var zm;
19
var tile = {width:256, height:256};
20
var ntiles = {x:228, y:9};
21
var border_width = 2;
22
var imageObj = new Array();
23

  
24
var last  = {x:0,y:0};
25
var shift = {x:0,y:0};
26
var mouse = {x:0,y:0};
27
var speed = {x:0,y:0};
28
var canvas_pos = {x:0,y:0};
29
var tmt;
30
var is_located = false;
31
var point_colors = {'pano_point' : '255,128,128',
32
		    'ref_point'  : '128,128,255',
33
		    'loc_point'  : '128,255,128',
34
		    'unlocated'  : '255,255,255'};
35
var test = {x:0, y:0, i:100};
36

  
37
function nmodulo(val, div) {                // pour obtenir un modulo dans l'espace des nombres naturels N.
38
    return Math.floor((val%div+div)%div);   // il y a peut être plus simple, mais en attendant .... 
39
}
40

  
41
function fmodulo(val, div) {                // pour obtenir un modulo dans l'espace des nombres réels positifs.
42
    return (val%div+div)%div;               // il y a peut être plus simple, mais en attendant .... 
43
}
44

  
45
function distort_canvas(p, x, y) {
46
    if (p == 0) distort = 0;
47
    else {
48
	cntext.save();
49
	distort++;
50
        cntext.clearRect(0, 0, canvas.width, 2*canvas.height);
51
	var ratio = (canvas.width-2*distort)/canvas.width;
52
	var shift = canvas.height/2*(1-ratio);
53
	cntext.scale(1, ratio);
54
	if (p == 1) cntext.translate(0, 0);
55
	else if (p == -1) cntext.translate(0, 0);
56
	draw_image(x, y);
57
	cntext.restore();
58
	document.getElementById('res').innerHTML = 'distort : ' + distort + ' shift ' + shift + ' ratio : ' + ratio + '<br/>';
59
    }
60
}
61

  
62
function draw_image(ox, oy) {
63
    var ref_vals  = {x:last.x, y:last.y, zoom:zoom};
64
    ox = nmodulo(ox-canvas.width/2, zm.im.width);        // pour placer l'origine au centre du canvas 
65
    oy = Math.floor(oy-canvas.height/2);                 // pas de rebouclage vertical
66

  
67
    cntext.clearRect(0, 0, canvas.width, canvas.height);
68
    cntext.fillStyle = "rgba(128,128,128,0.8)";
69
    
70
    if (canvas.height > zm.im.height) {
71
	var fy = Math.floor((oy+canvas.height/2-zm.im.height/2)/(tile.height*zm.ntiles.y))*zm.ntiles.y;
72
	if (fy < 0) fy = 0; 
73
	var ly = fy + zm.ntiles.y;
74
    } else {
75
	var fy = Math.floor(oy/tile.height);
76
	var ly = Math.floor((oy+canvas.height+tile.height-1)/tile.height+1);
77
	if (fy < 0) fy = 0; 
78
	if (ly > zm.ntiles.y) ly = zm.ntiles.y; 
79
    }
80

  
81
    for (var j=fy; j<ly; j++) {
82
	var delta_y = (Math.floor(j/zm.ntiles.y) - Math.floor(fy/zm.ntiles.y)) * (tile.height - zm.last_tile.height);
83
	var dy = j*tile.height - oy - delta_y;
84
	var ny = j%ntiles.y;
85
	var wy = zm.tile.width;
86
	if (ny == zm.ntiles.y - 1) wy = zm.last_tile.height;
87

  
88
	var cpx = 0;
89
	var i = 0;
90
	var Nx = zm.ntiles.x;
91
	while (cpx < ox+canvas.width) {
92
	    var cur_width = zm.tile.width;
93
	    if (i%Nx == zm.ntiles.x-1) cur_width = zm.last_tile.width;
94
	    if (cpx >= ox-cur_width) {
95
		var nx = i%Nx;
96
		var idx = nx+'-'+ny+'-'+ref_vals.zoom;
97
		if (imageObj[idx] && imageObj[idx].complete) {
98
		    draw_tile(idx, cpx-ox, dy); // l'image est déja en mémoire, on force le dessin sans attendre.
99
		} else {
100
		    var fname = get_file_name(nx, ny, ref_vals.zoom);
101
		    imageObj[idx] = new Image();
102
		    imageObj[idx].src = fname;
103
		    var ts = zm.get_tile_size(nx, ny);
104
		    cntext.fillRect(cpx-ox, dy, ts.width, ts.height);
105
		    imageObj[idx].addEventListener('load', (function(ref, idx, dx, dy, ox, oy, ts) {
106
			return function() {        // closure nécéssaire pour gestion assynchronisme !!!
107
			    draw_tile_del(ref, idx, dx, dy, ox, oy, ts.width, ts.height);
108
			};
109
		    })(ref_vals, idx, cpx-ox, dy, ox, oy, ts), false);
110
		}
111
//		load_image(zoom, nx, ny, shx, shy, cpx-ox, dy, ox, oy);
112
	    }
113
	    cpx += cur_width;
114
	    i++;
115
	}
116
    }
117
    drawDecorations(ox, oy);
118
}
119

  
120
function draw_tile_del(ref, idx, tx, ty, ox, oy, twidth, theight) {
121
    if (ref.zoom == zoom && ref.x == last.x && ref.y == last.y) {
122
	draw_tile(idx, tx, ty);
123
	drawDecorations(ox, oy, tx, ty, twidth, theight);
124
    }
125
}
126

  
127
function draw_tile(idx, ox, oy) {
128
    var img = imageObj[idx];
129
    cntext.drawImage(img, ox, oy);
130
}
131

  
132
function drawDecorations(ox, oy, tx, ty, twidth, theight) {
133
    if (twidth) {
134
	cntext.save();
135
	cntext.beginPath();
136
        cntext.rect(tx, ty, twidth, theight);
137
        cntext.clip();
138
    } 
139
    var wgrd = zm.im.width/360;
140
    var od = ((ox+canvas.width/2)/wgrd)%360;
141
    var el = (zm.im.height/2 - (oy+canvas.height/2))/wgrd;
142
    cntext.fillStyle = "rgba(0,128,128,0.9)";
143
    cntext.strokeStyle = "rgb(255,255,255)";
144
    cntext.lineWidth = 1;
145
    cntext.fillRect(canvas.width/2-5, canvas.height/2-5, 10, 10);
146
    cntext.strokeRect(canvas.width/2-5, canvas.height/2-5, 10, 10);
147
    for(var i = 0; i < zm.pt_list.length; i++) {
148
	if (zm.pt_list[i]['type'] != 'unlocated') {
149
	    cntext.fillStyle = 'rgba('+point_colors[zm.pt_list[i]['type']]+',0.5)';
150
	    var cx = nmodulo(zm.pt_list[i]['xc'] - ox, zm.im.width);
151
	    var cy = zm.pt_list[i]['yc'] - oy;
152
	    cntext.beginPath();
153
	    cntext.arc(cx, cy, 20, 0, 2*Math.PI, true);
154
	    cntext.fill();
155
	}
156
    }
157

  
158
    //cntext.font = "20pt Arial";
159
    //cntext.fillRect(0, 0, 200, 20);
160
    //cntext.fillStyle = "rgb(255,0,0)";
161
    //cntext.fillText(od.toFixed(2), 5, 20);
162
    //for (i=0; i<canvas.width/wgrd; i++) {
163
	//cntext.strokeRect(i*wgrd, 0, wgrd, 20);
164
    //}
165
    if (twidth) {
166
	cntext.restore();
167
    }
168
}
169

  
170
function get_file_name(x, y, z) { // recherche du fichier correspondant au zoom et à la position
171
    var prm = [z, x, y];
172
    var fname = img_prefix;
173
    for (var i = 0; i < prm.length; i++) {
174
	fname += '_';
175
	if (prm[i] < 10) fname += '00';
176
	else if (prm[i] < 100) fname += '0';
177
	fname += prm[i];
178
    }
179
    fname += '.jpg';
180
    return fname;
181
}
182

  
183
function keys(key) {
184
    hide_links();
185
    evt = key || event;
186
    evt.preventDefault();
187
    evt.stopPropagation();
188
    if (!key) {
189
	key = window.event;
190
	key.which = key.keyCode;
191
    }
192
//    alert(key);
193
//    if (!evt.shiftKey) return;
194
    switch (key.which) {
195
    case 66: // b
196
	alert(key.pageX);
197
	test.x=tile.width*(ntiles.x-3);
198
	test.y=0;
199
	putImage(test.x, test.y);
200
	return;
201
    case 67: // c
202
	test.x=0;
203
	test.y=tile.height*(ntiles.y-3);
204
	putImage(test.x, test.y);
205
	return;
206
    case 36: // home
207
	putImage(0, zm.im.height/2);
208
	return;
209
    case 35: // end
210
	putImage(last.x+zm.im.width/2, last.y);
211
	return;
212
    case 39: // left
213
	putImage(last.x+40, last.y);
214
	return;
215
    case 40: // up
216
	putImage(last.x, last.y+20);
217
	return;
218
    case 37: // right
219
	putImage(last.x-40, last.y);
220
	return;
221
    case 38: // down
222
	putImage(last.x, last.y-20);
223
	return;
224
    case 33: // pageup
225
	zoom_control.value--;
226
	change_zoom()
227
	return;
228
    case 34: // pagedown
229
	zoom_control.value++;
230
	change_zoom()
231
	return;
232
    default:
233
//	alert(key.which)
234
	return;
235
    }
236
}
237

  
238
function onImageClick(e) {
239
    hide_contextmenu();
240
    shift.x = last.x;
241
    shift.y = last.y;
242
    speed.x = 0;
243
    speed.y = 0;
244
    mouse.x = e.pageX;
245
    mouse.y = e.pageY;
246
    clearTimeout(tmt);  //arrêt de l'éffet eventuel d'amorti en cours.
247
    canvas.addEventListener('mousemove', stickImage, false);
248
    canvas.addEventListener('mouseup', launchImage, false);
249
    //canvas.addEventListener('mouseout', launchImage, false);
250
    canvas.style.cursor='move';
251
    //document.onmousemove = stickImage;
252
    document.onmouseup = launchImage;
253
    hide_links();
254
}
255

  
256

  
257
function stickImage(e) {
258
    var xs = mouse.x - e.pageX + shift.x;
259
    var ys = mouse.y - e.pageY + shift.y;
260
    speed.x = xs - last.x;  //mémorisation des vitesses horizontales
261
    speed.y = ys - last.y;  //et verticales lors de ce déplacement
262
    putImage(xs, ys);
263
}
264

  
265
function launchImage(e) {
266
    distort_canvas(0);
267
    canvas.removeEventListener('mousemove', stickImage, false);
268
    //document.onmousemove = null;
269
    shift.x = e.pageX - mouse.x + shift.x;
270
    shift.y = e.pageY - mouse.y + shift.y;
271
    tmt = setTimeout(inertialImage, 100);
272
}
273

  
274
function putImage(x, y) { // est destiné à permettre l'effet d'amortissement par la mémorisation de la position courante.
275
    if (!zm.is_updated) return; 
276
    if (x >= zm.im.width) {   // rebouclage horizontal
277
	shift.x -= zm.im.width;
278
	x -= zm.im.width;
279
    } else if (x < 0) {
280
	shift.x += zm.im.width;
281
	x += zm.im.width;
282
    }
283
    if (y >= zm.im.height) {   // pas de rebouclage vertical mais blocage
284
	//distort_canvas(1, x, y);
285
	shift.y = zm.im.height-1;
286
	y = zm.im.height-1;
287
    } else if (y < 0) {
288
	//distort_canvas(-1, x, y);
289
	shift.y = 0;
290
	y = 0;
291
    }
292

  
293
    last.x = x;
294
    last.y = y;
295
    draw_image(x, y);
296
}
297

  
298
function inertialImage() {
299
    speed.x *= 0.9;
300
    speed.y *= 0.9;
301
    if (Math.abs(speed.x) > 2 || Math.abs(speed.y) > 2) {
302
	putImage(last.x+speed.x, last.y+speed.y);
303
	tmt = setTimeout(inertialImage, 100);
304
    } else {
305
	show_links();
306
    }
307
}
308

  
309
function tri_ref_points(v1, v2) {
310
    return v1['x'] - v2['x'];
311
}
312

  
313

  
314

  
315
function tzoom(zv) {
316
    this.value = zv;
317
    this.ntiles = {x:0,y:0};
318
    this.tile = {width:0,height:0};
319
    this.last_tile = {width:0,height:0};
320
    this.max_tile = {width:0,height:0};
321
    this.im = {width:0,height:0};
322
    this.is_updated = false;
323

  
324
    this.refresh = function() {
325
	this.im.visible_width = this.tile.width*(this.ntiles.x-1)+this.last_tile.width;
326
	this.is_updated = true;
327

  
328
	this.im.width = this.im.visible_width;
329
	this.im.height = this.tile.height*(this.ntiles.y-1)+this.last_tile.height;
330
	if (this.last_tile.width > this.tile.width) this.max_tile.width = this.im.last_tile.width;
331
	else this.max_tile.width = this.tile.width;
332
	if (this.last_tile.height > this.tile.height) this.max_tile.height = this.im.last_tile.height;
333
	else this.max_tile.height = this.tile.height;
334

  
335
	var ord_pts = new Array();
336
	i=0;
337
	for(var label in ref_points) {
338
	    ord_pts[i++] = ref_points[label]
339
	}
340
	ord_pts = ord_pts.sort(tri_ref_points);
341
	is_located = i > 1 || image_loop && i > 0;
342

  
343
	var alpha_domain = {start:0, end:360}; 
344
	this.pixel_y_ratio = this.im.width/360;
345
	if (is_located) {
346
	    this.ref_pixels = new Array;
347
	    this.ref_pixels[0] = new Array();    // Attention il faut compter un intervalle de plus !
348
	    for (var i=0; i < ord_pts.length; i++) { // premier parcours pour les paramètres cap/x
349
		this.ref_pixels[i+1] = new Array();
350
		this.ref_pixels[i+1].x = Math.floor(ord_pts[i].x*this.im.width);
351
		this.ref_pixels[i+1].cap = fmodulo(ord_pts[i].cap, 360);
352
		if (i != ord_pts.length-1) {
353
		    this.ref_pixels[i+1].ratio_x = (ord_pts[i+1].x - ord_pts[i].x)/fmodulo(ord_pts[i+1].cap - ord_pts[i].cap, 360)*this.im.width;
354
		}
355
	    }
356
	    if (image_loop == true) {
357
		var dpix = this.im.width;
358
		var dangle = 360;
359
		if (ord_pts.length > 1) {
360
		    dpix = this.im.width - this.ref_pixels[this.ref_pixels.length-1].x + this.ref_pixels[1].x;
361
		    dangle = fmodulo(this.ref_pixels[1].cap - this.ref_pixels[this.ref_pixels.length-1].cap, 360);
362
		}
363
		this.ref_pixels[0].ratio_x = dpix/dangle;
364
		this.ref_pixels[ord_pts.length].ratio_x = this.ref_pixels[0].ratio_x;
365
		dpix = this.im.width - this.ref_pixels[ord_pts.length].x;
366
		this.ref_pixels[0].cap = fmodulo(this.ref_pixels[ord_pts.length].cap + dpix / this.ref_pixels[0].ratio_x, 360);
367
	    } else {
368
		this.ref_pixels[0].ratio_x = this.ref_pixels[1].ratio_x;
369
		this.ref_pixels[ord_pts.length].ratio_x = this.ref_pixels[ord_pts.length-1].ratio_x;
370
		this.ref_pixels[0].cap = fmodulo(this.ref_pixels[1].cap - this.ref_pixels[1].x / this.ref_pixels[1].ratio_x, 360);
371
		alpha_domain.start = this.ref_pixels[0].cap;
372
		alpha_domain.end = fmodulo(this.ref_pixels[ord_pts.length].cap+(this.im.width-this.ref_pixels[ord_pts.length].x)/this.ref_pixels[ord_pts.length].ratio_x, 360);
373
		this.pixel_y_ratio = this.im.width/fmodulo(alpha_domain.end-alpha_domain.start, 360);
374
	    }
375
	    this.ref_pixels[0].x = 0;
376

  
377
	    for (var i=0; i < ord_pts.length; i++) { // second parcours pour les paramètres elevation/y
378
		this.ref_pixels[i+1].shift_y = Math.floor(this.pixel_y_ratio*ord_pts[i].ele - ord_pts[i].y*this.im.height);
379
		if (i != ord_pts.length-1) {
380
		    var next_shift = Math.floor(this.pixel_y_ratio*ord_pts[i+1].ele - ord_pts[i+1].y*this.im.height);
381
		    this.ref_pixels[i+1].dshft_y = (next_shift - this.ref_pixels[i+1].shift_y)/(this.ref_pixels[i+2].x - this.ref_pixels[i+1].x);
382
		}
383
	    }
384

  
385
	    if (image_loop == true) {
386
		var dpix  = this.im.width;
387
		var delt = 0;
388
		if (ord_pts.length > 1) {
389
		    dpix  = this.im.width - this.ref_pixels[this.ref_pixels.length-1].x + this.ref_pixels[1].x;
390
		    delt = this.ref_pixels[this.ref_pixels.length-1].shift_y - this.ref_pixels[1].shift_y;
391
		}
392
		this.ref_pixels[0].dshft_y = delt/dpix;
393
		this.ref_pixels[ord_pts.length].dshft_y = this.ref_pixels[0].dshft_y;
394
		dpix = this.im.width - this.ref_pixels[ord_pts.length].x;
395
		this.ref_pixels[0].shift_y = this.ref_pixels[ord_pts.length].shift_y - dpix*this.ref_pixels[0].dshft_y;
396
	    } else {
397
		this.ref_pixels[0].shift_y = this.ref_pixels[1].shift_y;
398
		this.ref_pixels[ord_pts.length].shift_y = this.ref_pixels[ord_pts.length-1].shift_y;
399
		this.ref_pixels[0].dshft_y = 0;
400
		this.ref_pixels[ord_pts.length].dshft_y = 0;
401
	    }
402

  
403
	    if (debug_mode) {
404
		var res = document.getElementById('res');
405
		res.innerHTML = 'liste des '+this.ref_pixels.length+' valeurs de correction (image = '+this.im.width+'x'+this.im.height+') zoom = '+this.value+':<br/>';
406
		for (var i=0; i < this.ref_pixels.length; i++) { // pour le debug
407
		    res.innerHTML += '<p>point '+i+' :</p><ul>';
408
		    for (var key in this.ref_pixels[i]) { // pour le debug
409
			res.innerHTML += '<li>'+key + '['+i+'] = '+this.ref_pixels[i][key]+'</li>';
410
		    }
411
		    if (i != this.ref_pixels.length-1) {
412
			var tx0 = this.ref_pixels[i+1].x-1;
413
			//var ty0 = this.ref_pixels[i+1].shift_y;
414
			var ty0 = 0;
415
		    } else {
416
			var tx0 = this.im.width-1;
417
			var ty0 = 0;
418
		    }
419
		    res.innerHTML += '</ul><p>test sur : '+tx0+','+ty0+'</p>';
420
		    var tst = this.get_cap_ele(tx0, ty0);
421
		    res.innerHTML += '<p>cap:'+tst.cap+', shift:'+tst.ele+'</p>';
422
		    var tst2 = this.get_pos_xy(tst.cap, tst.ele);
423
		    res.innerHTML += '</ul><p>x:'+tst2.x+', y:'+tst2.y+'</p>';
424
		}
425
	    }
426
	}
427

  
428
	this.pt_list = new Array();
429
	for (var i=0; i<point_list.length; i++) {
430
	    var lbl = point_list[i][0];
431
	    var dst = point_list[i][1];
432
	    var cap = point_list[i][2];
433
	    var ele = point_list[i][3];
434
	    var lnk = point_list[i][4];
435
	    var typ = 'unlocated';
436
	    var rxy = this.get_pos_xy(cap, ele);
437
	    var is_visible = fmodulo(cap - alpha_domain.start, 360) <= fmodulo(alpha_domain.end - alpha_domain.start -0.0001, 360)+0.0001 && is_located;
438

  
439
	    this.pt_list[i] = new Array();
440
	    if (ref_points[lbl] != undefined) {
441
		typ = 'ref_point';
442
		if (!is_located) rxy = {x:ref_points[lbl].x*this.im.width, y:ref_points[lbl].y*this.im.height}
443
	    } else if(lnk == '' && is_visible) {
444
		typ = 'loc_point';
445
	    } else if(is_visible) {
446
		typ = 'pano_point';
447
		lnk += '&to_zoom='+this.value;
448
	    }
449
	    this.pt_list[i]['type'] = typ;
450
	    this.pt_list[i]['cap'] = cap;
451
	    this.pt_list[i]['ele'] = ele;
452
	    this.pt_list[i]['dist'] = dst;
453
	    this.pt_list[i]['label'] = lbl;
454
	    this.pt_list[i]['lnk'] = lnk;
455
	    this.pt_list[i]['xc'] = rxy.x;
456
	    this.pt_list[i]['yc'] = Math.floor(this.im.height/2 - rxy.y);
457
	}
458
    }
459
    
460
    this.get_tile_size = function(nx, ny) {
461
	var res = {width:0, height:0};
462
	if (nx == this.ntiles.x-1) res.width = this.last_tile.width;
463
	else res.width = this.tile.width;
464
	if (ny == this.ntiles.y-1) res.height = this.last_tile.height;
465
	else res.height = this.tile.height;
466
	return res;
467
    }
468
    
469
    this.get_cap_ele = function(px, py) {               // recherche d'un cap et d'une élévation à partir d'un pixel X,Y.
470
	if (is_located) {
471
	    for (var i=0; i < this.ref_pixels.length; i++) {
472
		if (i == this.ref_pixels.length - 1 || px < this.ref_pixels[i+1].x) {
473
		    var dpix = px-this.ref_pixels[i].x;
474
		    var cp = fmodulo(this.ref_pixels[i].cap + dpix/this.ref_pixels[i].ratio_x, 360);
475
		    var el = (py+this.ref_pixels[i].shift_y+this.ref_pixels[i].dshft_y*dpix)/this.pixel_y_ratio;
476
		    return {cap:cp, ele:el};
477
		}
478
	    }
479
	} else {
480
	    var cp = 360*px/this.im.width;
481
	    var el = 360*py/this.im.height;
482
	    return {cap:cp, ele:el};
483
	}
484
    }
485
    
486
    this.get_pos_xy = function(cap, ele) {                  // recherche des coordonnées pixel à partir d'un cap et d'une élévation.
487
	if (is_located) {
488
	    var dcap = fmodulo(cap-this.ref_pixels[0].cap, 360);
489
	    for (var i=0; i < this.ref_pixels.length; i++) {
490
		if (i == this.ref_pixels.length - 1 || dcap < fmodulo(this.ref_pixels[i+1].cap-this.ref_pixels[0].cap, 360)) {
491
		    var px = this.ref_pixels[i].x + this.ref_pixels[i].ratio_x*fmodulo(cap - this.ref_pixels[i].cap, 360);
492
		    var dpix = px-this.ref_pixels[i].x;
493
		    var py = this.pixel_y_ratio*ele - this.ref_pixels[i].shift_y - this.ref_pixels[i].dshft_y*dpix;
494
		    return {x:px, y:py};
495
		}
496
	    }
497
	} else {
498
	    var px = fmodulo(cap, 360)/360*this.im.width;
499
	    var py = ele/360*this.im.height;
500
	    return {x:px, y:py};
501
	}
502
    }
503
}
504

  
505
function reset_zooms () {
506
    for(i=0; i<zooms.length; i++) zooms[i].is_updated = false;
507
    zm.refresh();
508
}
509

  
510
function wheel_zoom (event) {
511
    var zshift = {x:0, y:0};
512
    if (event.pageX != undefined && event.pageX != undefined) {
513
	zshift.x = event.pageX-canvas.width/2-canvas_pos.x;
514
	zshift.y = event.pageY-canvas.height/2-canvas_pos.y;
515
    }
516
    event.preventDefault();
517
    if (event.wheelDelta < 0 && zoom_control.value < zoom_control.max) {
518
	zoom_control.value++;
519
	change_zoom(zshift.x, zshift.y);
520
    } else if (event.wheelDelta > 0 && zoom_control.value > zoom_control.min) {
521
	zoom_control.value--; 
522
	change_zoom(zshift.x, zshift.y);
523
    }
524
}
525

  
526
function change_zoom(shx, shy) {
527
    var zoom_control = document.getElementById("zoom_ctrl");
528
    var v = zoom_control.value;
529

  
530
    prev_zm = zm;
531

  
532
    if (zooms[v]) {
533
	if (!zooms[v].is_updated) zooms[v].refresh();
534
    } else {
535
	zooms[v] = new tzoom(v);
536
    }
537

  
538
    if (zooms[v].is_updated) {
539
	if (shx == undefined || shy == undefined) {
540
	    shx=0;
541
	    shy=0;
542
	}
543
	zm = zooms[v];
544
	var px = (last.x+shx)*zm.im.width/prev_zm.im.width - shx;
545
	var py = (last.y+shy)*zm.im.height/prev_zm.im.height - shy;
546
	if (py < zm.im.height && py >= 0) {
547
	    zoom = zm.value;
548
	    tile = zm.tile;
549
	    ntiles = zm.ntiles;
550
	    putImage(px, py);
551
	} else {
552
	    zm = prev_zm;
553
	    zoom_control.value = zm.value;
554
	}
555
    }
556
}
557

  
558
function change_angle() {
559
    var elvtn_control = document.getElementById('elvtn_ctrl');
560
    var angle_control = document.getElementById('angle_ctrl');
561
    var resxy = zm.get_pos_xy(angle_control.value, elvtn_control.value);
562
    var pos_x = resxy.x;
563
    var pos_y = Math.floor(zm.im.height/2 - resxy.y);
564
    putImage(pos_x, pos_y);
565
}
566

  
567
function check_prox(x, y, r) {   //verification si un point de coordonnées x, y est bien dans un cercle de rayon r centré en X,Y. 
568
    return Math.sqrt(x*x + y*y) < r;
569
}
570

  
571
function check_links(e) {
572
    var mouse_x = e.pageX-canvas_pos.x;
573
    var mouse_y = e.pageY-canvas_pos.y;
574
    var pos_x = nmodulo(last.x + mouse_x - canvas.width/2, zm.im.width);
575
    var pos_y = last.y + mouse_y - canvas.height/2;
576
    for(var i = 0; i < zm.pt_list.length; i++) {
577
	if (is_located && zm.pt_list[i]['type'] == 'pano_point') {
578
	    if (check_prox(zm.pt_list[i]['xc']-pos_x, zm.pt_list[i]['yc']-pos_y, 20)) {
579
		if (zm.pt_list[i]['lnk'] != '') window.location = zm.pt_list[i]['lnk'];
580
		break;
581
	    }
582
	}
583
    }
584
}
585

  
586
function display_links(e) {
587
    var info = document.getElementById('info');
588
    var mouse_x = e.pageX-canvas_pos.x;
589
    var mouse_y = e.pageY-canvas_pos.y;
590
    var pos_x = nmodulo(last.x + mouse_x - canvas.width/2, zm.im.width);
591
    var pos_y = last.y + mouse_y - canvas.height/2;
592
    //var cap = ((pos_x/zm.im.width)*360).toFixed(2);
593
    var res = zm.get_cap_ele(pos_x, zm.im.height/2 - pos_y);
594
    //var ele = ((zm.im.height/2 - pos_y)/zm.im.width)*360;
595
    info.innerHTML = 'élévation : '+res.ele.toFixed(2)+'<br/>cap : '+res.cap.toFixed(2);
596
    info.style.top = e.pageY+'px';
597
    info.style.left = e.pageX+'px';
598
    info.style.backgroundColor = '#FFC';
599
    info.style.display = 'block';
600
    canvas.style.cursor='crosshair';
601
    for(var i = 0; i < zm.pt_list.length; i++) {
602
	if (is_located || zm.pt_list[i]['type'] == 'ref_point') {
603
	    if (check_prox(zm.pt_list[i]['xc']-pos_x, zm.pt_list[i]['yc']-pos_y, 20)) {
604
		info.innerHTML = zm.pt_list[i]['label'];
605
		if (zm.pt_list[i]['dist'] < 10) var dst = Math.round(zm.pt_list[i]['dist']*1000)+' m';
606
		else var dst = zm.pt_list[i]['dist'].toFixed(1)+' kms';
607
		info.innerHTML += '<br/> à ' + dst;
608
		info.style.backgroundColor = 'rgb('+point_colors[zm.pt_list[i]['type']]+')';
609
		canvas.style.cursor='auto';
610
		break;
611
	    }
612
	}
613
    }
614
}
615

  
616
function hide_links() {
617
    canvas.removeEventListener( "mousemove", display_links, false);
618
    var info = document.getElementById('info');
619
    info.style.display = 'none';
620
}
621

  
622
function show_links() {
623
    canvas.addEventListener( "mousemove", display_links, false);
624
//    var info = document.getElementById('info');
625
//    info.style.display = 'block';
626
}
627

  
628
function hide_contextmenu() {
629
    document.getElementById('insert').style.display = 'none';
630
}
631

  
632
function manage_ref_points(e) {
633
    //event.preventDefault();
634
    //event.stopPropagation();
635
    var insrt = document.getElementById('insert');
636
    document.getElementById('do-cancel').onclick = hide_contextmenu;
637
    insrt.style.left = e.pageX+'px';
638
    insrt.style.top = e.pageY+'px';
639
    insrt.style.display = 'block';
640
    var sel_pt = document.getElementById('sel_point');
641
    var do_insert = document.getElementById('do-insert');
642
    var do_delete = document.getElementById('do-delete');
643
    var pos_x = nmodulo(last.x + e.pageX - canvas_pos.x - canvas.width/2, zm.im.width);
644
    var pos_y = last.y + e.pageY - canvas_pos.y - canvas.height/2;
645
    for(var i = 0; i < zm.pt_list.length; i++) {
646
	if (zm.pt_list[i]['type'] == 'ref_point') {
647
	    if (check_prox(zm.pt_list[i]['xc']-pos_x, zm.pt_list[i]['yc']-pos_y, 20)) {
648
		sel_pt.value = zm.pt_list[i]['label'];
649
	    }
650
	}
651
    }
652
    do_delete.onclick = function() {delete_ref_point(insrt)};
653
    do_insert.onclick = function() {insert_ref_point(insrt, e.pageX-canvas_pos.x, e.pageY-canvas_pos.y)};
654
    return false;
655
}
656

  
657
function insert_ref_point(el, x, y) {
658
    var label;
659
    el.style.display = 'none';
660
    for(var i = 0; i < zm.pt_list.length; i++) {
661
	label = zm.pt_list[i]['label'];
662
	if(label == document.getElementById('sel_point').value) {
663
	    var posx = nmodulo(last.x + x - canvas.width/2, zm.im.width)/zm.im.width;
664
	    var posy = 0.5 - (last.y + y - canvas.height/2)/zm.im.height;
665
	    var pval = {x:posx, y:posy, cap:zm.pt_list[i]['cap'], ele:zm.pt_list[i]['ele'], label:label};
666
	    ref_points[label] = pval;
667
	    document.getElementById('res').innerHTML = '<h4>Dernier point entré</h4>';
668
	    document.getElementById('res').innerHTML += '<p>reference["'+label+'"] = '+posx.toFixed(5)+','+posy.toFixed(5)+'</p>';
669
	    reset_zooms();
670
 	    putImage(last.x, last.y);
671
	    break;
672
	}
673
    }
674
    show_result();
675
}
676

  
677
function show_result(clear_before) {
678
    var res = document.getElementById('res');
679
    var strg = '';
680
    for (var lbl in ref_points) {
681
	strg += '<li>reference["'+lbl+'"] = '+ref_points[lbl].x.toFixed(5)+','+ref_points[lbl].y.toFixed(5)+'</li>';
682
    }
683
    if (strg) strg = '<h3>Liste de tous les points de référence</h3>\n<ul>' + strg + '</ul>';
684
    if (clear_before) res.innerHTML = strg;
685
    else res.innerHTML += strg;
686
}
687

  
688
function delete_ref_point(el) {
689
    el.style.display = 'none';
690
    delete ref_points[document.getElementById('sel_point').value];
691
    reset_zooms();
692
    putImage(last.x, last.y);
693
    show_result(true);
694
}
695

  
696
function clean_canvas_events(e) {
697
    canvas.removeEventListener('mousemove', stickImage, false);
698
    document.getElementById('info').style.display = 'none';
699
    speed.x = 0;
700
    speed.y = 0;
701
}
702

  
703
canvas_set_size = function() {
704
    canvas.style.border = border_width+"px solid red";
705
    canvas.width = window.innerWidth-2*border_width;
706
    canvas.height = window.innerHeight-2*border_width;
707
    canvas_pos.x = canvas.offsetLeft+border_width;
708
    canvas_pos.y = canvas.offsetTop+border_width;
709
}
710

  
711
canvas_resize = function() {
712
    canvas_set_size();
713
    putImage(last.x, last.y);
714
}
715

  
716
window.onload = function() {
717
    canvas = document.getElementById("mon-canvas");
718
    cntext = canvas.getContext("2d");
719
    canvas_set_size();
720
    canvas.addEventListener("click", check_links, false);
721
    //canvas.addEventListener("oncontextmenu", manage_ref_points, false);
722
    canvas.oncontextmenu = manage_ref_points;
723
    canvas.addEventListener("mouseout" , clean_canvas_events, false);
724
    show_links();
725

  
726
    var max_zoom = zooms.length - 1;
727
    zoom_control = document.getElementById("zoom_ctrl");
728
    zoom_control.onchange = change_zoom;
729
    zoom_control.max = max_zoom;
730
    if (to_zoom > max_zoom) to_zoom = Math.floor(max_zoom/2);
731
    zm = zooms[to_zoom];
732
    zoom_control.value = to_zoom;
733
    zm.refresh();
734

  
735
    zoom = zm.value;
736
    tile = zm.tile;
737
    ntiles = zm.ntiles;
738

  
739
    angle_control = document.getElementById("angle_ctrl");
740
    angle_control.value = to_cap;
741
    angle_control.onchange = change_angle;
742
    angle_control.onclick = change_angle;
743
    elvtn_control = document.getElementById("elvtn_ctrl");
744
    elvtn_control.value = to_ele;
745
    elvtn_control.onchange = change_angle;
746
    elvtn_control.onclick = change_angle;
747

  
748
    change_angle();
749

  
750
    canvas.addEventListener('mousedown', onImageClick, false);
751
    addEventListener('keydown', keys, false);
752
    canvas.addEventListener('mousewheel', wheel_zoom, false);
753
    window.onresize = canvas_resize;
754
};
js/pano_array.js
1
if (img_prefix == undefined) var img_prefix = './tiles/ttn_mediatheque/mediatheque_70';
2
if (to_cap == undefined) var to_cap = 0;
3
if (to_ele == undefined) var to_ele = 0;
4
if (cap == undefined) var cap = 0;
5
if (elevation == undefined) var elevation = 0;
6
if (cap_min == undefined) var cap_min = cap;
7
if (cap_max == undefined) var cap_max = cap_min+360;
8
if (ref_points == undefined) var ref_points = new Array();
9
if (image_loop == undefined) var image_loop = true;
10

  
11
var canvas;
12
var cntext;
13
var point_list = new Array();
14
var zoom;
15
var to_zoom;
16
var zooms = new Array();
17
var prev_zm;
18
var zm;
19
var tile = {width:256, height:256};
20
var ntiles = {x:228, y:9};
21
var border_width = 5;
22
var imageObj = new Array();
23

  
24
var last  = {x:0,y:0};
25
var shift = {x:0,y:0};
26
var mouse = {x:0,y:0};
27
var speed = {x:0,y:0};
28
var canvas_pos = {x:0,y:0};
29
var tmt;
30

  
31
var test = {x:0, y:0, i:100};
32

  
33
function nmodulo(val, div) {                // pour obtenir un modulo dans l'espace des nombres naturels N.
34
    return Math.floor((val%div+div)%div);   // il y a peut être plus simple, mais en attendant .... 
35
}
36

  
37
function fmodulo(val, div) {                // pour obtenir un modulo dans l'espace des nombres réels positifs.
38
    return (val%div+div)%div;               // il y a peut être plus simple, mais en attendant .... 
39
}
40

  
41
function distort_canvas(p, x, y) {
42
    if (p == 0) distort = 0;
43
    else {
44
	cntext.save();
45
	distort++;
46
        cntext.clearRect(0, 0, canvas.width, 2*canvas.height);
47
	var ratio = (canvas.width-2*distort)/canvas.width;
48
	var shift = canvas.height/2*(1-ratio);
49
	cntext.scale(1, ratio);
50
	if (p == 1) cntext.translate(0, 0);
51
	else if (p == -1) cntext.translate(0, 0);
52
	draw_image(x, y);
53
	cntext.restore();
54
	document.getElementById('res').innerHTML = 'distort : ' + distort + ' shift ' + shift + ' ratio : ' + ratio + '<br/>';
55
    }
56
}
57

  
58
function draw_image(ox, oy) {
59
    ox = nmodulo(ox-canvas.width/2, zm.im.width);        // pour placer l'origine au centre du canvas 
60
    oy = Math.floor(oy-canvas.height/2);                             // pas de rebouclage vertical
61

  
62
    cntext.clearRect(0, 0, canvas.width, canvas.height);
63
    cntext.fillStyle = "rgba(128,128,128,0.8)";
64
    
65
    if (canvas.height > zm.im.height) {
66
	var fy = Math.floor((oy+canvas.height/2-zm.im.height/2)/(tile.height*zm.ntiles.y))*zm.ntiles.y;
67
	if (fy < 0) fy = 0; 
68
	var ly = fy + zm.ntiles.y;
69
    } else {
70
	var fy = Math.floor(oy/tile.height);
71
	var ly = Math.floor((oy+canvas.height+tile.height-1)/tile.height+1);
72
	if (fy < 0) fy = 0; 
73
	if (ly > zm.ntiles.y) ly = zm.ntiles.y; 
74
    }
75

  
76
    for (var j=fy; j<ly; j++) {
77
	var delta_y = (Math.floor(j/zm.ntiles.y) - Math.floor(fy/zm.ntiles.y)) * (tile.height - zm.last_tile.height);
78
	var dy = j*tile.height - oy - delta_y;
79
	var ny = j%ntiles.y;
80
	var wy = zm.tile.width;
81
	if (ny == zm.ntiles.y - 1) wy = zm.last_tile.height;
82

  
83
	var cpx = 0;
84
	var i = 0;
85
	var Nx = zm.ntiles.x;
86
	while (cpx < ox+canvas.width) {
87
	    var cur_width = zm.tile.width;
88
	    if (i%Nx == zm.ntiles.x-1) cur_width = zm.last_tile.width;
89
	    if (cpx >= ox-cur_width) {
90
		var nx = i%Nx;
91
		load_image(nx, ny, cpx-ox, dy, ox, oy);
92
	    }
93
	    cpx += cur_width;
94
	    i++;
95
	}
96
    }
97
    drawDecorations(ox, oy);
98
}
99

  
100
function load_image(nx, ny, ox, oy, x, y) {
101
    var idx = nx+'-'+ny+'-'+zoom;
102
    if (imageObj[idx] && imageObj[idx].complete) {
103
	draw_tile(idx, ox, oy); // l'image est déja en mémoire, on force le dessin sans attendre.
104
    } else {
105
	var fname = get_file_name(nx, ny, zoom);
106
	imageObj[idx] = new Image();
107
	imageObj[idx].src = fname;
108
	var ts = zm.get_tile_size(nx, ny);
109
	cntext.fillRect(ox, oy, ts.width, ts.height);
110
	var dx = shift.x;
111
	var dy = shift.y;
112
	imageObj[idx].addEventListener('load', function() {draw_tile_del(zoom, dx, dy, idx, ox, oy, x, y)}, false);
113
    }
114
}
115

  
116
function draw_tile_del(ezoom, dx, dy, idx, ox, oy, x, y) {
117
    if (ezoom == zoom && dx == shift.x && dy == shift.y) {
118
	draw_tile(idx, ox, oy);
119
	drawDecorations(x, y);
120
    }
121
}
122

  
123
function draw_tile(idx, ox, oy) {
124
    var img = imageObj[idx];
125
    cntext.drawImage(img, ox, oy);
126
}
127

  
128
function drawDecorations(ox, oy) {
129
    var wgrd = zm.im.width/360;
130
    var od = ((ox+canvas.width/2)/wgrd)%360;
131
    var el = (zm.im.height/2 - (oy+canvas.height/2))/wgrd;
132
//    document.getElementById('angle_ctrl').value = od.toFixed(2);
133
//    document.getElementById('elvtn_ctrl').value = el.toFixed(2);
134
    cntext.fillStyle = "rgba(0,128,128,0.9)";
135
    cntext.strokeStyle = "rgb(255,255,255)";
136
    cntext.lineWidth = 1;
137
    cntext.fillRect(canvas.width/2-5, canvas.height/2-5, 10, 10);
138
    cntext.strokeRect(canvas.width/2-5, canvas.height/2-5, 10, 10);
139
    document.getElementById('res').innerHTML = '';
140
    for(var i = 0; i < zm.pt_list.length; i++) {
141
	var cx = nmodulo(zm.pt_list[i]['xc'] - ox, zm.im.width);
142
	var cy = zm.pt_list[i]['yc'] - oy;
143
	if (zm.pt_list[i]['lnk'] != undefined) cntext.fillStyle = "rgba(255,128,128,0.5)";
144
	else cntext.fillStyle = "rgba(128,255,128,0.5)";
145
	cntext.beginPath();
146
	cntext.arc(cx, cy, 20, 0, 2*Math.PI, true);
147
	cntext.fill();
148
	document.getElementById('res').innerHTML += 'cx : ' + cx + ' cy ' + cy + ' lnk : ' + zm.pt_list[i]['lnk'] + '<br/>';
149
    }
150

  
151
    //cntext.font = "20pt Arial";
152
    //cntext.fillRect(0, 0, 200, 20);
153
    //cntext.fillStyle = "rgb(255,0,0)";
154
    //cntext.fillText(od.toFixed(2), 5, 20);
155
    //for (i=0; i<canvas.width/wgrd; i++) {
156
	//cntext.strokeRect(i*wgrd, 0, wgrd, 20);
157
    //}
158
}
159

  
160
function get_file_name(x, y, z) { // recherche du fichier correspondant au zoom et à la position
161
    var prm = [z, x, y];
162
    var fname = img_prefix;
163
    for (var i = 0; i < prm.length; i++) {
164
	fname += '_';
165
	if (prm[i] < 10) fname += '00';
166
	else if (prm[i] < 100) fname += '0';
167
	fname += prm[i];
168
    }
169
    fname += '.jpg';
170
    return fname;
171
}
172

  
173
function keys(key) {
174
    event.preventDefault();
175
    event.stopPropagation();
176
    if (!key) {
177
	key = event;
178
	key.which = key.keyCode;
179
    }
180
    evt = key || event;
181
//    alert(key);
182
//    if (!evt.shiftKey) return;
183
    switch (key.which) {
184
    case 36: // home
185
	test.x=0;
186
	test.y=0;
187
	putImage(test.x, test.y);
188
	return;
189
    case 66: // b
190
	alert(key.pageX);
191
	test.x=tile.width*(ntiles.x-3);
192
	test.y=0;
193
	putImage(test.x, test.y);
194
	return;
195
    case 67: // c
196
	test.x=0;
197
	test.y=tile.height*(ntiles.y-3);
198
	putImage(test.x, test.y);
199
	return;
200
    case 35: // end
201
	test.x=tile.width*(ntiles.x-3);
202
	test.y=tile.height*(ntiles.y-3);
203
	putImage(test.x, test.y);
204
	return;
205
    case 39: // left
206
	test.x+=test.i;
207
	putImage(test.x, test.y);
208
	return;
209
    case 40: // up
210
	test.y+=test.i;
211
	putImage(test.x, test.y);
212
	return;
213
    case 37: // right
214
	test.x-=test.i;
215
	putImage(test.x, test.y);
216
	return;
217
    case 38: // down
218
	test.y-=test.i;
219
	putImage(test.x, test.y);
220
	return;
221
    case 33: // pageup
222
	test.y=0;
223
	putImage(test.x, test.y);
224
	return;
225
    case 34: // pagedown
226
	test.y=tile.height*(ntiles.y-3);
227
	putImage(test.x, test.y);
228
	return;
229
    default:
230
	//alert(key.which)
231
	return;
232
    }
233
}
234

  
235
function onImageClick(e) {
236
    shift.x = last.x;
237
    shift.y = last.y;
238
    speed.x = 0;
239
    speed.y = 0;
240
    mouse.x = e.pageX;
241
    mouse.y = e.pageY;
242
    clearTimeout(tmt);  //arrêt de l'éffet eventuel d'amorti en cours.
243
    canvas.addEventListener('mousemove', stickImage, false);
244
    canvas.addEventListener('mouseup', launchImage, false);
245
    //canvas.addEventListener('mouseout', launchImage, false);
246
    canvas.style.cursor='move';
247
    //document.onmousemove = stickImage;
248
    document.onmouseup = launchImage;
249
    hide_links();
250
}
251

  
252

  
253
function stickImage(e) {
254
    var xs = mouse.x - e.pageX + shift.x;
255
    var ys = mouse.y - e.pageY + shift.y;
256
    speed.x = xs - last.x;  //mémorisation des vitesses horizontales
257
    speed.y = ys - last.y;  //et verticales lors de ce déplacement
258
    putImage(xs, ys);
259
}
260

  
261
function launchImage(e) {
262
    distort_canvas(0);
263
    canvas.removeEventListener('mousemove', stickImage, false);
264
    show_links();
265
    //document.onmousemove = null;
266
    shift.x = e.pageX - mouse.x + shift.x;
267
    shift.y = e.pageY - mouse.y + shift.y;
268
    tmt = setTimeout(inertialImage, 100);
269
}
270

  
271
function putImage(x, y) { // est destiné à permettre l'effet d'amortissement par la mémorisation de la position courante.
272
    if (!zm.is_updated) return; 
273
    if (x >= zm.im.width) {   // rebouclage horizontal
274
	shift.x -= zm.im.width;
275
	x -= zm.im.width;
276
    } else if (x < 0) {
277
	shift.x += zm.im.width;
278
	x += zm.im.width;
279
    }
280
    if (y >= zm.im.height) {   // pas de rebouclage vertical mais blocage
281
	//distort_canvas(1, x, y);
282
	shift.y = zm.im.height-1;
283
	y = zm.im.height-1;
284
    } else if (y < 0) {
285
	//distort_canvas(-1, x, y);
286
	shift.y = 0;
287
	y = 0;
288
    }
289

  
290
    draw_image(x, y);
291
    last.x = x;
292
    last.y = y;
293
}
294

  
295
function inertialImage() {
296
    speed.x *= 0.9;
297
    speed.y *= 0.9;
298
    if (Math.abs(speed.x) > 2 || Math.abs(speed.y) > 2) {
299
	putImage(last.x+speed.x, last.y+speed.y);
300
	tmt = setTimeout(inertialImage, 100);
301
    }
302
}
303

  
304
function tri_ref_points(v1, v2) {
305
    return v1['x'] - v2['x'];
306
}
307

  
308

  
309

  
310
function tzoom(zv) {
311
    this.ref_pixels = new Array;
312
    this.value = zv;
313
    this.ntiles = {x:0,y:0};
314
    this.tile = {width:0,height:0};
315
    this.last_tile = {width:0,height:0};
316
    this.max_tile = {width:0,height:0};
317
    this.im = {width:0,height:0};
318
    this.pt_list = new Array();
319
    this.is_updated = false;
320

  
321
    this.refresh = function() {
322
	this.im.visible_width = this.tile.width*(this.ntiles.x-1)+this.last_tile.width;
323
	this.is_updated = true;
324

  
325
	this.im.width = this.im.visible_width;
326
	this.im.height = this.tile.height*(this.ntiles.y-1)+this.last_tile.height;
327
	if (this.last_tile.width > this.tile.width) this.max_tile.width = this.im.last_tile.width;
328
	else this.max_tile.width = this.tile.width;
329
	if (this.last_tile.height > this.tile.height) this.max_tile.height = this.im.last_tile.height;
330
	else this.max_tile.height = this.tile.height;
331

  
332
	this.ref_pixels[0] = new Array();    // Attention il faut compter un intervalle de plus !
333
	ord_pts = new Array();
334
	i=0;
335
	for(var label in ref_points) {
336
	    ord_pts[i] = ref_points[label]
337
	}
338
	ord_pts = ord_pts.sort(tri_ref_points);
339

  
340
	for (var i=0; i < ord_pts.length; i++) {
341
	    this.ref_pixels[i+1] = new Array();
342
	    if (i != ord_pts.length-1) {
343
		this.ref_pixels[i+1]['ratio_x'] = (ord_pts[i+1]['x'] - ord_pts[i]['x'])/fmodulo(ord_pts[i+1]['cap'] - ord_pts[i]['cap'], 360)*this.im.width;
344
		this.ref_pixels[i+1]['ratio_y'] = (ord_pts[i+1]['y'] - ord_pts[i]['y'])/fmodulo(ord_pts[i+1]['ele'] - ord_pts[i]['ele'], 360);
345
	    }
346
	    this.ref_pixels[i+1]['x'] = Math.floor(ord_pts[i]['x']*this.im.width);
347
	    this.ref_pixels[i+1]['cap'] = ord_pts[i]['cap'];
348
	    this.ref_pixels[i+1]['y'] = Math.floor(ord_pts[i]['y']*this.im.height);
349
	    this.ref_pixels[i+1]['ele'] = ord_pts[i]['ele'];
350
	}
351
	if (image_loop == true) {
352
	    var dpix = this.im.width;
353
	    var dangle = 360;
354
	    if (ord_pts.length > 1) {
355
		dpix = zm.im.width - this.ref_pixels[this.ref_pixels.length-1]['x'] + this.ref_pixels[1]['x'];
356
		dangle = fmodulo(this.ref_pixels[1]['cap'] - this.ref_pixels[this.ref_pixels.length-1]['cap'], 360);
357
	    }
358
	    this.ref_pixels[0]['ratio_x'] = dpix/dangle;
359
	    this.ref_pixels[ord_pts.length]['ratio_x'] = this.ref_pixels[0]['ratio_x'];
360
	    this.ref_pixels[ord_pts.length]['ratio_y'] = this.ref_pixels[0]['ratio_y'];
361
	    dpix = this.im.width - this.ref_pixels[ord_pts.length]['x'];
362
	    this.ref_pixels[0]['cap'] = this.ref_pixels[ord_pts.length]['cap'] + dpix / this.ref_pixels[0]['ratio_x'];
363
	} else {
364
	    this.ref_pixels[0]['ratio_x'] = this.ref_pixels[1]['ratio_x'];
365
	    this.ref_pixels[ord_pts.length]['ratio_x'] = this.ref_pixels[ord_pts.length-1]['ratio_x'];
366
	    this.ref_pixels[0]['ratio_y'] = this.ref_pixels[1]['ratio_y'];
367
	    this.ref_pixels[ord_pts.length]['ratio_y'] = this.ref_pixels[ord_pts.length-1]['ratio_y'];
368
	    this.ref_pixels[0]['cap'] = this.ref_pixels[1]['cap'] - this.ref_pixels[1]['x'] / this.ref_pixels[1]['ratio_x'];
369
	}
370
	this.ref_pixels[0]['x'] = 0;
371
	this.ref_pixels[0]['y'] = 0;
372
	this.ref_pixels[0]['ele'] = 0;
373

  
374

  
375
	for (var i=0; i<point_list.length; i++) {
376
	    this.pt_list[i] = new Array();
377
	    this.pt_list[i]['angle'] = point_list[i][2];
378
	    this.pt_list[i]['label'] = point_list[i][0];
379
	    this.pt_list[i]['xc'] = Math.floor(this.get_pxx(point_list[i][2], 360));
380
//	    var tmp = fmodulo(point_list[i][2], 360);
381
//	    this.pt_list[i]['xc'] = Math.floor(tmp * this.im.width/360);
382
	    this.pt_list[i]['yc'] = Math.floor(this.im.height/2 - (point_list[i][3] + elevation) * this.im.width/360);
383
	    if (point_list[i][4] != '') this.pt_list[i]['lnk'] = point_list[i][4]+'&to_zoom='+zv;
384
	}
385
    }
386
    
387
    this.get_tile_size = function(nx, ny) {
388
	var res = {width:0, height:0};
389
	if (nx == this.ntiles.x-1) res.width = this.last_tile.width;
... Ce différentiel a été tronqué car il excède la taille maximale pouvant être affichée.