pano.js 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. if (img_prefix == undefined) var img_prefix = 'http://pano.tetaneutral.net/data/tsf2/vpongnian/tiles/ttn_mediatheque/mediatheque_70';
  2. if (title == undefined) var title = 'point non défini';
  3. if (to_cap == undefined) var to_cap = 0;
  4. if (to_ele == undefined) var to_ele = 0;
  5. if (to_zoom == undefined) var to_zoom = 0;
  6. if (cap == undefined) var cap = 0;
  7. if (cap_min == undefined) var cap_min = cap;
  8. if (cap_max == undefined) var cap_max = cap_min+360;
  9. if (ref_points == undefined) var ref_points = new Array();
  10. if (image_loop == undefined) var image_loop = false;
  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. var fingr = 0; // mémorisation de lécart entre doigts;
  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 = {
  32. 'pano_point' : '255,128,128', // red
  33. 'ref_point' : '128,128,255', // blue
  34. 'loc_point' : '128,255,128', // green
  35. 'temporary' : '255,255,128', // yellow
  36. 'unlocated' : '255,255,255' // white
  37. };
  38. var test = {x:0, y:0, i:100};
  39. function getXMLHttpRequest() {
  40. var xhr = null;
  41. if (window.XMLHttpRequest || window.ActiveXObject) {
  42. if (window.ActiveXObject) {
  43. try {
  44. xhr = new ActiveXObject("Msxml2.XMLHTTP");
  45. } catch(e) {
  46. xhr = new ActiveXObject("Microsoft.XMLHTTP");
  47. }
  48. } else {
  49. xhr = new XMLHttpRequest();
  50. }
  51. } else {
  52. alert("Votre navigateur ne supporte pas l'objet XMLHTTPRequest...");
  53. return null;
  54. }
  55. return xhr;
  56. }
  57. function nmodulo(val, div) { // pour obtenir un modulo dans l'espace des nombres naturels N.
  58. return Math.floor((val%div+div)%div); // il y a peut être plus simple, mais en attendant ....
  59. }
  60. function fmodulo(val, div) { // pour obtenir un modulo dans l'espace des nombres réels positifs.
  61. return (val%div+div)%div; // il y a peut être plus simple, mais en attendant ....
  62. }
  63. function distort_canvas(p, x, y) {
  64. if (p == 0) distort = 0;
  65. else {
  66. cntext.save();
  67. distort++;
  68. cntext.clearRect(0, 0, canvas.width, 2*canvas.height);
  69. var ratio = (canvas.width-2*distort)/canvas.width;
  70. var shift = canvas.height/2*(1-ratio);
  71. cntext.scale(1, ratio);
  72. if (p == 1) cntext.translate(0, 0);
  73. else if (p == -1) cntext.translate(0, 0);
  74. draw_image(x, y);
  75. cntext.restore();
  76. document.getElementById('res').innerHTML = 'distort : ' + distort + ' shift ' + shift + ' ratio : ' + ratio + '<br/>';
  77. }
  78. }
  79. function draw_image(ox, oy) {
  80. var ref_vals = {x:last.x, y:last.y, zoom:zoom};
  81. ox = nmodulo(ox-canvas.width/2, zm.im.width); // pour placer l'origine au centre du canvas
  82. oy = Math.floor(oy-canvas.height/2); // pas de rebouclage vertical
  83. cntext.clearRect(0, 0, canvas.width, canvas.height);
  84. cntext.fillStyle = "rgba(128,128,128,0.8)";
  85. if (canvas.height > zm.im.height) {
  86. var fy = Math.floor((oy+canvas.height/2-zm.im.height/2)/(tile.height*zm.ntiles.y))*zm.ntiles.y;
  87. if (fy < 0) fy = 0;
  88. var ly = fy + zm.ntiles.y;
  89. } else {
  90. var fy = Math.floor(oy/tile.height);
  91. var ly = Math.floor((oy+canvas.height+tile.height-1)/tile.height+1);
  92. if (fy < 0) fy = 0;
  93. if (ly > zm.ntiles.y) ly = zm.ntiles.y;
  94. }
  95. for (var j=fy; j<ly; j++) {
  96. var delta_y = (Math.floor(j/zm.ntiles.y) - Math.floor(fy/zm.ntiles.y)) * (tile.height - zm.last_tile.height);
  97. var dy = j*tile.height - oy - delta_y;
  98. var ny = j%ntiles.y;
  99. var wy = zm.tile.width;
  100. if (ny == zm.ntiles.y - 1) wy = zm.last_tile.height;
  101. var cpx = 0;
  102. var i = 0;
  103. var Nx = zm.ntiles.x;
  104. while (cpx < ox+canvas.width) {
  105. var cur_width = zm.tile.width;
  106. if (i%Nx == zm.ntiles.x-1) cur_width = zm.last_tile.width;
  107. if (cpx >= ox-cur_width) {
  108. var nx = i%Nx;
  109. var idx = nx+'-'+ny+'-'+ref_vals.zoom;
  110. if (imageObj[idx] && imageObj[idx].complete) {
  111. draw_tile(idx, cpx-ox, dy); // l'image est déja en mémoire, on force le dessin sans attendre.
  112. } else {
  113. var fname = get_file_name(nx, ny, ref_vals.zoom);
  114. imageObj[idx] = new Image();
  115. imageObj[idx].src = fname;
  116. var ts = zm.get_tile_size(nx, ny);
  117. cntext.fillRect(cpx-ox, dy, ts.width, ts.height);
  118. imageObj[idx].addEventListener('load', (function(ref, idx, dx, dy, ox, oy, ts) {
  119. return function() { // closure nécéssaire pour gestion assynchronisme !!!
  120. draw_tile_del(ref, idx, dx, dy, ox, oy, ts.width, ts.height);
  121. };
  122. })(ref_vals, idx, cpx-ox, dy, ox, oy, ts), false);
  123. }
  124. // load_image(zoom, nx, ny, shx, shy, cpx-ox, dy, ox, oy);
  125. }
  126. cpx += cur_width;
  127. i++;
  128. }
  129. }
  130. drawDecorations(ox, oy);
  131. var cap_ele = zm.get_cap_ele(last.x, zm.im.height/2-last.y);
  132. angle_control.value = cap_ele.cap.toFixed(2);
  133. elvtn_control.value = cap_ele.ele.toFixed(2);
  134. }
  135. function draw_tile_del(ref, idx, tx, ty, ox, oy, twidth, theight) {
  136. if (ref.zoom == zoom && ref.x == last.x && ref.y == last.y) {
  137. draw_tile(idx, tx, ty);
  138. drawDecorations(ox, oy, tx, ty, twidth, theight);
  139. }
  140. }
  141. function draw_tile(idx, ox, oy) {
  142. var img = imageObj[idx];
  143. cntext.drawImage(img, ox, oy);
  144. }
  145. /** Draws the colored circles
  146. */
  147. function drawDecorations(ox, oy, tx, ty, twidth, theight) {
  148. if (twidth) {
  149. cntext.save();
  150. cntext.beginPath();
  151. cntext.rect(tx, ty, twidth, theight);
  152. cntext.clip();
  153. }
  154. var wgrd = zm.im.width/360;
  155. var od = ((ox+canvas.width/2)/wgrd)%360;
  156. var el = (zm.im.height/2 - (oy+canvas.height/2))/wgrd;
  157. cntext.fillStyle = "rgba(0,128,128,0.9)";
  158. cntext.strokeStyle = "rgb(255,255,255)";
  159. cntext.lineWidth = 1;
  160. cntext.fillRect(canvas.width/2-5, canvas.height/2-5, 10, 10);
  161. cntext.strokeRect(canvas.width/2-5, canvas.height/2-5, 10, 10);
  162. for(var i = 0; i < zm.pt_list.length; i++) {
  163. if (zm.pt_list[i]['type'] != 'unlocated') {
  164. cntext.fillStyle = 'rgba('+point_colors[zm.pt_list[i]['type']]+',0.5)';
  165. var cx = nmodulo(zm.pt_list[i]['xc'] - ox, zm.im.width);
  166. var cy = zm.pt_list[i]['yc'] - oy;
  167. cntext.beginPath();
  168. cntext.arc(cx, cy, 20, 0, 2*Math.PI, true);
  169. cntext.fill();
  170. }
  171. }
  172. if (twidth) {
  173. cntext.restore();
  174. }
  175. }
  176. function insert_drawn_point(lat, lon, alt) {
  177. var rt = 6371; // Rayon de la terre
  178. var pt_alt = document.getElementById('pos_alt').childNodes[0].nodeValue;
  179. var pt_lat = document.getElementById('pos_lat').childNodes[0].nodeValue;
  180. var pt_lon = document.getElementById('pos_lon').childNodes[0].nodeValue;
  181. var alt1 = pt_alt;
  182. var lat1 = pt_lat*Math.PI/180;
  183. var lon1 = pt_lon*Math.PI/180;
  184. var alt2 = alt;
  185. var lat2 = lat*Math.PI/180;
  186. var lon2 = lon*Math.PI/180;
  187. var dLat = lat2-lat1;
  188. var dLon = lon2-lon1;
  189. var a = Math.sin(dLat/2)*Math.sin(dLat/2) + Math.sin(dLon/2)*Math.sin(dLon/2)*Math.cos(lat1)*Math.cos(lat2); //
  190. var angle = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  191. var d = angle*rt; // distance du point en Kms
  192. var y = Math.sin(dLon) * Math.cos(lat2);
  193. var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
  194. var cap = Math.atan2(y,x); // cap pour atteindre le point en radians
  195. var e = Math.atan2((alt2 - alt1)/1000 - d*d/(2*rt),d); // angle de l'élévation en radians
  196. return {d:d, cap:cap*180/Math.PI, ele:e*180/Math.PI}; // les résultats sont en degrés
  197. }
  198. function localate_point() {
  199. var lat = document.getElementById("loca_latitude").value;
  200. var lon = document.getElementById("loca_longitude").value;
  201. var alt = document.getElementById("loca_altitude").value;
  202. if (lat == '' || isNaN(lat) || lat <= -90 || lat > 90) {
  203. alert("La latitude "+lat+"n'est pas correcte");
  204. return;
  205. }
  206. if (lat == '' || isNaN(lon) || lon <= -180 || lon > 180) {
  207. alert("La longitude "+lon+"n'est pas correcte");
  208. return;
  209. }
  210. if (lat == '' || isNaN(alt) || alt < -400 || alt > 10000000) {
  211. alert("l'altitude "+alt+"n'est pas correcte");
  212. return;
  213. }
  214. var opt_ced = new Array();
  215. opt_dce = insert_drawn_point(lat, lon, alt);
  216. display_temp(opt_dce.d, opt_dce.cap, opt_dce.ele);
  217. }
  218. function display_temp(d,cap,ele) {
  219. point_list[point_list.length] = new Array("point temporaire", d,cap,ele, "temporary");
  220. reset_zooms();
  221. putImage(last.x, last.y);
  222. }
  223. function arrayUnset(array, value){
  224. array.splice(array.indexOf(value), 1);
  225. }
  226. function erase_point() {
  227. for (var i=0; i<point_list.length; i++) {
  228. if(point_list[i][0] == "point temporaire"){
  229. arrayUnset(point_list,point_list[i]);
  230. loop = erase_point();
  231. }
  232. }
  233. reset_zooms();
  234. putImage(last.x, last.y);
  235. }
  236. /** Returns a 3-width zero-padded version of an int
  237. * ex: 3 -> "003"
  238. */
  239. function zero_pad(number) {
  240. var temp = number.toString(10);
  241. while (temp.length < 3) {
  242. temp = '0' + temp;
  243. }
  244. return temp;
  245. }
  246. function get_file_name(x, y, z) { // recherche du fichier correspondant au zoom et à la position
  247. return img_prefix+'/'+zero_pad(z)+'-'+zero_pad(x)+'-'+zero_pad(y)+'.jpg';
  248. }
  249. function get_base_name() {
  250. /**
  251. * @returns the base name, which is the name (not path) of the folder where
  252. * the tiles are.
  253. */
  254. return img_prefix.split('/').reverse()[0];
  255. }
  256. function keys(key) {
  257. hide_links();
  258. evt = key || event;
  259. //evt.preventDefault();
  260. //evt.stopPropagation();
  261. if (!key) {
  262. key = window.event;
  263. key.which = key.keyCode;
  264. }
  265. // alert(key);
  266. // if (!evt.shiftKey) return;
  267. switch (key.which) {
  268. /*case 66: // b
  269. alert(key.pageX);
  270. test.x=tile.width*(ntiles.x-3);
  271. test.y=0;
  272. putImage(test.x, test.y);
  273. return;
  274. case 67: // c
  275. test.x=0;
  276. test.y=tile.height*(ntiles.y-3);
  277. putImage(test.x, test.y);
  278. return;*/
  279. case 36: // home
  280. putImage(0, zm.im.height/2);
  281. return;
  282. case 35: // end
  283. putImage(last.x+zm.im.width/2, last.y);
  284. return;
  285. case 39: // left
  286. putImage(last.x+40, last.y);
  287. return;
  288. case 40: // up
  289. putImage(last.x, last.y+20);
  290. return;
  291. case 37: // right
  292. putImage(last.x-40, last.y);
  293. return;
  294. case 38: // down
  295. putImage(last.x, last.y-20);
  296. return;
  297. case 33: // pageup
  298. zoom_control.value--;
  299. change_zoom()
  300. return;
  301. case 34: // pagedown
  302. zoom_control.value++;
  303. change_zoom()
  304. return;
  305. default:
  306. // alert(key.which)
  307. return;
  308. }
  309. }
  310. function onImageClick(e) {
  311. hide_contextmenu();
  312. var index = {};
  313. if (e.touches && e.touches.length == 2) {
  314. e.preventDefault();
  315. fingr = Math.sqrt((e.touches[0].clientX - e.touches[1].clientX)^2 +
  316. (e.touches[0].clientY - e.touches[1].clientY)^2);
  317. } else {
  318. if (e.touches) {
  319. e.preventDefault();
  320. index.x = e.changedTouches[0].clientX;
  321. index.y = e.changedTouches[0].clientY;
  322. } else {
  323. index.x = e.pageX;
  324. index.y = e.pageY;
  325. }
  326. shift.x = last.x;
  327. shift.y = last.y;
  328. speed.x = 0;
  329. speed.y = 0;
  330. mouse.x = index.x;
  331. mouse.y = index.y;
  332. }
  333. clearTimeout(tmt); //arrêt de l'éffet eventuel d'amorti en cours.
  334. canvas.addEventListener('mousemove', stickImage, false);
  335. canvas.addEventListener('touchmove', stickImage, false);
  336. canvas.addEventListener('mouseup', launchImage, false);
  337. canvas.addEventListener('touchend', launchImage, false);
  338. //canvas.addEventListener('mouseout', launchImage, false);
  339. canvas.style.cursor='move';
  340. //document.onmousemove = stickImage;
  341. //document.onmouseup = launchImage;
  342. hide_links();
  343. }
  344. function stickImage(e) {
  345. var index = {};
  346. if (e.changedTouches && e.changedTouches.length == 2) {
  347. e.preventDefault();
  348. // cas du zoom à 2 doigts
  349. var nfingr = Math.sqrt((e.changedTouches[0].clientX - e.changedTouches[1].clientX)^2 +
  350. (e.changedTouches[0].clientY - e.changedTouches[1].clientY)^2);
  351. var evt = {}
  352. evt.pageX = (e.changedTouches[0].clientX + e.changedTouches[1].clientX)/2;
  353. evt.pageY = (e.changedTouches[0].clientY + e.changedTouches[1].clientY)/2;
  354. if (fingr > nfingr*2 || fingr < nfingr/2) {
  355. evt.wheelDelta = fingr - nfingr;
  356. fingr = nfingr;
  357. return wheel_zoom(evt);
  358. } else {
  359. return;
  360. }
  361. }
  362. if (e.touches) {
  363. e.preventDefault();
  364. index.x = e.changedTouches[0].clientX;
  365. index.y = e.changedTouches[0].clientY;
  366. } else {
  367. index.x = e.pageX;
  368. index.y = e.pageY;
  369. }
  370. var xs = mouse.x - index.x + shift.x;
  371. var ys = mouse.y - index.y + shift.y;
  372. speed.x = xs - last.x; //mémorisation des vitesses horizontales
  373. speed.y = ys - last.y; //et verticales lors de ce déplacement
  374. putImage(xs, ys);
  375. }
  376. function launchImage(e) {
  377. var index = {};
  378. if (e.touches) {
  379. e.preventDefault();
  380. index.x = e.changedTouches[0].clientX;
  381. index.y = e.changedTouches[0].clientY;
  382. } else {
  383. index.x = e.pageX;
  384. index.y = e.pageY;
  385. }
  386. distort_canvas(0);
  387. canvas.removeEventListener('mousemove', stickImage, false);
  388. canvas.removeEventListener('touchmove', stickImage, false);
  389. //document.onmousemove = null;
  390. shift.x = index.x - mouse.x + shift.x;
  391. shift.y = index.y - mouse.y + shift.y;
  392. tmt = setTimeout(inertialImage, 100);
  393. }
  394. function putImage(x, y) { // est destiné à permettre l'effet d'amortissement par la mémorisation de la position courante.
  395. if (!zm.is_updated) return;
  396. if (x >= zm.im.width) { // rebouclage horizontal
  397. shift.x -= zm.im.width;
  398. x -= zm.im.width;
  399. } else if (x < 0) {
  400. shift.x += zm.im.width;
  401. x += zm.im.width;
  402. }
  403. if (y >= zm.im.height) { // pas de rebouclage vertical mais blocage
  404. //distort_canvas(1, x, y);
  405. shift.y = zm.im.height-1;
  406. y = zm.im.height-1;
  407. } else if (y < 0) {
  408. //distort_canvas(-1, x, y);
  409. shift.y = 0;
  410. y = 0;
  411. }
  412. last.x = x;
  413. last.y = y;
  414. draw_image(x, y);
  415. }
  416. function inertialImage() {
  417. speed.x *= 0.9;
  418. speed.y *= 0.9;
  419. if (Math.abs(speed.x) > 2 || Math.abs(speed.y) > 2) {
  420. putImage(last.x+speed.x, last.y+speed.y);
  421. tmt = setTimeout(inertialImage, 100);
  422. } else {
  423. show_links();
  424. }
  425. }
  426. function tri_ref_points(v1, v2) {
  427. return v1['x'] - v2['x'];
  428. }
  429. function tzoom(zv) {
  430. this.value = zv;
  431. this.ntiles = {x:0,y:0};
  432. this.tile = {width:0,height:0};
  433. this.last_tile = {width:0,height:0};
  434. this.max_tile = {width:0,height:0};
  435. this.im = {width:0,height:0};
  436. this.is_updated = false;
  437. this.refresh = function() {
  438. this.im.visible_width = this.tile.width*(this.ntiles.x-1)+this.last_tile.width;
  439. this.is_updated = true;
  440. this.im.width = this.im.visible_width;
  441. this.im.height = this.tile.height*(this.ntiles.y-1)+this.last_tile.height;
  442. if (this.last_tile.width > this.tile.width) {
  443. this.max_tile.width = this.im.last_tile.width;
  444. } else {
  445. this.max_tile.width = this.tile.width;
  446. }
  447. if (this.last_tile.height > this.tile.height) {
  448. this.max_tile.height = this.im.last_tile.height;
  449. } else {
  450. this.max_tile.height = this.tile.height;
  451. }
  452. var ord_pts = new Array();
  453. for(var label in ref_points) {
  454. ord_pts.push(ref_points[label]);
  455. }
  456. ord_pts = ord_pts.sort(tri_ref_points);
  457. is_located = (ord_pts.length > 1)
  458. || image_loop && (ord_pts.length > 0);
  459. var alpha_domain = {start:0, end:360};
  460. this.pixel_y_ratio = this.im.width/360;
  461. if (is_located) {
  462. this.ref_pixels = new Array;
  463. this.ref_pixels[0] = new Array(); // Attention il faut compter un intervalle de plus !
  464. for (var i=0; i < ord_pts.length; i++) { // premier parcours pour les paramètres cap/x
  465. this.ref_pixels[i+1] = new Array();
  466. this.ref_pixels[i+1].x = Math.floor(ord_pts[i].x*this.im.width);
  467. this.ref_pixels[i+1].cap = fmodulo(ord_pts[i].cap, 360);
  468. if (i != ord_pts.length-1) {
  469. this.ref_pixels[i+1].ratio_x = (ord_pts[i+1].x - ord_pts[i].x) /
  470. fmodulo(ord_pts[i+1].cap - ord_pts[i].cap, 360)*this.im.width;
  471. }
  472. }
  473. if (image_loop == true) {
  474. var dpix = this.im.width;
  475. var dangle = 360;
  476. if (ord_pts.length > 1) {
  477. dpix = this.im.width - this.ref_pixels[this.ref_pixels.length-1].x + this.ref_pixels[1].x;
  478. dangle = fmodulo(this.ref_pixels[1].cap - this.ref_pixels[this.ref_pixels.length-1].cap, 360);
  479. }
  480. this.ref_pixels[0].ratio_x = dpix/dangle;
  481. this.ref_pixels[ord_pts.length].ratio_x = this.ref_pixels[0].ratio_x;
  482. dpix = this.im.width - this.ref_pixels[ord_pts.length].x;
  483. this.ref_pixels[0].cap = fmodulo(this.ref_pixels[ord_pts.length].cap + dpix / this.ref_pixels[0].ratio_x, 360);
  484. } else {
  485. this.ref_pixels[0].ratio_x = this.ref_pixels[1].ratio_x;
  486. this.ref_pixels[ord_pts.length].ratio_x = this.ref_pixels[ord_pts.length-1].ratio_x;
  487. this.ref_pixels[0].cap = fmodulo(this.ref_pixels[1].cap - this.ref_pixels[1].x / this.ref_pixels[1].ratio_x, 360);
  488. alpha_domain.start = this.ref_pixels[0].cap;
  489. 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);
  490. this.pixel_y_ratio = this.im.width/fmodulo(alpha_domain.end-alpha_domain.start, 360);
  491. }
  492. this.ref_pixels[0].x = 0;
  493. for (var i=0; i < ord_pts.length; i++) { // second parcours pour les paramètres elevation/y
  494. this.ref_pixels[i+1].shift_y = Math.floor(this.pixel_y_ratio*ord_pts[i].ele - ord_pts[i].y*this.im.height);
  495. if (i != ord_pts.length-1) {
  496. var next_shift = Math.floor(this.pixel_y_ratio*ord_pts[i+1].ele - ord_pts[i+1].y*this.im.height);
  497. 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);
  498. }
  499. }
  500. if (image_loop == true) {
  501. var dpix = this.im.width;
  502. var delt = 0;
  503. if (ord_pts.length > 1) {
  504. dpix = this.im.width - this.ref_pixels[this.ref_pixels.length-1].x + this.ref_pixels[1].x;
  505. delt = this.ref_pixels[this.ref_pixels.length-1].shift_y - this.ref_pixels[1].shift_y;
  506. }
  507. this.ref_pixels[0].dshft_y = -delt/dpix;
  508. this.ref_pixels[ord_pts.length].dshft_y = this.ref_pixels[0].dshft_y;
  509. dpix = this.im.width - this.ref_pixels[ord_pts.length].x;
  510. this.ref_pixels[0].shift_y = this.ref_pixels[ord_pts.length].shift_y + dpix*this.ref_pixels[0].dshft_y;
  511. } else {
  512. this.ref_pixels[0].shift_y = this.ref_pixels[1].shift_y;
  513. this.ref_pixels[0].dshft_y = 0;
  514. this.ref_pixels[ord_pts.length].dshft_y = 0;
  515. }
  516. if (debug_mode) {
  517. var res = document.getElementById('res');
  518. res.innerHTML = 'liste des '+this.ref_pixels.length+' valeurs de correction (image = '+this.im.width+'x'+this.im.height+') zoom = '+this.value+':<br/>';
  519. for (var i=0; i < this.ref_pixels.length; i++) { // pour le debug
  520. res.innerHTML += '<p>point '+i+' :</p><ul>';
  521. for (var key in this.ref_pixels[i]) { // pour le debug
  522. res.innerHTML += '<li>'+key + '['+i+'] = '+this.ref_pixels[i][key]+'</li>';
  523. }
  524. if (i != this.ref_pixels.length-1) {
  525. var tx0 = this.ref_pixels[i+1].x-1;
  526. //var ty0 = this.ref_pixels[i+1].shift_y;
  527. var ty0 = 0;
  528. } else {
  529. var tx0 = this.im.width-1;
  530. var ty0 = 0;
  531. }
  532. res.innerHTML += '</ul><p>test sur : '+tx0+','+ty0+'</p>';
  533. var tst = this.get_cap_ele(tx0, ty0);
  534. res.innerHTML += '<p>cap:'+tst.cap+', ele:'+tst.ele+'</p>';
  535. var tst2 = this.get_pos_xy(tst.cap, tst.ele);
  536. res.innerHTML += '</ul><p>x:'+tst2.x+', y:'+tst2.y+'</p>';
  537. }
  538. }
  539. }
  540. this.pt_list = new Array();
  541. for (var i=0; i<point_list.length; i++) {
  542. var lbl = point_list[i][0];
  543. var dst = point_list[i][1];
  544. var cap = point_list[i][2];
  545. var ele = point_list[i][3];
  546. var lnk = point_list[i][4];
  547. var url = point_list[i][5];
  548. var typ = 'unlocated';
  549. var rxy = this.get_pos_xy(cap, ele);
  550. var is_visible = (
  551. fmodulo(cap - alpha_domain.start, 360)
  552. <=
  553. fmodulo(alpha_domain.end -
  554. alpha_domain.start -0.0001, 360)+0.0001
  555. && is_located);
  556. this.pt_list[i] = new Array();
  557. if (ref_points[lbl] != undefined) {
  558. typ = 'ref_point';
  559. if (!is_located) {
  560. rxy = {
  561. x:ref_points[lbl].x*this.im.width,
  562. y:ref_points[lbl].y*this.im.height
  563. };
  564. }
  565. } else if(lnk == '' && is_visible && lbl != 'point temporaire') {
  566. typ = 'loc_point';
  567. }else if(is_visible && lbl =='point temporaire') {
  568. typ = 'temporary';
  569. } else if(is_visible) {
  570. typ = 'pano_point';
  571. lnk += '&to_zoom='+this.value;
  572. }
  573. this.pt_list[i]['type'] = typ;
  574. this.pt_list[i]['cap'] = cap;
  575. this.pt_list[i]['ele'] = ele;
  576. this.pt_list[i]['dist'] = dst;
  577. this.pt_list[i]['label'] = lbl;
  578. this.pt_list[i]['lnk'] = lnk;
  579. this.pt_list[i]['url'] = url;
  580. this.pt_list[i]['xc'] = rxy.x;
  581. this.pt_list[i]['yc'] = Math.floor(this.im.height/2 - rxy.y);
  582. }
  583. },
  584. this.get_tile_size = function(nx, ny) {
  585. var res = {width:0, height:0};
  586. if (nx == this.ntiles.x-1) res.width = this.last_tile.width;
  587. else res.width = this.tile.width;
  588. if (ny == this.ntiles.y-1) res.height = this.last_tile.height;
  589. else res.height = this.tile.height;
  590. return res;
  591. }
  592. this.get_cap_ele = function(px, py) { // recherche d'un cap et d'une élévation à partir d'un pixel X,Y.
  593. if (is_located) {
  594. for (var i=0; i < this.ref_pixels.length; i++) {
  595. if (i == this.ref_pixels.length - 1 || px < this.ref_pixels[i+1].x) {
  596. var dpix = px-this.ref_pixels[i].x;
  597. var cp = fmodulo(this.ref_pixels[i].cap + dpix/this.ref_pixels[i].ratio_x, 360);
  598. var el = (py+this.ref_pixels[i].shift_y+this.ref_pixels[i].dshft_y*dpix)/this.pixel_y_ratio;
  599. return {cap:cp, ele:el};
  600. }
  601. }
  602. } else {
  603. var cp = 360*px/this.im.width;
  604. var el = 360*py/this.im.height;
  605. return {cap:cp, ele:el};
  606. }
  607. }
  608. this.get_pos_xy = function(cap, ele) { // recherche des coordonnées pixel à partir d'un cap et d'une élévation.
  609. if (is_located) {
  610. var dcap = fmodulo(cap-this.ref_pixels[0].cap, 360);
  611. for (var i=0; i < this.ref_pixels.length; i++) {
  612. if (i == this.ref_pixels.length - 1 || dcap < fmodulo(this.ref_pixels[i+1].cap-this.ref_pixels[0].cap, 360)) {
  613. var px = this.ref_pixels[i].x + this.ref_pixels[i].ratio_x*fmodulo(cap - this.ref_pixels[i].cap, 360);
  614. var dpix = px-this.ref_pixels[i].x;
  615. var py = this.pixel_y_ratio*ele - this.ref_pixels[i].shift_y - this.ref_pixels[i].dshft_y*dpix;
  616. return {x:px, y:py};
  617. }
  618. }
  619. } else {
  620. var px = fmodulo(cap, 360)/360*this.im.width;
  621. var py = ele/360*this.im.height;
  622. return {x:px, y:py};
  623. }
  624. }
  625. }
  626. function reset_zooms () {
  627. for(i=0; i<zooms.length; i++) zooms[i].is_updated = false;
  628. zm.refresh();
  629. }
  630. function wheel_zoom (event) {
  631. var zshift = {x:0, y:0};
  632. if (event.pageX != undefined && event.pageX != undefined) {
  633. zshift.x = event.pageX-canvas.width/2-canvas_pos.x;
  634. zshift.y = event.pageY-canvas.height/2-canvas_pos.y;
  635. }
  636. //event.preventDefault();
  637. if (event.wheelDelta < 0 && zoom_control.value < zoom_control.max) {
  638. zoom_control.value++;
  639. change_zoom(zshift.x, zshift.y);
  640. } else if (event.wheelDelta > 0 && zoom_control.value > zoom_control.min) {
  641. zoom_control.value--;
  642. change_zoom(zshift.x, zshift.y);
  643. }
  644. }
  645. function change_zoom(shx, shy) {
  646. var zoom_control = document.getElementById("zoom_ctrl");
  647. var v = zoom_control.value;
  648. prev_zm = zm;
  649. if (zooms[v]) {
  650. if (!zooms[v].is_updated) zooms[v].refresh();
  651. } else {
  652. zooms[v] = new tzoom(v);
  653. }
  654. if (zooms[v].is_updated) {
  655. if (shx == undefined || shy == undefined) {
  656. shx=0;
  657. shy=0;
  658. }
  659. zm = zooms[v];
  660. var px = (last.x+shx)*zm.im.width/prev_zm.im.width - shx;
  661. var py = (last.y+shy)*zm.im.height/prev_zm.im.height - shy;
  662. if (py < zm.im.height && py >= 0) {
  663. zoom = zm.value;
  664. tile = zm.tile;
  665. ntiles = zm.ntiles;
  666. putImage(px, py);
  667. } else {
  668. zm = prev_zm;
  669. zoom_control.value = zm.value;
  670. }
  671. }
  672. }
  673. function change_angle() {
  674. var elvtn_control = document.getElementById('elvtn_ctrl');
  675. var angle_control = document.getElementById('angle_ctrl');
  676. var resxy = zm.get_pos_xy(angle_control.value, elvtn_control.value);
  677. var pos_x = resxy.x;
  678. var pos_y = Math.floor(zm.im.height/2 - resxy.y);
  679. putImage(pos_x, pos_y);
  680. }
  681. 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.
  682. return Math.sqrt(x*x + y*y) < r;
  683. }
  684. function check_links(e) {
  685. var mouse_x = e.pageX-canvas_pos.x;
  686. var mouse_y = e.pageY-canvas_pos.y;
  687. var pos_x = nmodulo(last.x + mouse_x - canvas.width/2, zm.im.width);
  688. var pos_y = last.y + mouse_y - canvas.height/2;
  689. for(var i = 0; i < zm.pt_list.length; i++) {
  690. if (is_located && zm.pt_list[i]['type'] == 'pano_point') {
  691. if (check_prox(zm.pt_list[i]['xc']-pos_x, zm.pt_list[i]['yc']-pos_y, 20)) {
  692. if (zm.pt_list[i]['lnk'] != '') window.location = zm.pt_list[i]['lnk'];
  693. break;
  694. }
  695. }
  696. }
  697. }
  698. function display_links(e) {
  699. var index = {};
  700. if (e.touches) {
  701. e.preventDefault();
  702. index.x = e.changedTouches[0].clientX;
  703. index.y = e.changedTouches[0].clientY;
  704. } else {
  705. index.x = e.pageX;
  706. index.y = e.pageY;
  707. }
  708. var info = document.getElementById('info');
  709. var mouse_x = index.x-canvas_pos.x;
  710. var mouse_y = index.y-canvas_pos.y;
  711. var pos_x = nmodulo(last.x + mouse_x - canvas.width/2, zm.im.width);
  712. var pos_y = last.y + mouse_y - canvas.height/2;
  713. //var cap = ((pos_x/zm.im.width)*360).toFixed(2);
  714. var res = zm.get_cap_ele(pos_x, zm.im.height/2 - pos_y);
  715. //var ele = ((zm.im.height/2 - pos_y)/zm.im.width)*360;
  716. info.innerHTML = 'élévation : '+res.ele.toFixed(2)+'<br/>cap : '+res.cap.toFixed(2);
  717. info.style.top = index.y+'px';
  718. info.style.left = index.x+'px';
  719. info.style.backgroundColor = '#FFC';
  720. info.style.display = 'block';
  721. canvas.style.cursor='crosshair';
  722. for(var i = 0; i < zm.pt_list.length; i++) {
  723. if (is_located || zm.pt_list[i]['type'] == 'ref_point') {
  724. if (check_prox(zm.pt_list[i]['xc']-pos_x, zm.pt_list[i]['yc']-pos_y, 20)) {
  725. info.innerHTML = zm.pt_list[i]['label'];
  726. if (zm.pt_list[i]['dist'] < 10) var dst = Math.round(zm.pt_list[i]['dist']*1000)+' m';
  727. else var dst = zm.pt_list[i]['dist'].toFixed(1)+' kms';
  728. info.innerHTML += '<br/> à ' + dst;
  729. info.style.backgroundColor = 'rgb('+point_colors[zm.pt_list[i]['type']]+')';
  730. canvas.style.cursor='auto';
  731. break;
  732. }
  733. }
  734. }
  735. }
  736. function hide_links() {
  737. canvas.removeEventListener( "mousemove", display_links, false);
  738. canvas.removeEventListener( "touchmove", display_links, false);
  739. var info = document.getElementById('info');
  740. info.style.display = 'none';
  741. }
  742. function show_links() {
  743. canvas.addEventListener( "mousemove", display_links, false);
  744. canvas.addEventListener( "touchmove", display_links, false);
  745. // var info = document.getElementById('info');
  746. // info.style.display = 'block';
  747. }
  748. function hide_contextmenu() {
  749. document.getElementById('insert').style.display = 'none';
  750. }
  751. function manage_ref_points(e) {
  752. //event.preventDefault();
  753. //event.stopPropagation();
  754. var sel_pt = document.getElementById('sel_point');
  755. var do_insert = document.getElementById('do-insert');
  756. var do_delete = document.getElementById('do-delete');
  757. var do_cancel = document.getElementById('do-cancel');
  758. var show_cap = document.getElementById('show-cap');
  759. var insrt = document.getElementById('insert');
  760. var pos_x = nmodulo(last.x + e.pageX - canvas_pos.x - canvas.width/2, zm.im.width);
  761. var pos_y = last.y + e.pageY - canvas_pos.y - canvas.height/2;
  762. insrt.style.left = e.pageX+'px';
  763. insrt.style.top = e.pageY+'px';
  764. insrt.style.display = 'block';
  765. if (do_insert) {// true if there are ref points
  766. for(var i = 0; i < zm.pt_list.length; i++) {
  767. if (zm.pt_list[i]['type'] == 'ref_point') {
  768. if (check_prox(zm.pt_list[i]['xc']-pos_x,
  769. zm.pt_list[i]['yc']-pos_y, 20)) {
  770. sel_pt.value = zm.pt_list[i]['label'];
  771. }
  772. }
  773. }
  774. do_delete.onclick = function() {delete_ref_point(insrt)};
  775. do_insert.onclick = function() {insert_ref_point(insrt, e.pageX-canvas_pos.x, e.pageY-canvas_pos.y)};
  776. show_cap.onclick = function() {
  777. window.open('show_capline.php?title='+encodeURIComponent(btoa(title))+'&cap='+res.cap+'&org_lat='+pt_lat+'&org_lon='+pt_lon+'&dist=120000');
  778. };
  779. }
  780. do_cancel.onclick = hide_contextmenu;
  781. var res = zm.get_cap_ele(pos_x, zm.im.height/2 - pos_y);
  782. var pt_lat = document.getElementById('pos_lat').childNodes[0].nodeValue;
  783. var pt_lon = document.getElementById('pos_lon').childNodes[0].nodeValue;
  784. return false;
  785. }
  786. function insert_ref_point(el, x, y) {
  787. var label, posx, posy;
  788. el.style.display = 'none';
  789. var selected_label = document.getElementById('sel_point').value;
  790. var found = false;
  791. var refpoint_url;
  792. for(var i = 0; i < zm.pt_list.length; i++) {
  793. label = zm.pt_list[i]['label'];
  794. if(label == selected_label) {
  795. refpoint_url = zm.pt_list[i]['url'];
  796. posx = nmodulo(last.x + x - canvas.width/2, zm.im.width)/zm.im.width;
  797. posy = 0.5 - (last.y + y - canvas.height/2)/zm.im.height;
  798. var pval = {x:posx, y:posy, cap:zm.pt_list[i]['cap'], ele:zm.pt_list[i]['ele'], label:label};
  799. ref_points[label] = pval;
  800. document.getElementById('res').innerHTML = '<h4>Dernier point entré</h4>';
  801. document.getElementById('res').innerHTML += '<p>reference["'+label+'"] = '+posx.toFixed(5)+','+posy.toFixed(5)+'</p>';
  802. reset_zooms();
  803. putImage(last.x, last.y);
  804. found = true;
  805. break;
  806. }
  807. }
  808. if (!found) {
  809. alert('unknown ref_point: '+label);
  810. }
  811. show_result();
  812. // Then push the modif
  813. var xhr = getXMLHttpRequest();
  814. xhr.open("POST", "/api/v1/references/", true);
  815. xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  816. alert("x=" + x + " y=" + y + " last.x=" + last.x + " last.y=" + last.y);
  817. xhr.send("reference_point=" + refpoint_url
  818. + "&panorama=" + panorama_url
  819. + "&csrfmiddlewaretoken=" + csrf_token
  820. + "&x=" + (last.x + x) + "&y=" + (last.y + y));
  821. }
  822. function show_result(clear_before) {
  823. var res = document.getElementById('res');
  824. var strg = '';
  825. for (var lbl in ref_points) {
  826. strg += '<li>reference["'+lbl+'"] = '+ref_points[lbl].x.toFixed(5)+','+ref_points[lbl].y.toFixed(5)+'</li>';
  827. }
  828. if (strg) strg = '<h3>Liste de tous les points de référence</h3>\n<ul>' + strg + '</ul>';
  829. if (clear_before) res.innerHTML = strg;
  830. else res.innerHTML += strg;
  831. }
  832. function delete_ref_point(el) {
  833. var ref_name = document.getElementById('sel_point').value;
  834. el.style.display = 'none';
  835. delete ref_points[ref_name];
  836. reset_zooms();
  837. putImage(last.x, last.y);
  838. show_result(true);
  839. // Then push the modif
  840. var xhr = getXMLHttpRequest();
  841. xhr.open("POST", "ajax/rm_reference.php", true);
  842. xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  843. xhr.send("ref_point="+encodeURIComponent(ref_name)
  844. +"&panorama="+encodeURIComponent(get_base_name()));
  845. }
  846. function clean_canvas_events(e) {
  847. canvas.removeEventListener('mousemove', stickImage, false);
  848. canvas.removeEventListener('touchmove', stickImage, false);
  849. document.getElementById('info').style.display = 'none';
  850. speed.x = 0;
  851. speed.y = 0;
  852. }
  853. canvas_set_size = function() {
  854. canvas.style.border = border_width+"px solid red";
  855. canvas.width = window.innerWidth-2*border_width;
  856. canvas.height = window.innerHeight-2*border_width;
  857. canvas_pos.x = canvas.offsetLeft+border_width;
  858. canvas_pos.y = canvas.offsetTop+border_width;
  859. }
  860. canvas_resize = function() {
  861. canvas_set_size();
  862. putImage(last.x, last.y);
  863. }
  864. function paramIn(e) {
  865. e = e || window.event;
  866. var relatedTarget = e.relatedTarget || e.fromElement;
  867. while (relatedTarget != adding && relatedTarget.nodeName != 'BODY' && relatedTarget != document && relatedTarget != localisation) {
  868. relatedTarget = relatedTarget.parentNode;
  869. }
  870. if (relatedTarget != adding && relatedTarget != localisation) {
  871. document.removeEventListener('keydown', keys, false);
  872. }
  873. }
  874. function paramOut(e) {
  875. e = e || window.event;
  876. var relatedTarget = e.relatedTarget || e.toElement;
  877. while (relatedTarget != adding && relatedTarget.nodeName != 'BODY' && relatedTarget != document && relatedTarget != localisation) {
  878. relatedTarget = relatedTarget.parentNode;
  879. }
  880. if (relatedTarget != adding && relatedTarget != localisation) {
  881. document.addEventListener('keydown', keys, false);
  882. }
  883. }
  884. function load_pano() {
  885. localisation = document.getElementById("locadraw");
  886. adding = document.getElementById("adding");
  887. canvas = document.getElementById("mon-canvas");
  888. cntext = canvas.getContext("2d");
  889. canvas_set_size();
  890. canvas.addEventListener("click", check_links, false);
  891. //canvas.addEventListener("oncontextmenu", manage_ref_points, false);
  892. canvas.oncontextmenu = manage_ref_points;
  893. canvas.addEventListener("mouseout" , clean_canvas_events, false);
  894. show_links();
  895. var max_zoom = zooms.length - 1;
  896. zoom_control = document.getElementById("zoom_ctrl");
  897. zoom_control.onchange = change_zoom;
  898. zoom_control.max = max_zoom;
  899. if (to_zoom > max_zoom) to_zoom = Math.floor(max_zoom/2);
  900. zm = zooms[to_zoom];
  901. zoom_control.value = to_zoom;
  902. zm.refresh();
  903. zoom = zm.value;
  904. tile = zm.tile;
  905. ntiles = zm.ntiles;
  906. angle_control = document.getElementById("angle_ctrl");
  907. angle_control.value = to_cap;
  908. angle_control.onchange = change_angle;
  909. angle_control.onclick = change_angle;
  910. elvtn_control = document.getElementById("elvtn_ctrl");
  911. elvtn_control.value = to_ele;
  912. elvtn_control.onchange = change_angle;
  913. elvtn_control.onclick = change_angle;
  914. change_angle();
  915. loca_temp = document.getElementById("loca_show");
  916. if (loca_temp) {
  917. loca_temp.onclick = showLoca;
  918. loca_temp = document.getElementById("loca_hide");
  919. loca_temp.onclick = hideLoca;
  920. loca_temp = document.getElementById("loca_button");
  921. loca_temp.onclick = localate_point;
  922. loca_erase = document.getElementById("loca_erase");
  923. loca_erase.onclick = erase_point;
  924. localisation.addEventListener('mouseover',paramIn,false);
  925. localisation.addEventListener('mouseout',paramOut,false);
  926. }
  927. canvas.addEventListener('mousedown', onImageClick, false);
  928. canvas.addEventListener('touchstart', onImageClick, false);
  929. document.addEventListener('keydown', keys, false);
  930. canvas.addEventListener('mousewheel', wheel_zoom, false);
  931. window.onresize = canvas_resize;
  932. if (adding) {
  933. document.getElementById("paramFormHide").onclick = hideForm;
  934. document.getElementById("paramFormShow").onclick = showForm;
  935. adding.addEventListener('mouseover', paramIn, false);
  936. adding.addEventListener('mouseout', paramOut, false);
  937. }
  938. };